Kouhei Sutou
null+****@clear*****
Thu Feb 16 10:42:37 JST 2017
Kouhei Sutou 2017-02-16 10:42:37 +0900 (Thu, 16 Feb 2017) New Revision: 72c1ba43f931c8b65de0fd0711b10e1fb38f6c46 https://github.com/groonga/groonga/commit/72c1ba43f931c8b65de0fd0711b10e1fb38f6c46 Message: Support index search for 'XXX || !(column @ "xxx")' Added files: test/command/suite/select/filter/unary_operation/match_or_not_match.expected test/command/suite/select/filter/unary_operation/match_or_not_match.test Modified files: lib/expr.c lib/mrb/scripts/scan_info_builder.rb test/mruby/suite/query_optimizer/index/test_match.rb Modified: lib/expr.c (+15 -0) =================================================================== --- lib/expr.c 2017-02-16 10:26:41 +0900 (b6114c3) +++ lib/expr.c 2017-02-16 10:42:37 +0900 (7b3399b) @@ -4619,6 +4619,21 @@ grn_scan_info_build_full_not(grn_ctx *ctx, case GRN_OP_AND_NOT : *next_code_op = GRN_OP_AND; break; + case GRN_OP_OR : + { + scan_info *all_records_si = NULL; + SI_ALLOC_RAW(all_records_si, 0); + if (!all_records_si) { + return GRN_FALSE; + } + all_records_si->op = GRN_OP_CALL; + all_records_si->args[all_records_si->nargs++] = + grn_ctx_get(ctx, "all_records", -1); + sis[*i] = sis[*i - 1]; + sis[*i - 1] = all_records_si; + put_logical_op(ctx, sis, i, GRN_OP_AND_NOT, code_end - code); + } + break; default : return GRN_FALSE; break; Modified: lib/mrb/scripts/scan_info_builder.rb (+5 -2) =================================================================== --- lib/mrb/scripts/scan_info_builder.rb 2017-02-16 10:26:41 +0900 (b29bf39) +++ lib/mrb/scripts/scan_info_builder.rb 2017-02-16 10:42:37 +0900 (98cedcc) @@ -152,7 +152,7 @@ module Groonga data.start_position = index.value context.status = :column1 when Operator::NOT - success = build_not(context, code) + success = build_not(context, code, i) return nil unless success end end @@ -329,7 +329,7 @@ module Groonga end end - def build_not(context, code) + def build_not(context, code, i) last_data = @data_list.last return false if last_data.nil? @@ -372,6 +372,9 @@ module Groonga context.code_op = Operator::AND_NOT when Operator::AND_NOT context.code_op = Operator::AND + when Operator::OR + @data_list[-1, 0] = create_all_match_data + put_logical_op(Operator::AND_NOT, i) else return false end Added: test/command/suite/select/filter/unary_operation/match_or_not_match.expected (+66 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/filter/unary_operation/match_or_not_match.expected 2017-02-16 10:42:37 +0900 (e83babf) @@ -0,0 +1,66 @@ +table_create Texts TABLE_PAT_KEY ShortText +[[0,0.0,0.0],true] +table_create Terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto +[[0,0.0,0.0],true] +column_create Terms texts_key COLUMN_INDEX|WITH_POSITION Texts _key +[[0,0.0,0.0],true] +load --table Texts +[ +{"_key": "Groonga and Rroonga"}, +{"_key": "Rroonga and Ruby"}, +{"_key": "Mroonga and Groonga"}, +{"_key": "MySQL and PostgreSQL"} +] +[[0,0.0,0.0],4] +log_level --level info +[[0,0.0,0.0],true] +select Texts --filter '(_key @ "Rroonga") || !(_key @ "Groonga")' +[ + [ + 0, + 0.0, + 0.0 + ], + [ + [ + [ + 3 + ], + [ + [ + "_id", + "UInt32" + ], + [ + "_key", + "ShortText" + ] + ], + [ + 1, + "Groonga and Rroonga" + ], + [ + 4, + "MySQL and PostgreSQL" + ], + [ + 2, + "Rroonga and Ruby" + ] + ] + ] +] +#|i| [table][select][index][selector][no-index][all_records] <Texts> +#|i| [object][search][index][key][exact] <Terms.texts_key> +#|i| grn_ii_sel > (Groonga) +#|i| n=1 (Groonga) +#|i| exact: 2 +#|i| hits=2 +#|i| [object][search][index][key][exact] <Terms.texts_key> +#|i| grn_ii_sel > (Rroonga) +#|i| n=1 (Rroonga) +#|i| exact: 3 +#|i| hits=3 +log_level --level notice +[[0,0.0,0.0],true] Added: test/command/suite/select/filter/unary_operation/match_or_not_match.test (+21 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/filter/unary_operation/match_or_not_match.test 2017-02-16 10:42:37 +0900 (2eb1aa2) @@ -0,0 +1,21 @@ +table_create Texts TABLE_PAT_KEY ShortText + +table_create Terms TABLE_PAT_KEY ShortText \ + --default_tokenizer TokenBigram \ + --normalizer NormalizerAuto +column_create Terms texts_key COLUMN_INDEX|WITH_POSITION \ + Texts _key + +load --table Texts +[ +{"_key": "Groonga and Rroonga"}, +{"_key": "Rroonga and Ruby"}, +{"_key": "Mroonga and Groonga"}, +{"_key": "MySQL and PostgreSQL"} +] + +log_level --level info +#@add-important-log-levels info +select Texts --filter '(_key @ "Rroonga") || !(_key @ "Groonga")' +#@remove-important-log-levels info +log_level --level notice Modified: test/mruby/suite/query_optimizer/index/test_match.rb (+22 -0) =================================================================== --- test/mruby/suite/query_optimizer/index/test_match.rb 2017-02-16 10:26:41 +0900 (102b58c) +++ test/mruby/suite/query_optimizer/index/test_match.rb 2017-02-16 10:42:37 +0900 (addc2f1) @@ -120,4 +120,26 @@ class TestIndexMatch < QueryOptimizerTestCase expr: <3..5> DUMP end + + def test_normal_or_not + assert_equal(<<-DUMP, dump_plan("(message @ 'Rroonga') || !(message @ 'Groonga')")) +[0] + op: <call> + logical_op: <or> + args[0]: <#<proc:function all_records arguments:[]>> + expr: <0..0> +[1] + op: <match> + logical_op: <and_not> + index: <[#<column:index Terms.Logs_message range:Logs sources:[Logs.message] flags:POSITION>]> + query: <"Groonga"> + expr: <3..5> +[2] + op: <match> + logical_op: <or> + index: <[#<column:index Terms.Logs_message range:Logs sources:[Logs.message] flags:POSITION>]> + query: <"Rroonga"> + expr: <0..2> + DUMP + end end -------------- next part -------------- HTML����������������������������...Download