[Groonga-commit] groonga/groonga at 0444ec9 [master] Add grn_output_columns_apply()

Back to archive index
Kouhei Sutou null+****@clear*****
Tue Dec 25 17:00:55 JST 2018


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>


More information about the Groonga-commit mailing list
Back to archive index