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>