Kouhei Sutou
null+****@clear*****
Mon Jul 6 16:47:29 JST 2015
Kouhei Sutou 2015-07-06 16:47:29 +0900 (Mon, 06 Jul 2015) New Revision: 3caff6e4c72956297e08b976d9c6bce37c422474 https://github.com/groonga/groonga/commit/3caff6e4c72956297e08b976d9c6bce37c422474 Message: logical_select: start to support labeled drilldowns Complex labeled drilldowns may not be worked. Added files: test/command/suite/sharding/logical_select/drilldown/labeled/keys/one.expected test/command/suite/sharding/logical_select/drilldown/labeled/keys/one.test Modified files: plugins/sharding/logical_select.rb Modified: plugins/sharding/logical_select.rb (+226 -13) =================================================================== --- plugins/sharding/logical_select.rb 2015-07-06 16:47:13 +0900 (e0c1e5e) +++ plugins/sharding/logical_select.rb 2015-07-06 16:47:29 +0900 (b4982de) @@ -30,12 +30,23 @@ module Groonga executor.execute n_results = 1 - drilldowns = context.drilldown.result_sets - n_results += drilldowns.size + n_plain_drilldowns = context.plain_drilldown.n_result_sets + n_labeled_drilldowns = context.labeled_drilldowns.n_result_sets + if n_plain_drilldowns > 0 + n_results += n_plain_drilldowns + elsif + if n_labeled_drilldowns > 0 + n_results += 1 + end + end writer.array("RESULT", n_results) do write_records(writer, context) - write_drilldowns(writer, context, drilldowns) + if n_plain_drilldowns > 0 + write_plain_drilldowns(writer, context) + elsif n_labeled_drilldowns > 0 + write_labeled_drilldowns(writer, context) + end end ensure context.close @@ -87,12 +98,14 @@ module Groonga end end - def write_drilldowns(writer, context, drilldowns) - output_columns = context.drilldown.output_columns + def write_plain_drilldowns(writer, context) + plain_drilldown = context.plain_drilldown + drilldowns = plain_drilldown.result_sets + output_columns = plain_drilldown.output_columns options = { - :offset => context.drilldown.output_offset, - :limit => context.drilldown.limit, + :offset => plain_drilldown.output_offset, + :limit => plain_drilldown.limit, } drilldowns.each do |drilldown| @@ -109,6 +122,33 @@ module Groonga end end + def write_labeled_drilldowns(writer, context) + labeled_drilldowns = context.labeled_drilldowns + + writer.map("DRILLDOWNS", labeled_drilldowns.n_result_sets) do + labeled_drilldowns.each do |drilldown| + writer.write(drilldown.label) + + result_set = drilldown.result_set + n_elements = 2 # for N hits and columns + n_elements += result_set.size + output_columns = drilldown.output_columns + options = { + :offset => drilldown.output_offset, + :limit => drilldown.limit, + } + + writer.array("RESULTSET", n_elements) do + writer.array("NHITS", 1) do + writer.write(result_set.size) + end + writer.write_table_columns(result_set, output_columns) + writer.write_table_records(result_set, output_columns, options) + end + end + end + end + module KeysParsable private def parse_keys(raw_keys) @@ -128,7 +168,8 @@ module Groonga attr_reader :sort_keys attr_reader :output_columns attr_reader :result_sets - attr_reader :drilldown + attr_reader :plain_drilldown + attr_reader :labeled_drilldowns def initialize(input) @input = input @enumerator = LogicalEnumerator.new("logical_select", @input) @@ -140,7 +181,8 @@ module Groonga @result_sets = [] - @drilldown = PlainDrilldownExecuteContext.new(@input) + @plain_drilldown = PlainDrilldownExecuteContext.new(@input) + @labeled_drilldowns = LabeledDrilldowns.parse(@input) end def close @@ -148,7 +190,8 @@ module Groonga result_set.close if result_set.temporary? end - @drilldown.close + @plain_drilldown.close + @labeled_drilldowns.close end end @@ -190,6 +233,135 @@ module Groonga result_set.close end end + + def have_keys? + @keys.size > 0 + end + + def n_result_sets + @result_sets.size + end + end + + class LabeledDrilldowns + class << self + def parse(input) + drilldowns = {} + arguments = input.arguments + argument = Record.new(arguments, nil) + arguments.each do |argument_id| + argument.id = argument_id + key = argument.key + match_data = /\Adrilldown\[(.+?)\]\.(.+)\z/.match(key) + next if match_data.nil? + drilldown = (drilldowns[match_data[1]] ||= {}) + drilldown[match_data[2]] = input[key] + end + + contexts = [] + drilldowns.each do |label, parameters| + next if parameters["keys"].nil? + contexts << LabeledDrilldownExecuteContext.new(label, parameters) + end + return nil if contexts.nil? + + new(contexts) + end + end + + def initialize(contexts) + @contexts = contexts + end + + def close + @contexts.each do |context| + context.close + end + end + + def have_keys? + @contexts.size > 0 + end + + def n_result_sets + @contexts.size + end + + def each(&block) + @contexts.each(&block) + end + end + + class LabeledDrilldownExecuteContext + include KeysParsable + + attr_reader :label + attr_reader :keys + attr_reader :offset + attr_reader :limit + attr_reader :sort_keys + attr_reader :output_columns + attr_reader :output_offset + attr_reader :calc_target_name + attr_reader :calc_types + attr_accessor :result_set + attr_accessor :unsorted_result_set + def initialize(label, parameters) + @label = label + @keys = parse_keys(parameters["keys"]) + @offset = (parameters["offset"] || 0).to_i + @limit = (parameters["limit"] || 10).to_i + @sort_keys = parse_keys(parameters["sortby"]) + @output_columns = parameters["output_columns"] + @output_columns ||= "_key, _nsubrecs" + @calc_target_name = parameters["calc_target"] + @calc_types = parse_calc_types(parameters["calc_types"]) + + if @sort_keys.empty? + @output_offset = @offset + else + @output_offset = 0 + end + + @result_set = nil + @unsorted_result_set = nil + end + + def close + @result_set.close if @result_set + @unsorted_result_set.close if @unsored_result_set + end + + def calc_target(table) + return nil if @calc_target_name.nil? + table.column(@calc_target_name) + end + + private + def parse_calc_types(raw_types) + return TableGroupFlags::CALC_COUNT if raw_types.nil? + + types = 0 + raw_types.strip.split(/ *, */).each do |name| + case name + when "COUNT" + types |= TableGroupFlags::CALC_COUNT + when "MAX" + types |= TableGroupFlags::CALC_MAX + when "MIN" + types |= TableGroupFlags::CALC_MIN + when "SUM" + types |= TableGroupFlags::CALC_SUM + when "AVG" + types |= TableGroupFlags::CALC_AVG + when "NONE" + # Do nothing + else + raise InvalidArgument, "invalid drilldown calc type: <#{name}>" + end + end + types + end end class Executor @@ -199,7 +371,11 @@ module Groonga def execute execute_search - execute_drilldown + if****@conte*****_drilldown.have_keys? + execute_plain_drilldown + elsif****@conte*****_drilldowns.have_keys? + execute_labeled_drilldowns + end end private @@ -228,8 +404,8 @@ module Groonga end end - def execute_drilldown - drilldown =****@conte***** + def execute_plain_drilldown + drilldown =****@conte*****_drilldown group_result = TableGroupResult.new sort_options = { :offset => drilldown.offset, @@ -258,6 +434,43 @@ module Groonga group_result.close end end + + def execute_labeled_drilldowns + drilldowns =****@conte*****_drilldowns + + drilldowns.each do |drilldown| + group_result = TableGroupResult.new + keys = drilldown.keys + sort_options = { + :offset => drilldown.offset, + :limit => drilldown.limit, + } + begin + group_result.key_begin = 0 + group_result.key_end = keys.size - 1 + if keys.size > 1 + group_result.max_n_sub_records = 1 + end + group_result.limit = 1 + group_result.flags = drilldown.calc_types + @context.result_sets.each do |result_set| + group_result.calc_target = drilldown.calc_target(result_set) + result_set.group(keys, group_result) + end + result_set = group_result.table + if drilldown.sort_keys.empty? + drilldown.result_set = result_set + else + drilldown.result_set = result_set.sort(drilldown.sort_keys, + sort_options) + drilldown.unsorted_result_set = result_set + end + group_result.table = nil + ensure + group_result.close + end + end + end end class ShardExecutor Added: test/command/suite/sharding/logical_select/drilldown/labeled/keys/one.expected (+141 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/sharding/logical_select/drilldown/labeled/keys/one.expected 2015-07-06 16:47:29 +0900 (828d2a1) @@ -0,0 +1,141 @@ +register sharding +[[0,0.0,0.0],true] +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] +column_create Logs_20150203 action 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] +column_create Logs_20150204 action 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] +column_create Logs_20150205 action COLUMN_SCALAR ShortText +[[0,0.0,0.0],true] +load --table Logs_20150203 +[ +{ + "timestamp": "2015-02-03 12:49:00", + "memo": "2015-02-03 12:49:00", + "action": "Start" +}, +{ + "timestamp": "2015-02-03 23:59:59", + "memo": "2015-02-03 23:59:59", + "action": "Shutdown" +} +] +[[0,0.0,0.0],2] +load --table Logs_20150204 +[ +{ + "timestamp": "2015-02-04 00:00:00", + "memo": "2015-02-04 00:00:00", + "action": "Start" +}, +{ + "timestamp": "2015-02-04 13:49:00", + "memo": "2015-02-04 13:49:00", + "action": "Restart" +}, +{ + "timestamp": "2015-02-04 13:50:00", + "memo": "2015-02-04 13:50:00", + "action": "Restart" +} +] +[[0,0.0,0.0],3] +load --table Logs_20150205 +[ +{ + "timestamp": "2015-02-05 13:49:00", + "memo": "2015-02-05 13:49:00", + "action": "Restart" +}, +{ + "timestamp": "2015-02-05 13:50:00", + "memo": "2015-02-05 13:50:00", + "action": "Restart" +}, +{ + "timestamp": "2015-02-05 13:51:00", + "memo": "2015-02-05 13:51:00", + "action": "Restart" +}, +{ + "timestamp": "2015-02-05 13:52:00", + "memo": "2015-02-05 13:52:00", + "action": "Restart" +} +] +[[0,0.0,0.0],4] +logical_select Logs timestamp --limit 0 --drilldown[action].keys action +[ + [ + 0, + 0.0, + 0.0 + ], + [ + [ + [ + 9 + ], + [ + [ + "action", + "ShortText" + ], + [ + "memo", + "ShortText" + ], + [ + "timestamp", + "Time" + ] + ] + ], + { + "action": [ + [ + 3 + ], + [ + [ + "_key", + "ShortText" + ], + [ + "_nsubrecs", + "Int32" + ] + ], + [ + "Start", + 2 + ], + [ + "Shutdown", + 1 + ], + [ + "Restart", + 6 + ] + ] + } + ] +] Added: test/command/suite/sharding/logical_select/drilldown/labeled/keys/one.test (+79 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/sharding/logical_select/drilldown/labeled/keys/one.test 2015-07-06 16:47:29 +0900 (ea68764) @@ -0,0 +1,79 @@ +#@on-error omit +register sharding +#@on-error default + +table_create Logs_20150203 TABLE_NO_KEY +column_create Logs_20150203 timestamp COLUMN_SCALAR Time +column_create Logs_20150203 memo COLUMN_SCALAR ShortText +column_create Logs_20150203 action 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 +column_create Logs_20150204 action 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 +column_create Logs_20150205 action COLUMN_SCALAR ShortText + +load --table Logs_20150203 +[ +{ + "timestamp": "2015-02-03 12:49:00", + "memo": "2015-02-03 12:49:00", + "action": "Start" +}, +{ + "timestamp": "2015-02-03 23:59:59", + "memo": "2015-02-03 23:59:59", + "action": "Shutdown" +} +] + +load --table Logs_20150204 +[ +{ + "timestamp": "2015-02-04 00:00:00", + "memo": "2015-02-04 00:00:00", + "action": "Start" +}, +{ + "timestamp": "2015-02-04 13:49:00", + "memo": "2015-02-04 13:49:00", + "action": "Restart" +}, +{ + "timestamp": "2015-02-04 13:50:00", + "memo": "2015-02-04 13:50:00", + "action": "Restart" +} +] + +load --table Logs_20150205 +[ +{ + "timestamp": "2015-02-05 13:49:00", + "memo": "2015-02-05 13:49:00", + "action": "Restart" +}, +{ + "timestamp": "2015-02-05 13:50:00", + "memo": "2015-02-05 13:50:00", + "action": "Restart" +}, +{ + "timestamp": "2015-02-05 13:51:00", + "memo": "2015-02-05 13:51:00", + "action": "Restart" +}, +{ + "timestamp": "2015-02-05 13:52:00", + "memo": "2015-02-05 13:52:00", + "action": "Restart" +} +] + +logical_select Logs timestamp \ + --limit 0 \ + --drilldown[action].keys action -------------- next part -------------- HTML����������������������������...ダウンロード