Kouhei Sutou
null+****@clear*****
Mon Jun 5 16:49:53 JST 2017
Kouhei Sutou 2017-06-05 16:49:53 +0900 (Mon, 05 Jun 2017) New Revision: 3ead800b4ebaa9b6c35d6bad528ba27117737d24 https://github.com/groonga/groonga/commit/3ead800b4ebaa9b6c35d6bad528ba27117737d24 Message: in_records: add selector implementation But it's disabled for now. Because it's doesn't support function call argument yet. Modified files: lib/proc/proc_in_records.c Modified: lib/proc/proc_in_records.c (+183 -6) =================================================================== --- lib/proc/proc_in_records.c 2017-06-05 16:47:46 +0900 (a1fc2b5) +++ lib/proc/proc_in_records.c 2017-06-05 16:49:53 +0900 (373a789) @@ -316,13 +316,190 @@ func_in_records_fin(grn_ctx *ctx, return NULL; } +static grn_rc +selector_in_records(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + int n_args, + grn_obj **args, + grn_obj *res, + grn_operator op) +{ + grn_obj *condition_table; + grn_operator *condition_modes = NULL; + grn_obj condition_columns; + int i, nth; + + /* TODO: Enable me when function call is supported. */ + return GRN_FUNCTION_NOT_IMPLEMENTED; + + if (n_args < 5) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): wrong number of arguments (%d for 4..)", + n_args - 1); + return ctx->rc; + } + + condition_table = args[1]; + if (!grn_obj_is_table(ctx, condition_table)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, condition_table); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): the first argument must be a table: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return ctx->rc; + } + + condition_modes = GRN_PLUGIN_MALLOCN(ctx, grn_operator, (n_args - 2) / 3); + GRN_PTR_INIT(&condition_columns, GRN_OBJ_VECTOR, GRN_ID_NIL); + for (i = 2, nth = 0; i < n_args; i += 3, nth++) { + int mode_name_i = i + 1; + int column_name_i = i + 2; + grn_obj *mode_name; + grn_operator mode; + grn_obj *column_name; + grn_obj *condition_column; + + mode_name = args[mode_name_i]; + mode = grn_proc_option_value_mode(ctx, + mode_name, + GRN_OP_EQUAL, + "in_records()"); + if (ctx->rc != GRN_SUCCESS) { + goto exit; + } + + condition_modes[nth] = mode; + + column_name = args[column_name_i]; + if (!grn_obj_is_text_family_bulk(ctx, column_name)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, condition_table); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): " + "the %dth argument must be column name as string: " + "<%.*s>", + column_name_i, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + goto exit; + } + + condition_column = grn_obj_column(ctx, condition_table, + GRN_TEXT_VALUE(column_name), + GRN_TEXT_LEN(column_name)); + if (!condition_column) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, condition_table); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): " + "the %dth argument must be existing column name: " + "<%.*s>: <%.*s>", + column_name_i, + (int)GRN_TEXT_LEN(column_name), + GRN_TEXT_VALUE(column_name), + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + goto exit; + } + GRN_PTR_PUT(ctx, &condition_columns, condition_column); + } + + { + grn_obj condition_column_value; + + GRN_VOID_INIT(&condition_column_value); + GRN_TABLE_EACH_BEGIN(ctx, condition_table, cursor, id) { + grn_obj *sub_res = NULL; + + for (i = 2; i < n_args; i += 3) { + int nth = (i - 2) / 3; + grn_operator sub_op; + grn_obj *condition_column; + grn_operator condition_mode; + grn_obj *column = args[i]; + grn_obj *expr; + grn_obj *variable; + + if (nth == 0) { + sub_op = GRN_OP_OR; + } else { + sub_op = GRN_OP_AND; + } + + condition_column = GRN_PTR_VALUE_AT(&condition_columns, nth); + condition_mode = condition_modes[nth]; + + GRN_BULK_REWIND(&condition_column_value); + grn_obj_get_value(ctx, + condition_column, + id, + &condition_column_value); + + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, expr, variable); + if (!expr) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): failed to create expression"); + GRN_OBJ_FIN(ctx, &condition_column_value); + if (sub_res) { + grn_obj_close(ctx, sub_res); + } + goto exit; + } + grn_expr_append_obj(ctx, expr, column, GRN_OP_GET_VALUE, 1); + grn_expr_append_obj(ctx, expr, &condition_column_value, GRN_OP_PUSH, 1); + grn_expr_append_op(ctx, expr, condition_mode, 2); + sub_res = grn_table_select(ctx, table, expr, sub_res, sub_op); + grn_obj_close(ctx, expr); + } + + if (sub_res) { + grn_table_setoperation(ctx, res, sub_res, res, op); + grn_obj_close(ctx, sub_res); + } + } GRN_TABLE_EACH_END(ctx, cursor); + GRN_OBJ_FIN(ctx, &condition_column_value); + } + +exit : + GRN_PLUGIN_FREE(ctx, condition_modes); + + for (i = 2; i < n_args; i += 3) { + int nth = (i - 2) / 3; + grn_obj *condition_column; + condition_column = GRN_PTR_VALUE_AT(&condition_columns, nth); + if (condition_column && condition_column->header.type == GRN_ACCESSOR) { + grn_obj_unlink(ctx, condition_column); + } + } + GRN_OBJ_FIN(ctx, &condition_columns); + + return ctx->rc; +} + void grn_proc_init_in_records(grn_ctx *ctx) { - grn_proc_create(ctx, "in_records", -1, GRN_PROC_FUNCTION, - func_in_records_init, - func_in_records_next, - func_in_records_fin, - 0, - NULL); + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "in_records", -1, GRN_PROC_FUNCTION, + func_in_records_init, + func_in_records_next, + func_in_records_fin, + 0, + NULL); + grn_proc_set_selector(ctx, selector_proc, selector_in_records); + grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_NOP); } -------------- next part -------------- HTML����������������������������...Download