[Groonga-commit] groonga/groonga at eeddabd [master] expr optimize: optimize "A && !B" to "A &! B"

Back to archive index
Kouhei Sutou null+****@clear*****
Mon Mar 4 14:53:57 JST 2019


Kouhei Sutou	2019-03-04 14:53:57 +0900 (Mon, 04 Mar 2019)

  Revision: eeddabdacc3d4ab9be5402548b9078e000e3f0de
  https://github.com/groonga/groonga/commit/eeddabdacc3d4ab9be5402548b9078e000e3f0de

  Message:
    expr optimize: optimize "A && !B" to "A &! B"

  Modified files:
    lib/mrb/scripts/expression_rewriters/optimizer.rb

  Modified: lib/mrb/scripts/expression_rewriters/optimizer.rb (+65 -12)
===================================================================
--- lib/mrb/scripts/expression_rewriters/optimizer.rb    2019-03-04 14:13:20 +0900 (07c92514f)
+++ lib/mrb/scripts/expression_rewriters/optimizer.rb    2019-03-04 14:53:57 +0900 (46115fc2f)
@@ -20,19 +20,21 @@ module Groonga
       def optimize_node(table, node)
         case node
         when ExpressionTree::LogicalOperation
-          optimized_sub_nodes = node.nodes.collect do |sub_node|
-            optimize_node(table, sub_node)
-          end
-          case node.operator
-          when Operator::AND
-            optimized_sub_nodes =
-              optimize_and_sub_nodes(table, optimized_sub_nodes)
-          when Operator::OR
-            optimized_sub_nodes =
-              optimize_or_sub_nodes(table, optimized_sub_nodes)
+          optimize_and_not(table, node) do |optimized_node|
+            optimized_sub_nodes = optimized_node.nodes.collect do |sub_node|
+              optimize_node(table, sub_node)
+            end
+            case optimized_node.operator
+            when Operator::AND
+              optimized_sub_nodes =
+                optimize_and_sub_nodes(table, optimized_sub_nodes)
+            when Operator::OR
+              optimized_sub_nodes =
+                optimize_or_sub_nodes(table, optimized_sub_nodes)
+            end
+            ExpressionTree::LogicalOperation.new(optimized_node.operator,
+                                                 optimized_sub_nodes)
           end
-          ExpressionTree::LogicalOperation.new(node.operator,
-                                               optimized_sub_nodes)
         when ExpressionTree::BinaryOperation
           optimize_binary_operation_node(table, node)
         else
@@ -40,6 +42,57 @@ module Groonga
         end
       end
 
+      def optimize_and_not(table, node)
+        return yield(node) unless node.operator == Operator::AND
+
+        optimized_sub_nodes = []
+        sub_nodes = []
+        node.nodes.each do |sub_node|
+          if sub_node.respond_to?(:operator)
+            sub_node_operator = sub_node.operator
+          else
+            sub_node_oeprator = nil
+          end
+          unless sub_node_operator == Operator::NOT
+            sub_nodes << sub_node
+            next
+          end
+
+          case sub_nodes.size
+          when 0
+            sub_nodes << sub_node
+          when 1
+            and_not_node =
+              ExpressionTree::LogicalOperation.new(Operator::AND_NOT,
+                                                   [sub_nodes.first,
+                                                    sub_node.value])
+            optimized_sub_nodes << yield(and_not_node)
+            sub_nodes = []
+          else
+            and_nodes = ExpressionTree::LogicalOperation.new(node.operator,
+                                                             sub_nodes)
+            optimized_and_nodes = yield(and_nodes)
+            and_not_node =
+              ExpressionTree::LogicalOperation.new(Operator::AND_NOT,
+                                                   [optimized_and_nodes,
+                                                    sub_node.value])
+            optimized_sub_nodes << yield(and_not_node)
+            sub_nodes = []
+          end
+        end
+        unless sub_nodes.empty?
+          and_nodes = ExpressionTree::LogicalOperation.new(node.operator,
+                                                           sub_nodes)
+          optimized_sub_nodes << yield(and_nodes)
+        end
+        if optimized_sub_nodes.size == 1
+          optimized_sub_nodes.first
+        else
+          ExpressionTree::LogicalOperation.new(node.operator,
+                                               optimized_sub_nodes)
+        end
+      end
+
       def optimize_binary_operation_node(table, node)
         optimized_left = optimize_node(table, node.left)
         optimized_right = optimize_node(table, node.right)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.osdn.me/mailman/archives/groonga-commit/attachments/20190304/d8486cea/attachment-0001.html>


More information about the Groonga-commit mailing list
Back to archive index