Kouhei Sutou 2018-12-25 17:00:55 +0900 (Tue, 25 Dec 2018) Revision: 0444ec90de62297f28de87ddb1110f1f8c4595ff https://github.com/groonga/groonga/commit/0444ec90de62297f28de87ddb1110f1f8c4595ff Message: Add grn_output_columns_apply() Modified files: include/groonga/output_columns.h lib/output_columns.c Modified: include/groonga/output_columns.h (+5 -0) =================================================================== --- include/groonga/output_columns.h 2018-12-25 16:59:25 +0900 (e2262d9a2) +++ include/groonga/output_columns.h 2018-12-25 17:00:55 +0900 (2534e009d) @@ -28,6 +28,11 @@ grn_output_columns_parse(grn_ctx *ctx, const char *raw_output_columns, size_t raw_output_columns_size); +GRN_API grn_rc +grn_output_columns_apply(grn_ctx *ctx, + grn_obj *output_columns, + grn_obj *columns); + #ifdef __cplusplus } #endif Modified: lib/output_columns.c (+205 -0) =================================================================== --- lib/output_columns.c 2018-12-25 16:59:25 +0900 (cc35f5b9c) +++ lib/output_columns.c 2018-12-25 17:00:55 +0900 (7ea6546a5) @@ -44,3 +44,208 @@ grn_output_columns_parse(grn_ctx *ctx, GRN_API_RETURN(output_columns); } + +static void +grn_output_columns_apply_one(grn_ctx *ctx, + grn_obj *output_columns, + grn_obj *ids, + grn_obj *variable, + int code_start_offset, + int code_end_offset, + grn_obj *column) +{ + grn_expr *expr = (grn_expr *)output_columns; + grn_expr_code *codes = expr->codes; + uint32_t codes_curr = expr->codes_curr; + grn_expr_executor executor; + size_t i; + size_t n_ids; + + expr->codes += code_start_offset; + expr->codes_curr = code_end_offset; + grn_expr_executor_init(ctx, &executor, output_columns); + n_ids = GRN_BULK_VSIZE(ids) / sizeof(grn_id); + for (i = 0; i < n_ids; i += 2) { + grn_id source_id = GRN_RECORD_VALUE_AT(ids, i); + grn_id target_id = GRN_RECORD_VALUE_AT(ids, i + 1); + grn_obj *value; + + value = grn_expr_executor_exec(ctx, &executor, source_id); + if (value) { + grn_obj_set_value(ctx, column, target_id, value, GRN_OBJ_SET); + } + } + grn_expr_executor_fin(ctx, &executor); + + expr->codes = codes; + expr->codes_curr = codes_curr; +} + +grn_rc +grn_output_columns_apply(grn_ctx *ctx, + grn_obj *output_columns, + grn_obj *columns) +{ + grn_obj *variable; + grn_obj *source_table; + grn_obj *target_table = NULL; + grn_bool use_keys = GRN_FALSE; + size_t n_columns; + grn_obj source_key_buffer; + grn_obj target_key_buffer; + grn_obj ids; + + GRN_API_ENTER; + + variable = grn_expr_get_var_by_offset(ctx, output_columns, 0); + source_table = grn_ctx_at(ctx, variable->header.domain); + + n_columns = GRN_BULK_VSIZE(columns) / sizeof(grn_obj *); + if (n_columns == 0) { + goto exit; + } + { + grn_obj *first_column; + + first_column = GRN_PTR_VALUE_AT(columns, 0); + if (grn_obj_is_accessor(ctx, first_column)) { + target_table = ((grn_accessor *)first_column)->obj; + } else { + grn_id target_table_id; + target_table_id = first_column->header.domain; + target_table = grn_ctx_at(ctx, target_table_id); + } + } + + use_keys = (target_table->header.type != GRN_TABLE_NO_KEY); + if (use_keys) { + if (source_table->header.domain == GRN_DB_SHORT_TEXT) { + GRN_SHORT_TEXT_INIT(&source_key_buffer, 0); + } else { + GRN_VALUE_FIX_SIZE_INIT(&source_key_buffer, + 0, + source_table->header.domain); + } + if (target_table->header.domain == GRN_DB_SHORT_TEXT) { + GRN_SHORT_TEXT_INIT(&target_key_buffer, 0); + } else { + GRN_VALUE_FIX_SIZE_INIT(&target_key_buffer, + 0, + target_table->header.domain); + } + } + + GRN_RECORD_INIT(&ids, 0, GRN_ID_NIL); + + if (use_keys) { + GRN_TABLE_EACH_BEGIN(ctx, source_table, cursor, source_id) { + void *key; + int key_size; + grn_rc cast_rc; + grn_id target_id; + + GRN_BULK_REWIND(&source_key_buffer); + GRN_BULK_REWIND(&target_key_buffer); + + /* TODO: no key -> key case */ + key_size = grn_table_cursor_get_key(ctx, cursor, &key); + grn_bulk_write(ctx, &source_key_buffer, key, key_size); + cast_rc = grn_obj_cast(ctx, + &source_key_buffer, + &target_key_buffer, + GRN_FALSE); + if (cast_rc != GRN_SUCCESS) { + break; + } + + target_id = grn_table_add(ctx, + target_table, + GRN_BULK_HEAD(&target_key_buffer), + GRN_BULK_VSIZE(&target_key_buffer), + NULL); + if (target_id == GRN_ID_NIL) { + break; + } + + GRN_RECORD_PUT(ctx, &ids, source_id); + GRN_RECORD_PUT(ctx, &ids, target_id); + } GRN_TABLE_EACH_END(ctx, cursor); + } else { + GRN_TABLE_EACH_BEGIN(ctx, source_table, cursor, source_id) { + grn_id target_id; + + target_id = grn_table_add(ctx, + target_table, + NULL, + 0, + NULL); + if (target_id == GRN_ID_NIL) { + break; + } + + GRN_RECORD_PUT(ctx, &ids, source_id); + GRN_RECORD_PUT(ctx, &ids, target_id); + } GRN_TABLE_EACH_END(ctx, cursor); + } + + { + int previous_comma_offset = -1; + grn_bool is_first_comma = GRN_TRUE; + grn_bool have_comma = GRN_FALSE; + grn_expr *expr = (grn_expr *)output_columns; + grn_expr_code *code; + grn_expr_code *code_end = expr->codes + expr->codes_curr; + size_t i = 0; + + for (code = expr->codes; code < code_end; code++) { + int code_start_offset; + + if (code->op != GRN_OP_COMMA) { + continue; + } + + have_comma = GRN_TRUE; + if (is_first_comma) { + unsigned int n_used_codes; + int code_end_offset; + + n_used_codes = grn_expr_code_n_used_codes(ctx, expr->codes, code - 1); + code_end_offset = code - expr->codes - n_used_codes; + + grn_output_columns_apply_one(ctx, + output_columns, + &ids, + variable, + 0, + code_end_offset, + GRN_PTR_VALUE_AT(columns, i)); + i++; + code_start_offset = code_end_offset; + is_first_comma = GRN_FALSE; + } else { + code_start_offset = previous_comma_offset + 1; + } + + grn_output_columns_apply_one(ctx, + output_columns, + &ids, + variable, + code_start_offset, + code - expr->codes - 1, + GRN_PTR_VALUE_AT(columns, i)); + i++; + previous_comma_offset = code - expr->codes; + } + } + +exit : + if (target_table) { + if (use_keys) { + GRN_OBJ_FIN(ctx, &source_key_buffer); + GRN_OBJ_FIN(ctx, &target_key_buffer); + } + GRN_OBJ_FIN(ctx, &ids); + } + + GRN_API_RETURN(ctx->rc); +} -------------- next part -------------- An HTML attachment was scrubbed... URL: <https://lists.osdn.me/mailman/archives/groonga-commit/attachments/20181225/7c368bde/attachment-0001.html>