[Groonga-commit] groonga/groonga at 95e80ec [master] Extract column related commands

Back to archive index

Kouhei Sutou null+****@clear*****
Mon Mar 14 18:45:33 JST 2016


Kouhei Sutou	2016-03-14 18:45:33 +0900 (Mon, 14 Mar 2016)

  New Revision: 95e80ec5f50ed95a9002457e874c139f12d96412
  https://github.com/groonga/groonga/commit/95e80ec5f50ed95a9002457e874c139f12d96412

  Message:
    Extract column related commands

  Added files:
    lib/proc/proc_column.c
  Modified files:
    lib/grn_proc.h
    lib/proc.c
    lib/proc/sources.am

  Modified: lib/grn_proc.h (+5 -0)
===================================================================
--- lib/grn_proc.h    2016-03-14 15:54:58 +0900 (13b5c2d)
+++ lib/grn_proc.h    2016-03-14 18:45:33 +0900 (f6abb09)
@@ -35,6 +35,11 @@ GRN_VAR const char *grn_document_root;
 void grn_db_init_builtin_query(grn_ctx *ctx);
 
 void grn_proc_init_clearlock(grn_ctx *ctx);
+void grn_proc_init_column_copy(grn_ctx *ctx);
+void grn_proc_init_column_create(grn_ctx *ctx);
+void grn_proc_init_column_list(grn_ctx *ctx);
+void grn_proc_init_column_remove(grn_ctx *ctx);
+void grn_proc_init_column_rename(grn_ctx *ctx);
 void grn_proc_init_config_get(grn_ctx *ctx);
 void grn_proc_init_config_set(grn_ctx *ctx);
 void grn_proc_init_config_delete(grn_ctx *ctx);

  Modified: lib/proc.c (+5 -786)
===================================================================
--- lib/proc.c    2016-03-14 15:54:58 +0900 (ce82a89)
+++ lib/proc.c    2016-03-14 18:45:33 +0900 (7ba47a9)
@@ -196,328 +196,8 @@ proc_status(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
   return NULL;
 }
 
-static grn_obj_flags
-grn_parse_column_create_flags(grn_ctx *ctx, const char *nptr, const char *end)
-{
-  grn_obj_flags flags = 0;
-  while (nptr < end) {
-    size_t name_size;
-
-    if (*nptr == '|' || *nptr == ' ') {
-      nptr += 1;
-      continue;
-    }
-
-#define CHECK_FLAG(name)                                                \
-    name_size = strlen(#name);                                          \
-    if ((end - nptr) >= name_size &&                                    \
-        memcmp(nptr, #name, name_size) == 0) {                          \
-      flags |= GRN_OBJ_ ## name;                                        \
-      nptr += name_size;                                                \
-      continue;                                                         \
-    }
-
-    CHECK_FLAG(COLUMN_SCALAR);
-    CHECK_FLAG(COLUMN_VECTOR);
-    CHECK_FLAG(COLUMN_INDEX);
-    CHECK_FLAG(COMPRESS_ZLIB);
-    CHECK_FLAG(COMPRESS_LZ4);
-    CHECK_FLAG(WITH_SECTION);
-    CHECK_FLAG(WITH_WEIGHT);
-    CHECK_FLAG(WITH_POSITION);
-    CHECK_FLAG(RING_BUFFER);
-
-#undef CHECK_FLAG
-
-    ERR(GRN_INVALID_ARGUMENT,
-        "[column][create][flags] unknown flag: <%.*s>",
-        (int)(end - nptr), nptr);
-    return 0;
-  }
-  return flags;
-}
-
-static grn_rc
-proc_column_create_resolve_source_name(grn_ctx *ctx,
-                                       grn_obj *table,
-                                       const char *source_name,
-                                       int source_name_length,
-                                       grn_obj *source_ids)
-{
-  grn_obj *column;
-
-  column = grn_obj_column(ctx, table, source_name, source_name_length);
-  if (!column) {
-    ERR(GRN_INVALID_ARGUMENT,
-        "[column][create] nonexistent source: <%.*s>",
-        source_name_length, source_name);
-    return ctx->rc;
-  }
-
-  if (column->header.type == GRN_ACCESSOR) {
-    if (strncmp(source_name, "_key", source_name_length) == 0) {
-      grn_id source_id = grn_obj_id(ctx, table);
-      GRN_UINT32_PUT(ctx, source_ids, source_id);
-    } else {
-      ERR(GRN_INVALID_ARGUMENT,
-          "[column][create] pseudo column except <_key> is invalid: <%.*s>",
-          source_name_length, source_name);
-    }
-  } else {
-    grn_id source_id = grn_obj_id(ctx, column);
-    GRN_UINT32_PUT(ctx, source_ids, source_id);
-  }
-  grn_obj_unlink(ctx, column);
-
-  return ctx->rc;
-}
-
-static grn_rc
-proc_column_create_resolve_source_names(grn_ctx *ctx,
-                                        grn_obj *table,
-                                        grn_obj *source_names,
-                                        grn_obj *source_ids)
-{
-  int i, names_length;
-  int start, source_name_length;
-  const char *names;
-
-  names = GRN_TEXT_VALUE(source_names);
-  start = 0;
-  source_name_length = 0;
-  names_length = GRN_TEXT_LEN(source_names);
-  for (i = 0; i < names_length; i++) {
-    switch (names[i]) {
-    case ' ' :
-      if (source_name_length == 0) {
-        start++;
-      }
-      break;
-    case ',' :
-      {
-        grn_rc rc;
-        const char *source_name = names + start;
-        rc = proc_column_create_resolve_source_name(ctx,
-                                                    table,
-                                                    source_name,
-                                                    source_name_length,
-                                                    source_ids);
-        if (rc) {
-          return rc;
-        }
-        start = i + 1;
-        source_name_length = 0;
-      }
-      break;
-    default :
-      source_name_length++;
-      break;
-    }
-  }
-
-  if (source_name_length > 0) {
-    grn_rc rc;
-    const char *source_name = names + start;
-    rc = proc_column_create_resolve_source_name(ctx,
-                                                table,
-                                                source_name,
-                                                source_name_length,
-                                                source_ids);
-    if (rc) {
-      return rc;
-    }
-  }
-
-  return GRN_SUCCESS;
-}
-
-static grn_obj *
-proc_column_create(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
-{
-  grn_bool succeeded = GRN_TRUE;
-  grn_obj *column, *table = NULL, *type = NULL;
-  const char *rest;
-  grn_obj_flags flags = grn_atoi(GRN_TEXT_VALUE(VAR(2)),
-                                 GRN_BULK_CURR(VAR(2)), &rest);
-  if (GRN_TEXT_VALUE(VAR(2)) == rest) {
-    flags = grn_parse_column_create_flags(ctx, GRN_TEXT_VALUE(VAR(2)),
-                                          GRN_BULK_CURR(VAR(2)));
-    if (ctx->rc) {
-      succeeded = GRN_FALSE;
-      goto exit;
-    }
-  }
-  table = grn_ctx_get(ctx, GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0)));
-  if (!table) {
-    ERR(GRN_INVALID_ARGUMENT,
-        "[column][create] table doesn't exist: <%.*s>",
-        (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)));
-    succeeded = GRN_FALSE;
-    goto exit;
-  }
-  type = grn_ctx_get(ctx, GRN_TEXT_VALUE(VAR(3)),
-                     GRN_TEXT_LEN(VAR(3)));
-  if (!type) {
-    ERR(GRN_INVALID_ARGUMENT,
-        "[column][create] type doesn't exist: <%.*s>",
-        (int)GRN_TEXT_LEN(VAR(3)), GRN_TEXT_VALUE(VAR(3))) ;
-    succeeded = GRN_FALSE;
-    goto exit;
-  }
-  if (GRN_TEXT_LEN(VAR(1))) {
-    flags |= GRN_OBJ_PERSISTENT;
-  } else {
-    ERR(GRN_INVALID_ARGUMENT, "[column][create] name is missing");
-    succeeded = GRN_FALSE;
-    goto exit;
-  }
-  column = grn_column_create(ctx, table,
-                             GRN_TEXT_VALUE(VAR(1)),
-                             GRN_TEXT_LEN(VAR(1)),
-                             NULL, flags, type);
-  if (column) {
-    if (GRN_TEXT_LEN(VAR(4))) {
-      grn_rc rc;
-      grn_obj source_ids;
-      GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR);
-      rc = proc_column_create_resolve_source_names(ctx,
-                                                   type,
-                                                   VAR(4),
-                                                   &source_ids);
-      if (!rc && GRN_BULK_VSIZE(&source_ids)) {
-        grn_obj_set_info(ctx, column, GRN_INFO_SOURCE, &source_ids);
-        rc = ctx->rc;
-      }
-      GRN_OBJ_FIN(ctx, &source_ids);
-      if (rc) {
-        grn_obj_remove(ctx, column);
-        succeeded = GRN_FALSE;
-        goto exit;
-      }
-    }
-    grn_obj_unlink(ctx, column);
-  } else {
-    succeeded = GRN_FALSE;
-  }
-exit :
-  GRN_OUTPUT_BOOL(succeeded);
-  if (table) { grn_obj_unlink(ctx, table); }
-  if (type) { grn_obj_unlink(ctx, type); }
-  return NULL;
-}
-
-static grn_obj *
-proc_column_remove(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
-{
-  grn_obj *table, *col;
-  char *colname,fullname[GRN_TABLE_MAX_KEY_SIZE];
-  unsigned int colname_len,fullname_len;
-
-  table = grn_ctx_get(ctx, GRN_TEXT_VALUE(VAR(0)),
-                           GRN_TEXT_LEN(VAR(0)));
-
-  colname = GRN_TEXT_VALUE(VAR(1));
-  colname_len = GRN_TEXT_LEN(VAR(1));
-
-  if ((fullname_len = grn_obj_name(ctx, table, fullname, GRN_TABLE_MAX_KEY_SIZE))) {
-    fullname[fullname_len] = GRN_DB_DELIMITER;
-    grn_memcpy((fullname + fullname_len + 1), colname, colname_len);
-    fullname_len += colname_len + 1;
-    //TODO:check fullname_len < GRN_TABLE_MAX_KEY_SIZE
-    col = grn_ctx_get(ctx, fullname, fullname_len);
-    if (col) {
-      grn_obj_remove(ctx, col);
-    } else {
-      ERR(GRN_INVALID_ARGUMENT, "[column][remove] column isn't found: <%.*s.%.*s>",
-          (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)),
-          colname_len, colname);
-    }
-  } else {
-    ERR(GRN_INVALID_ARGUMENT, "[column][remove] table isn't found: <%.*s>",
-        (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)));
-  }
-  GRN_OUTPUT_BOOL(!ctx->rc);
-  return NULL;
-}
-
-static grn_obj *
-proc_column_rename(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
-{
-  grn_rc rc = GRN_SUCCESS;
-  grn_obj *table = NULL;
-  grn_obj *column = NULL;
-  if (GRN_TEXT_LEN(VAR(0)) == 0) {
-    rc = GRN_INVALID_ARGUMENT;
-    ERR(rc, "[column][rename] table name isn't specified");
-    goto exit;
-  }
-  table = grn_ctx_get(ctx, GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0)));
-  if (!table) {
-    rc = GRN_INVALID_ARGUMENT;
-    ERR(rc,
-        "[column][rename] table isn't found: <%.*s>",
-        (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)));
-    goto exit;
-  }
-  if (GRN_TEXT_LEN(VAR(1)) == 0) {
-    rc = GRN_INVALID_ARGUMENT;
-    ERR(rc,
-        "[column][rename] column name isn't specified: <%.*s>",
-        (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)));
-    goto exit;
-  }
-  column = grn_obj_column(ctx, table,
-                          GRN_TEXT_VALUE(VAR(1)), GRN_TEXT_LEN(VAR(1)));
-  if (!column) {
-    rc = GRN_INVALID_ARGUMENT;
-    ERR(rc,
-        "[column][rename] column isn't found: <%.*s.%.*s>",
-        (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)),
-        (int)GRN_TEXT_LEN(VAR(1)), GRN_TEXT_VALUE(VAR(1)));
-    goto exit;
-  }
-  if (GRN_TEXT_LEN(VAR(2)) == 0) {
-    rc = GRN_INVALID_ARGUMENT;
-    ERR(rc,
-        "[column][rename] new column name isn't specified: <%.*s.%.*s>",
-        (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)),
-        (int)GRN_TEXT_LEN(VAR(1)), GRN_TEXT_VALUE(VAR(1)));
-    goto exit;
-  }
-  rc = grn_column_rename(ctx, column,
-                         GRN_TEXT_VALUE(VAR(2)), GRN_TEXT_LEN(VAR(2)));
-  if (rc != GRN_SUCCESS && ctx->rc == GRN_SUCCESS) {
-    ERR(rc,
-        "[column][rename] failed to rename: <%.*s.%.*s> -> <%.*s.%.*s>",
-        (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)),
-        (int)GRN_TEXT_LEN(VAR(1)), GRN_TEXT_VALUE(VAR(1)),
-        (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)),
-        (int)GRN_TEXT_LEN(VAR(2)), GRN_TEXT_VALUE(VAR(2)));
-  }
-exit :
-  GRN_OUTPUT_BOOL(!rc);
-  if (column) { grn_obj_unlink(ctx, column); }
-  if (table) { grn_obj_unlink(ctx, table); }
-  return NULL;
-}
-
 #define GRN_STRLEN(s) ((s) ? strlen(s) : 0)
 
-static void
-output_column_name(grn_ctx *ctx, grn_obj *column)
-{
-  grn_obj bulk;
-  int name_len;
-  char name[GRN_TABLE_MAX_KEY_SIZE];
-
-  GRN_TEXT_INIT(&bulk, GRN_OBJ_DO_SHALLOW_COPY);
-  name_len = grn_column_name(ctx, column, name, GRN_TABLE_MAX_KEY_SIZE);
-  GRN_TEXT_SET(ctx, &bulk, name, name_len);
-
-  GRN_OUTPUT_OBJ(&bulk, NULL);
-  GRN_OBJ_FIN(ctx, &bulk);
-}
-
 void
 grn_proc_output_object_name(grn_ctx *ctx, grn_obj *obj)
 {
@@ -549,164 +229,6 @@ grn_proc_output_object_id_name(grn_ctx *ctx, grn_id id)
   grn_proc_output_object_name(ctx, obj);
 }
 
-static int
-output_column_info(grn_ctx *ctx, grn_obj *column)
-{
-  grn_obj o;
-  grn_id id;
-  const char *type;
-  const char *path;
-
-  switch (column->header.type) {
-  case GRN_COLUMN_FIX_SIZE:
-    type = "fix";
-    break;
-  case GRN_COLUMN_VAR_SIZE:
-    type = "var";
-    break;
-  case GRN_COLUMN_INDEX:
-    type = "index";
-    break;
-  default:
-    GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid header type %d\n", column->header.type);
-    return 0;
-  }
-  id = grn_obj_id(ctx, column);
-  path = grn_obj_path(ctx, column);
-  GRN_TEXT_INIT(&o, 0);
-  GRN_OUTPUT_ARRAY_OPEN("COLUMN", 8);
-  GRN_OUTPUT_INT64(id);
-  output_column_name(ctx, column);
-  GRN_OUTPUT_CSTR(path);
-  GRN_OUTPUT_CSTR(type);
-  grn_dump_column_create_flags(ctx, column->header.flags, &o);
-  GRN_OUTPUT_OBJ(&o, NULL);
-  grn_proc_output_object_id_name(ctx, column->header.domain);
-  grn_proc_output_object_id_name(ctx, grn_obj_get_range(ctx, column));
-  {
-    grn_db_obj *obj = (grn_db_obj *)column;
-    grn_id *s = obj->source;
-    int i = 0, n = obj->source_size / sizeof(grn_id);
-    GRN_OUTPUT_ARRAY_OPEN("SOURCES", n);
-    for (i = 0; i < n; i++, s++) {
-      grn_proc_output_object_id_name(ctx, *s);
-    }
-    GRN_OUTPUT_ARRAY_CLOSE();
-
-  }
-  //  output_obj_source(ctx, (grn_db_obj *)column);
-  GRN_OUTPUT_ARRAY_CLOSE();
-  GRN_OBJ_FIN(ctx, &o);
-  return 1;
-}
-
-static grn_obj *
-proc_column_list(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
-{
-  grn_obj *table;
-  if ((table = grn_ctx_get(ctx, GRN_TEXT_VALUE(VAR(0)),
-                           GRN_TEXT_LEN(VAR(0))))) {
-    grn_hash *cols;
-    grn_obj *col;
-    int column_list_size = -1;
-#ifdef GRN_WITH_MESSAGE_PACK
-    column_list_size = 1; /* [header, (key), (COLUMNS)] */
-    if ((col = grn_obj_column(ctx, table,
-                              GRN_COLUMN_NAME_KEY,
-                              GRN_COLUMN_NAME_KEY_LEN))) {
-      column_list_size++;
-      grn_obj_unlink(ctx, col);
-    }
-    if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
-                                GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) {
-      column_list_size += grn_table_columns(ctx, table, NULL, 0,
-                                            (grn_obj *)cols);
-      grn_hash_close(ctx, cols);
-    }
-#endif
-    if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
-                                GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) {
-      GRN_OUTPUT_ARRAY_OPEN("COLUMN_LIST", column_list_size);
-      GRN_OUTPUT_ARRAY_OPEN("HEADER", 8);
-      GRN_OUTPUT_ARRAY_OPEN("PROPERTY", 2);
-      GRN_OUTPUT_CSTR("id");
-      GRN_OUTPUT_CSTR("UInt32");
-      GRN_OUTPUT_ARRAY_CLOSE();
-      GRN_OUTPUT_ARRAY_OPEN("PROPERTY", 2);
-      GRN_OUTPUT_CSTR("name");
-      GRN_OUTPUT_CSTR("ShortText");
-      GRN_OUTPUT_ARRAY_CLOSE();
-      GRN_OUTPUT_ARRAY_OPEN("PROPERTY", 2);
-      GRN_OUTPUT_CSTR("path");
-      GRN_OUTPUT_CSTR("ShortText");
-      GRN_OUTPUT_ARRAY_CLOSE();
-      GRN_OUTPUT_ARRAY_OPEN("PROPERTY", 2);
-      GRN_OUTPUT_CSTR("type");
-      GRN_OUTPUT_CSTR("ShortText");
-      GRN_OUTPUT_ARRAY_CLOSE();
-      GRN_OUTPUT_ARRAY_OPEN("PROPERTY", 2);
-      GRN_OUTPUT_CSTR("flags");
-      GRN_OUTPUT_CSTR("ShortText");
-      GRN_OUTPUT_ARRAY_CLOSE();
-      GRN_OUTPUT_ARRAY_OPEN("PROPERTY", 2);
-      GRN_OUTPUT_CSTR("domain");
-      GRN_OUTPUT_CSTR("ShortText");
-      GRN_OUTPUT_ARRAY_CLOSE();
-      GRN_OUTPUT_ARRAY_OPEN("PROPERTY", 2);
-      GRN_OUTPUT_CSTR("range");
-      GRN_OUTPUT_CSTR("ShortText");
-      GRN_OUTPUT_ARRAY_CLOSE();
-      GRN_OUTPUT_ARRAY_OPEN("PROPERTY", 2);
-      GRN_OUTPUT_CSTR("source");
-      GRN_OUTPUT_CSTR("ShortText");
-      GRN_OUTPUT_ARRAY_CLOSE();
-      GRN_OUTPUT_ARRAY_CLOSE();
-      if ((col = grn_obj_column(ctx, table,
-                                GRN_COLUMN_NAME_KEY,
-                                GRN_COLUMN_NAME_KEY_LEN))) {
-        int name_len;
-        char name_buf[GRN_TABLE_MAX_KEY_SIZE];
-        grn_id id;
-        grn_obj buf;
-        GRN_TEXT_INIT(&buf, 0);
-        GRN_OUTPUT_ARRAY_OPEN("COLUMN", 8);
-        id = grn_obj_id(ctx, table);
-        GRN_OUTPUT_INT64(id);
-        GRN_OUTPUT_CSTR(GRN_COLUMN_NAME_KEY);
-        GRN_OUTPUT_CSTR("");
-        GRN_OUTPUT_CSTR("");
-        grn_dump_column_create_flags(ctx, 0, &buf);
-        GRN_OUTPUT_OBJ(&buf, NULL);
-        name_len = grn_obj_name(ctx, table, name_buf, GRN_TABLE_MAX_KEY_SIZE);
-        GRN_OUTPUT_STR(name_buf, name_len);
-        grn_proc_output_object_id_name(ctx, table->header.domain);
-        GRN_OUTPUT_ARRAY_OPEN("SOURCES", 0);
-        GRN_OUTPUT_ARRAY_CLOSE();
-        GRN_OUTPUT_ARRAY_CLOSE();
-        GRN_OBJ_FIN(ctx, &buf);
-        grn_obj_unlink(ctx, col);
-      }
-      if (grn_table_columns(ctx, table, NULL, 0, (grn_obj *)cols) >= 0) {
-        grn_id *key;
-        GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, {
-          if ((col = grn_ctx_at(ctx, *key))) {
-            output_column_info(ctx, col);
-            grn_obj_unlink(ctx, col);
-          }
-        });
-      }
-      GRN_OUTPUT_ARRAY_CLOSE();
-      grn_hash_close(ctx, cols);
-    }
-    grn_obj_unlink(ctx, table);
-  } else {
-    ERR(GRN_INVALID_ARGUMENT, "table '%.*s' does not exist.",
-        (int)GRN_TEXT_LEN(VAR(0)),
-        GRN_TEXT_VALUE(VAR(0)));
-  }
-  return NULL;
-}
-
 static grn_obj *
 proc_missing(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
 {
@@ -4725,294 +4247,6 @@ proc_database_unmap(grn_ctx *ctx, int nargs, grn_obj **args,
   return NULL;
 }
 
-static grn_rc
-proc_column_copy_resolve_target(grn_ctx *ctx,
-                                const char *label,
-                                grn_obj *table_name,
-                                grn_obj *column_name,
-                                grn_obj **table,
-                                grn_obj **column)
-{
-  if (GRN_TEXT_LEN(table_name) == 0) {
-    ERR(GRN_INVALID_ARGUMENT,
-        "[column][copy] %s table name isn't specified",
-        label);
-    return ctx->rc;
-  }
-  *table = grn_ctx_get(ctx,
-                       GRN_TEXT_VALUE(table_name),
-                       GRN_TEXT_LEN(table_name));
-  if (!*table) {
-    ERR(GRN_INVALID_ARGUMENT,
-        "[column][copy] %s table isn't found: <%.*s>",
-        label,
-        (int)GRN_TEXT_LEN(table_name),
-        GRN_TEXT_VALUE(table_name));
-    return ctx->rc;
-  }
-
-  if (GRN_TEXT_LEN(column_name) == 0) {
-    ERR(GRN_INVALID_ARGUMENT,
-        "[column][copy] %s column name isn't specified: <%.*s>",
-        label,
-        (int)GRN_TEXT_LEN(table_name),
-        GRN_TEXT_VALUE(table_name));
-    return ctx->rc;
-  }
-  *column = grn_obj_column(ctx, *table,
-                           GRN_TEXT_VALUE(column_name),
-                           GRN_TEXT_LEN(column_name));
-  if (!*column) {
-    ERR(GRN_INVALID_ARGUMENT,
-        "[column][copy] %s column isn't found: <%.*s.%.*s>",
-        label,
-        (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name),
-        (int)GRN_TEXT_LEN(column_name), GRN_TEXT_VALUE(column_name));
-    return ctx->rc;
-  }
-
-  return ctx->rc;
-}
-
-static void
-proc_column_copy_same_table(grn_ctx *ctx, grn_obj *table,
-                            grn_obj *from_column, grn_obj *to_column)
-{
-  grn_table_cursor *cursor;
-  grn_id id;
-  grn_obj value;
-
-  cursor = grn_table_cursor_open(ctx, table,
-                                 NULL, 0,
-                                 NULL, 0,
-                                 0, -1, 0);
-  if (!cursor) {
-    return;
-  }
-
-  GRN_VOID_INIT(&value);
-  while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
-    GRN_BULK_REWIND(&value);
-    grn_obj_get_value(ctx, from_column, id, &value);
-    grn_obj_set_value(ctx, to_column, id, &value, GRN_OBJ_SET);
-  }
-  GRN_OBJ_FIN(ctx, &value);
-  grn_table_cursor_close(ctx, cursor);
-}
-
-static void
-proc_column_copy_same_key_type(grn_ctx *ctx,
-                               grn_obj *from_table,
-                               grn_obj *from_column,
-                               grn_obj *to_table,
-                               grn_obj *to_column)
-{
-  grn_table_cursor *cursor;
-  grn_id from_id;
-  grn_obj value;
-
-  cursor = grn_table_cursor_open(ctx, from_table,
-                                 NULL, 0,
-                                 NULL, 0,
-                                 0, -1, 0);
-  if (!cursor) {
-    return;
-  }
-
-  GRN_VOID_INIT(&value);
-  while ((from_id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
-    void *key;
-    int key_size;
-    grn_id to_id;
-
-    key_size = grn_table_cursor_get_key(ctx, cursor, &key);
-    to_id = grn_table_add(ctx, to_table, key, key_size, NULL);
-    if (to_id == GRN_ID_NIL) {
-      continue;
-    }
-
-    GRN_BULK_REWIND(&value);
-    grn_obj_get_value(ctx, from_column, from_id, &value);
-    grn_obj_set_value(ctx, to_column, to_id, &value, GRN_OBJ_SET);
-  }
-  GRN_OBJ_FIN(ctx, &value);
-  grn_table_cursor_close(ctx, cursor);
-}
-
-static void
-proc_column_copy_different(grn_ctx *ctx,
-                           grn_obj *from_table,
-                           grn_obj *from_column,
-                           grn_obj *to_table,
-                           grn_obj *to_column,
-                           grn_obj *from_table_name,
-                           grn_obj *from_column_name,
-                           grn_obj *to_table_name,
-                           grn_obj *to_column_name)
-{
-  grn_table_cursor *cursor;
-  grn_id from_id;
-  grn_obj from_key_buffer;
-  grn_obj to_key_buffer;
-  grn_obj value;
-
-  cursor = grn_table_cursor_open(ctx, from_table,
-                                 NULL, 0,
-                                 NULL, 0,
-                                 0, -1, 0);
-  if (!cursor) {
-    return;
-  }
-
-  if (from_table->header.domain == GRN_DB_SHORT_TEXT) {
-    GRN_SHORT_TEXT_INIT(&from_key_buffer, 0);
-  } else {
-    GRN_VALUE_FIX_SIZE_INIT(&from_key_buffer, 0, from_table->header.domain);
-  }
-  if (to_table->header.domain == GRN_DB_SHORT_TEXT) {
-    GRN_SHORT_TEXT_INIT(&to_key_buffer, 0);
-  } else {
-    GRN_VALUE_FIX_SIZE_INIT(&to_key_buffer, 0, to_table->header.domain);
-  }
-  GRN_VOID_INIT(&value);
-  while ((from_id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
-    void *key;
-    int key_size;
-    grn_rc cast_rc;
-    grn_id to_id;
-
-    GRN_BULK_REWIND(&from_key_buffer);
-    GRN_BULK_REWIND(&to_key_buffer);
-
-    key_size = grn_table_cursor_get_key(ctx, cursor, &key);
-    grn_bulk_write(ctx, &from_key_buffer, key, key_size);
-    cast_rc = grn_obj_cast(ctx, &from_key_buffer, &to_key_buffer, GRN_FALSE);
-    if (cast_rc != GRN_SUCCESS) {
-      grn_obj *to_key_type;
-      grn_obj inspected_key;
-      grn_obj inspected_to_key_type;
-
-      to_key_type = grn_ctx_at(ctx, to_table->header.domain);
-      GRN_TEXT_INIT(&inspected_key, 0);
-      GRN_TEXT_INIT(&inspected_to_key_type, 0);
-      grn_inspect(ctx, &inspected_key, &from_key_buffer);
-      grn_inspect(ctx, &inspected_to_key_type, to_key_type);
-      ERR(cast_rc,
-          "[column][copy] failed to cast key: <%.*s> -> %.*s: "
-          "<%.*s.%.*s> -> <%.*s.%.*s>",
-          (int)GRN_TEXT_LEN(&inspected_key),
-          GRN_TEXT_VALUE(&inspected_key),
-          (int)GRN_TEXT_LEN(&inspected_to_key_type),
-          GRN_TEXT_VALUE(&inspected_to_key_type),
-          (int)GRN_TEXT_LEN(from_table_name),
-          GRN_TEXT_VALUE(from_table_name),
-          (int)GRN_TEXT_LEN(from_column_name),
-          GRN_TEXT_VALUE(from_column_name),
-          (int)GRN_TEXT_LEN(to_table_name),
-          GRN_TEXT_VALUE(to_table_name),
-          (int)GRN_TEXT_LEN(to_column_name),
-          GRN_TEXT_VALUE(to_column_name));
-      GRN_OBJ_FIN(ctx, &inspected_key);
-      GRN_OBJ_FIN(ctx, &inspected_to_key_type);
-      break;
-    }
-    to_id = grn_table_add(ctx, to_table,
-                          GRN_BULK_HEAD(&to_key_buffer),
-                          GRN_BULK_VSIZE(&to_key_buffer),
-                          NULL);
-    if (to_id == GRN_ID_NIL) {
-      continue;
-    }
-
-    GRN_BULK_REWIND(&value);
-    grn_obj_get_value(ctx, from_column, from_id, &value);
-    grn_obj_set_value(ctx, to_column, to_id, &value, GRN_OBJ_SET);
-  }
-  GRN_OBJ_FIN(ctx, &from_key_buffer);
-  GRN_OBJ_FIN(ctx, &to_key_buffer);
-  GRN_OBJ_FIN(ctx, &value);
-
-  grn_table_cursor_close(ctx, cursor);
-}
-
-static grn_obj *
-proc_column_copy(grn_ctx *ctx, int nargs, grn_obj **args,
-                 grn_user_data *user_data)
-{
-  grn_rc rc = GRN_SUCCESS;
-  grn_obj *from_table = NULL;
-  grn_obj *from_column = NULL;
-  grn_obj *to_table = NULL;
-  grn_obj *to_column = NULL;
-  grn_obj *from_table_name = VAR(0);
-  grn_obj *from_column_name = VAR(1);
-  grn_obj *to_table_name = VAR(2);
-  grn_obj *to_column_name = VAR(3);
-
-  rc = proc_column_copy_resolve_target(ctx, "from",
-                                       from_table_name, from_column_name,
-                                       &from_table, &from_column);
-  if (rc != GRN_SUCCESS) {
-    goto exit;
-  }
-  rc = proc_column_copy_resolve_target(ctx, "to",
-                                       to_table_name, to_column_name,
-                                       &to_table, &to_column);
-  if (rc != GRN_SUCCESS) {
-    goto exit;
-  }
-
-  if ((from_table->header.type == GRN_TABLE_NO_KEY ||
-       to_table->header.type == GRN_TABLE_NO_KEY) &&
-      from_table != to_table) {
-    rc = GRN_OPERATION_NOT_SUPPORTED;
-    ERR(rc,
-        "[column][copy] copy from/to TABLE_NO_KEY isn't supported: "
-        "<%.*s.%.*s> -> <%.*s.%.*s>",
-        (int)GRN_TEXT_LEN(from_table_name), GRN_TEXT_VALUE(from_table_name),
-        (int)GRN_TEXT_LEN(from_column_name), GRN_TEXT_VALUE(from_column_name),
-        (int)GRN_TEXT_LEN(to_table_name), GRN_TEXT_VALUE(to_table_name),
-        (int)GRN_TEXT_LEN(to_column_name), GRN_TEXT_VALUE(to_column_name));
-    goto exit;
-  }
-
-  if (from_table == to_table) {
-    proc_column_copy_same_table(ctx, from_table, from_column, to_column);
-  } else if (from_table->header.domain == to_table->header.domain) {
-    proc_column_copy_same_key_type(ctx,
-                                   from_table, from_column,
-                                   to_table, to_column);
-  } else {
-    proc_column_copy_different(ctx,
-                               from_table,
-                               from_column,
-                               to_table,
-                               to_column,
-                               from_table_name,
-                               from_column_name,
-                               to_table_name,
-                               to_column_name);
-  }
-
-exit :
-  GRN_OUTPUT_BOOL(!rc);
-
-  if (to_column) {
-    grn_obj_unlink(ctx, to_column);
-  }
-  if (to_table) {
-    grn_obj_unlink(ctx, to_table);
-  }
-  if (from_column) {
-    grn_obj_unlink(ctx, from_column);
-  }
-  if (from_table) {
-    grn_obj_unlink(ctx, from_table);
-  }
-
-  return NULL;
-}
-
 static grn_obj *
 proc_reindex(grn_ctx *ctx, int nargs, grn_obj **args,
              grn_user_data *user_data)
@@ -5155,8 +4389,7 @@ grn_db_init_builtin_query(grn_ctx *ctx)
 
   grn_proc_init_table_list(ctx);
 
-  DEF_VAR(vars[0], "table");
-  DEF_COMMAND("column_list", proc_column_list, 1, vars);
+  grn_proc_init_column_list(ctx);
 
   grn_proc_init_table_create(ctx);
 
@@ -5164,21 +4397,11 @@ grn_db_init_builtin_query(grn_ctx *ctx)
 
   grn_proc_init_table_rename(ctx);
 
-  DEF_VAR(vars[0], "table");
-  DEF_VAR(vars[1], "name");
-  DEF_VAR(vars[2], "flags");
-  DEF_VAR(vars[3], "type");
-  DEF_VAR(vars[4], "source");
-  DEF_COMMAND("column_create", proc_column_create, 5, vars);
+  grn_proc_init_column_create(ctx);
 
-  DEF_VAR(vars[0], "table");
-  DEF_VAR(vars[1], "name");
-  DEF_COMMAND("column_remove", proc_column_remove, 2, vars);
+  grn_proc_init_column_remove(ctx);
 
-  DEF_VAR(vars[0], "table");
-  DEF_VAR(vars[1], "name");
-  DEF_VAR(vars[2], "new_name");
-  DEF_COMMAND("column_rename", proc_column_rename, 3, vars);
+  grn_proc_init_column_rename(ctx);
 
   DEF_VAR(vars[0], "path");
   DEF_COMMAND(GRN_EXPR_MISSING_NAME, proc_missing, 1, vars);
@@ -5374,11 +4597,7 @@ grn_db_init_builtin_query(grn_ctx *ctx)
 
   DEF_COMMAND("database_unmap", proc_database_unmap, 0, vars);
 
-  DEF_VAR(vars[0], "from_table");
-  DEF_VAR(vars[1], "from_name");
-  DEF_VAR(vars[2], "to_table");
-  DEF_VAR(vars[3], "to_name");
-  DEF_COMMAND("column_copy", proc_column_copy, 4, vars);
+  grn_proc_init_column_copy(ctx);
 
   grn_proc_init_schema(ctx);
 

  Added: lib/proc/proc_column.c (+1000 -0) 100644
===================================================================
--- /dev/null
+++ lib/proc/proc_column.c    2016-03-14 18:45:33 +0900 (8e9bf2d)
@@ -0,0 +1,1000 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+  Copyright(C) 2009-2016 Brazil
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License version 2.1 as published by the Free Software Foundation.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "../grn_proc.h"
+
+#include "../grn_ctx.h"
+#include "../grn_db.h"
+#include "../grn_str.h"
+
+#include <groonga/plugin.h>
+
+static grn_obj_flags
+command_column_create_parse_flags(grn_ctx *ctx,
+                                  const char *nptr,
+                                  const char *end)
+{
+  grn_obj_flags flags = 0;
+  while (nptr < end) {
+    size_t name_size;
+
+    if (*nptr == '|' || *nptr == ' ') {
+      nptr += 1;
+      continue;
+    }
+
+#define CHECK_FLAG(name)                                                \
+    name_size = strlen(#name);                                          \
+    if ((end - nptr) >= name_size &&                                    \
+        memcmp(nptr, #name, name_size) == 0) {                          \
+      flags |= GRN_OBJ_ ## name;                                        \
+      nptr += name_size;                                                \
+      continue;                                                         \
+    }
+
+    CHECK_FLAG(COLUMN_SCALAR);
+    CHECK_FLAG(COLUMN_VECTOR);
+    CHECK_FLAG(COLUMN_INDEX);
+    CHECK_FLAG(COMPRESS_ZLIB);
+    CHECK_FLAG(COMPRESS_LZ4);
+    CHECK_FLAG(WITH_SECTION);
+    CHECK_FLAG(WITH_WEIGHT);
+    CHECK_FLAG(WITH_POSITION);
+    CHECK_FLAG(RING_BUFFER);
+
+#undef CHECK_FLAG
+
+    ERR(GRN_INVALID_ARGUMENT,
+        "[column][create][flags] unknown flag: <%.*s>",
+        (int)(end - nptr), nptr);
+    return 0;
+  }
+  return flags;
+}
+
+static grn_rc
+command_column_create_resolve_source_name(grn_ctx *ctx,
+                                          grn_obj *table,
+                                          const char *source_name,
+                                          int source_name_length,
+                                          grn_obj *source_ids)
+{
+  grn_obj *column;
+
+  column = grn_obj_column(ctx, table, source_name, source_name_length);
+  if (!column) {
+    ERR(GRN_INVALID_ARGUMENT,
+        "[column][create] nonexistent source: <%.*s>",
+        source_name_length, source_name);
+    return ctx->rc;
+  }
+
+  if (column->header.type == GRN_ACCESSOR) {
+    if (strncmp(source_name, "_key", source_name_length) == 0) {
+      grn_id source_id = grn_obj_id(ctx, table);
+      GRN_UINT32_PUT(ctx, source_ids, source_id);
+    } else {
+      ERR(GRN_INVALID_ARGUMENT,
+          "[column][create] pseudo column except <_key> is invalid: <%.*s>",
+          source_name_length, source_name);
+    }
+  } else {
+    grn_id source_id = grn_obj_id(ctx, column);
+    GRN_UINT32_PUT(ctx, source_ids, source_id);
+  }
+  grn_obj_unlink(ctx, column);
+
+  return ctx->rc;
+}
+
+static grn_rc
+command_column_create_resolve_source_names(grn_ctx *ctx,
+                                           grn_obj *table,
+                                           grn_obj *source_names,
+                                           grn_obj *source_ids)
+{
+  int i, names_length;
+  int start, source_name_length;
+  const char *names;
+
+  names = GRN_TEXT_VALUE(source_names);
+  start = 0;
+  source_name_length = 0;
+  names_length = GRN_TEXT_LEN(source_names);
+  for (i = 0; i < names_length; i++) {
+    switch (names[i]) {
+    case ' ' :
+      if (source_name_length == 0) {
+        start++;
+      }
+      break;
+    case ',' :
+      {
+        grn_rc rc;
+        const char *source_name = names + start;
+        rc = command_column_create_resolve_source_name(ctx,
+                                                       table,
+                                                       source_name,
+                                                       source_name_length,
+                                                       source_ids);
+        if (rc) {
+          return rc;
+        }
+        start = i + 1;
+        source_name_length = 0;
+      }
+      break;
+    default :
+      source_name_length++;
+      break;
+    }
+  }
+
+  if (source_name_length > 0) {
+    grn_rc rc;
+    const char *source_name = names + start;
+    rc = command_column_create_resolve_source_name(ctx,
+                                                   table,
+                                                   source_name,
+                                                   source_name_length,
+                                                   source_ids);
+    if (rc) {
+      return rc;
+    }
+  }
+
+  return GRN_SUCCESS;
+}
+
+static grn_obj *
+command_column_create(grn_ctx *ctx, int nargs, grn_obj **args,
+                      grn_user_data *user_data)
+{
+  grn_bool succeeded = GRN_TRUE;
+  grn_obj *table;
+  grn_obj *column;
+  grn_obj *table_raw;
+  grn_obj *name;
+  grn_obj *flags_raw;
+  grn_obj *type_raw;
+  grn_obj *source_raw;
+  grn_obj_flags flags;
+  grn_obj *type = NULL;
+
+  table_raw  = grn_plugin_proc_get_var(ctx, user_data, "table", -1);
+  name       = grn_plugin_proc_get_var(ctx, user_data, "name", -1);
+  flags_raw  = grn_plugin_proc_get_var(ctx, user_data, "flags", -1);
+  type_raw   = grn_plugin_proc_get_var(ctx, user_data, "type", -1);
+  source_raw = grn_plugin_proc_get_var(ctx, user_data, "source", -1);
+
+  table = grn_ctx_get(ctx, GRN_TEXT_VALUE(table_raw), GRN_TEXT_LEN(table_raw));
+  if (!table) {
+    GRN_PLUGIN_ERROR(ctx,
+                     GRN_INVALID_ARGUMENT,
+                     "[column][create] table doesn't exist: <%.*s>",
+                     (int)GRN_TEXT_LEN(table_raw),
+                     GRN_TEXT_VALUE(table_raw));
+    succeeded = GRN_FALSE;
+    goto exit;
+  }
+
+  {
+    const char *rest;
+    flags = grn_atoi(GRN_TEXT_VALUE(flags_raw),
+                     GRN_BULK_CURR(flags_raw),
+                     &rest);
+    if (GRN_TEXT_VALUE(flags_raw) == rest) {
+      flags = command_column_create_parse_flags(ctx,
+                                                GRN_TEXT_VALUE(flags_raw),
+                                                GRN_BULK_CURR(flags_raw));
+      if (ctx->rc) {
+        succeeded = GRN_FALSE;
+        goto exit;
+      }
+    }
+  }
+
+  type = grn_ctx_get(ctx,
+                     GRN_TEXT_VALUE(type_raw),
+                     GRN_TEXT_LEN(type_raw));
+  if (!type) {
+    GRN_PLUGIN_ERROR(ctx,
+                     GRN_INVALID_ARGUMENT,
+                     "[column][create] type doesn't exist: <%.*s>",
+                     (int)GRN_TEXT_LEN(type_raw),
+                     GRN_TEXT_VALUE(type_raw));
+    succeeded = GRN_FALSE;
+    goto exit;
+  }
+
+  if (GRN_TEXT_LEN(name) == 0) {
+    GRN_PLUGIN_ERROR(ctx,
+                     GRN_INVALID_ARGUMENT,
+                     "[column][create] name is missing");
+    succeeded = GRN_FALSE;
+    goto exit;
+  }
+  flags |= GRN_OBJ_PERSISTENT;
+
+  column = grn_column_create(ctx, table,
+                             GRN_TEXT_VALUE(name),
+                             GRN_TEXT_LEN(name),
+                             NULL, flags, type);
+  if (!column) {
+    succeeded = GRN_FALSE;
+  }
+
+  if (GRN_TEXT_LEN(source_raw) > 0) {
+    grn_rc rc;
+    grn_obj source_ids;
+    GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR);
+    rc = command_column_create_resolve_source_names(ctx,
+                                                    type,
+                                                    source_raw,
+                                                    &source_ids);
+    if (rc == GRN_SUCCESS && GRN_BULK_VSIZE(&source_ids) > 0) {
+      grn_obj_set_info(ctx, column, GRN_INFO_SOURCE, &source_ids);
+      rc = ctx->rc;
+    }
+    GRN_OBJ_FIN(ctx, &source_ids);
+    if (rc != GRN_SUCCESS) {
+      grn_obj_remove(ctx, column);
+      succeeded = GRN_FALSE;
+      goto exit;
+    }
+  }
+
+  grn_obj_unlink(ctx, column);
+
+exit :
+  grn_ctx_output_bool(ctx, succeeded);
+  if (table) { grn_obj_unlink(ctx, table); }
+  if (type) { grn_obj_unlink(ctx, type); }
+
+  return NULL;
+}
+
+void
+grn_proc_init_column_create(grn_ctx *ctx)
+{
+  grn_expr_var vars[5];
+
+  grn_plugin_expr_var_init(ctx, &(vars[0]), "table", -1);
+  grn_plugin_expr_var_init(ctx, &(vars[1]), "name", -1);
+  grn_plugin_expr_var_init(ctx, &(vars[2]), "flags", -1);
+  grn_plugin_expr_var_init(ctx, &(vars[3]), "type", -1);
+  grn_plugin_expr_var_init(ctx, &(vars[4]), "source", -1);
+  grn_plugin_command_create(ctx,
+                            "column_create", -1,
+                            command_column_create,
+                            5,
+                            vars);
+}
+
+static grn_obj *
+command_column_remove(grn_ctx *ctx, int nargs, grn_obj **args,
+                      grn_user_data *user_data)
+{
+  grn_obj *table_raw;
+  grn_obj *name;
+  grn_obj *table;
+  grn_obj *column;
+  char fullname[GRN_TABLE_MAX_KEY_SIZE];
+  unsigned int fullname_len;
+
+  table_raw = grn_plugin_proc_get_var(ctx, user_data, "table", -1);
+  name      = grn_plugin_proc_get_var(ctx, user_data, "name", -1);
+
+  table = grn_ctx_get(ctx,
+                      GRN_TEXT_VALUE(table_raw),
+                      GRN_TEXT_LEN(table_raw));
+
+  fullname_len = grn_obj_name(ctx, table, fullname, GRN_TABLE_MAX_KEY_SIZE);
+  if (fullname_len == 0) {
+    GRN_PLUGIN_ERROR(ctx,
+                     GRN_INVALID_ARGUMENT,
+                     "[column][remove] table isn't found: <%.*s>",
+                     (int)GRN_TEXT_LEN(table_raw),
+                     GRN_TEXT_VALUE(table_raw));
+    grn_ctx_output_bool(ctx, GRN_FALSE);
+    return NULL;
+  }
+
+  fullname[fullname_len] = GRN_DB_DELIMITER;
+  grn_memcpy((fullname + fullname_len + 1),
+             GRN_TEXT_VALUE(name),
+             GRN_TEXT_LEN(name));
+  fullname_len += GRN_TEXT_LEN(name) + 1;
+  /* TODO:check fullname_len < GRN_TABLE_MAX_KEY_SIZE */
+  column = grn_ctx_get(ctx, fullname, fullname_len);
+  if (!column) {
+    GRN_PLUGIN_ERROR(ctx,
+                     GRN_INVALID_ARGUMENT,
+                     "[column][remove] column isn't found: <%.*s%c%.*s>",
+                     (int)GRN_TEXT_LEN(table_raw),
+                     GRN_TEXT_VALUE(table_raw),
+                     GRN_DB_DELIMITER,
+                     (int)GRN_TEXT_LEN(name),
+                     GRN_TEXT_VALUE(name));
+    grn_ctx_output_bool(ctx, GRN_FALSE);
+    return NULL;
+  }
+
+  grn_obj_remove(ctx, column);
+  grn_ctx_output_bool(ctx, ctx->rc == GRN_SUCCESS);
+  return NULL;
+}
+
+void
+grn_proc_init_column_remove(grn_ctx *ctx)
+{
+  grn_expr_var vars[2];
+
+  grn_plugin_expr_var_init(ctx, &(vars[0]), "table", -1);
+  grn_plugin_expr_var_init(ctx, &(vars[1]), "name", -1);
+  grn_plugin_command_create(ctx,
+                            "column_remove", -1,
+                            command_column_remove,
+                            2,
+                            vars);
+}
+
+static grn_obj *
+command_column_rename(grn_ctx *ctx, int nargs, grn_obj **args,
+                      grn_user_data *user_data)
+{
+  grn_rc rc = GRN_SUCCESS;
+  grn_obj *table_raw;
+  grn_obj *name;
+  grn_obj *new_name;
+  grn_obj *table = NULL;
+  grn_obj *column = NULL;
+
+  table_raw = grn_plugin_proc_get_var(ctx, user_data, "table", -1);
+  name      = grn_plugin_proc_get_var(ctx, user_data, "name", -1);
+  new_name  = grn_plugin_proc_get_var(ctx, user_data, "new_name", -1);
+
+  if (GRN_TEXT_LEN(table_raw) == 0) {
+    rc = GRN_INVALID_ARGUMENT;
+    GRN_PLUGIN_ERROR(ctx,
+                     rc,
+                     "[column][rename] table name isn't specified");
+    goto exit;
+  }
+
+  table = grn_ctx_get(ctx, GRN_TEXT_VALUE(table_raw), GRN_TEXT_LEN(table_raw));
+  if (!table) {
+    rc = GRN_INVALID_ARGUMENT;
+    GRN_PLUGIN_ERROR(ctx,
+                     rc,
+                     "[column][rename] table isn't found: <%.*s>",
+                     (int)GRN_TEXT_LEN(table_raw),
+                     GRN_TEXT_VALUE(table_raw));
+    goto exit;
+  }
+
+  if (GRN_TEXT_LEN(name) == 0) {
+    rc = GRN_INVALID_ARGUMENT;
+    GRN_PLUGIN_ERROR(ctx,
+                     rc,
+                     "[column][rename] column name isn't specified: <%.*s>",
+                     (int)GRN_TEXT_LEN(table_raw),
+                     GRN_TEXT_VALUE(table_raw));
+    goto exit;
+  }
+
+  column = grn_obj_column(ctx, table,
+                          GRN_TEXT_VALUE(name),
+                          GRN_TEXT_LEN(name));
+  if (!column) {
+    rc = GRN_INVALID_ARGUMENT;
+    GRN_PLUGIN_ERROR(ctx,
+                     rc,
+                     "[column][rename] column isn't found: <%.*s%c%.*s>",
+                     (int)GRN_TEXT_LEN(table_raw),
+                     GRN_TEXT_VALUE(table_raw),
+                     GRN_DB_DELIMITER,
+                     (int)GRN_TEXT_LEN(name),
+                     GRN_TEXT_VALUE(name));
+    goto exit;
+  }
+
+  if (GRN_TEXT_LEN(new_name) == 0) {
+    rc = GRN_INVALID_ARGUMENT;
+    GRN_PLUGIN_ERROR(ctx,
+                     rc,
+                     "[column][rename] new column name isn't specified: "
+                     "<%.*s%c%.*s>",
+                     (int)GRN_TEXT_LEN(table_raw),
+                     GRN_TEXT_VALUE(table_raw),
+                     GRN_DB_DELIMITER,
+                     (int)GRN_TEXT_LEN(name),
+                     GRN_TEXT_VALUE(name));
+    goto exit;
+  }
+
+  rc = grn_column_rename(ctx, column,
+                         GRN_TEXT_VALUE(new_name),
+                         GRN_TEXT_LEN(new_name));
+  if (rc != GRN_SUCCESS && ctx->rc == GRN_SUCCESS) {
+    GRN_PLUGIN_ERROR(ctx,
+                     rc,
+                     "[column][rename] failed to rename: "
+                     "<%.*s%c%.*s> -> <%.*s%c%.*s>",
+                     (int)GRN_TEXT_LEN(table_raw),
+                     GRN_TEXT_VALUE(table_raw),
+                     GRN_DB_DELIMITER,
+                     (int)GRN_TEXT_LEN(name),
+                     GRN_TEXT_VALUE(name),
+                     (int)GRN_TEXT_LEN(table_raw),
+                     GRN_TEXT_VALUE(table_raw),
+                     GRN_DB_DELIMITER,
+                     (int)GRN_TEXT_LEN(new_name),
+                     GRN_TEXT_VALUE(new_name));
+    goto exit;
+  }
+
+exit :
+  grn_ctx_output_bool(ctx, rc == GRN_SUCCESS);
+  if (column) { grn_obj_unlink(ctx, column); }
+  if (table) { grn_obj_unlink(ctx, table); }
+  return NULL;
+}
+
+void
+grn_proc_init_column_rename(grn_ctx *ctx)
+{
+  grn_expr_var vars[3];
+
+  grn_plugin_expr_var_init(ctx, &(vars[0]), "table", -1);
+  grn_plugin_expr_var_init(ctx, &(vars[1]), "name", -1);
+  grn_plugin_expr_var_init(ctx, &(vars[2]), "new_name", -1);
+  grn_plugin_command_create(ctx,
+                            "column_rename", -1,
+                            command_column_rename,
+                            3,
+                            vars);
+}
+
+static void
+output_column_name(grn_ctx *ctx, grn_obj *column)
+{
+  grn_obj bulk;
+  int name_len;
+  char name[GRN_TABLE_MAX_KEY_SIZE];
+
+  GRN_TEXT_INIT(&bulk, GRN_OBJ_DO_SHALLOW_COPY);
+  name_len = grn_column_name(ctx, column, name, GRN_TABLE_MAX_KEY_SIZE);
+  GRN_TEXT_SET(ctx, &bulk, name, name_len);
+
+  grn_ctx_output_obj(ctx, &bulk, NULL);
+  GRN_OBJ_FIN(ctx, &bulk);
+}
+
+static int
+output_column_info(grn_ctx *ctx, grn_obj *column)
+{
+  grn_obj o;
+  grn_id id;
+  const char *type;
+  const char *path;
+
+  switch (column->header.type) {
+  case GRN_COLUMN_FIX_SIZE:
+    type = "fix";
+    break;
+  case GRN_COLUMN_VAR_SIZE:
+    type = "var";
+    break;
+  case GRN_COLUMN_INDEX:
+    type = "index";
+    break;
+  default:
+    GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid header type %d\n", column->header.type);
+    return 0;
+  }
+  id = grn_obj_id(ctx, column);
+  path = grn_obj_path(ctx, column);
+  GRN_TEXT_INIT(&o, 0);
+  grn_ctx_output_array_open(ctx, "COLUMN", 8);
+  grn_ctx_output_int64(ctx, id);
+  output_column_name(ctx, column);
+  grn_ctx_output_cstr(ctx, path);
+  grn_ctx_output_cstr(ctx, type);
+  grn_dump_column_create_flags(ctx, column->header.flags, &o);
+  grn_ctx_output_obj(ctx, &o, NULL);
+  grn_proc_output_object_id_name(ctx, column->header.domain);
+  grn_proc_output_object_id_name(ctx, grn_obj_get_range(ctx, column));
+  {
+    grn_db_obj *obj = (grn_db_obj *)column;
+    grn_id *s = obj->source;
+    int i = 0, n = obj->source_size / sizeof(grn_id);
+    grn_ctx_output_array_open(ctx, "SOURCES", n);
+    for (i = 0; i < n; i++, s++) {
+      grn_proc_output_object_id_name(ctx, *s);
+    }
+    grn_ctx_output_array_close(ctx);
+
+  }
+  /* output_obj_source(ctx, (grn_db_obj *)column); */
+  grn_ctx_output_array_close(ctx);
+  GRN_OBJ_FIN(ctx, &o);
+  return 1;
+}
+
+static grn_obj *
+command_column_list(grn_ctx *ctx, int nargs, grn_obj **args,
+                    grn_user_data *user_data)
+{
+  grn_obj *table_raw;
+  grn_obj *table;
+  grn_hash *cols;
+  grn_obj *col;
+  int column_list_size = -1;
+
+  table_raw = grn_plugin_proc_get_var(ctx, user_data, "table", -1);
+
+  table = grn_ctx_get(ctx,
+                      GRN_TEXT_VALUE(table_raw),
+                      GRN_TEXT_LEN(table_raw));
+  if (!table) {
+    GRN_PLUGIN_ERROR(ctx,
+                     GRN_INVALID_ARGUMENT,
+                     "[column][list] table doesn't exist: <%.*s>",
+                     (int)GRN_TEXT_LEN(table_raw),
+                     GRN_TEXT_VALUE(table_raw));
+    return NULL;
+  }
+
+  if (!grn_obj_is_table(ctx, table)) {
+    const char *type_name;
+    type_name = grn_obj_type_to_string(table->header.type);
+    grn_obj_unlink(ctx, table);
+    GRN_PLUGIN_ERROR(ctx,
+                     GRN_INVALID_ARGUMENT,
+                     "[column][list] not table: <%.*s>: <%s>",
+                     (int)GRN_TEXT_LEN(table_raw),
+                     GRN_TEXT_VALUE(table_raw),
+                     type_name);
+    return NULL;
+  }
+
+  column_list_size = 1; /* [header, (key), (COLUMNS)] */
+  if (table->header.type != GRN_TABLE_NO_KEY) {
+    column_list_size++;
+  }
+  cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
+                         GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY);
+  if (!cols) {
+    grn_obj_unlink(ctx, table);
+    GRN_PLUGIN_ERROR(ctx,
+                     GRN_INVALID_ARGUMENT,
+                     "[column][list] "
+                     "failed to create temporary table to list columns: <%.*s>",
+                     (int)GRN_TEXT_LEN(table_raw),
+                     GRN_TEXT_VALUE(table_raw));
+    return NULL;
+  }
+
+  column_list_size += grn_table_columns(ctx, table, NULL, 0, (grn_obj *)cols);
+
+  grn_ctx_output_array_open(ctx, "COLUMN_LIST", column_list_size);
+  grn_ctx_output_array_open(ctx, "HEADER", 8);
+  grn_ctx_output_array_open(ctx, "PROPERTY", 2);
+  grn_ctx_output_cstr(ctx, "id");
+  grn_ctx_output_cstr(ctx, "UInt32");
+  grn_ctx_output_array_close(ctx);
+  grn_ctx_output_array_open(ctx, "PROPERTY", 2);
+  grn_ctx_output_cstr(ctx, "name");
+  grn_ctx_output_cstr(ctx, "ShortText");
+  grn_ctx_output_array_close(ctx);
+  grn_ctx_output_array_open(ctx, "PROPERTY", 2);
+  grn_ctx_output_cstr(ctx, "path");
+  grn_ctx_output_cstr(ctx, "ShortText");
+  grn_ctx_output_array_close(ctx);
+  grn_ctx_output_array_open(ctx, "PROPERTY", 2);
+  grn_ctx_output_cstr(ctx, "type");
+  grn_ctx_output_cstr(ctx, "ShortText");
+  grn_ctx_output_array_close(ctx);
+  grn_ctx_output_array_open(ctx, "PROPERTY", 2);
+  grn_ctx_output_cstr(ctx, "flags");
+  grn_ctx_output_cstr(ctx, "ShortText");
+  grn_ctx_output_array_close(ctx);
+  grn_ctx_output_array_open(ctx, "PROPERTY", 2);
+  grn_ctx_output_cstr(ctx, "domain");
+  grn_ctx_output_cstr(ctx, "ShortText");
+  grn_ctx_output_array_close(ctx);
+  grn_ctx_output_array_open(ctx, "PROPERTY", 2);
+  grn_ctx_output_cstr(ctx, "range");
+  grn_ctx_output_cstr(ctx, "ShortText");
+  grn_ctx_output_array_close(ctx);
+  grn_ctx_output_array_open(ctx, "PROPERTY", 2);
+  grn_ctx_output_cstr(ctx, "source");
+  grn_ctx_output_cstr(ctx, "ShortText");
+  grn_ctx_output_array_close(ctx);
+  grn_ctx_output_array_close(ctx);
+
+  if ((col = grn_obj_column(ctx, table,
+                            GRN_COLUMN_NAME_KEY,
+                            GRN_COLUMN_NAME_KEY_LEN))) {
+    int name_len;
+    char name_buf[GRN_TABLE_MAX_KEY_SIZE];
+    grn_id id;
+    grn_obj buf;
+    GRN_TEXT_INIT(&buf, 0);
+    grn_ctx_output_array_open(ctx, "COLUMN", 8);
+    id = grn_obj_id(ctx, table);
+    grn_ctx_output_int64(ctx, id);
+    grn_ctx_output_cstr(ctx, GRN_COLUMN_NAME_KEY);
+    grn_ctx_output_cstr(ctx, "");
+    grn_ctx_output_cstr(ctx, "");
+    grn_dump_column_create_flags(ctx, 0, &buf);
+    grn_ctx_output_obj(ctx, &buf, NULL);
+    name_len = grn_obj_name(ctx, table, name_buf, GRN_TABLE_MAX_KEY_SIZE);
+    grn_ctx_output_str(ctx, name_buf, name_len);
+    grn_proc_output_object_id_name(ctx, table->header.domain);
+    grn_ctx_output_array_open(ctx, "SOURCES", 0);
+    grn_ctx_output_array_close(ctx);
+    grn_ctx_output_array_close(ctx);
+    GRN_OBJ_FIN(ctx, &buf);
+    grn_obj_unlink(ctx, col);
+  }
+  {
+    grn_id *key;
+    GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, {
+      if ((col = grn_ctx_at(ctx, *key))) {
+        output_column_info(ctx, col);
+        grn_obj_unlink(ctx, col);
+      }
+    });
+  }
+  grn_ctx_output_array_close(ctx);
+  grn_hash_close(ctx, cols);
+  grn_obj_unlink(ctx, table);
+
+  return NULL;
+}
+
+void
+grn_proc_init_column_list(grn_ctx *ctx)
+{
+  grn_expr_var vars[1];
+
+  grn_plugin_expr_var_init(ctx, &(vars[0]), "table", -1);
+  grn_plugin_command_create(ctx,
+                            "column_list", -1,
+                            command_column_list,
+                            1,
+                            vars);
+}
+
+static grn_rc
+command_column_copy_resolve_target(grn_ctx *ctx,
+                                   const char *label,
+                                   grn_obj *table_name,
+                                   grn_obj *column_name,
+                                   grn_obj **table,
+                                   grn_obj **column)
+{
+  if (GRN_TEXT_LEN(table_name) == 0) {
+    ERR(GRN_INVALID_ARGUMENT,
+        "[column][copy] %s table name isn't specified",
+        label);
+    return ctx->rc;
+  }
+  *table = grn_ctx_get(ctx,
+                       GRN_TEXT_VALUE(table_name),
+                       GRN_TEXT_LEN(table_name));
+  if (!*table) {
+    ERR(GRN_INVALID_ARGUMENT,
+        "[column][copy] %s table isn't found: <%.*s>",
+        label,
+        (int)GRN_TEXT_LEN(table_name),
+        GRN_TEXT_VALUE(table_name));
+    return ctx->rc;
+  }
+
+  if (GRN_TEXT_LEN(column_name) == 0) {
+    ERR(GRN_INVALID_ARGUMENT,
+        "[column][copy] %s column name isn't specified: <%.*s>",
+        label,
+        (int)GRN_TEXT_LEN(table_name),
+        GRN_TEXT_VALUE(table_name));
+    return ctx->rc;
+  }
+  *column = grn_obj_column(ctx, *table,
+                           GRN_TEXT_VALUE(column_name),
+                           GRN_TEXT_LEN(column_name));
+  if (!*column) {
+    ERR(GRN_INVALID_ARGUMENT,
+        "[column][copy] %s column isn't found: <%.*s.%.*s>",
+        label,
+        (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name),
+        (int)GRN_TEXT_LEN(column_name), GRN_TEXT_VALUE(column_name));
+    return ctx->rc;
+  }
+
+  return ctx->rc;
+}
+
+static void
+command_column_copy_same_table(grn_ctx *ctx, grn_obj *table,
+                               grn_obj *from_column, grn_obj *to_column)
+{
+  grn_table_cursor *cursor;
+  grn_id id;
+  grn_obj value;
+
+  cursor = grn_table_cursor_open(ctx, table,
+                                 NULL, 0,
+                                 NULL, 0,
+                                 0, -1, 0);
+  if (!cursor) {
+    return;
+  }
+
+  GRN_VOID_INIT(&value);
+  while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
+    GRN_BULK_REWIND(&value);
+    grn_obj_get_value(ctx, from_column, id, &value);
+    grn_obj_set_value(ctx, to_column, id, &value, GRN_OBJ_SET);
+  }
+  GRN_OBJ_FIN(ctx, &value);
+  grn_table_cursor_close(ctx, cursor);
+}
+
+static void
+command_column_copy_same_key_type(grn_ctx *ctx,
+                                  grn_obj *from_table,
+                                  grn_obj *from_column,
+                                  grn_obj *to_table,
+                                  grn_obj *to_column)
+{
+  grn_table_cursor *cursor;
+  grn_id from_id;
+  grn_obj value;
+
+  cursor = grn_table_cursor_open(ctx, from_table,
+                                 NULL, 0,
+                                 NULL, 0,
+                                 0, -1, 0);
+  if (!cursor) {
+    return;
+  }
+
+  GRN_VOID_INIT(&value);
+  while ((from_id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
+    void *key;
+    int key_size;
+    grn_id to_id;
+
+    key_size = grn_table_cursor_get_key(ctx, cursor, &key);
+    to_id = grn_table_add(ctx, to_table, key, key_size, NULL);
+    if (to_id == GRN_ID_NIL) {
+      continue;
+    }
+
+    GRN_BULK_REWIND(&value);
+    grn_obj_get_value(ctx, from_column, from_id, &value);
+    grn_obj_set_value(ctx, to_column, to_id, &value, GRN_OBJ_SET);
+  }
+  GRN_OBJ_FIN(ctx, &value);
+  grn_table_cursor_close(ctx, cursor);
+}
+
+static void
+command_column_copy_different(grn_ctx *ctx,
+                              grn_obj *from_table,
+                              grn_obj *from_column,
+                              grn_obj *to_table,
+                              grn_obj *to_column,
+                              grn_obj *from_table_name,
+                              grn_obj *from_column_name,
+                              grn_obj *to_table_name,
+                              grn_obj *to_column_name)
+{
+  grn_table_cursor *cursor;
+  grn_id from_id;
+  grn_obj from_key_buffer;
+  grn_obj to_key_buffer;
+  grn_obj value;
+
+  cursor = grn_table_cursor_open(ctx, from_table,
+                                 NULL, 0,
+                                 NULL, 0,
+                                 0, -1, 0);
+  if (!cursor) {
+    return;
+  }
+
+  if (from_table->header.domain == GRN_DB_SHORT_TEXT) {
+    GRN_SHORT_TEXT_INIT(&from_key_buffer, 0);
+  } else {
+    GRN_VALUE_FIX_SIZE_INIT(&from_key_buffer, 0, from_table->header.domain);
+  }
+  if (to_table->header.domain == GRN_DB_SHORT_TEXT) {
+    GRN_SHORT_TEXT_INIT(&to_key_buffer, 0);
+  } else {
+    GRN_VALUE_FIX_SIZE_INIT(&to_key_buffer, 0, to_table->header.domain);
+  }
+  GRN_VOID_INIT(&value);
+  while ((from_id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
+    void *key;
+    int key_size;
+    grn_rc cast_rc;
+    grn_id to_id;
+
+    GRN_BULK_REWIND(&from_key_buffer);
+    GRN_BULK_REWIND(&to_key_buffer);
+
+    key_size = grn_table_cursor_get_key(ctx, cursor, &key);
+    grn_bulk_write(ctx, &from_key_buffer, key, key_size);
+    cast_rc = grn_obj_cast(ctx, &from_key_buffer, &to_key_buffer, GRN_FALSE);
+    if (cast_rc != GRN_SUCCESS) {
+      grn_obj *to_key_type;
+      grn_obj inspected_key;
+      grn_obj inspected_to_key_type;
+
+      to_key_type = grn_ctx_at(ctx, to_table->header.domain);
+      GRN_TEXT_INIT(&inspected_key, 0);
+      GRN_TEXT_INIT(&inspected_to_key_type, 0);
+      grn_inspect(ctx, &inspected_key, &from_key_buffer);
+      grn_inspect(ctx, &inspected_to_key_type, to_key_type);
+      ERR(cast_rc,
+          "[column][copy] failed to cast key: <%.*s> -> %.*s: "
+          "<%.*s.%.*s> -> <%.*s.%.*s>",
+          (int)GRN_TEXT_LEN(&inspected_key),
+          GRN_TEXT_VALUE(&inspected_key),
+          (int)GRN_TEXT_LEN(&inspected_to_key_type),
+          GRN_TEXT_VALUE(&inspected_to_key_type),
+          (int)GRN_TEXT_LEN(from_table_name),
+          GRN_TEXT_VALUE(from_table_name),
+          (int)GRN_TEXT_LEN(from_column_name),
+          GRN_TEXT_VALUE(from_column_name),
+          (int)GRN_TEXT_LEN(to_table_name),
+          GRN_TEXT_VALUE(to_table_name),
+          (int)GRN_TEXT_LEN(to_column_name),
+          GRN_TEXT_VALUE(to_column_name));
+      GRN_OBJ_FIN(ctx, &inspected_key);
+      GRN_OBJ_FIN(ctx, &inspected_to_key_type);
+      break;
+    }
+    to_id = grn_table_add(ctx, to_table,
+                          GRN_BULK_HEAD(&to_key_buffer),
+                          GRN_BULK_VSIZE(&to_key_buffer),
+                          NULL);
+    if (to_id == GRN_ID_NIL) {
+      continue;
+    }
+
+    GRN_BULK_REWIND(&value);
+    grn_obj_get_value(ctx, from_column, from_id, &value);
+    grn_obj_set_value(ctx, to_column, to_id, &value, GRN_OBJ_SET);
+  }
+  GRN_OBJ_FIN(ctx, &from_key_buffer);
+  GRN_OBJ_FIN(ctx, &to_key_buffer);
+  GRN_OBJ_FIN(ctx, &value);
+
+  grn_table_cursor_close(ctx, cursor);
+}
+
+static grn_obj *
+command_column_copy(grn_ctx *ctx, int nargs, grn_obj **args,
+                    grn_user_data *user_data)
+{
+  grn_rc rc = GRN_SUCCESS;
+  grn_obj *from_table = NULL;
+  grn_obj *from_column = NULL;
+  grn_obj *to_table = NULL;
+  grn_obj *to_column = NULL;
+  grn_obj *from_table_name;
+  grn_obj *from_column_name;
+  grn_obj *to_table_name;
+  grn_obj *to_column_name;
+
+  from_table_name  = grn_plugin_proc_get_var(ctx, user_data, "from_table", -1);
+  from_column_name = grn_plugin_proc_get_var(ctx, user_data, "from_name", -1);
+  to_table_name    = grn_plugin_proc_get_var(ctx, user_data, "to_table", -1);
+  to_column_name   = grn_plugin_proc_get_var(ctx, user_data, "to_name", -1);
+
+  rc = command_column_copy_resolve_target(ctx, "from",
+                                          from_table_name, from_column_name,
+                                          &from_table, &from_column);
+  if (rc != GRN_SUCCESS) {
+    goto exit;
+  }
+  rc = command_column_copy_resolve_target(ctx, "to",
+                                          to_table_name, to_column_name,
+                                          &to_table, &to_column);
+  if (rc != GRN_SUCCESS) {
+    goto exit;
+  }
+
+  if ((from_table->header.type == GRN_TABLE_NO_KEY ||
+       to_table->header.type == GRN_TABLE_NO_KEY) &&
+      from_table != to_table) {
+    rc = GRN_OPERATION_NOT_SUPPORTED;
+    GRN_PLUGIN_ERROR(ctx,
+                     rc,
+                     "[column][copy] copy from/to TABLE_NO_KEY isn't supported: "
+                     "<%.*s%c%.*s> -> <%.*s%c%.*s>",
+                     (int)GRN_TEXT_LEN(from_table_name),
+                     GRN_TEXT_VALUE(from_table_name),
+                     GRN_DB_DELIMITER,
+                     (int)GRN_TEXT_LEN(from_column_name),
+                     GRN_TEXT_VALUE(from_column_name),
+                     (int)GRN_TEXT_LEN(to_table_name),
+                     GRN_TEXT_VALUE(to_table_name),
+                     GRN_DB_DELIMITER,
+                     (int)GRN_TEXT_LEN(to_column_name),
+                     GRN_TEXT_VALUE(to_column_name));
+    goto exit;
+  }
+
+  if (from_table == to_table) {
+    command_column_copy_same_table(ctx, from_table, from_column, to_column);
+  } else if (from_table->header.domain == to_table->header.domain) {
+    command_column_copy_same_key_type(ctx,
+                                      from_table, from_column,
+                                      to_table, to_column);
+  } else {
+    command_column_copy_different(ctx,
+                                  from_table,
+                                  from_column,
+                                  to_table,
+                                  to_column,
+                                  from_table_name,
+                                  from_column_name,
+                                  to_table_name,
+                                  to_column_name);
+  }
+
+exit :
+  grn_ctx_output_bool(ctx, rc == GRN_SUCCESS);
+
+  if (to_column) {
+    grn_obj_unlink(ctx, to_column);
+  }
+  if (to_table) {
+    grn_obj_unlink(ctx, to_table);
+  }
+  if (from_column) {
+    grn_obj_unlink(ctx, from_column);
+  }
+  if (from_table) {
+    grn_obj_unlink(ctx, from_table);
+  }
+
+  return NULL;
+}
+
+void
+grn_proc_init_column_copy(grn_ctx *ctx)
+{
+  grn_expr_var vars[4];
+
+  grn_plugin_expr_var_init(ctx, &(vars[0]), "from_table", -1);
+  grn_plugin_expr_var_init(ctx, &(vars[1]), "from_name", -1);
+  grn_plugin_expr_var_init(ctx, &(vars[2]), "to_table", -1);
+  grn_plugin_expr_var_init(ctx, &(vars[3]), "to_name", -1);
+  grn_plugin_command_create(ctx,
+                            "column_copy", -1,
+                            command_column_copy,
+                            4,
+                            vars);
+}

  Modified: lib/proc/sources.am (+1 -0)
===================================================================
--- lib/proc/sources.am    2016-03-14 15:54:58 +0900 (f5ed82f)
+++ lib/proc/sources.am    2016-03-14 18:45:33 +0900 (0c0d174)
@@ -1,4 +1,5 @@
 libgrnproc_la_SOURCES =				\
+	proc_column.c				\
 	proc_config.c				\
 	proc_fuzzy_search.c			\
 	proc_lock.c				\




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