diff options
Diffstat (limited to 'storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb')
-rw-r--r-- | storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb | 162 |
1 files changed, 125 insertions, 37 deletions
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb index b0ebfea3cee..4a6e58a951a 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb @@ -1,3 +1,5 @@ +require "scan_info_search_index" + module Groonga class ScanInfoData attr_accessor :start @@ -6,23 +8,21 @@ module Groonga attr_accessor :logical_op attr_accessor :query attr_accessor :args - attr_accessor :indexes + attr_accessor :search_indexes attr_accessor :flags attr_accessor :max_interval attr_accessor :similarity_threshold - attr_accessor :scorer def initialize(start) @start = start @end = 0 - @op = 0 + @op = Operator::NOP @logical_op = Operator::OR @query = nil @args = [] - @indexes = [] + @search_indexes = [] @flags = ScanInfo::Flags::PUSH @max_interval = nil @similarity_threshold = nil - @scorer = nil end def match_resolve_index @@ -102,6 +102,41 @@ module Groonga self.query = arg end end + if @op == Operator::REGEXP and not index_searchable_regexp?(@query) + @search_indexes.clear + end + end + + def index_searchable_regexp?(pattern) + return false if pattern.nil? + + previous_char = nil + pattern.value.each_char do |char| + if previous_char == "\\" + case char + when "Z" + return false + when "b", "B" + return false + when "d", "D", "h", "H", "p", "s", "S", "w", "W" + return false + when "X" + return false + when "k", "g", "1", "2", "3", "4", "5", "6", "7", "8", "9" + return false + when "\\" + previous_char = nil + next + end + else + case char + when ".", "[", "]", "|", "?", "+", "*", "{", "}", "^", "$", "(", ")" + return false + end + end + previous_char = char + end + true end def match_resolve_index_expression(expression) @@ -109,19 +144,82 @@ module Groonga n_codes = codes.size i = 0 while i < n_codes - i = match_resolve_index_expression_codes(codes, i, n_codes) + i = match_resolve_index_expression_codes(expression, codes, i, n_codes) + end + end + + def match_resolve_index_expression_codes(expression, codes, i, n_codes) + code = codes[i] + value = code.value + return i + 1 if value.nil? + + case value + when Accessor, Column + index_info, offset = + match_resolve_index_expression_find_index(expression, + codes, i, n_codes) + i += offset - 1 + if index_info + if value.is_a?(Accessor) + self.flags |= ScanInfo::Flags::ACCESSOR + end + weight, offset = codes[i].weight + i += offset + put_search_index(index_info.index, index_info.section_id, weight) + end + when Procedure + unless value.scorer? + message = "procedure must be scorer: #{scorer.name}>" + raise ErrorMessage, message + end + scorer = value + i += 1 + index_info, offset = + match_resolve_index_expression_find_index(expression, + codes, i, n_codes) + i += offset + if index_info + scorer_args_expr_offset = 0 + if codes[i].op != Operator::CALL + scorer_args_expr_offset = i + end + while i < n_codes and codes[i].op != Operator::CALL + i += 1 + end + weight, offset = codes[i].weight + i += offset + search_index = ScanInfoSearchIndex.new(index_info.index, + index_info.section_id, + weight, + scorer, + expression, + scorer_args_expr_offset) + @search_indexes << search_index + end + when Table + raise ErrorMessage, "invalid match target: <#{value.name}>" end + i + 1 end - def match_resolve_index_expression_codes(codes, i, n_codes) + def match_resolve_index_expression_find_index(expression, codes, i, n_codes) code = codes[i] value = code.value + index_info = nil + offset = 1 case value when Accessor - match_resolve_index_expression_accessor(code) + accessor = value + index_info = accessor.find_index(@op) + if index_info + if accessor.have_next? and index_info.index != accessor.object + index_info = IndexInfo.new(accessor, index_info.section_id) + end + end when FixedSizeColumn, VariableSizeColumn - match_resolve_index_expression_data_column(code) + index_info = value.find_index(@op) when IndexColumn + index = value section_id = 0 rest_n_codes = n_codes - i if rest_n_codes >= 2 and @@ -130,26 +228,12 @@ module Groonga codes[i + 1].value.domain == ID::INT32) and codes[i + 2].op == Operator::GET_MEMBER section_id = codes[i + 1].value.value + 1 - code = codes[i + 2] - i += 2 + offset += 2 end - put_index(value, section_id, code.weight) - when Procedure - unless value.scorer? - message = "procedure must be scorer: #{scorer.name}>" - raise ErrorMessage, message - end - @scorer = value - rest_n_codes = n_codes - i - if rest_n_codes == 0 - message = "match target is required as an argument: <#{scorer.name}>" - raise ErrorMessage, message - end - i = match_resolve_index_expression_codes(codes, i + 1, n_codes) - when Table - raise ErrorMessage, "invalid match target: <#{value.name}>" + index_info = IndexInfo.new(index, section_id) end - i + 1 + + [index_info, offset] end def match_resolve_index_expression_accessor(expr_code) @@ -157,10 +241,13 @@ module Groonga self.flags |= ScanInfo::Flags::ACCESSOR index_info = accessor.find_index(op) return if index_info.nil? + + section_id = index_info.section_id + weight = expr_code.weight if accessor.next - put_index(accessor, index_info.section_id, expr_code.weight) + put_search_index(accessor, section_id, weight) else - put_index(index_info.index, index_info.section_id, expr_code.weight) + put_search_index(index_info.index, section_id, weight) end end @@ -168,13 +255,13 @@ module Groonga column = expr_code.value index_info = column.find_index(op) return if index_info.nil? - put_index(index_info.index, index_info.section_id, expr_code.weight) + put_search_index(index_info.index, index_info.section_id, expr_code.weight) end def match_resolve_index_db_obj(db_obj) index_info = db_obj.find_index(op) return if index_info.nil? - put_index(index_info.index, index_info.section_id, 1) + put_search_index(index_info.index, index_info.section_id, 1) end def match_resolve_index_accessor(accessor) @@ -182,9 +269,9 @@ module Groonga index_info = accessor.find_index(op) return if index_info.nil? if accessor.next - put_index(accessor, index_info.section_id, 1) + put_search_index(accessor, index_info.section_id, 1) else - put_index(index_info.index, index_info.section_id, 1) + put_search_index(index_info.index, index_info.section_id, 1) end end @@ -202,18 +289,19 @@ module Groonga def call_relational_resolve_index_db_obj(db_obj) index_info = db_obj.find_index(op) return if index_info.nil? - put_index(index_info.index, index_info.section_id, 1) + put_search_index(index_info.index, index_info.section_id, 1) end def call_relational_resolve_index_accessor(accessor) self.flags |= ScanInfo::Flags::ACCESSOR index_info = accessor.find_index(op) return if index_info.nil? - put_index(index_info.index, index_info.section_id, 1) + put_search_index(index_info.index, index_info.section_id, 1) end - def put_index(index, section_id, weight) - @indexes << [index, section_id, weight] + def put_search_index(index, section_id, weight) + search_index = ScanInfoSearchIndex.new(index, section_id, weight) + @search_indexes << search_index end end end |