Kouhei Sutou
null+****@clear*****
Fri Nov 11 17:31:28 JST 2016
Kouhei Sutou 2016-11-11 17:31:28 +0900 (Fri, 11 Nov 2016) New Revision: 25fbc269b1bf69ea113f1578bc4d9becaa6d17b6 https://github.com/groonga/groonga/commit/25fbc269b1bf69ea113f1578bc4d9becaa6d17b6 Message: select: support selectors that use index in slices Here are selectors supported by this change: * geo_in_circle() * geo_in_rectangle() * in_values() Added files: test/command/suite/select/slices/filtered/selector/geo_in_circle.expected test/command/suite/select/slices/filtered/selector/geo_in_circle.test test/command/suite/select/slices/filtered/selector/geo_in_rectangle.expected test/command/suite/select/slices/filtered/selector/geo_in_rectangle.test test/command/suite/select/slices/filtered/selector/in_values.expected test/command/suite/select/slices/filtered/selector/in_values.test Modified files: lib/expr.c lib/proc.c Modified: lib/expr.c (+98 -25) =================================================================== --- lib/expr.c 2016-11-11 16:17:45 +0900 (0be94a9) +++ lib/expr.c 2016-11-11 17:31:28 +0900 (13a6067) @@ -6429,6 +6429,98 @@ grn_table_select_index_range_accessor(grn_ctx *ctx, } static inline grn_bool +grn_table_select_index_call_selector(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + scan_info *si, + grn_obj *selector, + grn_obj *res) +{ + grn_bool processed = GRN_FALSE; + grn_proc *proc = (grn_proc *)selector; + grn_rc rc; + + if (grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + char tag[GRN_TABLE_MAX_KEY_SIZE]; + name_size = grn_obj_name(ctx, + (grn_obj *)selector, + name, + GRN_TABLE_MAX_KEY_SIZE); + grn_snprintf(tag, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE, + "[selector][%.*s]", + name_size, name); + grn_table_select_index_report(ctx, tag, index); + } + + if (index && index->header.type == GRN_ACCESSOR) { + grn_operator selector_op; + grn_obj *accessor = index; + unsigned int accessor_deep = 0; + grn_obj *base_table = NULL; + grn_obj *base_index = NULL; + grn_obj *base_res = NULL; + grn_accessor *a; + + selector_op = grn_proc_get_selector_operator(ctx, selector); + for (a = (grn_accessor *)accessor; a; a = a->next) { + if (a->next) { + accessor_deep++; + } else { + grn_index_datum index_data; + unsigned int n_index_datum; + + base_table = grn_ctx_at(ctx, a->obj->header.domain); + n_index_datum = grn_column_find_index_data(ctx, + a->obj, + selector_op, + &index_data, + 1); + if (n_index_datum > 0) { + base_index = index_data.index; + } + base_res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + base_table, NULL); + } + } + rc = proc->callbacks.function.selector(ctx, + base_table, + base_index, + si->nargs, + si->args, + base_res, + GRN_OP_OR); + if (rc == GRN_SUCCESS) { + grn_accessor_resolve(ctx, + accessor, + accessor_deep, + base_res, + res, + si->logical_op); + } + grn_obj_close(ctx, base_res); + } else { + rc = proc->callbacks.function.selector(ctx, + table, + index, + si->nargs, + si->args, + res, + si->logical_op); + } + + if (rc) { + /* TODO: report error */ + } else { + processed = GRN_TRUE; + } + + return processed; +} + +static inline grn_bool grn_table_select_index_range(grn_ctx *ctx, grn_obj *table, grn_obj *index, scan_info *si, grn_obj *res) { @@ -6656,31 +6748,12 @@ grn_table_select_index(grn_ctx *ctx, grn_obj *table, scan_info *si, break; case GRN_OP_CALL : if (grn_obj_is_selector_proc(ctx, si->args[0])) { - grn_rc rc; - grn_proc *proc = (grn_proc *)(si->args[0]); - if (grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) { - char proc_name[GRN_TABLE_MAX_KEY_SIZE]; - int proc_name_size; - char tag[GRN_TABLE_MAX_KEY_SIZE]; - proc_name_size = grn_obj_name(ctx, (grn_obj *)proc, - proc_name, GRN_TABLE_MAX_KEY_SIZE); - proc_name[proc_name_size] = '\0'; - grn_snprintf(tag, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE, - "[selector][%s]", proc_name); - grn_table_select_index_report(ctx, tag, index); - } - rc = proc->callbacks.function.selector(ctx, - table, - index, - si->nargs, - si->args, - res, - si->logical_op); - if (rc) { - /* TODO: report error */ - } else { - processed = GRN_TRUE; - } + processed = grn_table_select_index_call_selector(ctx, + table, + index, + si, + si->args[0], + res); } break; case GRN_OP_LESS : Modified: lib/proc.c (+7 -71) =================================================================== --- lib/proc.c 2016-11-11 16:17:45 +0900 (74e22c1) +++ lib/proc.c 2016-11-11 17:31:28 +0900 (496ab9e) @@ -2461,13 +2461,13 @@ selector_between_sequential_search(grn_ctx *ctx, } static grn_rc -selector_between_no_accessor(grn_ctx *ctx, - grn_obj *table, - grn_obj *index, - int nargs, - grn_obj **args, - grn_obj *res, - grn_operator op) +selector_between(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + int nargs, + grn_obj **args, + grn_obj *res, + grn_operator op) { grn_rc rc = GRN_SUCCESS; int offset = 0; @@ -2538,70 +2538,6 @@ exit : return rc; } -static grn_rc -selector_between(grn_ctx *ctx, - grn_obj *table, - grn_obj *index, - int nargs, - grn_obj **args, - grn_obj *res, - grn_operator op) -{ - grn_rc rc = GRN_SUCCESS; - - if (index && index->header.type == GRN_ACCESSOR) { - grn_obj *accessor = index; - unsigned int accessor_deep = 0; - grn_obj *base_table = NULL; - grn_obj *base_index = NULL; - grn_obj *base_res = NULL; - grn_accessor *a; - - for (a = (grn_accessor *)accessor; a; a = a->next) { - if (a->next) { - accessor_deep++; - } else { - grn_index_datum index_data; - unsigned int n_index_datum; - - base_table = grn_ctx_at(ctx, a->obj->header.domain); - n_index_datum = grn_column_find_index_data(ctx, - a->obj, - GRN_OP_LESS, - &index_data, - 1); - if (n_index_datum > 0) { - base_index = index_data.index; - } - base_res = grn_table_create(ctx, NULL, 0, NULL, - GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, - base_table, NULL); - } - } - rc = selector_between_no_accessor(ctx, - base_table, - base_index, - nargs, - args, - base_res, - GRN_OP_OR); - if (rc == GRN_SUCCESS) { - grn_accessor_resolve(ctx, accessor, accessor_deep, base_res, res, op); - } - grn_obj_close(ctx, base_res); - } else { - rc = selector_between_no_accessor(ctx, - table, - index, - nargs, - args, - res, - op); - } - - return rc; -} - static grn_obj * func_in_values(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) { Added: test/command/suite/select/slices/filtered/selector/geo_in_circle.expected (+154 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/slices/filtered/selector/geo_in_circle.expected 2016-11-11 17:31:28 +0900 (470e7b0) @@ -0,0 +1,154 @@ +log_level --level info +[[0,0.0,0.0],true] +select LandMarks --limit 0 --filter '_id > 1' --slices[point].filter 'geo_in_circle(point, "11x11", "11x8")' --slices[point].sort_keys _id --slices[point].limit -1 +[ + [ + 0, + 0.0, + 0.0 + ], + [ + [ + [ + 624 + ], + [ + [ + "_id", + "UInt32" + ], + [ + "point", + "WGS84GeoPoint" + ] + ] + ], + { + "point": [ + [ + 27 + ], + [ + [ + "_id", + "UInt32" + ], + [ + "point", + "WGS84GeoPoint" + ] + ], + [ + 235, + "9x9" + ], + [ + 236, + "9x10" + ], + [ + 237, + "9x11" + ], + [ + 238, + "9x12" + ], + [ + 239, + "9x13" + ], + [ + 260, + "10x9" + ], + [ + 261, + "10x10" + ], + [ + 262, + "10x11" + ], + [ + 263, + "10x12" + ], + [ + 264, + "10x13" + ], + [ + 284, + "11x8" + ], + [ + 285, + "11x9" + ], + [ + 286, + "11x10" + ], + [ + 287, + "11x11" + ], + [ + 288, + "11x12" + ], + [ + 289, + "11x13" + ], + [ + 290, + "11x14" + ], + [ + 310, + "12x9" + ], + [ + 311, + "12x10" + ], + [ + 312, + "12x11" + ], + [ + 313, + "12x12" + ], + [ + 314, + "12x13" + ], + [ + 335, + "13x9" + ], + [ + 336, + "13x10" + ], + [ + 337, + "13x11" + ], + [ + 338, + "13x12" + ], + [ + 339, + "13x13" + ] + ] + } + ] +] +#|i| [table][select][index][selector][geo_in_circle] <> +#|i| [accessor][resolve][table] (temporary) -> <LandMarks> Added: test/command/suite/select/slices/filtered/selector/geo_in_circle.test (+10 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/slices/filtered/selector/geo_in_circle.test 2016-11-11 17:31:28 +0900 (d057dac) @@ -0,0 +1,10 @@ +#@include fixture/geo/in_circle/north_east.grn + +log_level --level info +#@add-important-log-levels info +select LandMarks \ + --limit 0 \ + --filter '_id > 1' \ + --slices[point].filter 'geo_in_circle(point, "11x11", "11x8")' \ + --slices[point].sort_keys _id \ + --slices[point].limit -1 Added: test/command/suite/select/slices/filtered/selector/geo_in_rectangle.expected (+190 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/slices/filtered/selector/geo_in_rectangle.expected 2016-11-11 17:31:28 +0900 (cd571b7) @@ -0,0 +1,190 @@ +log_level --level info +[[0,0.0,0.0],true] +select LandMarks --limit 0 --filter '_id > 1' --slices[point].filter 'geo_in_rectangle(point, "13x8", "8x13")' --slices[point].sort_keys _id --slices[point].limit -1 +[ + [ + 0, + 0.0, + 0.0 + ], + [ + [ + [ + 624 + ], + [ + [ + "_id", + "UInt32" + ], + [ + "point", + "WGS84GeoPoint" + ] + ] + ], + { + "point": [ + [ + 36 + ], + [ + [ + "_id", + "UInt32" + ], + [ + "point", + "WGS84GeoPoint" + ] + ], + [ + 209, + "8x8" + ], + [ + 210, + "8x9" + ], + [ + 211, + "8x10" + ], + [ + 212, + "8x11" + ], + [ + 213, + "8x12" + ], + [ + 214, + "8x13" + ], + [ + 234, + "9x8" + ], + [ + 235, + "9x9" + ], + [ + 236, + "9x10" + ], + [ + 237, + "9x11" + ], + [ + 238, + "9x12" + ], + [ + 239, + "9x13" + ], + [ + 259, + "10x8" + ], + [ + 260, + "10x9" + ], + [ + 261, + "10x10" + ], + [ + 262, + "10x11" + ], + [ + 263, + "10x12" + ], + [ + 264, + "10x13" + ], + [ + 284, + "11x8" + ], + [ + 285, + "11x9" + ], + [ + 286, + "11x10" + ], + [ + 287, + "11x11" + ], + [ + 288, + "11x12" + ], + [ + 289, + "11x13" + ], + [ + 309, + "12x8" + ], + [ + 310, + "12x9" + ], + [ + 311, + "12x10" + ], + [ + 312, + "12x11" + ], + [ + 313, + "12x12" + ], + [ + 314, + "12x13" + ], + [ + 334, + "13x8" + ], + [ + 335, + "13x9" + ], + [ + 336, + "13x10" + ], + [ + 337, + "13x11" + ], + [ + 338, + "13x12" + ], + [ + 339, + "13x13" + ] + ] + } + ] +] +#|i| [table][select][index][selector][geo_in_rectangle] <> +#|i| [accessor][resolve][table] (temporary) -> <LandMarks> Added: test/command/suite/select/slices/filtered/selector/geo_in_rectangle.test (+10 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/slices/filtered/selector/geo_in_rectangle.test 2016-11-11 17:31:28 +0900 (8f3b7f4) @@ -0,0 +1,10 @@ +#@include fixture/geo/in_circle/north_east.grn + +log_level --level info +#@add-important-log-levels info +select LandMarks \ + --limit 0 \ + --filter '_id > 1' \ + --slices[point].filter 'geo_in_rectangle(point, "13x8", "8x13")' \ + --slices[point].sort_keys _id \ + --slices[point].limit -1 Added: test/command/suite/select/slices/filtered/selector/in_values.expected (+108 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/slices/filtered/selector/in_values.expected 2016-11-11 17:31:28 +0900 (352894d) @@ -0,0 +1,110 @@ +table_create Memos TABLE_HASH_KEY ShortText +[[0,0.0,0.0],true] +column_create Memos date COLUMN_SCALAR Time +[[0,0.0,0.0],true] +table_create Times TABLE_PAT_KEY Time +[[0,0.0,0.0],true] +column_create Times memos_date COLUMN_INDEX Memos date +[[0,0.0,0.0],true] +load --table Memos +[ +{"_key": "Groonga is fast!", "date": "2016-05-19 12:00:00"}, +{"_key": "Mroonga is fast!", "date": "2016-05-19 12:00:01"}, +{"_key": "Groonga sticker!", "date": "2016-05-19 12:00:02"}, +{"_key": "Rroonga is fast!", "date": "2016-05-19 12:00:03"} +] +[[0,0.0,0.0],4] +log_level --level info +[[0,0.0,0.0],true] +select Memos --filter '_id > 1' --slices[groonga].filter 'in_values(date, "2016-05-19 12:00:00", "2016-05-19 12:00:01", "2016-05-19 12:00:03")' +[ + [ + 0, + 0.0, + 0.0 + ], + [ + [ + [ + 3 + ], + [ + [ + "_id", + "UInt32" + ], + [ + "_key", + "ShortText" + ], + [ + "date", + "Time" + ] + ], + [ + 2, + "Mroonga is fast!", + 1463626801.0 + ], + [ + 3, + "Groonga sticker!", + 1463626802.0 + ], + [ + 4, + "Rroonga is fast!", + 1463626803.0 + ] + ], + { + "groonga": [ + [ + 2 + ], + [ + [ + "_id", + "UInt32" + ], + [ + "_key", + "ShortText" + ], + [ + "date", + "Time" + ] + ], + [ + 2, + "Mroonga is fast!", + 1463626801.0 + ], + [ + 4, + "Rroonga is fast!", + 1463626803.0 + ] + ] + } + ] +] +#|i| [table][select][index][selector][in_values] <> +#|i| [object][search][index][key][exact] <Times.memos_date> +#|i| grn_ii_sel > () +#|i| n=1 () +#|i| exact: 1 +#|i| hits=1 +#|i| [object][search][index][key][exact] <Times.memos_date> (binary line) (binary line) +#|i| exact: 2 +#|i| hits=2 +#|i| [object][search][index][key][exact] <Times.memos_date> +#|i| grn_ii_sel > (タ2ュ+)3) +#|i| n=1 (タ2ュ+)3) +#|i| exact: 3 +#|i| hits=3 +#|i| [accessor][resolve][table] (temporary) -> <Memos> -> <ShortText> Added: test/command/suite/select/slices/filtered/selector/in_values.test (+22 -0) 100644 =================================================================== --- /dev/null +++ test/command/suite/select/slices/filtered/selector/in_values.test 2016-11-11 17:31:28 +0900 (d701fa1) @@ -0,0 +1,22 @@ +table_create Memos TABLE_HASH_KEY ShortText +column_create Memos date COLUMN_SCALAR Time + +table_create Times TABLE_PAT_KEY Time +column_create Times memos_date COLUMN_INDEX Memos date + +load --table Memos +[ +{"_key": "Groonga is fast!", "date": "2016-05-19 12:00:00"}, +{"_key": "Mroonga is fast!", "date": "2016-05-19 12:00:01"}, +{"_key": "Groonga sticker!", "date": "2016-05-19 12:00:02"}, +{"_key": "Rroonga is fast!", "date": "2016-05-19 12:00:03"} +] + +log_level --level info +#@add-important-log-levels info +select Memos \ + --filter '_id > 1' \ + --slices[groonga].filter 'in_values(date, \ + "2016-05-19 12:00:00", \ + "2016-05-19 12:00:01", \ + "2016-05-19 12:00:03")' -------------- next part -------------- HTML����������������������������... ダウンロード