Kouhei Sutou 2019-04-25 16:38:20 +0900 (Thu, 25 Apr 2019) Revision: 4f0497672afe133d151653b258f1d8b1870ace82 https://github.com/groonga/groonga/commit/4f0497672afe133d151653b258f1d8b1870ace82 Message: Add support for in_values() estimation Modified files: lib/mrb/scripts/expression_tree/binary_operation.rb lib/mrb/scripts/expression_tree/function_call.rb test/mruby/suite/query_optimizer/test_estimate_size.rb Modified: lib/mrb/scripts/expression_tree/binary_operation.rb (+28 -0) =================================================================== --- lib/mrb/scripts/expression_tree/binary_operation.rb 2019-04-25 16:19:29 +0900 (3431e9821) +++ lib/mrb/scripts/expression_tree/binary_operation.rb 2019-04-25 16:38:20 +0900 (052d1086a) @@ -51,6 +51,8 @@ module Groonga ] def estimate_size(table) case @operator + when Operator::EQUAL + estimate_size_equal(table) when *RANGE_OPERATORS estimate_size_range(table) when *QUERY_OPERATIONS @@ -63,6 +65,32 @@ module Groonga end private + def estimate_size_equal(table) + return table.size unles****@left*****_a?(Variable) + return table.size unles****@right*****_a?(Constant) + + column =****@left***** + value =****@right***** + index_info = column.find_index(@operator) + return table.size if index_info.nil? + + index_column = index_info.index + return table.size unless index_column.respond_to?(:lexicon) + + lexicon = index_column.lexicon + term = value.value + if value.domain == lexicon.id + term_id = term.id + else + term_id = lexicon[term] + end + if term_id.nil? + 0 + else + index_column.estimate_size(term_id: term_id) + end + end + def estimate_size_range(table) return table.size unles****@left*****_a?(Variable) return table.size unles****@right*****_a?(Constant) Modified: lib/mrb/scripts/expression_tree/function_call.rb (+19 -1) =================================================================== --- lib/mrb/scripts/expression_tree/function_call.rb 2019-04-25 16:19:29 +0900 (23c04b6f6) +++ lib/mrb/scripts/expression_tree/function_call.rb 2019-04-25 16:38:20 +0900 (50ff3754e) @@ -21,8 +21,18 @@ module Groonga end def estimate_size(table) - return table.size unles****@proce***** == "between" + case****@proce***** + when "between" + estimate_size_between(table) + when "in_values" + estimate_size_in_values(table) + else + table.size + end + end + private + def estimate_size_between(table) column, min, min_border, max, max_border = @arguments if column.is_a?(Groonga::ExpressionTree::IndexColumn) @@ -65,6 +75,14 @@ module Groonga index_column.estimate_size(:lexicon_cursor => cursor) end end + + def estimate_size_in_values(table) + column, *values = @arguments + values.inject(0) do |sum, value| + node = BinaryOperation.new(Operator::EQUAL, column, value) + sum + node.estimate_size(table) + end + end end end end Modified: test/mruby/suite/query_optimizer/test_estimate_size.rb (+41 -0) =================================================================== --- test/mruby/suite/query_optimizer/test_estimate_size.rb 2019-04-25 16:19:29 +0900 (3515349b6) +++ test/mruby/suite/query_optimizer/test_estimate_size.rb 2019-04-25 16:38:20 +0900 (5804eb116) @@ -270,6 +270,47 @@ class TestEstimateSize < QueryOptimizerTestCase end end + class TestInValuesSearch < self + def setup + Groonga::Schema.define do |schema| + schema.create_table("Logs") do |table| + table.time("timestamp") + end + + schema.create_table("Times", + :type => :patricia_trie, + :key_type => :time) do |table| + table.index("Logs", "timestamp") + end + end + super + end + + def test_no_record + assert_equal(0, + estimate_size("in_values(timestamp, " + + "'2015-02-19 02:18:00', " + + "'2015-02-19 02:20:00')")) + end + + def test_have_record + @logs.add(:timestamp => "2015-02-19 02:17:00") + @logs.add(:timestamp => "2015-02-19 02:17:00") + @logs.add(:timestamp => "2015-02-19 02:18:00") + @logs.add(:timestamp => "2015-02-19 02:18:00") + @logs.add(:timestamp => "2015-02-19 02:19:00") + @logs.add(:timestamp => "2015-02-19 02:19:00") + @logs.add(:timestamp => "2015-02-19 02:20:00") + @logs.add(:timestamp => "2015-02-19 02:20:00") + @logs.add(:timestamp => "2015-02-19 02:21:00") + @logs.add(:timestamp => "2015-02-19 02:21:00") + assert_equal(8, + estimate_size("in_values(timestamp, " + + "'2015-02-19 02:18:00', " + + "'2015-02-19 02:20:00')")) + end + end + class TestAnd < self def setup Groonga::Schema.define do |schema| -------------- next part -------------- An HTML attachment was scrubbed... URL: <https://lists.osdn.me/mailman/archives/groonga-commit/attachments/20190425/6b279074/attachment-0001.html>