[Groonga-commit] groonga/groonga at ceaabf6 [master] logical_range_filter: add support for window function over shards

Back to archive index
Kouhei Sutou null+****@clear*****
Fri Apr 26 15:43:52 JST 2019


Kouhei Sutou	2019-04-26 15:43:52 +0900 (Fri, 26 Apr 2019)

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

  Message:
    logical_range_filter: add support for window function over shards

  Removed files:
    test/command/suite/sharding/logical_range_filter/columns/stage/filtered/window_function/shards.reject
    test/command/suite/sharding/logical_range_filter/columns/stage/initial/window_function/shards.reject
  Modified files:
    plugins/sharding/dynamic_columns.rb
    plugins/sharding/logical_range_filter.rb
    test/command/suite/sharding/logical_range_filter/columns/stage/filtered/window_function/shards.test
    test/command/suite/sharding/logical_range_filter/columns/stage/initial/range.expected
    test/command/suite/sharding/logical_range_filter/columns/stage/initial/window_function/shards.test

  Modified: plugins/sharding/dynamic_columns.rb (+34 -21)
===================================================================
--- plugins/sharding/dynamic_columns.rb    2019-04-26 15:43:03 +0900 (18cc3a8bf)
+++ plugins/sharding/dynamic_columns.rb    2019-04-26 15:43:52 +0900 (004c6527e)
@@ -1,6 +1,8 @@
 module Groonga
   module Sharding
     class DynamicColumns
+      include Enumerable
+
       class << self
         def parse(input)
           initial_contexts = {}
@@ -48,6 +50,12 @@ module Groonga
         not @output_contexts.empty?
       end
 
+      def have_window_function?
+        any? do |context|
+          context.window_function?
+        end
+      end
+
       def each_initial(&block)
         @initial_contexts.tsort_each(&block)
       end
@@ -66,16 +74,16 @@ module Groonga
         each_output(&block)
       end
 
-      def apply_initial(targets)
-        apply(@initial_contexts, targets)
+      def apply_initial(targets, options={})
+        apply(@initial_contexts, targets, options)
       end
 
-      def apply_filtered(targets)
-        apply(@filtered_contexts, targets)
+      def apply_filtered(targets, options={})
+        apply(@filtered_contexts, targets, options)
       end
 
-      def apply_output(targets)
-        apply(@output_contexts, targets)
+      def apply_output(targets, options={})
+        apply(@output_contexts, targets, options)
       end
 
       def empty?
@@ -105,7 +113,7 @@ module Groonga
       end
 
       private
-      def apply(contexts, targets)
+      def apply(contexts, targets, options)
         window_function_contexts = []
         normal_contexts = []
         contexts.each do |context|
@@ -116,13 +124,17 @@ module Groonga
           end
         end
 
-        targets.each do |result_set, options|
-          normal_contexts.each do |context|
-            context.apply(result_set, options)
+        if options.fetch(:normal, true)
+          targets.each do |result_set, options|
+            normal_contexts.each do |context|
+              context.apply(result_set, options)
+            end
           end
         end
-        window_function_contexts.each do |context|
-          context.apply_window_function(targets)
+        if options.fetch(:window_function, true)
+          window_function_contexts.each do |context|
+            context.apply_window_function(targets)
+          end
         end
       end
     end
@@ -196,11 +208,8 @@ module Groonga
       end
 
       def apply(table, options=nil)
-        if context_target?(options)
-          column = table.find_column(@label)
-        else
-          column = table.create_column(@label, @flags, @type)
-        end
+        return if table.find_column(@label)
+        column = table.create_column(@label, @flags, @type)
         return if table.empty?
 
         condition = nil
@@ -223,11 +232,15 @@ module Groonga
           executor.group_keys = @window_group_keys.join(", ")
           executor.output_column_name = @label
           targets.each do |table, options|
-            unless context_target?(options)
-              table.create_column(@label, @flags, @type)
-            end
+            is_context_table = context_target?(options)
+            column = table.find_column(@label)
+            column ||= table.create_column(@label, @flags, @type)
             next if table.empty?
-            executor.add_table(table)
+            if is_context_table
+              executor.add_context_table(table)
+            else
+              executor.add_table(table)
+            end
           end
           executor.execute
         ensure

  Modified: plugins/sharding/logical_range_filter.rb (+237 -114)
===================================================================
--- plugins/sharding/logical_range_filter.rb    2019-04-26 15:43:03 +0900 (80a0850ae)
+++ plugins/sharding/logical_range_filter.rb    2019-04-26 15:43:52 +0900 (a80b7825f)
@@ -97,6 +97,7 @@ module Groonga
         attr_reader :result_sets
         attr_reader :temporary_tables
         attr_reader :threshold
+        attr_reader :time_classify_types
         def initialize(input)
           @input = input
           @use_range_index = parse_use_range_index(@input[:use_range_index])
@@ -117,6 +118,8 @@ module Groonga
           @temporary_tables = []
 
           @threshold = compute_threshold
+
+          @time_classify_types = detect_time_classify_types
         end
 
         def close
@@ -125,6 +128,12 @@ module Groonga
           end
         end
 
+        def need_look_ahead?
+          return false unless @dynamic_columns.have_window_function?
+          return false unless @time_classify_types.empty?
+          true
+        end
+
         private
         def parse_use_range_index(use_range_index)
           case use_range_index
@@ -159,6 +168,33 @@ module Groonga
           default_threshold = 0.2
           (threshold_env || default_threshold).to_f
         end
+
+        def detect_time_classify_types
+          window_group_keys = []
+          @dynamic_columns.each_filtered do |dynamic_column|
+            window_group_keys.concat(dynamic_column.window_group_keys)
+          end
+          return [] if window_group_keys.empty?
+
+          types = []
+          @dynamic_columns.each do |dynamic_column|
+            next unless window_group_keys.include?(dynamic_column.label)
+            case dynamic_column.value.strip
+            when /\Atime_classify_(.+?)\s*\(\s*([a-zA-Z\d_]+)\s*[,)]/
+              type = $1
+              column = $2
+              next if column !=****@enume*****_key_name
+
+              case type
+              when "minute", "second"
+                types << type
+              when "day", "hour"
+                types << type
+              end
+            end
+          end
+          types
+        end
       end
 
       class Executor
@@ -168,20 +204,13 @@ module Groonga
 
         def execute
           first_shard = nil
-          enumerator =****@conte*****
-          target_range = enumerator.target_range
-          if****@conte***** == :descending
-            each_method = :reverse_each
-          else
-            each_method = :each
-          end
-          enumerator.send(each_method) do |shard, shard_range|
-            first_shard ||= shard
-            shard_executor = ShardExecutor.new(@context, shard, shard_range)
+          each_shard_executor do |shard_executor|
+            first_shard ||= shard_executor.shard
             shard_executor.execute
             break if****@conte*****_limit.zero?
           end
           if first_shard.nil?
+            enumerator =****@conte*****
             message =
               "[logical_range_filter] no shard exists: " +
               "logical_table: <#{enumerator.logical_table}>: " +
@@ -198,6 +227,36 @@ module Groonga
             @context.result_sets << result_set
           end
         end
+
+        private
+        def each_shard_executor(&block)
+          enumerator =****@conte*****
+          target_range = enumerator.target_range
+          if****@conte***** == :descending
+            each_method = :reverse_each
+          else
+            each_method = :each
+          end
+          if****@conte*****_look_ahead?
+            executors = []
+            previous_executor = nil
+            enumerator.send(each_method) do |shard, shard_range|
+              current_executor = ShardExecutor.new(@context, shard, shard_range)
+              if previous_executor
+                previous_executor.next_executor = current_executor
+                current_executor.previous_executor = previous_executor
+                executors << previous_executor
+              end
+              previous_executor = current_executor
+            end
+            executors << previous_executor if previous_executor
+            executors.each(&block)
+          else
+            enumerator.send(each_method) do |shard, shard_range|
+              yield(ShardExecutor.new(@context, shard, shard_range))
+            end
+          end
+        end
       end
 
       class Window
@@ -435,72 +494,137 @@ module Groonga
       end
 
       class ShardExecutor
+        attr_reader :shard
+        attr_writer :previous_executor
+        attr_writer :next_executor
         def initialize(context, shard, shard_range)
           @context = context
           @shard = shard
           @shard_range = shard_range
 
+          @shard_key = shard.key
           @target_table =****@shard*****
 
           @filter =****@conte*****
           @post_filter =****@conte*****_filter
           @result_sets =****@conte*****_sets
+          @filtered_result_sets = []
           @temporary_tables =****@conte*****_tables
 
           @target_range =****@conte*****_range
 
           @cover_type = @target_range.cover_type(@shard_range)
+
+          @previous_executor = nil
+          @next_executor = nil
+
+          @initital_table = nil
+
+          @range_index = nil
+          @window = nil
+
+          @prepared = false
+          @filtered = false
         end
 
         def execute
-          return if @cover_type == :none
-          return if @target_table.empty?
+          ensure_filtered
+
+          return if @filtered_result_sets.empty?
+
+          if @window
+            @filtered_result_sets.each do |result_set|
+              @window.each(result_set) do |windowed_result_set|
+                @temporary_tables << windowed_result_set
+                if****@conte*****_columns.have_filtered?
+                  apply_targets = [[windowed_result_set]]
+                  @context.dynamic_columns.apply_filtered(apply_targets)
+                end
+                sort_result_set(windowed_result_set)
+                return if****@conte*****_limit.zero?
+              end
+            end
+          else
+            apply_targets = []
+            if @previous_executor
+              @previous_executor.add_filtered_stage_context(apply_targets)
+            end
+            @filtered_result_sets.each do |result_set|
+              apply_targets << [result_set]
+            end
+            if @next_executor
+              @next_executor.add_filtered_stage_context(apply_targets)
+            end
+            options = {}
+            if****@conte*****_look_ahead?
+              options[:normal] = false
+            end
+            @context.dynamic_columns.apply_filtered(apply_targets, options)
+            @filtered_result_sets.each do |result_set|
+              sort_result_set(result_set)
+            end
+          end
+        end
+
+        def add_initial_stage_context(apply_targets)
+          ensure_prepared
+          return unless @initial_table
+          apply_targets << [@initial_table, {context: true}]
+        end
+
+        def add_filtered_stage_context(apply_targets)
+          ensure_filtered
+          @filtered_result_sets.each do |table|
+            apply_targets << [table, {context: true}]
+          end
+        end
 
-          shard_key =****@shard*****
-          if shard_key.nil?
+        private
+        def have_record?
+          return false if @cover_type == :none
+          return false if @target_table.empty?
+          true
+        end
+
+        def ensure_prepared
+          return if @prepared
+          @prepared = true
+
+          return unless have_record?
+
+          if @shard_key.nil?
             message = "[logical_range_filter] shard_key doesn't exist: " +
                       "<#{@shard.key_name}>"
             raise InvalidArgument, message
           end
 
-          expression_builder = RangeExpressionBuilder.new(shard_key,
-                                                          @target_range)
-          expression_builder.filter = @filter
-
-          index_info = shard_key.find_index(Operator::LESS)
-          if index_info
-            range_index = index_info.index
-            unless use_range_index?(range_index, expression_builder)
-              range_index = nil
-            end
-          else
-            range_index = nil
+          @expression_builder = RangeExpressionBuilder.new(@shard_key,
+                                                           @target_range)
+          @expression_builder.filter = @filter
+          index_info = @shard_key.find_index(Operator::LESS)
+          if index_info and use_range_index?
+            @range_index = index_info.index
           end
 
           if****@conte*****_columns.have_initial?
-            if @target_table ==****@shard*****
-              if @cover_type == :all
-                @target_table = @target_table.select_all
-              else
-                expression_builder.filter = nil
-                @target_table = create_expression(@target_table) do |expression|
-                  expression_builder.build(expression, @shard_range)
-                  @target_table.select(expression)
-                end
-                @cover_type = :all
-                expression_builder.filter = @filter
+            if @cover_type == :all
+              @target_table = @target_table.select_all
+            else
+              @expression_builder.filter = nil
+              @target_table = create_expression(@target_table) do |expression|
+                @expression_builder.build(expression, @shard_range)
+                @target_table.select(expression)
               end
-              @temporary_tables << @target_table
+              @expression_builder.filter = @filter
+              @cover_type = :all
             end
-            apply_targets = []
-            apply_targets << [@target_table]
-            @context.dynamic_columns.apply_initial(apply_targets)
+            @temporary_tables << @target_table
+            @initial_table = @target_table
           end
 
-          execute_filter(range_index, expression_builder)
+          @window = detect_window
         end
 
-        private
         def decide_use_range_index(use, reason, line, method)
           message = "[logical_range_filter]"
           if use
@@ -519,7 +643,7 @@ module Groonga
           use
         end
 
-        def use_range_index?(range_index, expression_builder)
+        def use_range_index?
           use_range_index_parameter_message =
             "force by use_range_index parameter"
           case****@conte*****_range_index
@@ -595,7 +719,7 @@ module Groonga
           when :all
             if @filter
               create_expression(table) do |expression|
-                expression_builder.build_all(expression)
+                @expression_builder.build_all(expression)
                 unless range_index_available_expression?(expression,
                                                          __LINE__, __method__)
                   return false
@@ -607,7 +731,7 @@ module Groonga
             end
           when :partial_min
             create_expression(table) do |expression|
-              expression_builder.build_partial_min(expression)
+              @expression_builder.build_partial_min(expression)
               unless range_index_available_expression?(expression,
                                                        __LINE__, __method__)
                 return false
@@ -616,7 +740,7 @@ module Groonga
             end
           when :partial_max
             create_expression(table) do |expression|
-              expression_builder.build_partial_max(expression)
+              @expression_builder.build_partial_max(expression)
               unless range_index_available_expression?(expression,
                                                        __LINE__, __method__)
                 return false
@@ -625,7 +749,7 @@ module Groonga
             end
           when :partial_min_and_max
             create_expression(table) do |expression|
-              expression_builder.build_partial_min_and_max(expression)
+              @expression_builder.build_partial_min_and_max(expression)
               unless range_index_available_expression?(expression,
                                                        __LINE__, __method__)
                 return false
@@ -698,65 +822,102 @@ module Groonga
           nil
         end
 
-        def execute_filter(range_index, expression_builder)
+        def ensure_filtered
+          return if @filtered
+
+          @filtered = true
+
+          ensure_prepared
+          return unless have_record?
+
+          if****@conte*****_columns.have_initial?
+            apply_targets = []
+            if @previous_executor
+              @previous_executor.add_initial_stage_context(apply_targets)
+            end
+            apply_targets << [@target_table]
+            if @next_executor
+              @next_executor.add_initial_stage_context(apply_targets)
+            end
+            @context.dynamic_columns.apply_initial(apply_targets)
+          end
+
+          execute_filter(@range_index)
+
+          return unles****@conte*****_look_ahead?
+
+          apply_targets = []
+          @filtered_result_sets = @filtered_result_sets.collect do |result_set|
+            if result_set ==****@shard*****
+              result_set = result_set.select_all
+              @temporary_tables << result_set
+            end
+            apply_targets << [result_set]
+            result_set
+          end
+          @context.dynamic_columns.apply_filtered(apply_targets,
+                                                  window_function: false)
+        end
+
+        def execute_filter(range_index)
           case @cover_type
           when :all
-            filter_shard_all(range_index, expression_builder)
+            filter_shard_all(range_index)
           when :partial_min
             if range_index
-              filter_by_range(range_index, expression_builder,
+              filter_by_range(range_index,
                               @target_range.min, @target_range.min_border,
                               nil, nil)
             else
               filter_table do |expression|
-                expression_builder.build_partial_min(expression)
+                @expression_builder.build_partial_min(expression)
               end
             end
           when :partial_max
             if range_index
-              filter_by_range(range_index, expression_builder,
+              filter_by_range(range_index,
                               nil, nil,
                               @target_range.max, @target_range.max_border)
             else
               filter_table do |expression|
-                expression_builder.build_partial_max(expression)
+                @expression_builder.build_partial_max(expression)
               end
             end
           when :partial_min_and_max
             if range_index
-              filter_by_range(range_index, expression_builder,
+              filter_by_range(range_index,
                               @target_range.min, @target_range.min_border,
                               @target_range.max, @target_range.max_border)
             else
               filter_table do |expression|
-                expression_builder.build_partial_min_and_max(expression)
+                @expression_builder.build_partial_min_and_max(expression)
               end
             end
           end
         end
 
-        def filter_shard_all(range_index, expression_builder)
+        def filter_shard_all(range_index)
           table = @target_table
           if****@filte*****?
             if @post_filter.nil? and table.size <=****@conte*****_offset
               @context.current_offset -= table.size
               return
             end
-            if range_index
-              filter_by_range(range_index, expression_builder,
+            if @range_index
+              filter_by_range(range_index,
                               nil, nil,
                               nil, nil)
             else
-              add_result_set(table)
+              add_filtered_result_set(table)
             end
           else
-            if range_index
-              filter_by_range(range_index, expression_builder,
+            if @range_index
+              filter_by_range(range_index,
                               nil, nil,
                               nil, nil)
             else
               filter_table do |expression|
-                expression_builder.build_all(expression)
+                @expression_builder.build_all(expression)
               end
             end
           end
@@ -771,8 +932,7 @@ module Groonga
           end
         end
 
-        def filter_by_range(range_index, expression_builder,
-                            min, min_border, max, max_border)
+        def filter_by_range(range_index, min, min_border, max, max_border)
           lexicon = range_index.domain
           data_table = range_index.range
           flags = build_range_search_flags(min_border, max_border)
@@ -819,7 +979,7 @@ module Groonga
                 decide_use_range_index(false,
                                        fallback_message,
                                        __LINE__, __method__)
-                execute_filter(nil, expression_builder)
+                execute_filter(nil)
                 return
               end
             end
@@ -886,7 +1046,7 @@ module Groonga
             yield(expression)
             result_set = table.select(expression)
             @temporary_tables << result_set
-            add_result_set(result_set)
+            add_filtered_result_set(result_set)
           end
         end
 
@@ -897,34 +1057,12 @@ module Groonga
           end
         end
 
-        def add_result_set(result_set)
-          if result_set.empty?
-            return
-          end
-
-          window = detect_window
-          if window
-            window.each(result_set) do |windowed_result_set|
-              @temporary_tables << windowed_result_set
-              sort_result_set(windowed_result_set)
-              break if****@conte*****_limit.zero?
-            end
-          else
-            sort_result_set(result_set)
-          end
+        def add_filtered_result_set(result_set)
+          return if result_set.empty?
+          @filtered_result_sets << result_set
         end
 
         def sort_result_set(result_set)
-          if****@conte*****_columns.have_filtered?
-            if result_set ==****@shard*****
-              result_set = result_set.select_all
-              @temporary_tables << result_set
-            end
-            apply_targets = []
-            apply_targets << [result_set]
-            @context.dynamic_columns.apply_filtered(apply_targets)
-          end
-
           unless @post_filter.nil?
             result_set = apply_post_filter(result_set)
             @temporary_tables << result_set
@@ -973,30 +1111,15 @@ module Groonga
         end
 
         def detect_window
-          window_group_keys = []
-          @context.dynamic_columns.each_filtered do |dynamic_column|
-            window_group_keys.concat(dynamic_column.window_group_keys)
-          end
-          return nil if window_group_keys.empty?
-
           # TODO: return nil if result_set is small enough
-
           windows = []
-          @context.dynamic_columns.each do |dynamic_column|
-            next unless window_group_keys.include?(dynamic_column.label)
-            case dynamic_column.value.strip
-            when /\Atime_classify_(.+?)\s*\(\s*([a-zA-Z\d_]+)/
-              type = $1
-              column = $2
-              next if column !=****@conte*****_key_name
-
-              case type
-              when "minute", "second"
-                windows << Window.new(@context, @shard, @shard_range, :hour, 1)
-              when "day", "hour"
-                unless @shard_range.is_a?(LogicalEnumerator::DayShardRange)
-                  windows << Window.new(@context, @shard, @shard_range, :day, 1)
-                end
+          @context.time_classify_types.each do |type|
+            case type
+            when "minute", "second"
+              windows << Window.new(@context, @shard, @shard_range, :hour, 1)
+            when "day", "hour"
+              unless @shard_range.is_a?(LogicalEnumerator::DayShardRange)
+                windows << Window.new(@context, @shard, @shard_range, :day, 1)
               end
             end
           end

  Deleted: test/command/suite/sharding/logical_range_filter/columns/stage/filtered/window_function/shards.reject (+0 -111) 100644
===================================================================
--- test/command/suite/sharding/logical_range_filter/columns/stage/filtered/window_function/shards.reject    2019-04-26 15:43:03 +0900 (80af6d986)
+++ /dev/null
@@ -1,111 +0,0 @@
-plugin_register sharding
-[[0,0.0,0.0],true]
-plugin_register functions/time
-[[0,0.0,0.0],true]
-table_create Logs_20170315 TABLE_NO_KEY
-[[0,0.0,0.0],true]
-column_create Logs_20170315 timestamp COLUMN_SCALAR Time
-[[0,0.0,0.0],true]
-column_create Logs_20170315 price COLUMN_SCALAR UInt32
-[[0,0.0,0.0],true]
-table_create Logs_20170316 TABLE_NO_KEY
-[[0,0.0,0.0],true]
-column_create Logs_20170316 timestamp COLUMN_SCALAR Time
-[[0,0.0,0.0],true]
-column_create Logs_20170316 price COLUMN_SCALAR UInt32
-[[0,0.0,0.0],true]
-table_create Logs_20170317 TABLE_NO_KEY
-[[0,0.0,0.0],true]
-column_create Logs_20170317 timestamp COLUMN_SCALAR Time
-[[0,0.0,0.0],true]
-column_create Logs_20170317 price COLUMN_SCALAR UInt32
-[[0,0.0,0.0],true]
-load --table Logs_20170315
-[
-{"timestamp": "2017/03/15 00:00:00", "price": 1000},
-{"timestamp": "2017/03/15 11:00:00", "price":  900},
-{"timestamp": "2017/03/15 12:00:00", "price":  300},
-{"timestamp": "2017/03/15 13:00:00", "price":  200}
-]
-[[0,0.0,0.0],4]
-load --table Logs_20170316
-[
-{"timestamp": "2017/03/16 04:00:00", "price":  530},
-{"timestamp": "2017/03/16 05:00:00", "price":  520},
-{"timestamp": "2017/03/16 09:00:00", "price":  110},
-{"timestamp": "2017/03/16 13:00:00", "price":  410},
-{"timestamp": "2017/03/16 14:00:00", "price":  710}
-]
-[[0,0.0,0.0],5]
-load --table Logs_20170317
-[
-{"timestamp": "2017/03/17 09:00:00", "price":  800},
-{"timestamp": "2017/03/17 21:00:00", "price":  400},
-{"timestamp": "2017/03/17 22:00:00", "price":  500},
-{"timestamp": "2017/03/17 23:00:00", "price":  300}
-]
-[[0,0.0,0.0],4]
-logical_range_filter Logs   --shard_key timestamp   --max '2017/03/17 10:00:00.000'   --max_border exclude   --filter 'price >= 300'   --columns[day].stage filtered   --columns[day].type Time   --columns[day].flags COLUMN_SCALAR   --columns[day].value 'time_classify_day(timestamp-36000000000)'   --columns[price_per_day].stage filtered   --columns[price_per_day].type UInt32   --columns[price_per_day].flags COLUMN_SCALAR   --columns[price_per_day].value 'window_sum(price)'   --columns[price_per_day].window.group_keys 'day'   --output_columns _id,day,price_per_day
-[
-  [
-    0,
-    0.0,
-    0.0
-  ],
-  [
-    [
-      [
-        "_id",
-        "UInt32"
-      ],
-      [
-        "day",
-        "Time"
-      ],
-      [
-        "price_per_day",
-        "UInt32"
-      ]
-    ],
-    [
-      1,
-      1489417200.0,
-      1000
-    ],
-    [
-      2,
-      1489503600.0,
-      1200
-    ],
-    [
-      3,
-      1489503600.0,
-      1200
-    ],
-    [
-      1,
-      1489503600.0,
-      1050
-    ],
-    [
-      2,
-      1489503600.0,
-      1050
-    ],
-    [
-      4,
-      1489590000.0,
-      1120
-    ],
-    [
-      5,
-      1489590000.0,
-      1120
-    ],
-    [
-      1,
-      1489590000.0,
-      800
-    ]
-  ]
-]

  Modified: test/command/suite/sharding/logical_range_filter/columns/stage/filtered/window_function/shards.test (+0 -2)
===================================================================
--- test/command/suite/sharding/logical_range_filter/columns/stage/filtered/window_function/shards.test    2019-04-26 15:43:03 +0900 (7ccf4fef5)
+++ test/command/suite/sharding/logical_range_filter/columns/stage/filtered/window_function/shards.test    2019-04-26 15:43:52 +0900 (00fd87edc)
@@ -1,5 +1,3 @@
-#@omit TODO: Implemente me
-
 #@on-error omit
 plugin_register sharding
 plugin_register functions/time

  Modified: test/command/suite/sharding/logical_range_filter/columns/stage/initial/range.expected (+6 -6)
===================================================================
--- test/command/suite/sharding/logical_range_filter/columns/stage/initial/range.expected    2019-04-26 15:43:03 +0900 (e4b09cd39)
+++ test/command/suite/sharding/logical_range_filter/columns/stage/initial/range.expected    2019-04-26 15:43:52 +0900 (760e2e691)
@@ -80,32 +80,32 @@ logical_range_filter Logs   --shard_key timestamp   --min "2017/03/15 01:00:00"
     [
       2,
       900,
-      1200
+      2360
     ],
     [
       3,
       300,
-      1200
+      2360
     ],
     [
       1,
       530,
-      1160
+      3160
     ],
     [
       2,
       520,
-      1160
+      3160
     ],
     [
       3,
       110,
-      1160
+      3160
     ],
     [
       1,
       800,
-      800
+      1960
     ]
   ]
 ]

  Deleted: test/command/suite/sharding/logical_range_filter/columns/stage/initial/window_function/shards.reject (+0 -121) 100644
===================================================================
--- test/command/suite/sharding/logical_range_filter/columns/stage/initial/window_function/shards.reject    2019-04-26 15:43:03 +0900 (a71b87a55)
+++ /dev/null
@@ -1,121 +0,0 @@
-plugin_register sharding
-[[0,0.0,0.0],true]
-plugin_register functions/time
-[[0,0.0,0.0],true]
-table_create Logs_20170315 TABLE_NO_KEY
-[[0,0.0,0.0],true]
-column_create Logs_20170315 timestamp COLUMN_SCALAR Time
-[[0,0.0,0.0],true]
-column_create Logs_20170315 price COLUMN_SCALAR UInt32
-[[0,0.0,0.0],true]
-table_create Logs_20170316 TABLE_NO_KEY
-[[0,0.0,0.0],true]
-column_create Logs_20170316 timestamp COLUMN_SCALAR Time
-[[0,0.0,0.0],true]
-column_create Logs_20170316 price COLUMN_SCALAR UInt32
-[[0,0.0,0.0],true]
-table_create Logs_20170317 TABLE_NO_KEY
-[[0,0.0,0.0],true]
-column_create Logs_20170317 timestamp COLUMN_SCALAR Time
-[[0,0.0,0.0],true]
-column_create Logs_20170317 price COLUMN_SCALAR UInt32
-[[0,0.0,0.0],true]
-load --table Logs_20170315
-[
-{"timestamp": "2017/03/15 00:00:00", "price": 1000},
-{"timestamp": "2017/03/15 11:00:00", "price":  900},
-{"timestamp": "2017/03/15 12:00:00", "price":  300},
-{"timestamp": "2017/03/15 13:00:00", "price":  200}
-]
-[[0,0.0,0.0],4]
-load --table Logs_20170316
-[
-{"timestamp": "2017/03/16 04:00:00", "price":  530},
-{"timestamp": "2017/03/16 05:00:00", "price":  520},
-{"timestamp": "2017/03/16 09:00:00", "price":  110},
-{"timestamp": "2017/03/16 13:00:00", "price":  410},
-{"timestamp": "2017/03/16 14:00:00", "price":  710}
-]
-[[0,0.0,0.0],5]
-load --table Logs_20170317
-[
-{"timestamp": "2017/03/17 09:00:00", "price":  800},
-{"timestamp": "2017/03/17 21:00:00", "price":  400},
-{"timestamp": "2017/03/17 22:00:00", "price":  500},
-{"timestamp": "2017/03/17 23:00:00", "price":  300}
-]
-[[0,0.0,0.0],4]
-logical_range_filter Logs   --shard_key timestamp   --max '2017/03/17 10:00:00.000'   --max_border exclude   --columns[day].stage initial   --columns[day].type Time   --columns[day].flags COLUMN_SCALAR   --columns[day].value 'time_classify_day(timestamp-36000000000)'   --columns[price_per_day].stage initial   --columns[price_per_day].type UInt32   --columns[price_per_day].flags COLUMN_SCALAR   --columns[price_per_day].value 'window_sum(price)'   --columns[price_per_day].window.group_keys 'day'   --output_columns _id,day,price_per_day
-[
-  [
-    0,
-    0.0,
-    0.0
-  ],
-  [
-    [
-      [
-        "_id",
-        "UInt32"
-      ],
-      [
-        "day",
-        "Time"
-      ],
-      [
-        "price_per_day",
-        "UInt32"
-      ]
-    ],
-    [
-      1,
-      1489417200.0,
-      1000
-    ],
-    [
-      2,
-      1489503600.0,
-      1400
-    ],
-    [
-      3,
-      1489503600.0,
-      1400
-    ],
-    [
-      4,
-      1489503600.0,
-      1400
-    ],
-    [
-      1,
-      1489503600.0,
-      1160
-    ],
-    [
-      2,
-      1489503600.0,
-      1160
-    ],
-    [
-      3,
-      1489503600.0,
-      1160
-    ],
-    [
-      4,
-      1489590000.0,
-      1120
-    ],
-    [
-      5,
-      1489590000.0,
-      1120
-    ],
-    [
-      1,
-      1489590000.0,
-      800
-    ]
-  ]
-]

  Modified: test/command/suite/sharding/logical_range_filter/columns/stage/initial/window_function/shards.test (+0 -2)
===================================================================
--- test/command/suite/sharding/logical_range_filter/columns/stage/initial/window_function/shards.test    2019-04-26 15:43:03 +0900 (e4aef3666)
+++ test/command/suite/sharding/logical_range_filter/columns/stage/initial/window_function/shards.test    2019-04-26 15:43:52 +0900 (6b04900c5)
@@ -1,5 +1,3 @@
-#@omit TODO: Implemente me
-
 #@on-error omit
 plugin_register sharding
 plugin_register functions/time
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.osdn.me/mailman/archives/groonga-commit/attachments/20190426/cb4d01a3/attachment-0001.html>


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