[Groonga-commit] groonga/groonga at 188649a [master] mrb estimate_size: support "(... || ...) && (... || ...)" case

Back to archive index

Kouhei Sutou null+****@clear*****
Wed Jul 8 14:30:13 JST 2015


Kouhei Sutou	2015-07-08 14:30:13 +0900 (Wed, 08 Jul 2015)

  New Revision: 188649a5ab0259e8ab94d0b7f25ec97f0cf6faaf
  https://github.com/groonga/groonga/commit/188649a5ab0259e8ab94d0b7f25ec97f0cf6faaf

  Message:
    mrb estimate_size: support "(... || ...) && (... || ...)" case

  Modified files:
    lib/mrb/scripts/expression_size_estimator.rb
    test/query_optimizer/suite/test_estimate_size.rb

  Modified: lib/mrb/scripts/expression_size_estimator.rb (+31 -28)
===================================================================
--- lib/mrb/scripts/expression_size_estimator.rb    2015-07-08 14:13:11 +0900 (28b80fc)
+++ lib/mrb/scripts/expression_size_estimator.rb    2015-07-08 14:30:13 +0900 (ba7cf11)
@@ -11,43 +11,46 @@ module Groonga
       data_list = builder.build
       return @table_size if data_list.nil?
 
-      or_data_list = group_data_list(data_list)
-      or_sizes = or_data_list.collect do |and_data_list|
-        and_sizes = and_data_list.collect do |data|
-          size = estimate_data(data)
-          if data.logical_op == Operator::AND_NOT
-            size = @table_size - size
-            size = 0 if size < 0
-          end
-          size
-        end
-        and_sizes.min
-      end
-      or_sizes.max
-    end
-
-    private
-    def group_data_list(data_list)
-      or_data_list = [[]]
+      current_size = 0
+      sizes = []
       data_list.each do |data|
-        next if data.op == Operator::NOP
-
-        and_data_list = or_data_list.last
-        if and_data_list.empty?
-          and_data_list << data
-        else
+        if (data.flags & ScanInfo::Flags::POP) != 0
+          size = sizes.pop
           case data.logical_op
           when Operator::AND, Operator::AND_NOT
-            and_data_list << data
+            current_size = size if size < current_size
+          when Operator::OR
+            current_size = size if size > current_size
           else
-            and_data_list = [data]
-            or_data_list << and_data_list
+            message = "invalid logical operator: <#{data.logical_op.inspect}>"
+            raise InvalidArgument, message
+          end
+        else
+          if (data.flags & ScanInfo::Flags::PUSH) != 0
+            sizes.push(current_size)
+            current_size = 0
+          end
+
+          size = estimate_data(data)
+          case data.logical_op
+          when Operator::AND
+            current_size = size if size < current_size
+          when Operator::AND_NOT
+            size = @table_size - size
+            size = 0 if size < 0
+            current_size = size if size < current_size
+          when Operator::OR
+            current_size = size if size > current_size
+          else
+            message = "invalid logical operator: <#{data.logical_op.inspect}>"
+            raise InvalidArgument, message
           end
         end
       end
-      or_data_list
+      current_size
     end
 
+    private
     def estimate_data(data)
       search_index = data.search_indexes.first
       return @table_size if search_index.nil?

  Modified: test/query_optimizer/suite/test_estimate_size.rb (+24 -0)
===================================================================
--- test/query_optimizer/suite/test_estimate_size.rb    2015-07-08 14:13:11 +0900 (cad86b2)
+++ test/query_optimizer/suite/test_estimate_size.rb    2015-07-08 14:30:13 +0900 (3c1d0e1)
@@ -488,5 +488,29 @@ class TestEstimateSize < QueryOptimizerTestCase
                                     "type == 1" +
                                     ")"))
     end
+
+    def test_or_and
+      @logs.add(:message => "Groonga is fast", :type => 1)
+      @logs.add(:message => "Rroonga is fast", :type => 1)
+      @logs.add(:message => "Mroonga is fast", :type => 1)
+      @logs.add(:timestamp => "2015-02-19 02:17:00", :type => 2)
+      @logs.add(:timestamp => "2015-02-19 02:17:00", :type => 2)
+      @logs.add(:timestamp => "2015-02-19 02:18:00", :type => 2)
+      @logs.add(:timestamp => "2015-02-19 02:18:00", :type => 2)
+      @logs.add(:timestamp => "2015-02-19 02:19:00", :type => 3)
+      @logs.add(:timestamp => "2015-02-19 02:19:00", :type => 3)
+      @logs.add(:timestamp => "2015-02-19 02:19:00", :type => 3)
+      @logs.add(:timestamp => "2015-02-19 02:19:00", :type => 3)
+
+      assert_equal(1,
+                   estimate_size("(" +
+                                 "timestamp < '2015-02-19 02:19:00' || " +
+                                 "type == 2 " +
+                                 ") && " +
+                                 "(" +
+                                 "message @ 'Groonga' || " +
+                                 "message @ 'Rroonga'" +
+                                 ")"))
+    end
   end
 end
-------------- next part --------------
HTML����������������������������...
다운로드 



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