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 \