[Groonga-commit] groonga/groonga at a0de830 [master] logical_range_filter: implement roughly based on filter and sort

Back to archive index

Kouhei Sutou null+****@clear*****
Tue Feb 10 00:08:23 JST 2015


Kouhei Sutou	2015-02-10 00:08:23 +0900 (Tue, 10 Feb 2015)

  New Revision: a0de8309ce7a0e3dd8e00807de2271ee586b6153
  https://github.com/groonga/groonga/commit/a0de8309ce7a0e3dd8e00807de2271ee586b6153

  Message:
    logical_range_filter: implement roughly based on filter and sort

  Modified files:
    plugins/sharding/logical_range_filter.rb
    test/command/suite/sharding/logical_range_filter/no_condition/multiple_physical_tables.expected
    test/command/suite/sharding/logical_range_filter/no_condition/multiple_physical_tables.test

  Modified: plugins/sharding/logical_range_filter.rb (+141 -5)
===================================================================
--- plugins/sharding/logical_range_filter.rb    2015-02-10 00:06:46 +0900 (5cf3cfd)
+++ plugins/sharding/logical_range_filter.rb    2015-02-10 00:08:23 +0900 (7e765f7)
@@ -19,14 +19,26 @@ module Groonga
       def run_body(input)
         enumerator = LogicalEnumerator.new("logical_range_filter", input)
         filter = input[:filter]
-        offset = input[:offset] || 0
-        limit = input[:limit] || 10
+        offset = (input[:offset] || 0).to_i
+        limit = (input[:limit] || 10).to_i
         output_columns = input[:output_columns] || "_key, *"
 
         result_sets = []
-        enumerator.each do |table, shard_key, shard_range, cover_type|
-          # TODO: result_sets << result_set
+        n_records = 0
+        enumerator.each do |table, shard_key, shard_range|
+          result_set = filter_shard(table, filter,
+                                    shard_key, shard_range,
+                                    enumerator.target_range)
+          next if result_set.nil?
+          if result_set.empty?
+            result_set.close if result_set.temporary?
+            next
+          end
+          result_sets << result_set
+          n_records += result_set.size
+          break if n_records >= offset + limit
         end
+
         if result_sets.empty?
           n_elements = 0
         else
@@ -35,14 +47,138 @@ module Groonga
             n_elements += result_set.size
           end
         end
+
+        sort_keys = [
+          {
+            :key => enumerator.shard_key_name,
+            :order => :ascending,
+          },
+        ]
+        current_offset = offset
+        current_limit = limit
         writer.array("RESULTSET", n_elements) do
           first_result_set = result_sets.first
           if first_result_set
             writer.write_table_columns(first_result_set, output_columns)
           end
           result_sets.each do |result_set|
-            writer.write_table_records(result_set, output_columns)
+            if result_set.size <= current_offset
+              current_offset -= result_set.size
+              next
+            end
+            sorted_result_set = result_set.sort(sort_keys,
+                                                :offset => current_offset,
+                                                :limit => current_limit)
+            writer.write_table_records(sorted_result_set, output_columns)
+            current_limit -= sorted_result_set.size
+            sorted_result_set.close
+          end
+        end
+
+        result_sets.each do |result_set|
+          result_set.close if result_set.temporary?
+        end
+      end
+
+      def filter_shard(table, filter, shard_key, shard_range, target_range)
+        cover_type = target_range.cover_type(shard_range)
+        return nil if cover_type == :none
+
+        if cover_type == :all
+          if filter.nil?
+            return table
+          else
+            return filter_table(table, filter)
+          end
+        end
+
+        use_range_index = false
+        range_index = nil
+        # TODO
+        # if filter.nil?
+        #   index_info = shard_key.find_index(Operator::LESS)
+        #   if index_info
+        #     range_index = index_info.index
+        #     use_range_index = true
+        #   end
+        # end
+
+        case cover_type
+        when :partial_min
+          if use_range_index
+            # TODO
+            # count_n_records_in_range(range_index,
+            #                          target_range.min, target_range.min_border,
+            #                          nil, nil)
+          else
+            filter_table(table, filter) do |expression|
+              expression.append_object(shard_key, Operator::PUSH, 1)
+              expression.append_operator(Operator::GET_VALUE, 1)
+              expression.append_constant(target_range.min, Operator::PUSH, 1)
+              if target_range.min_border == :include
+                expression.append_operator(Operator::GREATER_EQUAL, 2)
+              else
+                expression.append_operator(Operator::GREATER, 2)
+              end
+            end
+          end
+        when :partial_max
+          if use_range_index
+            # TODO
+            # count_n_records_in_range(range_index,
+            #                          nil, nil,
+            #                          target_range.max, target_range.max_border)
+          else
+            filter_table(table, filter) do |expression|
+              expression.append_object(shard_key, Operator::PUSH, 1)
+              expression.append_operator(Operator::GET_VALUE, 1)
+              expression.append_constant(target_range.max, Operator::PUSH, 1)
+              if target_range.max_border == :include
+                expression.append_operator(Operator::LESS_EQUAL, 2)
+              else
+                expression.append_operator(Operator::LESS, 2)
+              end
+            end
+          end
+        when :partial_min_and_max
+          if use_range_index
+            # TODO
+            # count_n_records_in_range(range_index,
+            #                          target_range.min, target_range.min_border,
+            #                          target_range.max, target_range.max_border)
+          else
+            filter_table(table, filter) do |expression|
+              expression.append_object(context["between"], Operator::PUSH, 1)
+              expression.append_object(shard_key, Operator::PUSH, 1)
+              expression.append_operator(Operator::GET_VALUE, 1)
+              expression.append_constant(target_range.min, Operator::PUSH, 1)
+              expression.append_constant(target_range.min_border,
+                                         Operator::PUSH, 1)
+              expression.append_constant(target_range.max, Operator::PUSH, 1)
+              expression.append_constant(target_range.max_border,
+                                         Operator::PUSH, 1)
+              expression.append_operator(Operator::CALL, 5)
+            end
+          end
+        end
+      end
+
+      def filter_table(table, filter)
+        expression = nil
+        begin
+          expression = Expression.create(table)
+          if block_given?
+            yield(expression)
+            if filter
+              expression.parse(filter)
+              expression.append_operator(Operator::AND, 2)
+            end
+          else
+            expression.parse(filter)
           end
+          table.select(expression)
+        ensure
+          expression.close if expression
         end
       end
     end

  Modified: test/command/suite/sharding/logical_range_filter/no_condition/multiple_physical_tables.expected (+55 -7)
===================================================================
--- test/command/suite/sharding/logical_range_filter/no_condition/multiple_physical_tables.expected    2015-02-10 00:06:46 +0900 (adb5220)
+++ test/command/suite/sharding/logical_range_filter/no_condition/multiple_physical_tables.expected    2015-02-10 00:08:23 +0900 (430167f)
@@ -4,31 +4,79 @@ table_create Logs_20150203 TABLE_NO_KEY
 [[0,0.0,0.0],true]
 column_create Logs_20150203 timestamp COLUMN_SCALAR Time
 [[0,0.0,0.0],true]
+column_create Logs_20150203 memo COLUMN_SCALAR ShortText
+[[0,0.0,0.0],true]
 table_create Logs_20150204 TABLE_NO_KEY
 [[0,0.0,0.0],true]
 column_create Logs_20150204 timestamp COLUMN_SCALAR Time
 [[0,0.0,0.0],true]
+column_create Logs_20150204 memo COLUMN_SCALAR ShortText
+[[0,0.0,0.0],true]
 table_create Logs_20150205 TABLE_NO_KEY
 [[0,0.0,0.0],true]
 column_create Logs_20150205 timestamp COLUMN_SCALAR Time
 [[0,0.0,0.0],true]
+column_create Logs_20150205 memo COLUMN_SCALAR ShortText
+[[0,0.0,0.0],true]
 load --table Logs_20150203
 [
-{"timestamp": "2015-02-03 12:49:00"}
+{"timestamp": "2015-02-03 12:49:00", "memo": "2015-02-03 12:49:00"}
 ]
 [[0,0.0,0.0],1]
 load --table Logs_20150204
 [
-{"timestamp": "2015-02-04 13:49:00"},
-{"timestamp": "2015-02-04 13:50:00"}
+{"timestamp": "2015-02-04 13:49:00", "memo": "2015-02-04 13:49:00"},
+{"timestamp": "2015-02-04 13:50:00", "memo": "2015-02-04 13:50:00"}
 ]
 [[0,0.0,0.0],2]
 load --table Logs_20150205
 [
-{"timestamp": "2015-02-05 13:49:00"},
-{"timestamp": "2015-02-05 13:50:00"},
-{"timestamp": "2015-02-05 13:51:00"}
+{"timestamp": "2015-02-05 13:49:00", "memo": "2015-02-05 13:49:00"},
+{"timestamp": "2015-02-05 13:50:00", "memo": "2015-02-05 13:50:00"},
+{"timestamp": "2015-02-05 13:51:00", "memo": "2015-02-05 13:51:00"}
 ]
 [[0,0.0,0.0],3]
 logical_range_filter Logs timestamp
-[[0,0.0,0.0],[]]
+[
+  [
+    0,
+    0.0,
+    0.0
+  ],
+  [
+    [
+      [
+        "memo",
+        "ShortText"
+      ],
+      [
+        "timestamp",
+        "Time"
+      ]
+    ],
+    [
+      "2015-02-03 12:49:00",
+      1422935340.0
+    ],
+    [
+      "2015-02-04 13:49:00",
+      1423025340.0
+    ],
+    [
+      "2015-02-04 13:50:00",
+      1423025400.0
+    ],
+    [
+      "2015-02-05 13:49:00",
+      1423111740.0
+    ],
+    [
+      "2015-02-05 13:50:00",
+      1423111800.0
+    ],
+    [
+      "2015-02-05 13:51:00",
+      1423111860.0
+    ]
+  ]
+]

  Modified: test/command/suite/sharding/logical_range_filter/no_condition/multiple_physical_tables.test (+9 -6)
===================================================================
--- test/command/suite/sharding/logical_range_filter/no_condition/multiple_physical_tables.test    2015-02-10 00:06:46 +0900 (86c4059)
+++ test/command/suite/sharding/logical_range_filter/no_condition/multiple_physical_tables.test    2015-02-10 00:08:23 +0900 (9aa627e)
@@ -4,29 +4,32 @@ register sharding
 
 table_create Logs_20150203 TABLE_NO_KEY
 column_create Logs_20150203 timestamp COLUMN_SCALAR Time
+column_create Logs_20150203 memo COLUMN_SCALAR ShortText
 
 table_create Logs_20150204 TABLE_NO_KEY
 column_create Logs_20150204 timestamp COLUMN_SCALAR Time
+column_create Logs_20150204 memo COLUMN_SCALAR ShortText
 
 table_create Logs_20150205 TABLE_NO_KEY
 column_create Logs_20150205 timestamp COLUMN_SCALAR Time
+column_create Logs_20150205 memo COLUMN_SCALAR ShortText
 
 load --table Logs_20150203
 [
-{"timestamp": "2015-02-03 12:49:00"}
+{"timestamp": "2015-02-03 12:49:00", "memo": "2015-02-03 12:49:00"}
 ]
 
 load --table Logs_20150204
 [
-{"timestamp": "2015-02-04 13:49:00"},
-{"timestamp": "2015-02-04 13:50:00"}
+{"timestamp": "2015-02-04 13:49:00", "memo": "2015-02-04 13:49:00"},
+{"timestamp": "2015-02-04 13:50:00", "memo": "2015-02-04 13:50:00"}
 ]
 
 load --table Logs_20150205
 [
-{"timestamp": "2015-02-05 13:49:00"},
-{"timestamp": "2015-02-05 13:50:00"},
-{"timestamp": "2015-02-05 13:51:00"}
+{"timestamp": "2015-02-05 13:49:00", "memo": "2015-02-05 13:49:00"},
+{"timestamp": "2015-02-05 13:50:00", "memo": "2015-02-05 13:50:00"},
+{"timestamp": "2015-02-05 13:51:00", "memo": "2015-02-05 13:51:00"}
 ]
 
 logical_range_filter Logs timestamp
-------------- next part --------------
HTML����������������������������...
Download 



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