Kouhei Sutou
null+****@clear*****
Thu May 12 17:39:33 JST 2016
Kouhei Sutou 2016-05-12 17:39:33 +0900 (Thu, 12 May 2016) New Revision: 8ffbc3758c59b626093282ddaa43ec094340f881 https://github.com/groonga/groonga/commit/8ffbc3758c59b626093282ddaa43ec094340f881 Message: select: reorder Modified files: lib/proc/proc_select.c Modified: lib/proc/proc_select.c (+556 -556) =================================================================== --- lib/proc/proc_select.c 2016-05-12 17:32:50 +0900 (30c91e6) +++ lib/proc/proc_select.c 2016-05-12 17:39:33 +0900 (4b900b3) @@ -130,266 +130,614 @@ grn_proc_syntax_expand_query(grn_ctx *ctx, query_expander, expanded_query); } -static grn_expr_flags -grn_parse_query_flags(grn_ctx *ctx, const char *query_flags, - unsigned int query_flags_len) +static const char * +grn_column_stage_name(grn_column_stage stage) { - grn_expr_flags flags = 0; - const char *query_flags_end = query_flags + query_flags_len; + switch (stage) { + case GRN_COLUMN_STAGE_INITIAL : + return "initial"; + case GRN_COLUMN_STAGE_FILTERED : + return "filtered"; + default : + return "unknown"; + } +} - while (query_flags < query_flags_end) { - if (*query_flags == '|' || *query_flags == ' ') { - query_flags += 1; - continue; - } +static grn_bool +grn_column_data_init(grn_ctx *ctx, + const char *label, + size_t label_len, + grn_column_stage stage, + grn_hash **columns) +{ + void *column_raw; + grn_column_data *column; -#define CHECK_EXPR_FLAG(name)\ - if (((query_flags_end - query_flags) >= (sizeof(#name) - 1)) &&\ - (!memcmp(query_flags, #name, sizeof(#name) - 1))) {\ - flags |= GRN_EXPR_ ## name;\ - query_flags += sizeof(#name) - 1;\ - continue;\ + if (!*columns) { + *columns = grn_hash_create(ctx, + NULL, + GRN_TABLE_MAX_KEY_SIZE, + sizeof(grn_column_data), + GRN_OBJ_TABLE_HASH_KEY | + GRN_OBJ_KEY_VAR_SIZE | + GRN_HASH_TINY); } + if (!*columns) { + return GRN_FALSE; + } + grn_hash_add(ctx, + *columns, + label, + label_len, + &column_raw, + NULL); + column = column_raw; + column->label.value = label; + column->label.length = label_len; + column->stage = stage; + column->type = grn_ctx_at(ctx, GRN_DB_TEXT); + column->flags = GRN_OBJ_COLUMN_SCALAR; + column->value.value = NULL; + column->value.length = 0; + column->sortby.value = NULL; + column->sortby.length = 0; + return GRN_TRUE; +} - CHECK_EXPR_FLAG(ALLOW_PRAGMA); - CHECK_EXPR_FLAG(ALLOW_COLUMN); - CHECK_EXPR_FLAG(ALLOW_UPDATE); - CHECK_EXPR_FLAG(ALLOW_LEADING_NOT); - -#define GRN_EXPR_NONE 0 - CHECK_EXPR_FLAG(NONE); -#undef GNR_EXPR_NONE +static grn_bool +grn_column_data_fill(grn_ctx *ctx, + grn_column_data *column, + grn_obj *type_raw, + grn_obj *flags, + grn_obj *value, + grn_obj *sortby) +{ + if (type_raw && GRN_TEXT_LEN(type_raw) > 0) { + grn_obj *type; - GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, - "invalid query flag: <%.*s>", - (int)(query_flags_end - query_flags), - query_flags); - return 0; -#undef CHECK_EXPR_FLAG + type = grn_ctx_get(ctx, GRN_TEXT_VALUE(type_raw), GRN_TEXT_LEN(type_raw)); + if (!type) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][column][%s][%.*s] unknown type: <%.*s>", + grn_column_stage_name(column->stage), + (int)(column->label.length), + column->label.value, + (int)(GRN_TEXT_LEN(type_raw)), + GRN_TEXT_VALUE(type_raw)); + return GRN_FALSE; + } + if (!(grn_obj_is_type(ctx, type) || grn_obj_is_table(ctx, type))) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, type); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][column][%s][%.*s] invalid type: %.*s", + grn_column_stage_name(column->stage), + (int)(column->label.length), + column->label.value, + (int)(GRN_TEXT_LEN(&inspected)), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + grn_obj_unlink(ctx, type); + return GRN_FALSE; + } + column->type = type; } - return flags; -} + if (flags && GRN_TEXT_LEN(flags) > 0) { + char error_message_tag[GRN_TABLE_MAX_KEY_SIZE]; -static int -grn_select_apply_adjuster_ensure_factor(grn_ctx *ctx, grn_obj *factor_object) -{ - if (!factor_object) { - return 1; - } else if (factor_object->header.domain == GRN_DB_INT32) { - return GRN_INT32_VALUE(factor_object); - } else { - grn_rc rc; - grn_obj int32_object; - int factor; - GRN_INT32_INIT(&int32_object, 0); - rc = grn_obj_cast(ctx, factor_object, &int32_object, GRN_FALSE); - if (rc == GRN_SUCCESS) { - factor = GRN_INT32_VALUE(&int32_object); - } else { - /* TODO: Log or return error? */ - factor = 1; + grn_snprintf(error_message_tag, + GRN_TABLE_MAX_KEY_SIZE, + GRN_TABLE_MAX_KEY_SIZE, + "[select][column][%s][%.*s]", + grn_column_stage_name(column->stage), + (int)(column->label.length), + column->label.value); + column->flags = + grn_proc_column_parse_flags(ctx, + error_message_tag, + GRN_TEXT_VALUE(flags), + GRN_TEXT_VALUE(flags) + GRN_TEXT_LEN(flags)); + if (ctx->rc != GRN_SUCCESS) { + return GRN_FALSE; } - GRN_OBJ_FIN(ctx, &int32_object); - return factor; } + + GRN_SELECT_FILL_STRING(column->value, value); + GRN_SELECT_FILL_STRING(column->sortby, sortby); + + return GRN_TRUE; } -static void -grn_select_apply_adjuster_adjust(grn_ctx *ctx, grn_obj *table, grn_obj *res, - grn_obj *column, grn_obj *value, - grn_obj *factor) +static grn_bool +grn_column_data_collect(grn_ctx *ctx, + grn_user_data *user_data, + grn_hash *columns, + const char *prefix_label, + size_t prefix_label_len) { - grn_obj *index; - unsigned int n_indexes; - int factor_value; - - n_indexes = grn_column_index(ctx, column, GRN_OP_MATCH, &index, 1, NULL); - if (n_indexes == 0) { - char column_name[GRN_TABLE_MAX_KEY_SIZE]; - int column_name_size; - column_name_size = grn_obj_name(ctx, column, - column_name, GRN_TABLE_MAX_KEY_SIZE); - ERR(GRN_INVALID_ARGUMENT, - "adjuster requires index column for the target column: <%.*s>", - column_name_size, column_name); - return; + grn_hash_cursor *cursor = NULL; + cursor = grn_hash_cursor_open(ctx, columns, + NULL, 0, NULL, 0, 0, -1, 0); + if (!cursor) { + return GRN_FALSE; } - factor_value = grn_select_apply_adjuster_ensure_factor(ctx, factor); + while (grn_hash_cursor_next(ctx, cursor)) { + grn_column_data *column; + char key_name[GRN_TABLE_MAX_KEY_SIZE]; + grn_obj *type; + grn_obj *flags; + grn_obj *value; + grn_obj *sortby; - { - grn_search_optarg options; - memset(&options, 0, sizeof(grn_search_optarg)); + grn_hash_cursor_get_value(ctx, cursor, (void **)&column); - options.mode = GRN_OP_EXACT; - options.similarity_threshold = 0; - options.max_interval = 0; - options.weight_vector = NULL; - options.vector_size = factor_value; - options.proc = NULL; - options.max_size = 0; - options.scorer = NULL; +#define GET_VAR(name) \ + grn_snprintf(key_name, \ + GRN_TABLE_MAX_KEY_SIZE, \ + GRN_TABLE_MAX_KEY_SIZE, \ + "%.*scolumn[%.*s]." # name, \ + (int)prefix_label_len, \ + prefix_label, \ + (int)(column->label.length), \ + column->label.value); \ + name = grn_plugin_proc_get_var(ctx, user_data, key_name, -1); - grn_obj_search(ctx, index, value, res, GRN_OP_ADJUST, &options); + GET_VAR(type); + GET_VAR(flags); + GET_VAR(value); + GET_VAR(sortby); + +#undef GET_VAR + + grn_column_data_fill(ctx, column, + type, flags, value, sortby); } + grn_hash_cursor_close(ctx, cursor); + return GRN_TRUE; } static void -grn_select_apply_adjuster(grn_ctx *ctx, grn_obj *table, grn_obj *res, - grn_obj *adjuster) +grn_columns_init(grn_ctx *ctx, grn_columns *columns) { - grn_expr *expr = (grn_expr *)adjuster; - grn_expr_code *code, *code_end; - - code = expr->codes; - code_end = expr->codes + expr->codes_curr; - while (code < code_end) { - grn_obj *column, *value, *factor; + columns->initial = NULL; + columns->filtered = NULL; +} - if (code->op == GRN_OP_PLUS) { - code++; - continue; - } +static void +grn_columns_fin(grn_ctx *ctx, grn_columns *columns) +{ + if (columns->initial) { + grn_hash_close(ctx, columns->initial); + } - column = code->value; - code++; - value = code->value; - code++; - code++; /* op == GRN_OP_MATCH */ - if ((code_end - code) >= 2 && code[1].op == GRN_OP_STAR) { - factor = code->value; - code++; - code++; /* op == GRN_OP_STAR */ - } else { - factor = NULL; - } - grn_select_apply_adjuster_adjust(ctx, table, res, column, value, factor); + if (columns->filtered) { + grn_hash_close(ctx, columns->filtered); } } -static void -grn_select_expression_set_condition(grn_ctx *ctx, - grn_obj *expression, - grn_obj *condition) +static grn_bool +grn_columns_collect(grn_ctx *ctx, + grn_user_data *user_data, + grn_columns *columns, + const char *base_prefix, + size_t base_prefix_len) { - grn_obj *condition_ptr; + grn_obj *vars; + grn_table_cursor *cursor; + const char *prefix = "column["; + size_t prefix_len; + const char *suffix = "].stage"; + size_t suffix_len; - if (!expression) { - return; + vars = grn_plugin_proc_get_vars(ctx, user_data); + cursor = grn_table_cursor_open(ctx, vars, NULL, 0, NULL, 0, 0, -1, 0); + if (!cursor) { + return GRN_FALSE; } - condition_ptr = - grn_expr_get_or_add_var(ctx, expression, - GRN_SELECT_INTERNAL_VAR_CONDITION, - strlen(GRN_SELECT_INTERNAL_VAR_CONDITION)); - GRN_PTR_INIT(condition_ptr, 0, GRN_DB_OBJECT); - GRN_PTR_SET(ctx, condition_ptr, condition); -} + prefix_len = strlen(prefix); + suffix_len = strlen(suffix); + while (grn_table_cursor_next(ctx, cursor)) { + void *key; + char *variable_name; + int variable_name_len; + char *column_name; + size_t column_name_len; + void *value_raw; + grn_obj *value; + grn_column_stage stage; + grn_hash **target_columns; -void -grn_proc_select_output_columns(grn_ctx *ctx, grn_obj *res, - int n_hits, int offset, int limit, - const char *columns, int columns_len, - grn_obj *condition) -{ - grn_rc rc; - grn_obj_format format; + variable_name_len = grn_table_cursor_get_key(ctx, cursor, &key); + variable_name = key; + if (variable_name_len < base_prefix_len + prefix_len + suffix_len + 1) { + continue; + } - GRN_OBJ_FORMAT_INIT(&format, n_hits, offset, limit, offset); - format.flags = - GRN_OBJ_FORMAT_WITH_COLUMN_NAMES| - GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET; - rc = grn_output_format_set_columns(ctx, &format, res, columns, columns_len); - if (rc != GRN_SUCCESS) { - GRN_OBJ_FORMAT_FIN(ctx, &format); - return; + if (base_prefix_len > 0) { + if (memcmp(base_prefix, variable_name, base_prefix_len) != 0) { + continue; + } + } + + if (memcmp(prefix, variable_name + base_prefix_len, prefix_len) != 0) { + continue; + } + + if (memcmp(suffix, + variable_name + (variable_name_len - suffix_len), + suffix_len) != 0) { + continue; + } + + grn_table_cursor_get_value(ctx, cursor, &value_raw); + value = value_raw; + if (GRN_BULK_EQUAL_STRING(value, "initial")) { + stage = GRN_COLUMN_STAGE_INITIAL; + target_columns = &(columns->initial); + } else if (GRN_BULK_EQUAL_STRING(value, "filtered")) { + stage = GRN_COLUMN_STAGE_FILTERED; + target_columns = &(columns->filtered); + } else { + continue; + } + + column_name = variable_name + base_prefix_len + prefix_len; + column_name_len = + variable_name_len - base_prefix_len - prefix_len - suffix_len; + if (!grn_column_data_init(ctx, + column_name, + column_name_len, + stage, + target_columns)) { + grn_table_cursor_close(ctx, cursor); + return GRN_FALSE; + } } + grn_table_cursor_close(ctx, cursor); - grn_select_expression_set_condition(ctx, format.expression, condition); - GRN_OUTPUT_OBJ(res, &format); - GRN_OBJ_FORMAT_FIN(ctx, &format); + return GRN_TRUE; } -static const char * -grn_column_stage_name(grn_column_stage stage) +static grn_bool +grn_columns_fill(grn_ctx *ctx, + grn_user_data *user_data, + grn_columns *columns, + const char *prefix, + size_t prefix_length) { - switch (stage) { - case GRN_COLUMN_STAGE_INITIAL : - return "initial"; - case GRN_COLUMN_STAGE_FILTERED : - return "filtered"; - default : - return "unknown"; + if (!grn_columns_collect(ctx, user_data, columns, prefix, prefix_length)) { + return GRN_FALSE; + } + + if (columns->initial) { + if (!grn_column_data_collect(ctx, + user_data, + columns->initial, + prefix, + prefix_length)) { + return GRN_FALSE; + } + } + + if (columns->filtered) { + if (!grn_column_data_collect(ctx, + user_data, + columns->filtered, + prefix, + prefix_length)) { + return GRN_FALSE; + } } + + return GRN_TRUE; } static void -grn_select_apply_columns(grn_ctx *ctx, - grn_obj *table, - grn_hash *columns, - grn_obj *condition) +grn_drilldown_data_fill(grn_ctx *ctx, + grn_drilldown_data *drilldown, + grn_obj *keys, + grn_obj *sortby, + grn_obj *output_columns, + grn_obj *offset, + grn_obj *limit, + grn_obj *calc_types, + grn_obj *calc_target, + grn_obj *filter, + grn_obj *table) { - grn_hash_cursor *columns_cursor; + GRN_SELECT_FILL_STRING(drilldown->keys, keys); - columns_cursor = grn_hash_cursor_open(ctx, columns, - NULL, 0, NULL, 0, 0, -1, 0); - if (!columns_cursor) { - return; + GRN_SELECT_FILL_STRING(drilldown->sortby, sortby); + + GRN_SELECT_FILL_STRING(drilldown->output_columns, output_columns); + if (drilldown->output_columns.length == 0) { + drilldown->output_columns.value = DEFAULT_DRILLDOWN_OUTPUT_COLUMNS; + drilldown->output_columns.length = strlen(DEFAULT_DRILLDOWN_OUTPUT_COLUMNS); } - while (grn_hash_cursor_next(ctx, columns_cursor) != GRN_ID_NIL) { - grn_column_data *column_data; - grn_obj *column; - grn_obj *expression; - grn_obj *record; - grn_table_cursor *table_cursor; - grn_id id; - grn_obj *target_table = table; + if (offset && GRN_TEXT_LEN(offset)) { + drilldown->offset = + grn_atoi(GRN_TEXT_VALUE(offset), GRN_BULK_CURR(offset), NULL); + } else { + drilldown->offset = 0; + } - grn_hash_cursor_get_value(ctx, columns_cursor, (void **)&column_data); + if (limit && GRN_TEXT_LEN(limit)) { + drilldown->limit = + grn_atoi(GRN_TEXT_VALUE(limit), GRN_BULK_CURR(limit), NULL); + } else { + drilldown->limit = DEFAULT_DRILLDOWN_LIMIT; + } - column = grn_column_create(ctx, - table, - column_data->label.value, - column_data->label.length, - NULL, - column_data->flags, - column_data->type); - if (!column) { - GRN_PLUGIN_ERROR(ctx, - GRN_INVALID_ARGUMENT, - "[select][column][%s][%.*s] failed to create column: %s", - grn_column_stage_name(column_data->stage), - (int)(column_data->label.length), - column_data->label.value, - ctx->errbuf); - break; - } + if (calc_types && GRN_TEXT_LEN(calc_types)) { + drilldown->calc_types = + grn_parse_table_group_calc_types(ctx, + GRN_TEXT_VALUE(calc_types), + GRN_TEXT_LEN(calc_types)); + } else { + drilldown->calc_types = 0; + } - if (column_data->sortby.length > 0) { - grn_table_sort_key *sort_keys; - uint32_t n_sort_keys; - sort_keys = grn_table_sort_key_from_str(ctx, - column_data->sortby.value, - column_data->sortby.length, - table, &n_sort_keys); - if (!sort_keys) { - grn_obj_close(ctx, column); - GRN_PLUGIN_ERROR(ctx, - GRN_INVALID_ARGUMENT, - "[select][column][%s][%.*s] failed to parse sort key: %s", - grn_column_stage_name(column_data->stage), - (int)(column_data->label.length), - column_data->label.value, - ctx->errbuf); - break; - } + GRN_SELECT_FILL_STRING(drilldown->calc_target_name, calc_target); - target_table = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY, - NULL, table); - if (!target_table) { - grn_obj_close(ctx, column); + GRN_SELECT_FILL_STRING(drilldown->filter, filter); + + GRN_SELECT_FILL_STRING(drilldown->table_name, table); +} + +static grn_expr_flags +grn_parse_query_flags(grn_ctx *ctx, const char *query_flags, + unsigned int query_flags_len) +{ + grn_expr_flags flags = 0; + const char *query_flags_end = query_flags + query_flags_len; + + while (query_flags < query_flags_end) { + if (*query_flags == '|' || *query_flags == ' ') { + query_flags += 1; + continue; + } + +#define CHECK_EXPR_FLAG(name)\ + if (((query_flags_end - query_flags) >= (sizeof(#name) - 1)) &&\ + (!memcmp(query_flags, #name, sizeof(#name) - 1))) {\ + flags |= GRN_EXPR_ ## name;\ + query_flags += sizeof(#name) - 1;\ + continue;\ + } + + CHECK_EXPR_FLAG(ALLOW_PRAGMA); + CHECK_EXPR_FLAG(ALLOW_COLUMN); + CHECK_EXPR_FLAG(ALLOW_UPDATE); + CHECK_EXPR_FLAG(ALLOW_LEADING_NOT); + +#define GRN_EXPR_NONE 0 + CHECK_EXPR_FLAG(NONE); +#undef GNR_EXPR_NONE + + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "invalid query flag: <%.*s>", + (int)(query_flags_end - query_flags), + query_flags); + return 0; +#undef CHECK_EXPR_FLAG + } + + return flags; +} + +static int +grn_select_apply_adjuster_ensure_factor(grn_ctx *ctx, grn_obj *factor_object) +{ + if (!factor_object) { + return 1; + } else if (factor_object->header.domain == GRN_DB_INT32) { + return GRN_INT32_VALUE(factor_object); + } else { + grn_rc rc; + grn_obj int32_object; + int factor; + GRN_INT32_INIT(&int32_object, 0); + rc = grn_obj_cast(ctx, factor_object, &int32_object, GRN_FALSE); + if (rc == GRN_SUCCESS) { + factor = GRN_INT32_VALUE(&int32_object); + } else { + /* TODO: Log or return error? */ + factor = 1; + } + GRN_OBJ_FIN(ctx, &int32_object); + return factor; + } +} + +static void +grn_select_apply_adjuster_adjust(grn_ctx *ctx, grn_obj *table, grn_obj *res, + grn_obj *column, grn_obj *value, + grn_obj *factor) +{ + grn_obj *index; + unsigned int n_indexes; + int factor_value; + + n_indexes = grn_column_index(ctx, column, GRN_OP_MATCH, &index, 1, NULL); + if (n_indexes == 0) { + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + int column_name_size; + column_name_size = grn_obj_name(ctx, column, + column_name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "adjuster requires index column for the target column: <%.*s>", + column_name_size, column_name); + return; + } + + factor_value = grn_select_apply_adjuster_ensure_factor(ctx, factor); + + { + grn_search_optarg options; + memset(&options, 0, sizeof(grn_search_optarg)); + + options.mode = GRN_OP_EXACT; + options.similarity_threshold = 0; + options.max_interval = 0; + options.weight_vector = NULL; + options.vector_size = factor_value; + options.proc = NULL; + options.max_size = 0; + options.scorer = NULL; + + grn_obj_search(ctx, index, value, res, GRN_OP_ADJUST, &options); + } +} + +static void +grn_select_apply_adjuster(grn_ctx *ctx, grn_obj *table, grn_obj *res, + grn_obj *adjuster) +{ + grn_expr *expr = (grn_expr *)adjuster; + grn_expr_code *code, *code_end; + + code = expr->codes; + code_end = expr->codes + expr->codes_curr; + while (code < code_end) { + grn_obj *column, *value, *factor; + + if (code->op == GRN_OP_PLUS) { + code++; + continue; + } + + column = code->value; + code++; + value = code->value; + code++; + code++; /* op == GRN_OP_MATCH */ + if ((code_end - code) >= 2 && code[1].op == GRN_OP_STAR) { + factor = code->value; + code++; + code++; /* op == GRN_OP_STAR */ + } else { + factor = NULL; + } + grn_select_apply_adjuster_adjust(ctx, table, res, column, value, factor); + } +} + +static void +grn_select_expression_set_condition(grn_ctx *ctx, + grn_obj *expression, + grn_obj *condition) +{ + grn_obj *condition_ptr; + + if (!expression) { + return; + } + + condition_ptr = + grn_expr_get_or_add_var(ctx, expression, + GRN_SELECT_INTERNAL_VAR_CONDITION, + strlen(GRN_SELECT_INTERNAL_VAR_CONDITION)); + GRN_PTR_INIT(condition_ptr, 0, GRN_DB_OBJECT); + GRN_PTR_SET(ctx, condition_ptr, condition); +} + +void +grn_proc_select_output_columns(grn_ctx *ctx, grn_obj *res, + int n_hits, int offset, int limit, + const char *columns, int columns_len, + grn_obj *condition) +{ + grn_rc rc; + grn_obj_format format; + + GRN_OBJ_FORMAT_INIT(&format, n_hits, offset, limit, offset); + format.flags = + GRN_OBJ_FORMAT_WITH_COLUMN_NAMES| + GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET; + rc = grn_output_format_set_columns(ctx, &format, res, columns, columns_len); + if (rc != GRN_SUCCESS) { + GRN_OBJ_FORMAT_FIN(ctx, &format); + return; + } + + grn_select_expression_set_condition(ctx, format.expression, condition); + GRN_OUTPUT_OBJ(res, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); +} + +static void +grn_select_apply_columns(grn_ctx *ctx, + grn_obj *table, + grn_hash *columns, + grn_obj *condition) +{ + grn_hash_cursor *columns_cursor; + + columns_cursor = grn_hash_cursor_open(ctx, columns, + NULL, 0, NULL, 0, 0, -1, 0); + if (!columns_cursor) { + return; + } + + while (grn_hash_cursor_next(ctx, columns_cursor) != GRN_ID_NIL) { + grn_column_data *column_data; + grn_obj *column; + grn_obj *expression; + grn_obj *record; + grn_table_cursor *table_cursor; + grn_id id; + grn_obj *target_table = table; + + grn_hash_cursor_get_value(ctx, columns_cursor, (void **)&column_data); + + column = grn_column_create(ctx, + table, + column_data->label.value, + column_data->label.length, + NULL, + column_data->flags, + column_data->type); + if (!column) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][column][%s][%.*s] failed to create column: %s", + grn_column_stage_name(column_data->stage), + (int)(column_data->label.length), + column_data->label.value, + ctx->errbuf); + break; + } + + if (column_data->sortby.length > 0) { + grn_table_sort_key *sort_keys; + uint32_t n_sort_keys; + sort_keys = grn_table_sort_key_from_str(ctx, + column_data->sortby.value, + column_data->sortby.length, + table, &n_sort_keys); + if (!sort_keys) { + grn_obj_close(ctx, column); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][column][%s][%.*s] failed to parse sort key: %s", + grn_column_stage_name(column_data->stage), + (int)(column_data->label.length), + column_data->label.value, + ctx->errbuf); + break; + } + + target_table = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY, + NULL, table); + if (!target_table) { + grn_obj_close(ctx, column); grn_table_sort_key_close(ctx, sort_keys, n_sort_keys); GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, @@ -537,59 +885,6 @@ grn_parse_table_group_calc_types(grn_ctx *ctx, } static void -grn_drilldown_data_fill(grn_ctx *ctx, - grn_drilldown_data *drilldown, - grn_obj *keys, - grn_obj *sortby, - grn_obj *output_columns, - grn_obj *offset, - grn_obj *limit, - grn_obj *calc_types, - grn_obj *calc_target, - grn_obj *filter, - grn_obj *table) -{ - GRN_SELECT_FILL_STRING(drilldown->keys, keys); - - GRN_SELECT_FILL_STRING(drilldown->sortby, sortby); - - GRN_SELECT_FILL_STRING(drilldown->output_columns, output_columns); - if (drilldown->output_columns.length == 0) { - drilldown->output_columns.value = DEFAULT_DRILLDOWN_OUTPUT_COLUMNS; - drilldown->output_columns.length = strlen(DEFAULT_DRILLDOWN_OUTPUT_COLUMNS); - } - - if (offset && GRN_TEXT_LEN(offset)) { - drilldown->offset = - grn_atoi(GRN_TEXT_VALUE(offset), GRN_BULK_CURR(offset), NULL); - } else { - drilldown->offset = 0; - } - - if (limit && GRN_TEXT_LEN(limit)) { - drilldown->limit = - grn_atoi(GRN_TEXT_VALUE(limit), GRN_BULK_CURR(limit), NULL); - } else { - drilldown->limit = DEFAULT_DRILLDOWN_LIMIT; - } - - if (calc_types && GRN_TEXT_LEN(calc_types)) { - drilldown->calc_types = - grn_parse_table_group_calc_types(ctx, - GRN_TEXT_VALUE(calc_types), - GRN_TEXT_LEN(calc_types)); - } else { - drilldown->calc_types = 0; - } - - GRN_SELECT_FILL_STRING(drilldown->calc_target_name, calc_target); - - GRN_SELECT_FILL_STRING(drilldown->filter, filter); - - GRN_SELECT_FILL_STRING(drilldown->table_name, table); -} - -static void grn_select_drilldown(grn_ctx *ctx, grn_obj *table, grn_table_sort_key *keys, @@ -1534,301 +1829,6 @@ exit : return ctx->rc; } -static grn_bool -grn_column_data_init(grn_ctx *ctx, - const char *label, - size_t label_len, - grn_column_stage stage, - grn_hash **columns) -{ - void *column_raw; - grn_column_data *column; - - if (!*columns) { - *columns = grn_hash_create(ctx, - NULL, - GRN_TABLE_MAX_KEY_SIZE, - sizeof(grn_column_data), - GRN_OBJ_TABLE_HASH_KEY | - GRN_OBJ_KEY_VAR_SIZE | - GRN_HASH_TINY); - } - if (!*columns) { - return GRN_FALSE; - } - grn_hash_add(ctx, - *columns, - label, - label_len, - &column_raw, - NULL); - column = column_raw; - column->label.value = label; - column->label.length = label_len; - column->stage = stage; - column->type = grn_ctx_at(ctx, GRN_DB_TEXT); - column->flags = GRN_OBJ_COLUMN_SCALAR; - column->value.value = NULL; - column->value.length = 0; - column->sortby.value = NULL; - column->sortby.length = 0; - return GRN_TRUE; -} - -static grn_bool -grn_column_data_fill(grn_ctx *ctx, - grn_column_data *column, - grn_obj *type_raw, - grn_obj *flags, - grn_obj *value, - grn_obj *sortby) -{ - if (type_raw && GRN_TEXT_LEN(type_raw) > 0) { - grn_obj *type; - - type = grn_ctx_get(ctx, GRN_TEXT_VALUE(type_raw), GRN_TEXT_LEN(type_raw)); - if (!type) { - GRN_PLUGIN_ERROR(ctx, - GRN_INVALID_ARGUMENT, - "[select][column][%s][%.*s] unknown type: <%.*s>", - grn_column_stage_name(column->stage), - (int)(column->label.length), - column->label.value, - (int)(GRN_TEXT_LEN(type_raw)), - GRN_TEXT_VALUE(type_raw)); - return GRN_FALSE; - } - if (!(grn_obj_is_type(ctx, type) || grn_obj_is_table(ctx, type))) { - grn_obj inspected; - GRN_TEXT_INIT(&inspected, 0); - grn_inspect(ctx, &inspected, type); - GRN_PLUGIN_ERROR(ctx, - GRN_INVALID_ARGUMENT, - "[select][column][%s][%.*s] invalid type: %.*s", - grn_column_stage_name(column->stage), - (int)(column->label.length), - column->label.value, - (int)(GRN_TEXT_LEN(&inspected)), - GRN_TEXT_VALUE(&inspected)); - GRN_OBJ_FIN(ctx, &inspected); - grn_obj_unlink(ctx, type); - return GRN_FALSE; - } - column->type = type; - } - - if (flags && GRN_TEXT_LEN(flags) > 0) { - char error_message_tag[GRN_TABLE_MAX_KEY_SIZE]; - - grn_snprintf(error_message_tag, - GRN_TABLE_MAX_KEY_SIZE, - GRN_TABLE_MAX_KEY_SIZE, - "[select][column][%s][%.*s]", - grn_column_stage_name(column->stage), - (int)(column->label.length), - column->label.value); - column->flags = - grn_proc_column_parse_flags(ctx, - error_message_tag, - GRN_TEXT_VALUE(flags), - GRN_TEXT_VALUE(flags) + GRN_TEXT_LEN(flags)); - if (ctx->rc != GRN_SUCCESS) { - return GRN_FALSE; - } - } - - GRN_SELECT_FILL_STRING(column->value, value); - GRN_SELECT_FILL_STRING(column->sortby, sortby); - - return GRN_TRUE; -} - -static grn_bool -grn_column_data_collect(grn_ctx *ctx, - grn_user_data *user_data, - grn_hash *columns, - const char *prefix_label, - size_t prefix_label_len) -{ - grn_hash_cursor *cursor = NULL; - cursor = grn_hash_cursor_open(ctx, columns, - NULL, 0, NULL, 0, 0, -1, 0); - if (!cursor) { - return GRN_FALSE; - } - - while (grn_hash_cursor_next(ctx, cursor)) { - grn_column_data *column; - char key_name[GRN_TABLE_MAX_KEY_SIZE]; - grn_obj *type; - grn_obj *flags; - grn_obj *value; - grn_obj *sortby; - - grn_hash_cursor_get_value(ctx, cursor, (void **)&column); - -#define GET_VAR(name) \ - grn_snprintf(key_name, \ - GRN_TABLE_MAX_KEY_SIZE, \ - GRN_TABLE_MAX_KEY_SIZE, \ - "%.*scolumn[%.*s]." # name, \ - (int)prefix_label_len, \ - prefix_label, \ - (int)(column->label.length), \ - column->label.value); \ - name = grn_plugin_proc_get_var(ctx, user_data, key_name, -1); - - GET_VAR(type); - GET_VAR(flags); - GET_VAR(value); - GET_VAR(sortby); - -#undef GET_VAR - - grn_column_data_fill(ctx, column, - type, flags, value, sortby); - } - grn_hash_cursor_close(ctx, cursor); - return GRN_TRUE; -} - -static void -grn_columns_init(grn_ctx *ctx, grn_columns *columns) -{ - columns->initial = NULL; - columns->filtered = NULL; -} - -static void -grn_columns_fin(grn_ctx *ctx, grn_columns *columns) -{ - if (columns->initial) { - grn_hash_close(ctx, columns->initial); - } - - if (columns->filtered) { - grn_hash_close(ctx, columns->filtered); - } -} - -static grn_bool -grn_columns_collect(grn_ctx *ctx, - grn_user_data *user_data, - grn_columns *columns, - const char *base_prefix, - size_t base_prefix_len) -{ - grn_obj *vars; - grn_table_cursor *cursor; - const char *prefix = "column["; - size_t prefix_len; - const char *suffix = "].stage"; - size_t suffix_len; - - vars = grn_plugin_proc_get_vars(ctx, user_data); - cursor = grn_table_cursor_open(ctx, vars, NULL, 0, NULL, 0, 0, -1, 0); - if (!cursor) { - return GRN_FALSE; - } - - prefix_len = strlen(prefix); - suffix_len = strlen(suffix); - while (grn_table_cursor_next(ctx, cursor)) { - void *key; - char *variable_name; - int variable_name_len; - char *column_name; - size_t column_name_len; - void *value_raw; - grn_obj *value; - grn_column_stage stage; - grn_hash **target_columns; - - variable_name_len = grn_table_cursor_get_key(ctx, cursor, &key); - variable_name = key; - if (variable_name_len < base_prefix_len + prefix_len + suffix_len + 1) { - continue; - } - - if (base_prefix_len > 0) { - if (memcmp(base_prefix, variable_name, base_prefix_len) != 0) { - continue; - } - } - - if (memcmp(prefix, variable_name + base_prefix_len, prefix_len) != 0) { - continue; - } - - if (memcmp(suffix, - variable_name + (variable_name_len - suffix_len), - suffix_len) != 0) { - continue; - } - - grn_table_cursor_get_value(ctx, cursor, &value_raw); - value = value_raw; - if (GRN_BULK_EQUAL_STRING(value, "initial")) { - stage = GRN_COLUMN_STAGE_INITIAL; - target_columns = &(columns->initial); - } else if (GRN_BULK_EQUAL_STRING(value, "filtered")) { - stage = GRN_COLUMN_STAGE_FILTERED; - target_columns = &(columns->filtered); - } else { - continue; - } - - column_name = variable_name + base_prefix_len + prefix_len; - column_name_len = - variable_name_len - base_prefix_len - prefix_len - suffix_len; - if (!grn_column_data_init(ctx, - column_name, - column_name_len, - stage, - target_columns)) { - grn_table_cursor_close(ctx, cursor); - return GRN_FALSE; - } - } - grn_table_cursor_close(ctx, cursor); - - return GRN_TRUE; -} - -static grn_bool -grn_columns_fill(grn_ctx *ctx, - grn_user_data *user_data, - grn_columns *columns, - const char *prefix, - size_t prefix_length) -{ - if (!grn_columns_collect(ctx, user_data, columns, prefix, prefix_length)) { - return GRN_FALSE; - } - - if (columns->initial) { - if (!grn_column_data_collect(ctx, - user_data, - columns->initial, - prefix, - prefix_length)) { - return GRN_FALSE; - } - } - - if (columns->filtered) { - if (!grn_column_data_collect(ctx, - user_data, - columns->filtered, - prefix, - prefix_length)) { - return GRN_FALSE; - } - } - - return GRN_TRUE; -} - static grn_drilldown_data * grn_select_data_drilldowns_add(grn_ctx *ctx, grn_select_data *data, -------------- next part -------------- HTML����������������������������...下载