[Groonga-commit] groonga/groonga at 8ffbc37 [master] select: reorder

アーカイブの一覧に戻る

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����������������������������...
ダウンロード 



More information about the Groonga-commit mailing list
アーカイブの一覧に戻る