summaryrefslogtreecommitdiff
path: root/storage/mroonga/vendor/groonga/lib/db.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/mroonga/vendor/groonga/lib/db.c')
-rw-r--r--storage/mroonga/vendor/groonga/lib/db.c5509
1 files changed, 3412 insertions, 2097 deletions
diff --git a/storage/mroonga/vendor/groonga/lib/db.c b/storage/mroonga/vendor/groonga/lib/db.c
index 05e4d73e5ed..01aa1e25581 100644
--- a/storage/mroonga/vendor/groonga/lib/db.c
+++ b/storage/mroonga/vendor/groonga/lib/db.c
@@ -1,5 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2015 Brazil
+/*
+ Copyright(C) 2009-2017 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -15,11 +16,14 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "grn.h"
+#include "grn_config.h"
#include "grn_db.h"
+#include "grn_obj.h"
#include "grn_hash.h"
#include "grn_pat.h"
#include "grn_dat.h"
#include "grn_ii.h"
+#include "grn_index_column.h"
#include "grn_ctx_impl.h"
#include "grn_token_cursor.h"
#include "grn_tokenizers.h"
@@ -30,8 +34,12 @@
#include "grn_snip.h"
#include "grn_string.h"
#include "grn_normalizer.h"
+#include "grn_report.h"
#include "grn_util.h"
+#include "grn_cache.h"
+#include "grn_window_functions.h"
#include <string.h>
+#include <math.h>
typedef struct {
grn_id id;
@@ -40,8 +48,6 @@ typedef struct {
#define IS_WEIGHT_UVECTOR(obj) ((obj)->header.flags & GRN_OBJ_WITH_WEIGHT)
-#define NEXT_ADDR(p) (((byte *)(p)) + sizeof(*(p)))
-
#define GRN_TABLE_GROUPED (0x01<<0)
#define GRN_TABLE_IS_GROUPED(table)\
((table)->header.impl_flags & GRN_TABLE_GROUPED)
@@ -85,9 +91,7 @@ inline static void
grn_obj_get_range_info(grn_ctx *ctx, grn_obj *obj,
grn_id *range_id, grn_obj_flags *range_flags);
-
static char grn_db_key[GRN_ENV_BUFFER_SIZE];
-static uint64_t grn_index_sparsity = 10;
void
grn_db_init_from_env(void)
@@ -95,21 +99,6 @@ grn_db_init_from_env(void)
grn_getenv("GRN_DB_KEY",
grn_db_key,
GRN_ENV_BUFFER_SIZE);
-
- {
- char grn_index_sparsity_env[GRN_ENV_BUFFER_SIZE];
- grn_getenv("GRN_INDEX_SPARSITY",
- grn_index_sparsity_env,
- GRN_ENV_BUFFER_SIZE);
- if (grn_index_sparsity_env[0]) {
- uint64_t sparsity;
- errno = 0;
- sparsity = strtoull(grn_index_sparsity_env, NULL, 0);
- if (errno == 0) {
- grn_index_sparsity = sparsity;
- }
- }
- }
}
inline static void
@@ -126,192 +115,304 @@ gen_pathname(const char *path, char *buffer, int fno)
}
}
+void
+grn_db_generate_pathname(grn_ctx *ctx, grn_obj *db, grn_id id, char *buffer)
+{
+ gen_pathname(grn_obj_get_io(ctx, db)->path, buffer, id);
+}
+
+typedef struct {
+ grn_obj *ptr;
+ uint32_t lock;
+ uint32_t done;
+} db_value;
+
+static const char *GRN_DB_CONFIG_PATH_FORMAT = "%s.conf";
+
static grn_bool
-is_text_object(grn_obj *object)
+grn_db_config_create(grn_ctx *ctx, grn_db *s, const char *path,
+ const char *context_tag)
{
- if (!object) {
- return GRN_FALSE;
- }
+ char *config_path;
+ char config_path_buffer[PATH_MAX];
+ uint32_t flags = GRN_OBJ_KEY_VAR_SIZE;
- if (object->header.type != GRN_BULK) {
+ if (path) {
+ grn_snprintf(config_path_buffer, PATH_MAX, PATH_MAX,
+ GRN_DB_CONFIG_PATH_FORMAT, path);
+ config_path = config_path_buffer;
+ } else {
+ config_path = NULL;
+ }
+ s->config = grn_hash_create(ctx, config_path,
+ GRN_CONFIG_MAX_KEY_SIZE,
+ GRN_CONFIG_VALUE_SPACE_SIZE,
+ flags);
+ if (!s->config) {
+ ERR(GRN_NO_MEMORY_AVAILABLE,
+ "%s failed to create data store for configuration: <%s>",
+ context_tag,
+ config_path ? config_path : "(temporary)");
return GRN_FALSE;
}
- switch (object->header.domain) {
- case GRN_DB_SHORT_TEXT:
- case GRN_DB_TEXT:
- case GRN_DB_LONG_TEXT:
- return GRN_TRUE;
- default:
- return GRN_FALSE;
- }
+ return GRN_TRUE;
}
-static void
-limited_size_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *object)
+static grn_bool
+grn_db_config_open(grn_ctx *ctx, grn_db *s, const char *path)
{
- unsigned int original_size = 0;
- unsigned int max_size = GRN_CTX_MSGSIZE / 2;
-
- if (object) {
- original_size = GRN_BULK_VSIZE(object);
- }
+ char config_path[PATH_MAX];
- if (original_size > max_size && is_text_object(object)) {
- grn_text_esc(ctx, buffer, GRN_TEXT_VALUE(object), max_size);
- GRN_TEXT_PUTS(ctx, buffer, "...(");
- grn_text_lltoa(ctx, buffer, original_size);
- GRN_TEXT_PUTS(ctx, buffer, ")");
+ grn_snprintf(config_path, PATH_MAX, PATH_MAX, GRN_DB_CONFIG_PATH_FORMAT, path);
+ if (grn_path_exist(config_path)) {
+ s->config = grn_hash_open(ctx, config_path);
+ if (!s->config) {
+ ERR(GRN_NO_MEMORY_AVAILABLE,
+ "[db][open] failed to open data store for configuration: <%s>",
+ config_path);
+ return GRN_FALSE;
+ }
+ return GRN_TRUE;
} else {
- grn_inspect(ctx, buffer, object);
+ return grn_db_config_create(ctx, s, path, "[db][open]");
}
}
-typedef struct {
- grn_obj *ptr;
- uint32_t lock;
- uint32_t done;
-} db_value;
+static grn_rc
+grn_db_config_remove(grn_ctx *ctx, const char *path)
+{
+ char config_path[PATH_MAX];
+
+ grn_snprintf(config_path, PATH_MAX, PATH_MAX, GRN_DB_CONFIG_PATH_FORMAT, path);
+ return grn_hash_remove(ctx, config_path);
+}
grn_obj *
grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg)
{
- grn_db *s;
+ grn_db *s = NULL;
+
GRN_API_ENTER;
- if (!path || strlen(path) <= PATH_MAX - 14) {
- if ((s = GRN_MALLOC(sizeof(grn_db)))) {
- grn_bool use_default_db_key = GRN_TRUE;
- grn_bool use_pat_as_db_keys = GRN_FALSE;
- if (grn_db_key[0]) {
- if (!strcmp(grn_db_key, "pat")) {
- use_default_db_key = GRN_FALSE;
- use_pat_as_db_keys = GRN_TRUE;
- } else if (!strcmp(grn_db_key, "dat")) {
- use_default_db_key = GRN_FALSE;
- }
- }
- if (use_default_db_key && !strcmp(GRN_DEFAULT_DB_KEY, "pat")) {
+
+ if (path && strlen(path) > PATH_MAX - 14) {
+ ERR(GRN_INVALID_ARGUMENT, "too long path");
+ goto exit;
+ }
+
+ s = GRN_MALLOC(sizeof(grn_db));
+ if (!s) {
+ ERR(GRN_NO_MEMORY_AVAILABLE, "grn_db alloc failed");
+ goto exit;
+ }
+
+ CRITICAL_SECTION_INIT(s->lock);
+ grn_tiny_array_init(ctx, &s->values, sizeof(db_value),
+ GRN_TINY_ARRAY_CLEAR|
+ GRN_TINY_ARRAY_THREADSAFE|
+ GRN_TINY_ARRAY_USE_MALLOC);
+ s->keys = NULL;
+ s->specs = NULL;
+ s->config = NULL;
+
+ {
+ grn_bool use_default_db_key = GRN_TRUE;
+ grn_bool use_pat_as_db_keys = GRN_FALSE;
+ if (grn_db_key[0]) {
+ if (!strcmp(grn_db_key, "pat")) {
+ use_default_db_key = GRN_FALSE;
use_pat_as_db_keys = GRN_TRUE;
+ } else if (!strcmp(grn_db_key, "dat")) {
+ use_default_db_key = GRN_FALSE;
}
- grn_tiny_array_init(ctx, &s->values, sizeof(db_value),
- GRN_TINY_ARRAY_CLEAR|
- GRN_TINY_ARRAY_THREADSAFE|
- GRN_TINY_ARRAY_USE_MALLOC);
- if (use_pat_as_db_keys) {
- s->keys = (grn_obj *)grn_pat_create(ctx, path, GRN_TABLE_MAX_KEY_SIZE,
- 0, GRN_OBJ_KEY_VAR_SIZE);
- } else {
- s->keys = (grn_obj *)grn_dat_create(ctx, path, GRN_TABLE_MAX_KEY_SIZE,
- 0, GRN_OBJ_KEY_VAR_SIZE);
- }
- if (s->keys) {
- CRITICAL_SECTION_INIT(s->lock);
- GRN_DB_OBJ_SET_TYPE(s, GRN_DB);
- s->obj.db = (grn_obj *)s;
- s->obj.header.domain = GRN_ID_NIL;
- DB_OBJ(&s->obj)->range = GRN_ID_NIL;
- // prepare builtin classes and load builtin plugins.
- if (path) {
- char specs_path[PATH_MAX];
- gen_pathname(path, specs_path, 0);
- if ((s->specs = grn_ja_create(ctx, specs_path, 65536, 0))) {
- grn_ctx_use(ctx, (grn_obj *)s);
- grn_db_init_builtin_types(ctx);
- GRN_API_RETURN((grn_obj *)s);
- } else {
- ERR(GRN_NO_MEMORY_AVAILABLE,
- "failed to create specs: <%s>", specs_path);
- }
- } else {
- s->specs = NULL;
- grn_ctx_use(ctx, (grn_obj *)s);
- grn_db_init_builtin_types(ctx);
- GRN_API_RETURN((grn_obj *)s);
- }
- if (use_pat_as_db_keys) {
- grn_pat_close(ctx, (grn_pat *)s->keys);
- grn_pat_remove(ctx, path);
- } else {
- grn_dat_close(ctx, (grn_dat *)s->keys);
- grn_dat_remove(ctx, path);
- }
- }
- grn_tiny_array_fin(&s->values);
- GRN_FREE(s);
+ }
+
+ if (use_default_db_key && !strcmp(GRN_DEFAULT_DB_KEY, "pat")) {
+ use_pat_as_db_keys = GRN_TRUE;
+ }
+ if (use_pat_as_db_keys) {
+ s->keys = (grn_obj *)grn_pat_create(ctx, path, GRN_TABLE_MAX_KEY_SIZE,
+ 0, GRN_OBJ_KEY_VAR_SIZE);
} else {
- ERR(GRN_NO_MEMORY_AVAILABLE, "grn_db alloc failed");
+ s->keys = (grn_obj *)grn_dat_create(ctx, path, GRN_TABLE_MAX_KEY_SIZE,
+ 0, GRN_OBJ_KEY_VAR_SIZE);
}
+ }
+
+ if (!s->keys) {
+ goto exit;
+ }
+
+ GRN_DB_OBJ_SET_TYPE(s, GRN_DB);
+ s->obj.db = (grn_obj *)s;
+ s->obj.header.domain = GRN_ID_NIL;
+ DB_OBJ(&s->obj)->range = GRN_ID_NIL;
+ /* prepare builtin classes and load builtin plugins. */
+ if (path) {
+ {
+ char specs_path[PATH_MAX];
+ gen_pathname(path, specs_path, 0);
+ s->specs = grn_ja_create(ctx, specs_path, 65536, 0);
+ if (!s->specs) {
+ ERR(GRN_NO_MEMORY_AVAILABLE,
+ "failed to create specs: <%s>", specs_path);
+ goto exit;
+ }
+ }
+ if (!grn_db_config_create(ctx, s, path, "[db][create]")) {
+ goto exit;
+ }
+ grn_ctx_use(ctx, (grn_obj *)s);
+ grn_db_init_builtin_types(ctx);
+ grn_obj_flush(ctx, (grn_obj *)s);
+ GRN_API_RETURN((grn_obj *)s);
} else {
- ERR(GRN_INVALID_ARGUMENT, "too long path");
+ if (!grn_db_config_create(ctx, s, NULL, "[db][create]")) {
+ goto exit;
+ }
+ grn_ctx_use(ctx, (grn_obj *)s);
+ grn_db_init_builtin_types(ctx);
+ GRN_API_RETURN((grn_obj *)s);
+ }
+
+exit:
+ if (s) {
+ if (s->keys) {
+ if (s->keys->header.type == GRN_TABLE_PAT_KEY) {
+ grn_pat_close(ctx, (grn_pat *)s->keys);
+ grn_pat_remove(ctx, path);
+ } else {
+ grn_dat_close(ctx, (grn_dat *)s->keys);
+ grn_dat_remove(ctx, path);
+ }
+ }
+ if (s->specs) {
+ const char *specs_path;
+ specs_path = grn_obj_path(ctx, (grn_obj *)(s->specs));
+ grn_ja_close(ctx, s->specs);
+ grn_ja_remove(ctx, specs_path);
+ }
+ grn_tiny_array_fin(&s->values);
+ CRITICAL_SECTION_FIN(s->lock);
+ GRN_FREE(s);
}
+
GRN_API_RETURN(NULL);
}
grn_obj *
grn_db_open(grn_ctx *ctx, const char *path)
{
- grn_db *s;
+ grn_db *s = NULL;
+
GRN_API_ENTER;
- if (path && strlen(path) <= PATH_MAX - 14) {
- if ((s = GRN_MALLOC(sizeof(grn_db)))) {
- uint32_t type = grn_io_detect_type(ctx, path);
- grn_tiny_array_init(ctx, &s->values, sizeof(db_value),
- GRN_TINY_ARRAY_CLEAR|
- GRN_TINY_ARRAY_THREADSAFE|
- GRN_TINY_ARRAY_USE_MALLOC);
- switch (type) {
- case GRN_TABLE_PAT_KEY :
- s->keys = (grn_obj *)grn_pat_open(ctx, path);
- break;
- case GRN_TABLE_DAT_KEY :
- s->keys = (grn_obj *)grn_dat_open(ctx, path);
- break;
- default :
- s->keys = NULL;
- if (ctx->rc == GRN_SUCCESS) {
- ERR(GRN_INVALID_ARGUMENT,
- "[db][open] invalid keys table's type: %#x", type);
- }
- break;
+
+ if (!path) {
+ ERR(GRN_INVALID_ARGUMENT, "[db][open] path is missing");
+ goto exit;
+ }
+
+ if (strlen(path) > PATH_MAX - 14) {
+ ERR(GRN_INVALID_ARGUMENT, "inappropriate path");
+ goto exit;
+ }
+
+ s = GRN_MALLOC(sizeof(grn_db));
+ if (!s) {
+ ERR(GRN_NO_MEMORY_AVAILABLE, "grn_db alloc failed");
+ goto exit;
+ }
+
+ CRITICAL_SECTION_INIT(s->lock);
+ grn_tiny_array_init(ctx, &s->values, sizeof(db_value),
+ GRN_TINY_ARRAY_CLEAR|
+ GRN_TINY_ARRAY_THREADSAFE|
+ GRN_TINY_ARRAY_USE_MALLOC);
+ s->keys = NULL;
+ s->specs = NULL;
+ s->config = NULL;
+
+ {
+ uint32_t type = grn_io_detect_type(ctx, path);
+ switch (type) {
+ case GRN_TABLE_PAT_KEY :
+ s->keys = (grn_obj *)grn_pat_open(ctx, path);
+ break;
+ case GRN_TABLE_DAT_KEY :
+ s->keys = (grn_obj *)grn_dat_open(ctx, path);
+ break;
+ default :
+ s->keys = NULL;
+ if (ctx->rc == GRN_SUCCESS) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[db][open] invalid keys table's type: %#x", type);
+ goto exit;
}
- if (s->keys) {
- char specs_path[PATH_MAX];
- gen_pathname(path, specs_path, 0);
- if ((s->specs = grn_ja_open(ctx, specs_path))) {
- CRITICAL_SECTION_INIT(s->lock);
- GRN_DB_OBJ_SET_TYPE(s, GRN_DB);
- s->obj.db = (grn_obj *)s;
- s->obj.header.domain = GRN_ID_NIL;
- DB_OBJ(&s->obj)->range = GRN_ID_NIL;
- grn_ctx_use(ctx, (grn_obj *)s);
+ break;
+ }
+ }
+
+ if (!s->keys) {
+ goto exit;
+ }
+
+ {
+ char specs_path[PATH_MAX];
+ gen_pathname(path, specs_path, 0);
+ s->specs = grn_ja_open(ctx, specs_path);
+ if (!s->specs) {
+ ERR(GRN_NO_MEMORY_AVAILABLE,
+ "[db][open] failed to open specs: <%s>", specs_path);
+ goto exit;
+ }
+ }
+ if (!grn_db_config_open(ctx, s, path)) {
+ goto exit;
+ }
+
+ GRN_DB_OBJ_SET_TYPE(s, GRN_DB);
+ s->obj.db = (grn_obj *)s;
+ s->obj.header.domain = GRN_ID_NIL;
+ DB_OBJ(&s->obj)->range = GRN_ID_NIL;
+ grn_ctx_use(ctx, (grn_obj *)s);
+ {
+ unsigned int n_records;
+
+ n_records = grn_table_size(ctx, (grn_obj *)s);
#ifdef GRN_WITH_MECAB
- if (grn_db_init_mecab_tokenizer(ctx)) {
- ERRCLR(ctx);
- }
+ if (grn_db_init_mecab_tokenizer(ctx)) {
+ ERRCLR(ctx);
+ }
#endif
- grn_db_init_builtin_tokenizers(ctx);
- grn_db_init_builtin_normalizers(ctx);
- grn_db_init_builtin_scorers(ctx);
- grn_db_init_builtin_query(ctx);
- GRN_API_RETURN((grn_obj *)s);
- }
- switch (type) {
- case GRN_TABLE_PAT_KEY :
- grn_pat_close(ctx, (grn_pat *)s->keys);
- break;
- case GRN_TABLE_DAT_KEY :
- grn_dat_close(ctx, (grn_dat *)s->keys);
- break;
- }
+ grn_db_init_builtin_tokenizers(ctx);
+ grn_db_init_builtin_normalizers(ctx);
+ grn_db_init_builtin_scorers(ctx);
+ grn_db_init_builtin_commands(ctx);
+ grn_db_init_builtin_window_functions(ctx);
+
+ if (grn_table_size(ctx, (grn_obj *)s) > n_records) {
+ grn_obj_flush(ctx, (grn_obj *)s);
+ }
+ }
+ GRN_API_RETURN((grn_obj *)s);
+
+exit:
+ if (s) {
+ if (s->specs) {
+ grn_ja_close(ctx, s->specs);
+ }
+ if (s->keys) {
+ if (s->keys->header.type == GRN_TABLE_PAT_KEY) {
+ grn_pat_close(ctx, (grn_pat *)s->keys);
+ } else {
+ grn_dat_close(ctx, (grn_dat *)s->keys);
}
- grn_tiny_array_fin(&s->values);
- GRN_FREE(s);
- } else {
- ERR(GRN_NO_MEMORY_AVAILABLE, "grn_db alloc failed");
}
- } else {
- ERR(GRN_INVALID_ARGUMENT, "inappropriate path");
+ grn_tiny_array_fin(&s->values);
+ CRITICAL_SECTION_FIN(s->lock);
+ GRN_FREE(s);
}
+
GRN_API_RETURN(NULL);
}
@@ -383,6 +484,7 @@ grn_db_close(grn_ctx *ctx, grn_obj *db)
}
CRITICAL_SECTION_FIN(s->lock);
if (s->specs) { grn_ja_close(ctx, s->specs); }
+ grn_hash_close(ctx, s->config);
GRN_FREE(s);
if (ctx_used_db) {
@@ -400,7 +502,6 @@ grn_db_close(grn_ctx *ctx, grn_obj *db)
grn_obj *
grn_ctx_get(grn_ctx *ctx, const char *name, int name_size)
{
- grn_id id;
grn_obj *obj = NULL;
grn_obj *db;
if (!ctx || !ctx->impl || !(db = ctx->impl->db)) {
@@ -409,12 +510,70 @@ grn_ctx_get(grn_ctx *ctx, const char *name, int name_size)
GRN_API_ENTER;
if (GRN_DB_P(db)) {
grn_db *s = (grn_db *)db;
+ grn_obj *alias_table = NULL;
+ grn_obj *alias_column = NULL;
+ grn_obj alias_name_buffer;
+
if (name_size < 0) {
name_size = strlen(name);
}
- if ((id = grn_table_get(ctx, s->keys, name, name_size))) {
- obj = grn_ctx_at(ctx, id);
+ GRN_TEXT_INIT(&alias_name_buffer, 0);
+ while (GRN_TRUE) {
+ grn_id id;
+
+ id = grn_table_get(ctx, s->keys, name, name_size);
+ if (id) {
+ obj = grn_ctx_at(ctx, id);
+ break;
+ }
+
+ if (!alias_column) {
+ grn_id alias_column_id;
+ const char *alias_column_name;
+ uint32_t alias_column_name_size;
+
+ grn_config_get(ctx,
+ "alias.column", -1,
+ &alias_column_name, &alias_column_name_size);
+ if (!alias_column_name) {
+ break;
+ }
+ alias_column_id = grn_table_get(ctx,
+ s->keys,
+ alias_column_name,
+ alias_column_name_size);
+ if (!alias_column_id) {
+ break;
+ }
+ alias_column = grn_ctx_at(ctx, alias_column_id);
+ if (alias_column->header.type != GRN_COLUMN_VAR_SIZE) {
+ break;
+ }
+ if (alias_column->header.flags & GRN_OBJ_VECTOR) {
+ break;
+ }
+ if (DB_OBJ(alias_column)->range != GRN_DB_SHORT_TEXT) {
+ break;
+ }
+ alias_table = grn_ctx_at(ctx, alias_column->header.domain);
+ if (alias_table->header.type == GRN_TABLE_NO_KEY) {
+ break;
+ }
+ }
+
+ {
+ grn_id alias_id;
+ alias_id = grn_table_get(ctx, alias_table, name, name_size);
+ if (!alias_id) {
+ break;
+ }
+ GRN_BULK_REWIND(&alias_name_buffer);
+ grn_obj_get_value(ctx, alias_column, alias_id, &alias_name_buffer);
+ name = GRN_TEXT_VALUE(&alias_name_buffer);
+ name_size = GRN_TEXT_LEN(&alias_name_buffer);
+ }
}
+ GRN_OBJ_FIN(ctx, &alias_name_buffer);
}
GRN_API_RETURN(obj);
}
@@ -431,55 +590,175 @@ grn_db_keys(grn_obj *s)
return (grn_obj *)(((grn_db *)s)->keys);
}
-static grn_io*
-grn_obj_io(grn_obj *obj)
+uint32_t
+grn_obj_get_last_modified(grn_ctx *ctx, grn_obj *obj)
{
- grn_io *io = NULL;
- if (obj) {
- if (obj->header.type == GRN_DB) { obj = ((grn_db *)obj)->keys; }
- switch (obj->header.type) {
- case GRN_TABLE_PAT_KEY :
- io = ((grn_pat *)obj)->io;
- break;
- case GRN_TABLE_DAT_KEY :
- io = ((grn_dat *)obj)->io;
- break;
- case GRN_TABLE_HASH_KEY :
- io = ((grn_hash *)obj)->io;
- break;
- case GRN_TABLE_NO_KEY :
- io = ((grn_array *)obj)->io;
- break;
- case GRN_COLUMN_VAR_SIZE :
- io = ((grn_ja *)obj)->io;
- break;
- case GRN_COLUMN_FIX_SIZE :
- io = ((grn_ra *)obj)->io;
- break;
- case GRN_COLUMN_INDEX :
- io = ((grn_ii *)obj)->seg;
- break;
- }
+ if (!obj) {
+ return 0;
+ }
+
+ return grn_obj_get_io(ctx, obj)->header->last_modified;
+}
+
+grn_bool
+grn_obj_is_dirty(grn_ctx *ctx, grn_obj *obj)
+{
+ if (!obj) {
+ return GRN_FALSE;
+ }
+
+ switch (obj->header.type) {
+ case GRN_DB :
+ return grn_db_is_dirty(ctx, obj);
+ case GRN_TABLE_PAT_KEY :
+ return grn_pat_is_dirty(ctx, (grn_pat *)obj);
+ case GRN_TABLE_DAT_KEY :
+ return grn_dat_is_dirty(ctx, (grn_dat *)obj);
+ default :
+ return GRN_FALSE;
}
- return io;
}
uint32_t
-grn_db_lastmod(grn_obj *s)
+grn_db_get_last_modified(grn_ctx *ctx, grn_obj *db)
+{
+ return grn_obj_get_last_modified(ctx, db);
+}
+
+grn_bool
+grn_db_is_dirty(grn_ctx *ctx, grn_obj *db)
+{
+ grn_obj *keys;
+
+ if (!db) {
+ return GRN_FALSE;
+ }
+
+ keys = ((grn_db *)db)->keys;
+ return grn_obj_is_dirty(ctx, keys);
+}
+
+static grn_rc
+grn_db_dirty(grn_ctx *ctx, grn_obj *db)
{
- return grn_obj_io(((grn_db *)s)->keys)->header->lastmod;
+ grn_obj *keys;
+
+ if (!db) {
+ return GRN_SUCCESS;
+ }
+
+ keys = ((grn_db *)db)->keys;
+ switch (keys->header.type) {
+ case GRN_TABLE_PAT_KEY :
+ return grn_pat_dirty(ctx, (grn_pat *)keys);
+ case GRN_TABLE_DAT_KEY :
+ return grn_dat_dirty(ctx, (grn_dat *)keys);
+ default :
+ return GRN_SUCCESS;
+ }
+}
+
+static grn_rc
+grn_db_clean(grn_ctx *ctx, grn_obj *db)
+{
+ grn_obj *keys;
+
+ if (!db) {
+ return GRN_SUCCESS;
+ }
+
+ keys = ((grn_db *)db)->keys;
+ switch (keys->header.type) {
+ case GRN_TABLE_PAT_KEY :
+ return grn_pat_clean(ctx, (grn_pat *)keys);
+ case GRN_TABLE_DAT_KEY :
+ return grn_dat_clean(ctx, (grn_dat *)keys);
+ default :
+ return GRN_SUCCESS;
+ }
+}
+
+static grn_rc
+grn_db_clear_dirty(grn_ctx *ctx, grn_obj *db)
+{
+ grn_obj *keys;
+
+ if (!db) {
+ return GRN_SUCCESS;
+ }
+
+ keys = ((grn_db *)db)->keys;
+ switch (keys->header.type) {
+ case GRN_TABLE_PAT_KEY :
+ return grn_pat_clear_dirty(ctx, (grn_pat *)keys);
+ case GRN_TABLE_DAT_KEY :
+ return grn_dat_clear_dirty(ctx, (grn_dat *)keys);
+ default :
+ return GRN_SUCCESS;
+ }
}
void
grn_db_touch(grn_ctx *ctx, grn_obj *s)
{
- grn_timeval tv;
- grn_timeval_now(ctx, &tv);
- grn_obj_io(s)->header->lastmod = tv.tv_sec;
+ grn_obj_touch(ctx, s, NULL);
+}
+
+grn_bool
+grn_obj_is_corrupt(grn_ctx *ctx, grn_obj *obj)
+{
+ grn_bool is_corrupt = GRN_FALSE;
+
+ GRN_API_ENTER;
+
+ if (!obj) {
+ ERR(GRN_INVALID_ARGUMENT, "[object][corrupt] object must not be NULL");
+ GRN_API_RETURN(GRN_FALSE);
+ }
+
+ switch (obj->header.type) {
+ case GRN_DB :
+ is_corrupt = grn_io_is_corrupt(ctx, grn_obj_get_io(ctx, obj));
+ if (!is_corrupt) {
+ is_corrupt = grn_io_is_corrupt(ctx, ((grn_db *)obj)->specs->io);
+ }
+ if (!is_corrupt) {
+ is_corrupt = grn_io_is_corrupt(ctx, ((grn_db *)obj)->config->io);
+ }
+ break;
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ is_corrupt = grn_io_is_corrupt(ctx, grn_obj_get_io(ctx, obj));
+ break;
+ case GRN_TABLE_DAT_KEY :
+ is_corrupt = grn_dat_is_corrupt(ctx, (grn_dat *)obj);
+ break;
+ case GRN_COLUMN_FIX_SIZE :
+ case GRN_COLUMN_VAR_SIZE :
+ is_corrupt = grn_io_is_corrupt(ctx, grn_obj_get_io(ctx, obj));
+ break;
+ case GRN_COLUMN_INDEX :
+ is_corrupt = grn_io_is_corrupt(ctx, ((grn_ii *)obj)->seg);
+ if (!is_corrupt) {
+ is_corrupt = grn_io_is_corrupt(ctx, ((grn_ii *)obj)->chunk);
+ }
+ break;
+ default :
+ break;
+ }
+
+ GRN_API_RETURN(is_corrupt);
}
#define IS_TEMP(obj) (DB_OBJ(obj)->id & GRN_OBJ_TMP_OBJECT)
+static inline void
+grn_obj_touch_db(grn_ctx *ctx, grn_obj *obj, grn_timeval *tv)
+{
+ grn_obj_get_io(ctx, obj)->header->last_modified = tv->tv_sec;
+ grn_db_dirty(ctx, obj);
+}
+
void
grn_obj_touch(grn_ctx *ctx, grn_obj *obj, grn_timeval *tv)
{
@@ -491,7 +770,7 @@ grn_obj_touch(grn_ctx *ctx, grn_obj *obj, grn_timeval *tv)
if (obj) {
switch (obj->header.type) {
case GRN_DB :
- grn_obj_io(obj)->header->lastmod = tv->tv_sec;
+ grn_obj_touch_db(ctx, obj, tv);
break;
case GRN_TABLE_HASH_KEY :
case GRN_TABLE_PAT_KEY :
@@ -501,7 +780,8 @@ grn_obj_touch(grn_ctx *ctx, grn_obj *obj, grn_timeval *tv)
case GRN_COLUMN_FIX_SIZE :
case GRN_COLUMN_INDEX :
if (!IS_TEMP(obj)) {
- grn_obj_io(DB_OBJ(obj)->db)->header->lastmod = tv->tv_sec;
+ grn_obj_get_io(ctx, obj)->header->last_modified = tv->tv_sec;
+ grn_obj_touch(ctx, DB_OBJ(obj)->db, tv);
}
break;
}
@@ -533,41 +813,6 @@ grn_db_check_name(grn_ctx *ctx, const char *name, unsigned int name_size)
return GRN_SUCCESS;
}
-grn_obj *
-grn_type_create(grn_ctx *ctx, const char *name, unsigned int name_size,
- grn_obj_flags flags, unsigned int size)
-{
- grn_id id;
- struct _grn_type *res = NULL;
- grn_obj *db;
- if (!ctx || !ctx->impl || !(db = ctx->impl->db)) {
- ERR(GRN_INVALID_ARGUMENT, "db not initialized");
- return NULL;
- }
- GRN_API_ENTER;
- if (grn_db_check_name(ctx, name, name_size)) {
- GRN_DB_CHECK_NAME_ERR("[type][create]", name, name_size);
- GRN_API_RETURN(NULL);
- }
- if (!GRN_DB_P(db)) {
- ERR(GRN_INVALID_ARGUMENT, "invalid db assigned");
- GRN_API_RETURN(NULL);
- }
- id = grn_obj_register(ctx, db, name, name_size);
- if (id && (res = GRN_MALLOC(sizeof(grn_db_obj)))) {
- GRN_DB_OBJ_SET_TYPE(res, GRN_TYPE);
- res->obj.header.flags = flags;
- res->obj.header.domain = GRN_ID_NIL;
- GRN_TYPE_SIZE(&res->obj) = size;
- if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) {
- // grn_obj_delete(ctx, db, id);
- GRN_FREE(res);
- GRN_API_RETURN(NULL);
- }
- }
- GRN_API_RETURN((grn_obj *)res);
-}
-
static grn_obj *
grn_type_open(grn_ctx *ctx, grn_obj_spec *spec)
{
@@ -591,12 +836,13 @@ grn_proc_create(grn_ctx *ctx, const char *name, int name_size, grn_proc_type typ
grn_id range = GRN_ID_NIL;
int added = 0;
grn_obj *db;
- const char *path = ctx->impl->plugin_path;
+ const char *path;
if (!ctx || !ctx->impl || !(db = ctx->impl->db)) {
ERR(GRN_INVALID_ARGUMENT, "db not initialized");
return NULL;
}
GRN_API_ENTER;
+ path = ctx->impl->plugin_path;
if (path) {
range = grn_plugin_reference(ctx, path);
}
@@ -653,8 +899,9 @@ grn_proc_create(grn_ctx *ctx, const char *name, int name_size, grn_proc_type typ
res->funcs[PROC_INIT] = init;
res->funcs[PROC_NEXT] = next;
res->funcs[PROC_FIN] = fin;
- res->selector = NULL;
memset(&(res->callbacks), 0, sizeof(res->callbacks));
+ res->callbacks.function.selector_op = GRN_OP_NOP;
+ res->callbacks.function.is_stable = GRN_TRUE;
GRN_TEXT_INIT(&res->name_buf, 0);
res->vars = NULL;
res->nvars = 0;
@@ -678,7 +925,7 @@ grn_proc_create(grn_ctx *ctx, const char *name, int name_size, grn_proc_type typ
/* grn_table */
static void
-calc_rec_size(grn_obj_flags flags, uint32_t max_n_subrecs, uint32_t range_size,
+calc_rec_size(grn_table_flags flags, uint32_t max_n_subrecs, uint32_t range_size,
uint32_t additional_value_size,
uint8_t *subrec_size, uint8_t *subrec_offset,
uint32_t *key_size, uint32_t *value_size)
@@ -726,56 +973,94 @@ calc_rec_size(grn_obj_flags flags, uint32_t max_n_subrecs, uint32_t range_size,
*value_size += additional_value_size;
}
-static void _grn_obj_remove(grn_ctx *ctx, grn_obj *obj);
+static grn_rc _grn_obj_remove(grn_ctx *ctx, grn_obj *obj, grn_bool dependent);
static grn_rc
grn_table_create_validate(grn_ctx *ctx, const char *name, unsigned int name_size,
- const char *path, grn_obj_flags flags,
+ const char *path, grn_table_flags flags,
grn_obj *key_type, grn_obj *value_type)
{
- switch (flags & GRN_OBJ_TABLE_TYPE_MASK) {
+ grn_table_flags table_type;
+ const char *table_type_name = NULL;
+
+ table_type = (flags & GRN_OBJ_TABLE_TYPE_MASK);
+ switch (table_type) {
case GRN_OBJ_TABLE_HASH_KEY :
- if (flags & GRN_OBJ_KEY_WITH_SIS) {
- ERR(GRN_INVALID_ARGUMENT,
- "[table][create] "
- "key with SIS isn't available for hash table: <%.*s>",
- name_size, name);
- }
+ table_type_name = "TABLE_HASH_KEY";
break;
case GRN_OBJ_TABLE_PAT_KEY :
+ table_type_name = "TABLE_PAT_KEY";
break;
case GRN_OBJ_TABLE_DAT_KEY :
+ table_type_name = "TABLE_DAT_KEY";
break;
case GRN_OBJ_TABLE_NO_KEY :
- if (key_type) {
- int key_name_size;
- char key_name[GRN_TABLE_MAX_KEY_SIZE];
- key_name_size = grn_obj_name(ctx, key_type, key_name,
- GRN_TABLE_MAX_KEY_SIZE);
- ERR(GRN_INVALID_ARGUMENT,
- "[table][create] "
- "key isn't available for no key table: <%.*s> (%.*s)",
- name_size, name, key_name_size, key_name);
- } else if (flags & GRN_OBJ_KEY_WITH_SIS) {
- ERR(GRN_INVALID_ARGUMENT,
- "[table][create] "
- "key with SIS isn't available for no key table: <%.*s>",
- name_size, name);
- } else if (flags & GRN_OBJ_KEY_NORMALIZE) {
- ERR(GRN_INVALID_ARGUMENT,
- "[table][create] "
- "key normalization isn't available for no key table: <%.*s>",
- name_size, name);
- }
+ table_type_name = "TABLE_NO_KEY";
+ break;
+ default :
+ table_type_name = "unknown";
break;
}
+
+ if (!key_type && table_type != GRN_OBJ_TABLE_NO_KEY &&
+ !(flags & GRN_OBJ_KEY_VAR_SIZE)) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[table][create] "
+ "key type is required for TABLE_HASH_KEY, TABLE_PAT_KEY or "
+ "TABLE_DAT_KEY: <%.*s>", name_size, name);
+ return ctx->rc;
+ }
+
+ if (key_type && table_type == GRN_OBJ_TABLE_NO_KEY) {
+ int key_name_size;
+ char key_name[GRN_TABLE_MAX_KEY_SIZE];
+ key_name_size = grn_obj_name(ctx, key_type, key_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ ERR(GRN_INVALID_ARGUMENT,
+ "[table][create] "
+ "key isn't available for TABLE_NO_KEY table: <%.*s> (%.*s)",
+ name_size, name, key_name_size, key_name);
+ return ctx->rc;
+ }
+
+ if ((flags & GRN_OBJ_KEY_WITH_SIS) &&
+ table_type != GRN_OBJ_TABLE_PAT_KEY) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[table][create] "
+ "key with SIS is available only for TABLE_PAT_KEY table: "
+ "<%.*s>(%s)",
+ name_size, name,
+ table_type_name);
+ return ctx->rc;
+ }
+
+ if ((flags & GRN_OBJ_KEY_NORMALIZE) &&
+ table_type == GRN_OBJ_TABLE_NO_KEY) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[table][create] "
+ "key normalization isn't available for TABLE_NO_KEY table: <%.*s>",
+ name_size, name);
+ return ctx->rc;
+ }
+
+ if ((flags & GRN_OBJ_KEY_LARGE) &&
+ table_type != GRN_OBJ_TABLE_HASH_KEY) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[table][create] "
+ "large key support is available only for TABLE_HASH_KEY key table: "
+ "<%.*s>(%s)",
+ name_size, name,
+ table_type_name);
+ return ctx->rc;
+ }
+
return ctx->rc;
}
static grn_obj *
grn_table_create_with_max_n_subrecs(grn_ctx *ctx, const char *name,
unsigned int name_size, const char *path,
- grn_obj_flags flags, grn_obj *key_type,
+ grn_table_flags flags, grn_obj *key_type,
grn_obj *value_type,
uint32_t max_n_subrecs,
uint32_t additional_value_size)
@@ -890,10 +1175,11 @@ grn_table_create_with_max_n_subrecs(grn_ctx *ctx, const char *name,
id = grn_obj_register(ctx, db, name, name_size);
if (ERRP(ctx, GRN_ERROR)) { return NULL; }
if (GRN_OBJ_PERSISTENT & flags) {
- GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:table_create %.*s", name_size, name);
+ GRN_LOG(ctx, GRN_LOG_NOTICE,
+ "DDL:%u:table_create %.*s", id, name_size, name);
if (!path) {
if (GRN_DB_PERSISTENT_P(db)) {
- gen_pathname(grn_obj_io(db)->path, buffer, id);
+ grn_db_generate_pathname(ctx, db, id, buffer);
path = buffer;
} else {
ERR(GRN_INVALID_ARGUMENT, "path not assigned for persistent table");
@@ -941,7 +1227,7 @@ grn_table_create_with_max_n_subrecs(grn_ctx *ctx, const char *name,
DB_OBJ(res)->subrec_offset = subrec_offset;
DB_OBJ(res)->flags.group = 0;
if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) {
- _grn_obj_remove(ctx, res);
+ _grn_obj_remove(ctx, res, GRN_FALSE);
res = NULL;
}
} else {
@@ -952,7 +1238,7 @@ grn_table_create_with_max_n_subrecs(grn_ctx *ctx, const char *name,
grn_obj *
grn_table_create(grn_ctx *ctx, const char *name, unsigned int name_size,
- const char *path, grn_obj_flags flags,
+ const char *path, grn_table_flags flags,
grn_obj *key_type, grn_obj *value_type)
{
grn_obj *res;
@@ -1123,19 +1409,8 @@ grn_table_lcp_search(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int
GRN_API_RETURN(id);
}
-typedef struct {
- grn_id target;
- unsigned int section;
-} default_set_value_hook_data;
-
-struct _grn_hook {
- grn_hook *next;
- grn_proc *proc;
- uint32_t hld_size;
-};
-
-static grn_obj *
-default_set_value_hook(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
+grn_obj *
+grn_obj_default_set_value_hook(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
{
grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
if (!pctx) {
@@ -1146,7 +1421,7 @@ default_set_value_hook(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *u
grn_obj *oldvalue = grn_ctx_pop(ctx);
grn_obj *id = grn_ctx_pop(ctx);
grn_hook *h = pctx->currh;
- default_set_value_hook_data *data = (void *)NEXT_ADDR(h);
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(h);
grn_obj *target = grn_ctx_at(ctx, data->target);
int section = data->section;
if (flags) { /* todo */ }
@@ -1265,7 +1540,7 @@ grn_table_add(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_si
if (hooks->proc) {
hooks->proc->funcs[PROC_INIT](ctx, 1, &table, &pctx.user_data);
} else {
- default_set_value_hook(ctx, 1, &table, &pctx.user_data);
+ grn_obj_default_set_value_hook(ctx, 1, &table, &pctx.user_data);
}
if (ctx->rc) { break; }
hooks = hooks->next;
@@ -1288,7 +1563,8 @@ grn_table_get_by_key(grn_ctx *ctx, grn_obj *table, grn_obj *key)
grn_obj buf;
GRN_OBJ_INIT(&buf, GRN_BULK, 0, table->header.domain);
if ((rc = grn_obj_cast(ctx, key, &buf, GRN_TRUE))) {
- ERR(rc, "cast failed");
+ grn_obj *domain = grn_ctx_at(ctx, table->header.domain);
+ ERR_CAST(table, domain, key);
} else {
id = grn_table_get(ctx, table, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf));
}
@@ -1308,7 +1584,8 @@ grn_table_add_by_key(grn_ctx *ctx, grn_obj *table, grn_obj *key, int *added)
grn_obj buf;
GRN_OBJ_INIT(&buf, GRN_BULK, 0, table->header.domain);
if ((rc = grn_obj_cast(ctx, key, &buf, GRN_TRUE))) {
- ERR(rc, "cast failed");
+ grn_obj *domain = grn_ctx_at(ctx, table->header.domain);
+ ERR_CAST(table, domain, key);
} else {
id = grn_table_add(ctx, table, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf), added);
}
@@ -1454,6 +1731,9 @@ grn_table_get_key(grn_ctx *ctx, grn_obj *table, grn_id id, void *keybuf, int buf
int r = 0;
GRN_API_ENTER;
if (table) {
+ if (table->header.type == GRN_DB) {
+ table = ((grn_db *)table)->keys;
+ }
switch (table->header.type) {
case GRN_TABLE_HASH_KEY :
r = grn_hash_get_key(ctx, (grn_hash *)table, id, keybuf, buf_size);
@@ -1487,6 +1767,9 @@ grn_table_get_key2(grn_ctx *ctx, grn_obj *table, grn_id id, grn_obj *bulk)
int r = 0;
GRN_API_ENTER;
if (table) {
+ if (table->header.type == GRN_DB) {
+ table = ((grn_db *)table)->keys;
+ }
switch (table->header.type) {
case GRN_TABLE_HASH_KEY :
r = grn_hash_get_key2(ctx, (grn_hash *)table, id, bulk);
@@ -1558,7 +1841,7 @@ call_delete_hook(grn_ctx *ctx, grn_obj *table, grn_id rid, const void *key, unsi
if (hooks->proc) {
hooks->proc->funcs[PROC_INIT](ctx, 1, &table, &pctx.user_data);
} else {
- default_set_value_hook(ctx, 1, &table, &pctx.user_data);
+ grn_obj_default_set_value_hook(ctx, 1, &table, &pctx.user_data);
}
if (ctx->rc) { break; }
hooks = hooks->next;
@@ -1593,7 +1876,7 @@ delete_reference_records_in_index(grn_ctx *ctx, grn_obj *table, grn_id id,
{
grn_ii *ii = (grn_ii *)index;
grn_ii_cursor *ii_cursor = NULL;
- grn_ii_posting *posting;
+ grn_posting *posting;
grn_obj source_ids;
unsigned int i, n_ids;
grn_obj sources;
@@ -1733,11 +2016,9 @@ delete_reference_records(grn_ctx *ctx, grn_obj *table, grn_id id)
continue;
}
if (col->header.type != GRN_COLUMN_INDEX) {
- grn_obj_unlink(ctx, col);
continue;
}
delete_reference_records_in_index(ctx, table, id, col);
- grn_obj_unlink(ctx, col);
if (ctx->rc != GRN_SUCCESS) {
break;
}
@@ -1874,7 +2155,7 @@ grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id)
grn_rc rc;
grn_io *io;
GRN_API_ENTER;
- if ((io = grn_obj_io(table)) && !(io->flags & GRN_IO_TEMPORARY)) {
+ if ((io = grn_obj_get_io(ctx, table)) && !(io->flags & GRN_IO_TEMPORARY)) {
if (!(rc = grn_io_lock(ctx, io, grn_lock_timeout))) {
rc = _grn_table_delete_by_id(ctx, table, id, NULL);
grn_io_unlock(io);
@@ -1888,7 +2169,6 @@ grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id)
GRN_API_RETURN(rc);
}
-grn_rc grn_ii_truncate(grn_ctx *ctx, grn_ii *ii);
grn_rc grn_ja_truncate(grn_ctx *ctx, grn_ja *ja);
grn_rc grn_ra_truncate(grn_ctx *ctx, grn_ra *ra);
@@ -1905,7 +2185,7 @@ grn_column_truncate(grn_ctx *ctx, grn_obj *column)
break;
case GRN_COLUMN_VAR_SIZE :
for (hooks = DB_OBJ(column)->hooks[GRN_HOOK_SET]; hooks; hooks = hooks->next) {
- default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks);
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
grn_obj *target = grn_ctx_at(ctx, data->target);
if (target->header.type != GRN_COLUMN_INDEX) { continue; }
if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; }
@@ -1914,7 +2194,7 @@ grn_column_truncate(grn_ctx *ctx, grn_obj *column)
break;
case GRN_COLUMN_FIX_SIZE :
for (hooks = DB_OBJ(column)->hooks[GRN_HOOK_SET]; hooks; hooks = hooks->next) {
- default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks);
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
grn_obj *target = grn_ctx_at(ctx, data->target);
if (target->header.type != GRN_COLUMN_INDEX) { continue; }
if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; }
@@ -1960,7 +2240,7 @@ grn_table_truncate(grn_ctx *ctx, grn_obj *table)
switch (table->header.type) {
case GRN_TABLE_PAT_KEY :
for (hooks = DB_OBJ(table)->hooks[GRN_HOOK_INSERT]; hooks; hooks = hooks->next) {
- default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks);
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
grn_obj *target = grn_ctx_at(ctx, data->target);
if (target->header.type != GRN_COLUMN_INDEX) { continue; }
if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; }
@@ -1969,7 +2249,7 @@ grn_table_truncate(grn_ctx *ctx, grn_obj *table)
break;
case GRN_TABLE_DAT_KEY :
for (hooks = DB_OBJ(table)->hooks[GRN_HOOK_INSERT]; hooks; hooks = hooks->next) {
- default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks);
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
grn_obj *target = grn_ctx_at(ctx, data->target);
if (target->header.type != GRN_COLUMN_INDEX) { continue; }
if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; }
@@ -1978,7 +2258,7 @@ grn_table_truncate(grn_ctx *ctx, grn_obj *table)
break;
case GRN_TABLE_HASH_KEY :
for (hooks = DB_OBJ(table)->hooks[GRN_HOOK_INSERT]; hooks; hooks = hooks->next) {
- default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks);
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
grn_obj *target = grn_ctx_at(ctx, data->target);
if (target->header.type != GRN_COLUMN_INDEX) { continue; }
if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; }
@@ -2004,7 +2284,7 @@ exit :
}
grn_rc
-grn_table_get_info(grn_ctx *ctx, grn_obj *table, grn_obj_flags *flags,
+grn_table_get_info(grn_ctx *ctx, grn_obj *table, grn_table_flags *flags,
grn_encoding *encoding, grn_obj **tokenizer,
grn_obj **normalizer,
grn_obj **token_filters)
@@ -2014,7 +2294,7 @@ grn_table_get_info(grn_ctx *ctx, grn_obj *table, grn_obj_flags *flags,
if (table) {
switch (table->header.type) {
case GRN_TABLE_PAT_KEY :
- if (flags) { *flags = ((grn_pat *)table)->obj.header.flags; }
+ if (flags) { *flags = ((grn_pat *)table)->header->flags; }
if (encoding) { *encoding = ((grn_pat *)table)->encoding; }
if (tokenizer) { *tokenizer = ((grn_pat *)table)->tokenizer; }
if (normalizer) { *normalizer = ((grn_pat *)table)->normalizer; }
@@ -2022,7 +2302,7 @@ grn_table_get_info(grn_ctx *ctx, grn_obj *table, grn_obj_flags *flags,
rc = GRN_SUCCESS;
break;
case GRN_TABLE_DAT_KEY :
- if (flags) { *flags = ((grn_dat *)table)->obj.header.flags; }
+ if (flags) { *flags = ((grn_dat *)table)->header->flags; }
if (encoding) { *encoding = ((grn_dat *)table)->encoding; }
if (tokenizer) { *tokenizer = ((grn_dat *)table)->tokenizer; }
if (normalizer) { *normalizer = ((grn_dat *)table)->normalizer; }
@@ -2030,7 +2310,7 @@ grn_table_get_info(grn_ctx *ctx, grn_obj *table, grn_obj_flags *flags,
rc = GRN_SUCCESS;
break;
case GRN_TABLE_HASH_KEY :
- if (flags) { *flags = ((grn_hash *)table)->obj.header.flags; }
+ if (flags) { *flags = ((grn_hash *)table)->header.common->flags; }
if (encoding) { *encoding = ((grn_hash *)table)->encoding; }
if (tokenizer) { *tokenizer = ((grn_hash *)table)->tokenizer; }
if (normalizer) { *normalizer = ((grn_hash *)table)->normalizer; }
@@ -2038,9 +2318,9 @@ grn_table_get_info(grn_ctx *ctx, grn_obj *table, grn_obj_flags *flags,
rc = GRN_SUCCESS;
break;
case GRN_TABLE_NO_KEY :
- if (flags) { *flags = 0; }
+ if (flags) { *flags = grn_array_get_flags(ctx, ((grn_array *)table)); }
if (encoding) { *encoding = GRN_ENC_NONE; }
- if (tokenizer) { *tokenizer = grn_tokenizer_uvector; }
+ if (tokenizer) { *tokenizer = NULL; }
if (normalizer) { *normalizer = NULL; }
if (token_filters) { *token_filters = NULL; }
rc = GRN_SUCCESS;
@@ -2067,10 +2347,10 @@ grn_table_size(grn_ctx *ctx, grn_obj *table)
n = grn_dat_size(ctx, (grn_dat *)table);
break;
case GRN_TABLE_HASH_KEY :
- n = GRN_HASH_SIZE((grn_hash *)table);
+ n = grn_hash_size(ctx, (grn_hash *)table);
break;
case GRN_TABLE_NO_KEY :
- n = GRN_ARRAY_SIZE((grn_array *)table);
+ n = grn_array_size(ctx, (grn_array *)table);
break;
default :
ERR(GRN_INVALID_ARGUMENT, "not supported");
@@ -2185,12 +2465,12 @@ grn_table_cursor_open(grn_ctx *ctx, grn_obj *table,
"can't use negative offset with GRN_CURSOR_PREFIX: %d", offset);
} else if (offset != 0 && offset >= table_size) {
ERR(GRN_TOO_LARGE_OFFSET,
- "offset is rather than table size: offset:%d, table_size:%d",
+ "offset is not less than table size: offset:%d, table_size:%d",
offset, table_size);
} else {
if (limit < -1) {
ERR(GRN_TOO_SMALL_LIMIT,
- "can't use small limit rather than -1 with GRN_CURSOR_PREFIX: %d",
+ "can't use smaller limit than -1 with GRN_CURSOR_PREFIX: %d",
limit);
} else if (limit == -1) {
limit = table_size;
@@ -2298,11 +2578,12 @@ grn_table_cursor_open_by_id(grn_ctx *ctx, grn_obj *table,
grn_rc
grn_table_cursor_close(grn_ctx *ctx, grn_table_cursor *tc)
{
+ const char *tag = "[table][cursor][close]";
grn_rc rc = GRN_SUCCESS;
GRN_API_ENTER;
if (!tc) {
- ERR(GRN_INVALID_ARGUMENT, "tc is null");
rc = GRN_INVALID_ARGUMENT;
+ ERR(rc, "%s invalid cursor", tag);
} else {
{
if (DB_OBJ(tc)->finalizer) {
@@ -2334,6 +2615,7 @@ grn_table_cursor_close(grn_ctx *ctx, grn_table_cursor *tc)
break;
default :
rc = GRN_INVALID_ARGUMENT;
+ ERR(rc, "%s invalid type %d", tag, tc->header.type);
break;
}
}
@@ -2343,9 +2625,10 @@ grn_table_cursor_close(grn_ctx *ctx, grn_table_cursor *tc)
inline static grn_id
grn_table_cursor_next_inline(grn_ctx *ctx, grn_table_cursor *tc)
{
+ const char *tag = "[table][cursor][next]";
grn_id id = GRN_ID_NIL;
if (!tc) {
- ERR(GRN_INVALID_ARGUMENT, "tc is null");
+ ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor", tag);
} else {
switch (tc->header.type) {
case GRN_CURSOR_TABLE_PAT_KEY :
@@ -2366,6 +2649,9 @@ grn_table_cursor_next_inline(grn_ctx *ctx, grn_table_cursor *tc)
if (ip) { id = ip->rid; }
}
break;
+ default :
+ ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d", tag, tc->header.type);
+ break;
}
}
return id;
@@ -2383,10 +2669,11 @@ grn_table_cursor_next(grn_ctx *ctx, grn_table_cursor *tc)
int
grn_table_cursor_get_key(grn_ctx *ctx, grn_table_cursor *tc, void **key)
{
+ const char *tag = "[table][cursor][get-key]";
int len = 0;
GRN_API_ENTER;
if (!tc) {
- ERR(GRN_INVALID_ARGUMENT, "tc is null");
+ ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor", tag);
} else {
switch (tc->header.type) {
case GRN_CURSOR_TABLE_PAT_KEY :
@@ -2399,7 +2686,7 @@ grn_table_cursor_get_key(grn_ctx *ctx, grn_table_cursor *tc, void **key)
len = grn_hash_cursor_get_key(ctx, (grn_hash_cursor *)tc, key);
break;
default :
- ERR(GRN_INVALID_ARGUMENT, "invalid type %d", tc->header.type);
+ ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d", tag, tc->header.type);
break;
}
}
@@ -2409,9 +2696,10 @@ grn_table_cursor_get_key(grn_ctx *ctx, grn_table_cursor *tc, void **key)
inline static int
grn_table_cursor_get_value_inline(grn_ctx *ctx, grn_table_cursor *tc, void **value)
{
+ const char *tag = "[table][cursor][get-value]";
int len = 0;
if (!tc) {
- ERR(GRN_INVALID_ARGUMENT, "tc is null");
+ ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor", tag);
} else {
switch (tc->header.type) {
case GRN_CURSOR_TABLE_PAT_KEY :
@@ -2428,7 +2716,7 @@ grn_table_cursor_get_value_inline(grn_ctx *ctx, grn_table_cursor *tc, void **val
len = grn_array_cursor_get_value(ctx, (grn_array_cursor *)tc, value);
break;
default :
- ERR(GRN_INVALID_ARGUMENT, "invalid type %d", tc->header.type);
+ ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d", tag, tc->header.type);
break;
}
}
@@ -2448,10 +2736,11 @@ grn_rc
grn_table_cursor_set_value(grn_ctx *ctx, grn_table_cursor *tc,
const void *value, int flags)
{
+ const char *tag = "[table][cursor][set-value]";
grn_rc rc = GRN_INVALID_ARGUMENT;
GRN_API_ENTER;
if (!tc) {
- ERR(GRN_INVALID_ARGUMENT, "tc is null");
+ ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor", tag);
} else {
switch (tc->header.type) {
case GRN_CURSOR_TABLE_PAT_KEY :
@@ -2467,7 +2756,7 @@ grn_table_cursor_set_value(grn_ctx *ctx, grn_table_cursor *tc,
rc = grn_array_cursor_set_value(ctx, (grn_array_cursor *)tc, value, flags);
break;
default :
- ERR(GRN_INVALID_ARGUMENT, "invalid type %d", tc->header.type);
+ ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d", tag, tc->header.type);
break;
}
}
@@ -2477,10 +2766,11 @@ grn_table_cursor_set_value(grn_ctx *ctx, grn_table_cursor *tc,
grn_rc
grn_table_cursor_delete(grn_ctx *ctx, grn_table_cursor *tc)
{
+ const char *tag = "[table][cursor][delete]";
grn_rc rc = GRN_INVALID_ARGUMENT;
GRN_API_ENTER;
if (!tc) {
- ERR(GRN_INVALID_ARGUMENT, "tc is null");
+ ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor", tag);
} else {
grn_id id;
grn_obj *table;
@@ -2529,7 +2819,7 @@ grn_table_cursor_delete(grn_ctx *ctx, grn_table_cursor *tc)
}
break;
default :
- ERR(GRN_INVALID_ARGUMENT, "invalid type %d", tc->header.type);
+ ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d", tag, tc->header.type);
break;
}
}
@@ -2540,10 +2830,11 @@ exit :
grn_obj *
grn_table_cursor_table(grn_ctx *ctx, grn_table_cursor *tc)
{
+ const char *tag = "[table][cursor][table]";
grn_obj *obj = NULL;
GRN_API_ENTER;
if (!tc) {
- ERR(GRN_INVALID_ARGUMENT, "tc is null");
+ ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor", tag);
} else {
switch (tc->header.type) {
case GRN_CURSOR_TABLE_PAT_KEY :
@@ -2559,7 +2850,7 @@ grn_table_cursor_table(grn_ctx *ctx, grn_table_cursor *tc)
obj = (grn_obj *)(((grn_array_cursor *)tc)->array);
break;
default :
- ERR(GRN_INVALID_ARGUMENT, "invalid type %d", tc->header.type);
+ ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d", tag, tc->header.type);
break;
}
}
@@ -2605,7 +2896,7 @@ grn_index_cursor_open(grn_ctx *ctx, grn_table_cursor *tc,
grn_posting *
grn_index_cursor_next(grn_ctx *ctx, grn_obj *c, grn_id *tid)
{
- grn_ii_posting *ip = NULL;
+ grn_posting *ip = NULL;
grn_index_cursor *ic = (grn_index_cursor *)c;
GRN_API_ENTER;
if (ic->iic) {
@@ -2764,6 +3055,44 @@ grn_table_search(grn_ctx *ctx, grn_obj *table, const void *key, uint32_t key_siz
GRN_API_RETURN(rc);
}
+grn_rc
+grn_table_fuzzy_search(grn_ctx *ctx, grn_obj *table, const void *key, uint32_t key_size,
+ grn_fuzzy_search_optarg *args, grn_obj *res, grn_operator op)
+{
+ grn_rc rc = GRN_SUCCESS;
+ GRN_API_ENTER;
+ switch (table->header.type) {
+ case GRN_TABLE_PAT_KEY :
+ {
+ grn_pat *pat = (grn_pat *)table;
+ if (!grn_table_size(ctx, res) && op == GRN_OP_OR) {
+ WITH_NORMALIZE(pat, key, key_size, {
+ rc = grn_pat_fuzzy_search(ctx, pat, key, key_size,
+ args, (grn_hash *)res);
+ });
+ } else {
+ grn_obj *hash;
+ hash = grn_table_create(ctx, NULL, 0, NULL,
+ GRN_OBJ_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC,
+ table, NULL);
+ WITH_NORMALIZE(pat, key, key_size, {
+ rc = grn_pat_fuzzy_search(ctx, pat, key, key_size,
+ args, (grn_hash *)hash);
+ });
+ if (rc == GRN_SUCCESS) {
+ rc = grn_table_setoperation(ctx, res, hash, res, op);
+ }
+ grn_obj_unlink(ctx, hash);
+ }
+ }
+ break;
+ default :
+ rc = GRN_OPERATION_NOT_SUPPORTED;
+ break;
+ }
+ GRN_API_RETURN(rc);
+}
+
grn_id
grn_table_next(grn_ctx *ctx, grn_obj *table, grn_id id)
{
@@ -2790,8 +3119,7 @@ grn_table_next(grn_ctx *ctx, grn_obj *table, grn_id id)
static grn_rc
grn_accessor_resolve_one_index_column(grn_ctx *ctx, grn_accessor *accessor,
- grn_obj *current_res, grn_obj **next_res,
- grn_search_optarg *optarg)
+ grn_obj *current_res, grn_obj **next_res)
{
grn_rc rc = GRN_SUCCESS;
grn_obj *column = NULL;
@@ -2842,7 +3170,7 @@ grn_accessor_resolve_one_index_column(grn_ctx *ctx, grn_accessor *accessor,
{
grn_obj_flags column_value_flags = 0;
grn_obj column_value;
- grn_ii_posting add_posting;
+ grn_posting add_posting;
grn_id *tid;
grn_rset_recinfo *recinfo;
@@ -2893,21 +3221,121 @@ grn_accessor_resolve_one_index_column(grn_ctx *ctx, grn_accessor *accessor,
}
static grn_rc
+grn_accessor_resolve_one_table(grn_ctx *ctx, grn_accessor *accessor,
+ grn_obj *current_res, grn_obj **next_res)
+{
+ grn_rc rc = GRN_SUCCESS;
+ grn_obj *table;
+
+ table = accessor->obj;
+ *next_res = grn_table_create(ctx, NULL, 0, NULL,
+ GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC,
+ table, NULL);
+ if (!*next_res) {
+ return ctx->rc;
+ }
+
+ grn_report_table(ctx,
+ "[accessor][resolve]",
+ "",
+ table);
+
+ {
+ grn_posting posting;
+
+ memset(&posting, 0, sizeof(posting));
+ GRN_HASH_EACH_BEGIN(ctx, (grn_hash *)current_res, cursor, id) {
+ void *key;
+ void *value;
+ grn_id *record_id;
+ grn_rset_recinfo *recinfo;
+ grn_id next_record_id;
+
+ grn_hash_cursor_get_key_value(ctx, cursor, &key, NULL, &value);
+ record_id = key;
+ recinfo = value;
+ next_record_id = grn_table_get(ctx,
+ table,
+ record_id,
+ sizeof(grn_id));
+ if (next_record_id == GRN_ID_NIL) {
+ continue;
+ }
+
+ posting.rid = next_record_id;
+ posting.weight = recinfo->score;
+ rc = grn_ii_posting_add(ctx,
+ &posting,
+ (grn_hash *)*next_res,
+ GRN_OP_OR);
+ if (rc != GRN_SUCCESS) {
+ break;
+ }
+ } GRN_HASH_EACH_END(ctx, cursor);
+ }
+
+ if (rc != GRN_SUCCESS) {
+ grn_obj_unlink(ctx, *next_res);
+ }
+
+ return rc;
+}
+
+static grn_rc
grn_accessor_resolve_one_data_column(grn_ctx *ctx, grn_accessor *accessor,
- grn_obj *current_res, grn_obj **next_res,
- grn_search_optarg *optarg)
+ grn_obj *current_res, grn_obj **next_res)
{
grn_rc rc = GRN_SUCCESS;
- grn_obj *index = NULL;
- grn_operator index_op = GRN_OP_MATCH;
+ grn_index_datum index_datum;
+ unsigned int n_index_data;
grn_id next_res_domain_id = GRN_ID_NIL;
- if (grn_column_index(ctx, accessor->obj, index_op, &index, 1, NULL) == 0) {
+ n_index_data = grn_column_get_all_index_data(ctx,
+ accessor->obj,
+ &index_datum,
+ 1);
+ if (n_index_data == 0) {
return GRN_INVALID_ARGUMENT;
}
- next_res_domain_id = DB_OBJ(index)->range;
{
+ grn_obj *lexicon;
+ lexicon = grn_ctx_at(ctx, index_datum.index->header.domain);
+ if (grn_obj_id(ctx, lexicon) != current_res->header.domain) {
+ char index_name[GRN_TABLE_MAX_KEY_SIZE];
+ int index_name_size;
+ grn_obj *expected;
+ char expected_name[GRN_TABLE_MAX_KEY_SIZE];
+ int expected_name_size;
+
+ index_name_size = grn_obj_name(ctx,
+ index_datum.index,
+ index_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ expected = grn_ctx_at(ctx, current_res->header.domain);
+ expected_name_size = grn_obj_name(ctx,
+ expected,
+ expected_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ ERR(GRN_INVALID_ARGUMENT,
+ "[accessor][resolve][data-column] lexicon mismatch index: "
+ "<%.*s> "
+ "expected:<%.*s>",
+ index_name_size,
+ index_name,
+ expected_name_size,
+ expected_name);
+ return ctx->rc;
+ }
+ }
+
+ next_res_domain_id = DB_OBJ(index_datum.index)->range;
+
+ grn_report_index(ctx,
+ "[accessor][resolve][data-column]",
+ "",
+ index_datum.index);
+ {
grn_rc rc;
grn_obj *next_res_domain = grn_ctx_at(ctx, next_res_domain_id);
*next_res = grn_table_create(ctx, NULL, 0, NULL,
@@ -2925,9 +3353,9 @@ grn_accessor_resolve_one_data_column(grn_ctx *ctx, grn_accessor *accessor,
grn_rset_recinfo *recinfo;
GRN_HASH_EACH(ctx, (grn_hash *)current_res, id, &tid, NULL, &recinfo, {
- grn_ii *ii = (grn_ii *)index;
+ grn_ii *ii = (grn_ii *)(index_datum.index);
grn_ii_cursor *ii_cursor;
- grn_ii_posting *posting;
+ grn_posting *posting;
ii_cursor = grn_ii_cursor_open(ctx, ii, *tid,
GRN_ID_NIL, GRN_ID_MAX,
@@ -2938,7 +3366,13 @@ grn_accessor_resolve_one_data_column(grn_ctx *ctx, grn_accessor *accessor,
}
while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) {
- grn_ii_posting add_posting = *posting;
+ grn_posting add_posting;
+
+ if (index_datum.section > 0 && posting->sid != index_datum.section) {
+ continue;
+ }
+
+ add_posting = *posting;
add_posting.weight += recinfo->score - 1;
rc = grn_ii_posting_add(ctx,
&add_posting,
@@ -2965,8 +3399,8 @@ grn_accessor_resolve_one_data_column(grn_ctx *ctx, grn_accessor *accessor,
grn_rc
grn_accessor_resolve(grn_ctx *ctx, grn_obj *accessor, int deep,
- grn_obj *base_res, grn_obj **res,
- grn_search_optarg *optarg)
+ grn_obj *base_res, grn_obj *res,
+ grn_operator op)
{
grn_rc rc = GRN_SUCCESS;
grn_accessor *a;
@@ -2990,12 +3424,13 @@ grn_accessor_resolve(grn_ctx *ctx, grn_obj *accessor, int deep,
a = (grn_accessor *)GRN_PTR_VALUE_AT(&accessor_stack, i - 1);
if (a->obj->header.type == GRN_COLUMN_INDEX) {
rc = grn_accessor_resolve_one_index_column(ctx, a,
- current_res, &next_res,
- optarg);
+ current_res, &next_res);
+ } else if (grn_obj_is_table(ctx, a->obj)) {
+ rc = grn_accessor_resolve_one_table(ctx, a,
+ current_res, &next_res);
} else {
rc = grn_accessor_resolve_one_data_column(ctx, a,
- current_res, &next_res,
- optarg);
+ current_res, &next_res);
}
if (current_res != base_res) {
@@ -3010,9 +3445,19 @@ grn_accessor_resolve(grn_ctx *ctx, grn_obj *accessor, int deep,
}
if (rc == GRN_SUCCESS && current_res != base_res) {
- *res = current_res;
+ grn_id *record_id;
+ grn_rset_recinfo *recinfo;
+ GRN_HASH_EACH(ctx, (grn_hash *)current_res, id, &record_id, NULL, &recinfo, {
+ grn_posting posting;
+ posting.rid = *record_id;
+ posting.sid = 1;
+ posting.pos = 0;
+ posting.weight = recinfo->score - 1;
+ grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op);
+ });
+ grn_obj_unlink(ctx, current_res);
+ grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op);
} else {
- *res = NULL;
if (rc == GRN_SUCCESS) {
rc = GRN_INVALID_ARGUMENT;
}
@@ -3022,6 +3467,12 @@ grn_accessor_resolve(grn_ctx *ctx, grn_obj *accessor, int deep,
return rc;
}
+static inline void
+grn_obj_search_index_report(grn_ctx *ctx, const char *tag, grn_obj *index)
+{
+ grn_report_index(ctx, "[object][search]", tag, index);
+}
+
static inline grn_rc
grn_obj_search_accessor(grn_ctx *ctx, grn_obj *obj, grn_obj *query,
grn_obj *res, grn_operator op, grn_search_optarg *optarg)
@@ -3059,7 +3510,6 @@ grn_obj_search_accessor(grn_ctx *ctx, grn_obj *obj, grn_obj *query,
rc = grn_obj_search(ctx, index, query, res, op, optarg);
} else {
grn_obj *base_res;
- grn_obj *resolve_res = NULL;
grn_obj *range = grn_ctx_at(ctx, DB_OBJ(index)->range);
base_res = grn_table_create(ctx, NULL, 0, NULL,
GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC,
@@ -3070,28 +3520,15 @@ grn_obj_search_accessor(grn_ctx *ctx, grn_obj *obj, grn_obj *query,
if (!base_res) {
goto exit;
}
+ if (optarg) {
+ optarg->match_info.min = GRN_ID_NIL;
+ }
rc = grn_obj_search(ctx, index, query, base_res, GRN_OP_OR, optarg);
if (rc != GRN_SUCCESS) {
grn_obj_unlink(ctx, base_res);
goto exit;
}
- rc = grn_accessor_resolve(ctx, obj, n_accessors - 1, base_res,
- &resolve_res, optarg);
- if (resolve_res) {
- grn_id *record_id;
- grn_rset_recinfo *recinfo;
- GRN_HASH_EACH(ctx, (grn_hash *)resolve_res, id, &record_id, NULL,
- &recinfo, {
- grn_ii_posting posting;
- posting.rid = *record_id;
- posting.sid = 1;
- posting.pos = 0;
- posting.weight = recinfo->score - 1;
- grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op);
- });
- grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op);
- grn_obj_unlink(ctx, resolve_res);
- }
+ rc = grn_accessor_resolve(ctx, obj, n_accessors - 1, base_res, res, op);
grn_obj_unlink(ctx, base_res);
}
}
@@ -3106,10 +3543,14 @@ grn_obj_search_column_index_by_id(grn_ctx *ctx, grn_obj *obj,
grn_obj *res, grn_operator op,
grn_search_optarg *optarg)
{
- grn_ii_cursor *c = grn_ii_cursor_open(ctx, (grn_ii *)obj, tid,
- GRN_ID_NIL, GRN_ID_MAX, 1, 0);
+ grn_ii_cursor *c;
+
+ grn_obj_search_index_report(ctx, "[id]", obj);
+
+ c = grn_ii_cursor_open(ctx, (grn_ii *)obj, tid,
+ GRN_ID_NIL, GRN_ID_MAX, 1, 0);
if (c) {
- grn_ii_posting *pos;
+ grn_posting *pos;
grn_hash *s = (grn_hash *)res;
while ((pos = grn_ii_cursor_next(ctx, c))) {
/* todo: support orgarg(op)
@@ -3157,6 +3598,40 @@ grn_obj_search_column_index_by_key(grn_ctx *ctx, grn_obj *obj,
key_len = GRN_BULK_VSIZE(query);
}
if (rc == GRN_SUCCESS) {
+ if (grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) {
+ const char *tag;
+ if (optarg) {
+ switch (optarg->mode) {
+ case GRN_OP_MATCH :
+ tag = "[key][match]";
+ break;
+ case GRN_OP_EXACT :
+ tag = "[key][exact]";
+ break;
+ case GRN_OP_NEAR :
+ tag = "[key][near]";
+ break;
+ case GRN_OP_NEAR2 :
+ tag = "[key][near2]";
+ break;
+ case GRN_OP_SIMILAR :
+ tag = "[key][similar]";
+ break;
+ case GRN_OP_REGEXP :
+ tag = "[key][regexp]";
+ break;
+ case GRN_OP_FUZZY :
+ tag = "[key][fuzzy]";
+ break;
+ default :
+ tag = "[key][unknown]";
+ break;
+ }
+ } else {
+ tag = "[key][exact]";
+ }
+ grn_obj_search_index_report(ctx, tag, obj);
+ }
rc = grn_ii_sel(ctx, (grn_ii *)obj, key, key_len,
(grn_hash *)res, op, optarg);
}
@@ -3213,7 +3688,43 @@ grn_obj_search(grn_ctx *ctx, grn_obj *obj, grn_obj *query,
uint32_t key_size = GRN_BULK_VSIZE(query);
grn_operator mode = optarg ? optarg->mode : GRN_OP_EXACT;
if (key && key_size) {
- rc = grn_table_search(ctx, obj, key, key_size, mode, res, op);
+ if (grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) {
+ const char *tag;
+ if (optarg) {
+ switch (optarg->mode) {
+ case GRN_OP_EXACT :
+ tag = "[table][exact]";
+ break;
+ case GRN_OP_LCP :
+ tag = "[table][lcp]";
+ break;
+ case GRN_OP_SUFFIX :
+ tag = "[table][suffix]";
+ break;
+ case GRN_OP_PREFIX :
+ tag = "[table][prefix]";
+ break;
+ case GRN_OP_TERM_EXTRACT :
+ tag = "[table][term-extract]";
+ break;
+ case GRN_OP_FUZZY :
+ tag = "[table][fuzzy]";
+ break;
+ default :
+ tag = "[table][unknown]";
+ break;
+ }
+ } else {
+ tag = "[table][exact]";
+ }
+ grn_obj_search_index_report(ctx, tag, obj);
+ }
+ if (optarg && optarg->mode == GRN_OP_FUZZY) {
+ rc = grn_table_fuzzy_search(ctx, obj, key, key_size,
+ &(optarg->fuzzy), res, op);
+ } else {
+ rc = grn_table_search(ctx, obj, key, key_size, mode, res, op);
+ }
}
}
break;
@@ -3389,20 +3900,36 @@ grn_table_group_single_key_records(grn_ctx *ctx, grn_obj *table,
switch (bulk.header.type) {
case GRN_UVECTOR :
{
- // todo : support objects except grn_id
- grn_id *v = (grn_id *)GRN_BULK_HEAD(&bulk);
- grn_id *ve = (grn_id *)GRN_BULK_CURR(&bulk);
- while (v < ve) {
- if ((*v != GRN_ID_NIL) &&
- grn_table_add_v_inline(ctx, res,
- v, sizeof(grn_id), &value, NULL)) {
- grn_table_group_add_subrec(ctx, res, value,
- ri ? ri->score : 0,
- (grn_rset_posinfo *)&id, 0,
- calc_target,
- &value_buffer);
+ grn_bool is_reference;
+ unsigned int element_size;
+ uint8_t *elements;
+ int i, n_elements;
+
+ is_reference = !grn_type_id_is_builtin(ctx, bulk.header.type);
+
+ element_size = grn_uvector_element_size(ctx, &bulk);
+ elements = GRN_BULK_HEAD(&bulk);
+ n_elements = GRN_BULK_VSIZE(&bulk) / element_size;
+ for (i = 0; i < n_elements; i++) {
+ uint8_t *element = elements + (element_size * i);
+
+ if (is_reference) {
+ grn_id id = *((grn_id *)element);
+ if (id == GRN_ID_NIL) {
+ continue;
+ }
}
- v++;
+
+ if (!grn_table_add_v_inline(ctx, res, element, element_size,
+ &value, NULL)) {
+ continue;
+ }
+
+ grn_table_group_add_subrec(ctx, res, value,
+ ri ? ri->score : 0,
+ (grn_rset_posinfo *)&id, 0,
+ calc_target,
+ &value_buffer);
}
}
break;
@@ -3448,7 +3975,45 @@ grn_table_group_single_key_records(grn_ctx *ctx, grn_obj *table,
}
grn_table_cursor_close(ctx, tc);
}
- grn_obj_close(ctx, &bulk);
+ GRN_OBJ_FIN(ctx, &value_buffer);
+ GRN_OBJ_FIN(ctx, &bulk);
+}
+
+#define GRN_TABLE_GROUP_ALL_NAME "_all"
+#define GRN_TABLE_GROUP_ALL_NAME_LEN (sizeof(GRN_TABLE_GROUP_ALL_NAME) - 1)
+
+static void
+grn_table_group_all_records(grn_ctx *ctx, grn_obj *table,
+ grn_table_group_result *result)
+{
+ grn_obj value_buffer;
+ grn_table_cursor *tc;
+ grn_obj *res = result->table;
+ grn_obj *calc_target = result->calc_target;
+
+ GRN_VOID_INIT(&value_buffer);
+ if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) {
+ grn_id id;
+ void *value;
+ if (grn_table_add_v_inline(ctx, res,
+ GRN_TABLE_GROUP_ALL_NAME,
+ GRN_TABLE_GROUP_ALL_NAME_LEN,
+ &value, NULL)) {
+ while ((id = grn_table_cursor_next_inline(ctx, tc))) {
+ grn_rset_recinfo *ri = NULL;
+ if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) {
+ grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri);
+ }
+ grn_table_group_add_subrec(ctx, res, value,
+ ri ? ri->score : 0,
+ (grn_rset_posinfo *)&id, 0,
+ calc_target,
+ &value_buffer);
+ }
+ }
+ grn_table_cursor_close(ctx, tc);
+ }
+ GRN_OBJ_FIN(ctx, &value_buffer);
}
grn_rc
@@ -3817,7 +4382,10 @@ grn_table_group(grn_ctx *ctx, grn_obj *table,
grn_table_group_result *results, int n_results)
{
grn_rc rc = GRN_SUCCESS;
- if (!table || !n_keys || !n_results) {
+ grn_bool group_by_all_records = GRN_FALSE;
+ if (n_keys == 0 && n_results == 1) {
+ group_by_all_records = GRN_TRUE;
+ } else if (!table || !n_keys || !n_results) {
ERR(GRN_INVALID_ARGUMENT, "table or n_keys or n_results is void");
return GRN_INVALID_ARGUMENT;
}
@@ -3834,14 +4402,16 @@ grn_table_group(grn_ctx *ctx, grn_obj *table,
}
for (r = 0, rp = results; r < n_results; r++, rp++) {
if (!rp->table) {
- grn_obj_flags flags;
+ grn_table_flags flags;
grn_obj *key_type = NULL;
uint32_t additional_value_size;
flags = GRN_TABLE_HASH_KEY|
GRN_OBJ_WITH_SUBREC|
GRN_OBJ_UNIT_USERDEF_DOCUMENT;
- if (n_keys == 1) {
+ if (group_by_all_records) {
+ key_type = grn_ctx_at(ctx, GRN_DB_SHORT_TEXT);
+ } else if (n_keys == 1) {
key_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, keys[0].key));
} else {
flags |= GRN_OBJ_KEY_VAR_SIZE;
@@ -3862,7 +4432,9 @@ grn_table_group(grn_ctx *ctx, grn_obj *table,
DB_OBJ(rp->table)->flags.group = rp->flags;
}
}
- if (n_keys == 1 && n_results == 1) {
+ if (group_by_all_records) {
+ grn_table_group_all_records(ctx, table, results);
+ } else if (n_keys == 1 && n_results == 1) {
if (!accelerated_table_group(ctx, table, keys->key, results)) {
grn_table_group_single_key_records(ctx, table, keys->key, results);
}
@@ -3899,18 +4471,34 @@ grn_rc
grn_table_setoperation(grn_ctx *ctx, grn_obj *table1, grn_obj *table2, grn_obj *res,
grn_operator op)
{
- grn_rc rc = GRN_SUCCESS;
void *key = NULL, *value1 = NULL, *value2 = NULL;
uint32_t value_size = 0;
uint32_t key_size = 0;
grn_bool have_subrec;
+
+ GRN_API_ENTER;
+ if (!table1) {
+ ERR(GRN_INVALID_ARGUMENT, "[table][setoperation] table1 is NULL");
+ GRN_API_RETURN(ctx->rc);
+ }
+ if (!table2) {
+ ERR(GRN_INVALID_ARGUMENT, "[table][setoperation] table2 is NULL");
+ GRN_API_RETURN(ctx->rc);
+ }
+ if (!res) {
+ ERR(GRN_INVALID_ARGUMENT, "[table][setoperation] result table is NULL");
+ GRN_API_RETURN(ctx->rc);
+ }
+
if (table1 != res) {
if (table2 == res) {
grn_obj *t = table1;
table1 = table2;
table2 = t;
} else {
- return GRN_INVALID_ARGUMENT;
+ ERR(GRN_INVALID_ARGUMENT,
+ "[table][setoperation] table1 or table2 must be result table");
+ GRN_API_RETURN(ctx->rc);
}
}
have_subrec = ((DB_OBJ(table1)->header.flags & GRN_OBJ_WITH_SUBREC) &&
@@ -3997,16 +4585,26 @@ grn_table_setoperation(grn_ctx *ctx, grn_obj *table1, grn_obj *table2, grn_obj *
});
break;
case GRN_OP_ADJUST :
- GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, {
- if (grn_table_get_v(ctx, table1, key, key_size, &value1)) {
- grn_memcpy(value1, value2, value_size);
- }
- });
+ if (have_subrec) {
+ GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, {
+ if (grn_table_get_v(ctx, table1, key, key_size, &value1)) {
+ grn_rset_recinfo *ri1 = value1;
+ grn_rset_recinfo *ri2 = value2;
+ ri1->score += ri2->score;
+ }
+ });
+ } else {
+ GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, {
+ if (grn_table_get_v(ctx, table1, key, key_size, &value1)) {
+ grn_memcpy(value1, value2, value_size);
+ }
+ });
+ }
break;
default :
break;
}
- return rc;
+ GRN_API_RETURN(ctx->rc);
}
grn_rc
@@ -4042,20 +4640,34 @@ static grn_obj *grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj,
static grn_obj *
grn_obj_column_(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int name_size)
{
+ grn_id table_id = DB_OBJ(table)->id;
grn_obj *column = NULL;
- char buf[GRN_TABLE_MAX_KEY_SIZE];
- int len = grn_obj_name(ctx, table, buf, GRN_TABLE_MAX_KEY_SIZE);
- if (len) {
- buf[len++] = GRN_DB_DELIMITER;
- if (len + name_size <= GRN_TABLE_MAX_KEY_SIZE) {
- grn_memcpy(buf + len, name, name_size);
- column = grn_ctx_get(ctx, buf, len + name_size);
- } else {
- ERR(GRN_INVALID_ARGUMENT, "name is too long");
+
+ if (table_id & GRN_OBJ_TMP_OBJECT) {
+ char column_name[GRN_TABLE_MAX_KEY_SIZE];
+ void *value = NULL;
+ grn_snprintf(column_name, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE,
+ "%u%c%.*s", table_id, GRN_DB_DELIMITER, name_size, name);
+ grn_pat_get(ctx, ctx->impl->temporary_columns,
+ column_name, strlen(column_name),
+ &value);
+ if (value) {
+ column = *((grn_obj **)value);
}
} else {
- /* todo : support temporary table */
+ char buf[GRN_TABLE_MAX_KEY_SIZE];
+ int len = grn_obj_name(ctx, table, buf, GRN_TABLE_MAX_KEY_SIZE);
+ if (len) {
+ buf[len++] = GRN_DB_DELIMITER;
+ if (len + name_size <= GRN_TABLE_MAX_KEY_SIZE) {
+ grn_memcpy(buf + len, name, name_size);
+ column = grn_ctx_get(ctx, buf, len + name_size);
+ } else {
+ ERR(GRN_INVALID_ARGUMENT, "name is too long");
+ }
+ }
}
+
return column;
}
@@ -4080,14 +4692,46 @@ grn_table_columns(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int n
grn_obj *res)
{
int n = 0;
+ grn_id id;
+
GRN_API_ENTER;
- if (GRN_OBJ_TABLEP(table) && DB_OBJ(table)->id &&
- !(DB_OBJ(table)->id & GRN_OBJ_TMP_OBJECT)) {
+
+ if (!GRN_OBJ_TABLEP(table)) {
+ GRN_API_RETURN(n);
+ }
+
+ id = DB_OBJ(table)->id;
+
+ if (id == GRN_ID_NIL) {
+ GRN_API_RETURN(n);
+ }
+
+ if (id & GRN_OBJ_TMP_OBJECT) {
+ char search_key[GRN_TABLE_MAX_KEY_SIZE];
+ grn_pat_cursor *cursor;
+ grn_snprintf(search_key, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE,
+ "%u%c%.*s", id, GRN_DB_DELIMITER, name_size, name);
+ cursor = grn_pat_cursor_open(ctx, ctx->impl->temporary_columns,
+ search_key, strlen(search_key),
+ NULL, 0,
+ 0, -1, GRN_CURSOR_PREFIX);
+ if (cursor) {
+ grn_id column_id;
+ while ((column_id = grn_pat_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
+ column_id |= GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN;
+ grn_hash_add(ctx, (grn_hash *)res,
+ &column_id, sizeof(grn_id),
+ NULL, NULL);
+ n++;
+ }
+ grn_pat_cursor_close(ctx, cursor);
+ }
+ } else {
grn_db *s = (grn_db *)DB_OBJ(table)->db;
if (s->keys) {
grn_obj bulk;
GRN_TEXT_INIT(&bulk, 0);
- grn_table_get_key2(ctx, s->keys, DB_OBJ(table)->id, &bulk);
+ grn_table_get_key2(ctx, s->keys, id, &bulk);
GRN_TEXT_PUTC(ctx, &bulk, GRN_DB_DELIMITER);
grn_bulk_write(ctx, &bulk, name, name_size);
grn_table_search(ctx, s->keys, GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk),
@@ -4096,6 +4740,7 @@ grn_table_columns(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int n
n = grn_table_size(ctx, res);
}
}
+
GRN_API_RETURN(n);
}
@@ -4133,7 +4778,7 @@ _grn_table_key(grn_ctx *ctx, grn_obj *table, grn_id id, uint32_t *key_size)
grn_obj *
grn_column_create(grn_ctx *ctx, grn_obj *table,
const char *name, unsigned int name_size,
- const char *path, grn_obj_flags flags, grn_obj *type)
+ const char *path, grn_column_flags flags, grn_obj *type)
{
grn_db *s;
uint32_t value_size;
@@ -4141,8 +4786,11 @@ grn_column_create(grn_ctx *ctx, grn_obj *table,
grn_id id = GRN_ID_NIL;
grn_id range = GRN_ID_NIL;
grn_id domain = GRN_ID_NIL;
+ grn_bool is_persistent_table;
char fullname[GRN_TABLE_MAX_KEY_SIZE];
+ unsigned int fullname_size;
char buffer[PATH_MAX];
+
GRN_API_ENTER;
if (!table) {
ERR(GRN_INVALID_ARGUMENT, "[column][create] table is missing");
@@ -4167,46 +4815,50 @@ grn_column_create(grn_ctx *ctx, grn_obj *table,
table_name_len, table_name, name_size, name);
goto exit;
}
- if (DB_OBJ(table)->id & GRN_OBJ_TMP_OBJECT) {
- ERR(GRN_INVALID_ARGUMENT,
- "[column][create] temporary table doesn't support column: <%.*s>",
- name_size, name);
- goto exit;
- }
- {
- uint32_t s = 0;
- const char *n = _grn_table_key(ctx, ctx->impl->db, DB_OBJ(table)->id, &s);
- GRN_LOG(ctx, GRN_LOG_NOTICE,
- "DDL:column_create %.*s %.*s", s, n, name_size, name);
- }
+
if (grn_db_check_name(ctx, name, name_size)) {
GRN_DB_CHECK_NAME_ERR("[column][create]", name, name_size);
goto exit;
}
- if ((domain = DB_OBJ(table)->id)) {
- int len = grn_table_get_key(ctx, s->keys, domain, fullname, GRN_TABLE_MAX_KEY_SIZE);
- if (name_size + 1 + len > GRN_TABLE_MAX_KEY_SIZE) {
+
+ domain = DB_OBJ(table)->id;
+ is_persistent_table = !(domain & GRN_OBJ_TMP_OBJECT);
+
+ if (!domain) {
+ ERR(GRN_FUNCTION_NOT_IMPLEMENTED,
+ "[column][create] [todo] table-less column isn't supported yet");
+ goto exit;
+ }
+
+ {
+ int table_name_len;
+ if (is_persistent_table) {
+ table_name_len = grn_table_get_key(ctx, s->keys, domain,
+ fullname, GRN_TABLE_MAX_KEY_SIZE);
+ } else {
+ grn_snprintf(fullname, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE,
+ "%u", domain);
+ table_name_len = strlen(fullname);
+ }
+ if (name_size + 1 + table_name_len > GRN_TABLE_MAX_KEY_SIZE) {
ERR(GRN_INVALID_ARGUMENT,
"[column][create] too long column name: required name_size(%d) < %d"
": <%.*s>.<%.*s>",
- name_size, GRN_TABLE_MAX_KEY_SIZE - 1 - len,
- len, fullname, name_size, name);
+ name_size, GRN_TABLE_MAX_KEY_SIZE - 1 - table_name_len,
+ table_name_len, fullname, name_size, name);
goto exit;
}
- fullname[len] = GRN_DB_DELIMITER;
- grn_memcpy(fullname + len + 1, name, name_size);
- name_size += len + 1;
- } else {
- ERR(GRN_FUNCTION_NOT_IMPLEMENTED,
- "[column][create] [todo] table-less column isn't supported yet");
- goto exit;
+ fullname[table_name_len] = GRN_DB_DELIMITER;
+ grn_memcpy(fullname + table_name_len + 1, name, name_size);
+ fullname_size = table_name_len + 1 + name_size;
}
+
range = DB_OBJ(type)->id;
switch (type->header.type) {
case GRN_TYPE :
{
grn_db_obj *t = (grn_db_obj *)type;
- flags |= t->header.flags;
+ flags |= t->header.flags & ~GRN_OBJ_KEY_MASK;
value_size = GRN_TYPE_SIZE(t);
}
break;
@@ -4224,12 +4876,46 @@ grn_column_create(grn_ctx *ctx, grn_obj *table,
*/
value_size = sizeof(grn_id);
}
- id = grn_obj_register(ctx, db, fullname, name_size);
- if (ERRP(ctx, GRN_ERROR)) { goto exit; }
- if (GRN_OBJ_PERSISTENT & flags) {
+
+ if (is_persistent_table) {
+ id = grn_obj_register(ctx, db, fullname, fullname_size);
+ if (ERRP(ctx, GRN_ERROR)) { goto exit; }
+
+ {
+ uint32_t table_name_size = 0;
+ const char *table_name;
+ table_name = _grn_table_key(ctx, ctx->impl->db, domain, &table_name_size);
+ GRN_LOG(ctx, GRN_LOG_NOTICE,
+ "DDL:%u:column_create %.*s %.*s",
+ id,
+ table_name_size, table_name,
+ name_size, name);
+ }
+ } else {
+ int added;
+ id = grn_pat_add(ctx, ctx->impl->temporary_columns,
+ fullname, fullname_size, NULL,
+ &added);
+ if (!id) {
+ ERR(GRN_NO_MEMORY_AVAILABLE,
+ "[column][create][temporary] "
+ "failed to register temporary column name: <%.*s>",
+ fullname_size, fullname);
+ goto exit;
+ } else if (!added) {
+ id = GRN_ID_NIL;
+ ERR(GRN_NO_MEMORY_AVAILABLE,
+ "[column][create][temporary] already used name was assigned: <%.*s>",
+ fullname_size, fullname);
+ goto exit;
+ }
+ id |= GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN;
+ }
+
+ if (is_persistent_table && flags & GRN_OBJ_PERSISTENT) {
if (!path) {
if (GRN_DB_PERSISTENT_P(db)) {
- gen_pathname(grn_obj_io(db)->path, buffer, id);
+ grn_db_generate_pathname(ctx, db, id, buffer);
path = buffer;
} else {
int table_name_len;
@@ -4281,7 +4967,7 @@ grn_column_create(grn_ctx *ctx, grn_obj *table,
DB_OBJ(res)->header.flags = flags;
res->header.flags = flags;
if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) {
- _grn_obj_remove(ctx, res);
+ _grn_obj_remove(ctx, res, GRN_FALSE);
res = NULL;
} else {
grn_obj_touch(ctx, res, NULL);
@@ -4634,21 +5320,20 @@ grn_vector_decode(grn_ctx *ctx, grn_obj *v, const char *data, uint32_t data_size
}
{
grn_section *vp;
+ grn_obj *body = grn_vector_body(ctx, v);
+ uint32_t offset = GRN_BULK_VSIZE(body);
uint32_t o = 0, l, i;
for (i = n, vp = v->u.v.sections + n0; i; i--, vp++) {
if (pe <= p) { return GRN_INVALID_ARGUMENT; }
GRN_B_DEC(l, p);
vp->length = l;
- vp->offset = o;
+ vp->offset = offset + o;
vp->weight = 0;
vp->domain = 0;
o += l;
}
if (pe < p + o) { return GRN_INVALID_ARGUMENT; }
- {
- grn_obj *body = grn_vector_body(ctx, v);
- grn_bulk_write(ctx, body, (char *)p, o);
- }
+ grn_bulk_write(ctx, body, (char *)p, o);
p += o;
if (p < pe) {
for (i = n, vp = v->u.v.sections + n0; i; i--, vp++) {
@@ -4861,8 +5546,10 @@ accessor_new(grn_ctx *ctx)
res->header.impl_flags = GRN_OBJ_ALLOCATED;
res->header.flags = 0;
res->header.domain = GRN_ID_NIL;
+ res->range = GRN_ID_NIL;
res->action = GRN_ACCESSOR_VOID;
res->offset = 0;
+ res->obj = NULL;
res->next = NULL;
}
return res;
@@ -4879,6 +5566,17 @@ grn_obj_get_accessor_rset_value(grn_ctx *ctx, grn_obj *obj,
*rp = accessor_new(ctx);
(*rp)->obj = obj;
+#define CHECK_GROUP_CALC_FLAG(flag) do { \
+ if (GRN_TABLE_IS_GROUPED(obj)) { \
+ grn_table_group_flags flags; \
+ flags = DB_OBJ(obj)->flags.group; \
+ if (flags & flag) { \
+ succeeded = GRN_TRUE; \
+ (*rp)->action = action; \
+ goto exit; \
+ } \
+ } \
+ } while(GRN_FALSE)
switch (action) {
case GRN_ACCESSOR_GET_SCORE :
if (DB_OBJ(obj)->header.flags & GRN_OBJ_WITH_SUBREC) {
@@ -4888,9 +5586,17 @@ grn_obj_get_accessor_rset_value(grn_ctx *ctx, grn_obj *obj,
}
break;
case GRN_ACCESSOR_GET_MAX :
+ CHECK_GROUP_CALC_FLAG(GRN_TABLE_GROUP_CALC_MAX);
+ break;
case GRN_ACCESSOR_GET_MIN :
+ CHECK_GROUP_CALC_FLAG(GRN_TABLE_GROUP_CALC_MIN);
+ break;
case GRN_ACCESSOR_GET_SUM :
+ CHECK_GROUP_CALC_FLAG(GRN_TABLE_GROUP_CALC_SUM);
+ break;
case GRN_ACCESSOR_GET_AVG :
+ CHECK_GROUP_CALC_FLAG(GRN_TABLE_GROUP_CALC_AVG);
+ break;
case GRN_ACCESSOR_GET_NSUBRECS :
if (GRN_TABLE_IS_GROUPED(obj)) {
(*rp)->action = action;
@@ -4899,6 +5605,7 @@ grn_obj_get_accessor_rset_value(grn_ctx *ctx, grn_obj *obj,
}
break;
}
+#undef CHECK_GROUP_CALC_FLAG
switch (obj->header.type) {
case GRN_TABLE_PAT_KEY :
@@ -5303,7 +6010,12 @@ inline static void
grn_obj_get_range_info(grn_ctx *ctx, grn_obj *obj,
grn_id *range_id, grn_obj_flags *range_flags)
{
- if (GRN_DB_OBJP(obj)) {
+ if (!obj) {
+ *range_id = GRN_ID_NIL;
+ } else if (grn_obj_is_proc(ctx, obj)) {
+ /* TODO */
+ *range_id = GRN_ID_NIL;
+ } else if (GRN_DB_OBJP(obj)) {
*range_id = DB_OBJ(obj)->range;
if (grn_column_is_vector(ctx, obj)) {
*range_flags = GRN_OBJ_VECTOR;
@@ -5401,30 +6113,37 @@ grn_obj_is_persistent(grn_ctx *ctx, grn_obj *obj)
grn_obj key;\
GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain);\
if (src->header.domain != table->header.domain) {\
- grn_obj_cast(ctx, src, &key, GRN_TRUE);\
+ rc = grn_obj_cast(ctx, src, &key, GRN_TRUE);\
p_key = &key;\
}\
- if (GRN_BULK_VSIZE(p_key)) {\
- id = addp ? grn_table_add_by_key(ctx, table, p_key, NULL)\
- : grn_table_get_by_key(ctx, table, p_key);\
- if (id) {\
- GRN_RECORD_SET(ctx, dest, id);\
+ if (!rc) {\
+ if (GRN_BULK_VSIZE(p_key)) {\
+ if (add_record_if_not_exist) {\
+ id = grn_table_add_by_key(ctx, table, p_key, NULL);\
+ } else {\
+ id = grn_table_get_by_key(ctx, table, p_key);\
+ }\
+ if (id) {\
+ GRN_RECORD_SET(ctx, dest, id);\
+ } else {\
+ rc = GRN_INVALID_ARGUMENT;\
+ }\
} else {\
- rc = GRN_INVALID_ARGUMENT;\
+ GRN_RECORD_SET(ctx, dest, GRN_ID_NIL);\
}\
- } else {\
- GRN_RECORD_SET(ctx, dest, GRN_ID_NIL);\
}\
GRN_OBJ_FIN(ctx, &key);\
} else {\
grn_obj record_id;\
GRN_UINT32_INIT(&record_id, 0);\
- grn_obj_cast(ctx, src, &record_id, GRN_TRUE);\
- id = GRN_UINT32_VALUE(&record_id);\
- if (id) {\
- GRN_RECORD_SET(ctx, dest, id);\
- } else {\
- rc = GRN_INVALID_ARGUMENT;\
+ rc = grn_obj_cast(ctx, src, &record_id, GRN_TRUE);\
+ if (!rc) {\
+ id = GRN_UINT32_VALUE(&record_id);\
+ if (id) {\
+ GRN_RECORD_SET(ctx, dest, id);\
+ } else {\
+ rc = GRN_INVALID_ARGUMENT;\
+ }\
}\
}\
} else {\
@@ -5433,7 +6152,8 @@ grn_obj_is_persistent(grn_ctx *ctx, grn_obj *obj)
} while (0)
inline static grn_rc
-grn_obj_cast_bool(grn_ctx *ctx, grn_obj *src, grn_obj *dest, grn_bool addp)
+grn_obj_cast_bool(grn_ctx *ctx, grn_obj *src, grn_obj *dest,
+ grn_bool add_record_if_not_exist)
{
grn_rc rc = GRN_SUCCESS;
@@ -5552,7 +6272,7 @@ grn_obj_cast_bool(grn_ctx *ctx, grn_obj *src, grn_obj *dest, grn_bool addp)
GRN_VOID_INIT(&buf);\
rc = grn_aton(ctx, str, str_end, &rest, &buf);\
if (!rc) {\
- rc = grn_obj_cast(ctx, &buf, dest, addp);\
+ rc = grn_obj_cast(ctx, &buf, dest, add_record_if_not_exist);\
}\
GRN_OBJ_FIN(ctx, &buf);\
} else {\
@@ -5570,8 +6290,10 @@ grn_obj_cast_bool(grn_ctx *ctx, grn_obj *src, grn_obj *dest, grn_bool addp)
GRN_TIME_SET(ctx, dest, (long long int)(value) * GRN_TIME_USEC_PER_SEC);
#define TIME2TIME(ctx, dest, value)\
GRN_TIME_SET(ctx, dest, value);
-#define FLOAT2TIME(ctx, dest, value)\
- GRN_TIME_SET(ctx, dest, (long long int)(value * GRN_TIME_USEC_PER_SEC));
+#define FLOAT2TIME(ctx, dest, value) do {\
+ int64_t usec = llround(value * GRN_TIME_USEC_PER_SEC);\
+ GRN_TIME_SET(ctx, dest, usec);\
+} while (0)
#define NUM2FLOAT(ctx, dest, value)\
GRN_FLOAT_SET(ctx, dest, value);
@@ -5580,13 +6302,67 @@ grn_obj_cast_bool(grn_ctx *ctx, grn_obj *src, grn_obj *dest, grn_bool addp)
#define FLOAT2FLOAT(ctx, dest, value)\
GRN_FLOAT_SET(ctx, dest, value);
+static grn_rc
+grn_obj_cast_record(grn_ctx *ctx,
+ grn_obj *src,
+ grn_obj *dest,
+ grn_bool add_record_if_not_exist)
+{
+ grn_obj *src_table;
+ grn_obj *dest_table;
+ const char *key;
+ uint32_t key_size;
+ grn_id dest_id;
+
+ if (src->header.domain == dest->header.domain) {
+ GRN_RECORD_SET(ctx, dest, GRN_RECORD_VALUE(src));
+ return GRN_SUCCESS;
+ }
+
+ src_table = grn_ctx_at(ctx, src->header.domain);
+ if (!src_table) {
+ return GRN_INVALID_ARGUMENT;
+ }
+ if (src_table->header.type == GRN_TABLE_NO_KEY) {
+ return GRN_INVALID_ARGUMENT;
+ }
+
+ dest_table = grn_ctx_at(ctx, dest->header.domain);
+ if (!dest_table) {
+ return GRN_INVALID_ARGUMENT;
+ }
+ switch (dest_table->header.type) {
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ break;
+ default :
+ return GRN_INVALID_ARGUMENT;
+ }
+
+ if (GRN_RECORD_VALUE(src) == GRN_ID_NIL) {
+ GRN_RECORD_SET(ctx, dest, GRN_RECORD_VALUE(src));
+ return GRN_SUCCESS;
+ }
+
+ key = _grn_table_key(ctx, src_table, GRN_RECORD_VALUE(src), &key_size);
+ if (add_record_if_not_exist) {
+ dest_id = grn_table_add(ctx, dest_table, key, key_size, NULL);
+ } else {
+ dest_id = grn_table_get(ctx, dest_table, key, key_size);
+ }
+ GRN_RECORD_SET(ctx, dest, dest_id);
+ return GRN_SUCCESS;
+}
+
grn_rc
-grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest, grn_bool addp)
+grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest,
+ grn_bool add_record_if_not_exist)
{
grn_rc rc = GRN_SUCCESS;
switch (src->header.domain) {
case GRN_DB_BOOL :
- rc = grn_obj_cast_bool(ctx, src, dest, addp);
+ rc = grn_obj_cast_bool(ctx, src, dest, add_record_if_not_exist);
break;
case GRN_DB_INT8 :
NUM2DEST(GRN_INT8_VALUE, grn_text_itoa, NUM2BOOL, NUM2TIME, NUM2FLOAT);
@@ -5835,7 +6611,23 @@ grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest, grn_bool addp)
rc = grn_obj_reinit(ctx, dest, dest->header.domain, dest->header.flags);
break;
default :
- rc = GRN_FUNCTION_NOT_IMPLEMENTED;
+ if (src->header.domain >= GRN_N_RESERVED_TYPES) {
+ grn_obj *table;
+ table = grn_ctx_at(ctx, src->header.domain);
+ switch (table->header.type) {
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ case GRN_TABLE_NO_KEY :
+ rc = grn_obj_cast_record(ctx, src, dest, add_record_if_not_exist);
+ break;
+ default :
+ rc = GRN_FUNCTION_NOT_IMPLEMENTED;
+ break;
+ }
+ } else {
+ rc = GRN_FUNCTION_NOT_IMPLEMENTED;
+ }
break;
}
return rc;
@@ -6363,7 +7155,7 @@ call_hook(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value, int flags)
if (hooks->proc) {
hooks->proc->funcs[PROC_INIT](ctx, 1, &obj, &pctx.user_data);
} else {
- default_set_value_hook(ctx, 1, &obj, &pctx.user_data);
+ grn_obj_default_set_value_hook(ctx, 1, &obj, &pctx.user_data);
}
if (ctx->rc) {
grn_obj_close(ctx, oldvalue);
@@ -6378,48 +7170,6 @@ call_hook(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value, int flags)
return 0;
}
-inline static int
-call_hook_for_build(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value, int flags)
-{
- grn_hook *hooks = DB_OBJ(obj)->hooks[GRN_HOOK_SET];
-
- if (hooks || obj->header.type == GRN_COLUMN_VAR_SIZE) {
- grn_obj oldvalue;
- GRN_TEXT_INIT(&oldvalue, 0);
-
- if (hooks) {
- // todo : grn_proc_ctx_open()
- grn_obj id_, flags_;
- grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4};
- GRN_UINT32_INIT(&id_, 0);
- GRN_UINT32_INIT(&flags_, 0);
- GRN_UINT32_SET(ctx, &id_, id);
- GRN_UINT32_SET(ctx, &flags_, flags);
- while (hooks) {
- grn_ctx_push(ctx, &id_);
- grn_ctx_push(ctx, &oldvalue);
- grn_ctx_push(ctx, value);
- grn_ctx_push(ctx, &flags_);
- pctx.caller = NULL;
- pctx.currh = hooks;
- if (hooks->proc) {
- hooks->proc->funcs[PROC_INIT](ctx, 1, &obj, &pctx.user_data);
- } else {
- default_set_value_hook(ctx, 1, &obj, &pctx.user_data);
- }
- if (ctx->rc) {
- grn_obj_close(ctx, &oldvalue);
- return 1;
- }
- hooks = hooks->next;
- pctx.offset++;
- }
- }
- grn_obj_close(ctx, &oldvalue);
- }
- return 0;
-}
-
static grn_rc
grn_obj_set_value_table_pat_key(grn_ctx *ctx, grn_obj *obj, grn_id id,
grn_obj *value, int flags)
@@ -6430,6 +7180,9 @@ grn_obj_set_value_table_pat_key(grn_ctx *ctx, grn_obj *obj, grn_id id,
grn_obj buf;
if (call_hook(ctx, obj, id, value, flags)) {
+ if (ctx->rc) {
+ rc = ctx->rc;
+ }
return rc;
}
@@ -6457,6 +7210,9 @@ grn_obj_set_value_table_hash_key(grn_ctx *ctx, grn_obj *obj, grn_id id,
grn_obj buf;
if (call_hook(ctx, obj, id, value, flags)) {
+ if (ctx->rc) {
+ rc = ctx->rc;
+ }
return rc;
}
@@ -6484,6 +7240,9 @@ grn_obj_set_value_table_no_key(grn_ctx *ctx, grn_obj *obj, grn_id id,
grn_obj buf;
if (call_hook(ctx, obj, id, value, flags)) {
+ if (ctx->rc) {
+ rc = ctx->rc;
+ }
return rc;
}
@@ -6513,6 +7272,9 @@ grn_obj_set_value_column_var_size_scalar(grn_ctx *ctx, grn_obj *obj, grn_id id,
grn_id buf_domain = GRN_DB_VOID;
if (call_hook(ctx, obj, id, value, flags)) {
+ if (ctx->rc) {
+ rc = ctx->rc;
+ }
return rc;
}
@@ -6558,10 +7320,12 @@ grn_obj_set_value_column_var_size_vector_uvector(grn_ctx *ctx, grn_obj *column,
grn_id id, grn_obj *value,
int flags)
{
- grn_rc rc = GRN_INVALID_ARGUMENT;
+ grn_rc rc = GRN_SUCCESS;
grn_obj uvector;
grn_obj_flags uvector_flags = 0;
grn_bool need_convert = GRN_FALSE;
+ grn_bool need_cast = GRN_FALSE;
+ grn_id column_range_id;
void *raw_value;
unsigned int size;
@@ -6575,17 +7339,67 @@ grn_obj_set_value_column_var_size_vector_uvector(grn_ctx *ctx, grn_obj *column,
uvector_flags = GRN_OBJ_WITH_WEIGHT;
}
}
+ column_range_id = DB_OBJ(column)->range;
+ if (column_range_id != value->header.domain) {
+ need_convert = GRN_TRUE;
+ need_cast = GRN_TRUE;
+ }
if (need_convert) {
unsigned int i, n;
- GRN_VALUE_FIX_SIZE_INIT(&uvector, GRN_OBJ_VECTOR, value->header.domain);
+
+ GRN_VALUE_FIX_SIZE_INIT(&uvector, GRN_OBJ_VECTOR, column_range_id);
uvector.header.flags |= uvector_flags;
n = grn_uvector_size(ctx, value);
- for (i = 0; i < n; i++) {
- grn_id id;
- unsigned int weight = 0;
- id = grn_uvector_get_element(ctx, value, i, NULL);
- grn_uvector_add_element(ctx, &uvector, id, weight);
+ if (need_cast) {
+ grn_obj value_record;
+ grn_obj casted_record;
+
+ GRN_VALUE_FIX_SIZE_INIT(&value_record, 0, value->header.domain);
+ GRN_VALUE_FIX_SIZE_INIT(&casted_record, 0, column_range_id);
+ for (i = 0; i < n; i++) {
+ grn_id id;
+ grn_id casted_id;
+ unsigned int weight = 0;
+
+ GRN_BULK_REWIND(&value_record);
+ GRN_BULK_REWIND(&casted_record);
+
+ id = grn_uvector_get_element(ctx, value, i, NULL);
+ GRN_RECORD_SET(ctx, &value_record, id);
+ rc = grn_obj_cast(ctx, &value_record, &casted_record, GRN_TRUE);
+ if (rc != GRN_SUCCESS) {
+ char column_name[GRN_TABLE_MAX_KEY_SIZE];
+ int column_name_size;
+ grn_obj inspected;
+ column_name_size = grn_obj_name(ctx,
+ column,
+ column_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ GRN_TEXT_INIT(&inspected, 0);
+ grn_inspect(ctx, &inspected, &value_record);
+ ERR(rc,
+ "[column][set-value] failed to cast: <%.*s>: <%.*s>",
+ column_name_size,
+ column_name,
+ (int)GRN_TEXT_LEN(&inspected),
+ GRN_TEXT_VALUE(&inspected));
+ GRN_OBJ_FIN(ctx, &inspected);
+ break;
+ }
+ casted_id = GRN_RECORD_VALUE(&casted_record);
+ grn_uvector_add_element(ctx, &uvector, casted_id, weight);
+ }
+
+ GRN_OBJ_FIN(ctx, &value_record);
+ GRN_OBJ_FIN(ctx, &casted_record);
+ } else {
+ for (i = 0; i < n; i++) {
+ grn_id id;
+ unsigned int weight = 0;
+ id = grn_uvector_get_element(ctx, value, i, NULL);
+ grn_uvector_add_element(ctx, &uvector, id, weight);
+ }
}
raw_value = GRN_BULK_HEAD(&uvector);
size = GRN_BULK_VSIZE(&uvector);
@@ -6594,7 +7408,9 @@ grn_obj_set_value_column_var_size_vector_uvector(grn_ctx *ctx, grn_obj *column,
size = GRN_BULK_VSIZE(value);
}
- rc = grn_ja_put(ctx, (grn_ja *)column, id, raw_value, size, flags, NULL);
+ if (rc == GRN_SUCCESS) {
+ rc = grn_ja_put(ctx, (grn_ja *)column, id, raw_value, size, flags, NULL);
+ }
if (need_convert) {
GRN_OBJ_FIN(ctx, &uvector);
@@ -6614,6 +7430,9 @@ grn_obj_set_value_column_var_size_vector(grn_ctx *ctx, grn_obj *obj, grn_id id,
grn_obj *lexicon = grn_ctx_at(ctx, range);
if (call_hook(ctx, obj, id, value, flags)) {
+ if (ctx->rc) {
+ rc = ctx->rc;
+ }
return rc;
}
@@ -6770,6 +7589,9 @@ grn_obj_set_value_column_fix_size(grn_ctx *ctx, grn_obj *obj, grn_id id,
switch (flags & GRN_OBJ_SET_MASK) {
case GRN_OBJ_SET :
if (call_hook(ctx, obj, id, value_, flags)) {
+ if (ctx->rc) {
+ rc = ctx->rc;
+ }
GRN_OBJ_FIN(ctx, &buf);
grn_ra_unref(ctx, (grn_ra *)obj, id);
return rc;
@@ -7233,6 +8055,30 @@ grn_obj_get_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *valueb
GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE);
#endif /* GRN_WITH_LZ4 */
break;
+ case GRN_INFO_SUPPORT_ZSTD :
+ if (!valuebuf && !(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_BOOL))) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "failed to open value buffer for GRN_INFO_ZSTD_SUPPORT");
+ goto exit;
+ }
+#ifdef GRN_WITH_ZSTD
+ GRN_BOOL_PUT(ctx, valuebuf, GRN_TRUE);
+#else /* GRN_WITH_ZSTD */
+ GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE);
+#endif /* GRN_WITH_ZSTD */
+ break;
+ case GRN_INFO_SUPPORT_ARROW :
+ if (!valuebuf && !(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_BOOL))) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "failed to open value buffer for GRN_INFO_ARROW_SUPPORT");
+ goto exit;
+ }
+#ifdef GRN_WITH_ARROW
+ GRN_BOOL_PUT(ctx, valuebuf, GRN_TRUE);
+#else /* GRN_WITH_ARROW */
+ GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE);
+#endif /* GRN_WITH_ARROW */
+ break;
default :
if (!obj) {
ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_info failed");
@@ -7352,82 +8198,11 @@ exit :
}
static void
-build_index(grn_ctx *ctx, grn_obj *obj)
-{
- grn_obj *src, **cp, **col, *target;
- grn_id *s = DB_OBJ(obj)->source;
- if (!(DB_OBJ(obj)->source_size) || !s) { return; }
- if ((src = grn_ctx_at(ctx, *s))) {
- target = GRN_OBJ_TABLEP(src) ? src : grn_ctx_at(ctx, src->header.domain);
- if (target) {
- int i, ncol = DB_OBJ(obj)->source_size / sizeof(grn_id);
- grn_obj_flags flags;
- grn_ii *ii = (grn_ii *)obj;
- grn_bool use_grn_ii_build;
- grn_table_get_info(ctx, ii->lexicon, &flags, NULL, NULL, NULL, NULL);
- switch (flags & GRN_OBJ_TABLE_TYPE_MASK) {
- case GRN_OBJ_TABLE_PAT_KEY :
- case GRN_OBJ_TABLE_DAT_KEY :
- use_grn_ii_build = GRN_TRUE;
- break;
- default :
- use_grn_ii_build = GRN_FALSE;
- break;
- }
- if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) {
- use_grn_ii_build = GRN_FALSE;
- }
- if ((col = GRN_MALLOC(ncol * sizeof(grn_obj *)))) {
- for (cp = col, i = ncol; i; s++, cp++, i--) {
- if (!(*cp = grn_ctx_at(ctx, *s))) {
- ERR(GRN_INVALID_ARGUMENT, "source invalid, n=%d",i);
- GRN_FREE(col);
- return;
- }
- if (GRN_OBJ_TABLEP(grn_ctx_at(ctx, DB_OBJ(*cp)->range))) {
- use_grn_ii_build = GRN_FALSE;
- }
- }
- if (use_grn_ii_build) {
- grn_ii_build(ctx, ii, grn_index_sparsity);
- } else {
- grn_table_cursor *tc;
- if ((tc = grn_table_cursor_open(ctx, target, NULL, 0, NULL, 0,
- 0, -1, GRN_CURSOR_BY_ID))) {
- grn_id id;
- grn_obj rv;
- GRN_TEXT_INIT(&rv, 0);
- while ((id = grn_table_cursor_next_inline(ctx, tc)) != GRN_ID_NIL) {
- for (cp = col, i = ncol; i; i--, cp++) {
- GRN_BULK_REWIND(&rv);
- if (GRN_OBJ_TABLEP(*cp)) {
- grn_table_get_key2(ctx, *cp, id, &rv);
- } else {
- grn_obj_get_value(ctx, *cp, id, &rv);
- }
- call_hook_for_build(ctx, *cp, id, &rv, 0);
- }
- }
- GRN_OBJ_FIN(ctx, &rv);
- grn_table_cursor_close(ctx, tc);
- }
- }
- GRN_FREE(col);
- }
- } else {
- ERR(GRN_INVALID_ARGUMENT, "invalid target");
- }
- } else {
- ERR(GRN_INVALID_ARGUMENT, "invalid source");
- }
-}
-
-static void
update_source_hook(grn_ctx *ctx, grn_obj *obj)
{
grn_id *s = DB_OBJ(obj)->source;
int i, n = DB_OBJ(obj)->source_size / sizeof(grn_id);
- default_set_value_hook_data hook_data = { DB_OBJ(obj)->id, 0 };
+ grn_obj_default_set_value_hook_data hook_data = { DB_OBJ(obj)->id, 0 };
grn_obj *source, data;
GRN_TEXT_INIT(&data, GRN_OBJ_DO_SHALLOW_COPY);
GRN_TEXT_SET_REF(&data, &hook_data, sizeof(hook_data));
@@ -7466,7 +8241,7 @@ del_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, grn_obj *hld)
hld_size = GRN_BULK_VSIZE(hld);
if (!hld_size) { return; }
for (i = 0, last = &DB_OBJ(obj)->hooks[entry]; *last; i++, last = &(*last)->next) {
- if (!memcmp(NEXT_ADDR(*last), hld_value, hld_size)) {
+ if (!memcmp(GRN_NEXT_ADDR(*last), hld_value, hld_size)) {
grn_obj_delete_hook(ctx, obj, entry, i);
return;
}
@@ -7478,28 +8253,33 @@ delete_source_hook(grn_ctx *ctx, grn_obj *obj)
{
grn_id *s = DB_OBJ(obj)->source;
int i, n = DB_OBJ(obj)->source_size / sizeof(grn_id);
- default_set_value_hook_data hook_data = { DB_OBJ(obj)->id, 0 };
+ grn_obj_default_set_value_hook_data hook_data = { DB_OBJ(obj)->id, 0 };
grn_obj *source, data;
GRN_TEXT_INIT(&data, GRN_OBJ_DO_SHALLOW_COPY);
GRN_TEXT_SET_REF(&data, &hook_data, sizeof(hook_data));
for (i = 1; i <= n; i++, s++) {
hook_data.section = i;
- if ((source = grn_ctx_at(ctx, *s))) {
- switch (source->header.type) {
- case GRN_TABLE_HASH_KEY :
- case GRN_TABLE_PAT_KEY :
- case GRN_TABLE_DAT_KEY :
- del_hook(ctx, source, GRN_HOOK_INSERT, &data);
- del_hook(ctx, source, GRN_HOOK_DELETE, &data);
- break;
- case GRN_COLUMN_FIX_SIZE :
- case GRN_COLUMN_VAR_SIZE :
- del_hook(ctx, source, GRN_HOOK_SET, &data);
- break;
- default :
- /* invalid target */
- break;
- }
+
+ source = grn_ctx_at(ctx, *s);
+ if (!source) {
+ ERRCLR(ctx);
+ continue;
+ }
+
+ switch (source->header.type) {
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ del_hook(ctx, source, GRN_HOOK_INSERT, &data);
+ del_hook(ctx, source, GRN_HOOK_DELETE, &data);
+ break;
+ case GRN_COLUMN_FIX_SIZE :
+ case GRN_COLUMN_VAR_SIZE :
+ del_hook(ctx, source, GRN_HOOK_SET, &data);
+ break;
+ default :
+ /* invalid target */
+ break;
}
}
grn_obj_close(ctx, &data);
@@ -7518,7 +8298,7 @@ grn_hook_pack(grn_ctx *ctx, grn_db_obj *obj, grn_obj *buf)
grn_id id = hooks->proc ? hooks->proc->obj.id : 0;
if ((rc = grn_text_benc(ctx, buf, id + 1))) { goto exit; }
if ((rc = grn_text_benc(ctx, buf, hooks->hld_size))) { goto exit; }
- if ((rc = grn_bulk_write(ctx, buf, (char *)NEXT_ADDR(hooks), hooks->hld_size))) { goto exit; }
+ if ((rc = grn_bulk_write(ctx, buf, (char *)GRN_NEXT_ADDR(hooks), hooks->hld_size))) { goto exit; }
}
if ((rc = grn_text_benc(ctx, buf, 0))) { goto exit; }
}
@@ -7554,7 +8334,7 @@ grn_hook_unpack(grn_ctx *ctx, grn_db_obj *obj, const char *buf, uint32_t buf_siz
new->proc = NULL;
}
if ((new->hld_size = hld_size)) {
- grn_memcpy(NEXT_ADDR(new), p, hld_size);
+ grn_memcpy(GRN_NEXT_ADDR(new), p, hld_size);
p += hld_size;
}
*last = new;
@@ -7583,15 +8363,79 @@ grn_token_filters_pack(grn_ctx *ctx,
}
}
+static grn_bool
+grn_obj_encoded_spec_equal(grn_ctx *ctx,
+ grn_obj *encoded_spec1,
+ grn_obj *encoded_spec2)
+{
+ unsigned int i, n_elements;
+
+ if (encoded_spec1->header.type != GRN_VECTOR) {
+ return GRN_FALSE;
+ }
+
+ if (encoded_spec1->header.type != encoded_spec2->header.type) {
+ return GRN_FALSE;
+ }
+
+ n_elements = grn_vector_size(ctx, encoded_spec1);
+ if (grn_vector_size(ctx, encoded_spec2) != n_elements) {
+ return GRN_FALSE;
+ }
+
+ for (i = 0; i < n_elements; i++) {
+ const char *content1;
+ const char *content2;
+ unsigned int content_size1;
+ unsigned int content_size2;
+ unsigned int weight1;
+ unsigned int weight2;
+ grn_id domain1;
+ grn_id domain2;
+
+ content_size1 = grn_vector_get_element(ctx,
+ encoded_spec1,
+ i,
+ &content1,
+ &weight1,
+ &domain1);
+ content_size2 = grn_vector_get_element(ctx,
+ encoded_spec2,
+ i,
+ &content2,
+ &weight2,
+ &domain2);
+ if (content_size1 != content_size2) {
+ return GRN_FALSE;
+ }
+ if (memcmp(content1, content2, content_size1) != 0) {
+ return GRN_FALSE;
+ }
+ if (weight1 != weight2) {
+ return GRN_FALSE;
+ }
+ if (domain1 != domain2) {
+ return GRN_FALSE;
+ }
+ }
+
+ return GRN_TRUE;
+}
+
void
grn_obj_spec_save(grn_ctx *ctx, grn_db_obj *obj)
{
grn_db *s;
grn_obj v, *b;
grn_obj_spec spec;
+ grn_bool need_update = GRN_TRUE;
+
if (obj->id & GRN_OBJ_TMP_OBJECT) { return; }
if (!ctx->impl || !GRN_DB_OBJP(obj)) { return; }
if (!(s = (grn_db *)ctx->impl->db) || !s->specs) { return; }
+ if (obj->header.type == GRN_PROC && obj->range == GRN_ID_NIL) {
+ return;
+ }
GRN_OBJ_INIT(&v, GRN_VECTOR, 0, GRN_DB_TEXT);
if (!(b = grn_vector_body(ctx, &v))) { return; }
spec.header = obj->header;
@@ -7624,32 +8468,107 @@ grn_obj_spec_save(grn_ctx *ctx, grn_db_obj *obj)
grn_vector_delimit(ctx, &v, 0, 0);
break;
}
+
+ {
+ grn_io_win jw;
+ uint32_t current_spec_raw_len;
+ char *current_spec_raw;
+
+ current_spec_raw = grn_ja_ref(ctx,
+ s->specs,
+ obj->id,
+ &jw,
+ &current_spec_raw_len);
+ if (current_spec_raw) {
+ grn_rc rc;
+ grn_obj current_spec;
+
+ GRN_OBJ_INIT(&current_spec, GRN_VECTOR, 0, GRN_DB_TEXT);
+ rc = grn_vector_decode(ctx,
+ &current_spec,
+ current_spec_raw,
+ current_spec_raw_len);
+ if (rc == GRN_SUCCESS) {
+ need_update = !grn_obj_encoded_spec_equal(ctx, &v, &current_spec);
+ }
+ GRN_OBJ_FIN(ctx, &current_spec);
+ grn_ja_unref(ctx, &jw);
+ }
+ }
+
+ if (!need_update) {
+ grn_obj_close(ctx, &v);
+ return;
+ }
+
+ {
+ const char *name;
+ uint32_t name_size = 0;
+ const char *range_name = NULL;
+ uint32_t range_name_size = 0;
+
+ name = _grn_table_key(ctx, s->keys, obj->id, &name_size);
+ switch (obj->header.type) {
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ case GRN_TABLE_NO_KEY :
+ case GRN_COLUMN_FIX_SIZE :
+ case GRN_COLUMN_VAR_SIZE :
+ case GRN_COLUMN_INDEX :
+ if (obj->range != GRN_ID_NIL) {
+ range_name = _grn_table_key(ctx, s->keys, obj->range, &range_name_size);
+ }
+ break;
+ default :
+ break;
+ }
+ /* TODO: reduce log level. */
+ GRN_LOG(ctx, GRN_LOG_NOTICE,
+ "spec:%u:update:%.*s:%u(%s):%u%s%.*s%s",
+ obj->id,
+ name_size, name,
+ obj->header.type,
+ grn_obj_type_to_string(obj->header.type),
+ obj->range,
+ range_name_size == 0 ? "" : "(",
+ range_name_size, range_name,
+ range_name_size == 0 ? "" : ")");
+ }
grn_ja_putv(ctx, s->specs, obj->id, &v, 0);
grn_obj_close(ctx, &v);
}
-inline static grn_rc
-grn_obj_set_info_source_validate_report_error(grn_ctx *ctx,
- grn_obj *column,
- grn_obj *table_domain,
- grn_obj *source,
- grn_id source_type_id)
-{
- char column_name[GRN_TABLE_MAX_KEY_SIZE];
- char table_domain_name[GRN_TABLE_MAX_KEY_SIZE];
+inline static void
+grn_obj_set_info_source_invalid_lexicon_error(grn_ctx *ctx,
+ const char *message,
+ grn_obj *actual_type,
+ grn_obj *expected_type,
+ grn_obj *index_column,
+ grn_obj *source)
+{
+ char actual_type_name[GRN_TABLE_MAX_KEY_SIZE];
+ int actual_type_name_size;
+ char expected_type_name[GRN_TABLE_MAX_KEY_SIZE];
+ int expected_type_name_size;
+ char index_column_name[GRN_TABLE_MAX_KEY_SIZE];
+ int index_column_name_size;
char source_name[GRN_TABLE_MAX_KEY_SIZE];
- char source_type_name[GRN_TABLE_MAX_KEY_SIZE];
- int column_name_size;
- int table_domain_name_size;
int source_name_size;
- int source_type_name_size;
- grn_obj *source_type;
- column_name_size = grn_obj_name(ctx, column,
- column_name, GRN_TABLE_MAX_KEY_SIZE);
+ actual_type_name_size = grn_obj_name(ctx, actual_type,
+ actual_type_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ expected_type_name_size = grn_obj_name(ctx, expected_type,
+ expected_type_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ index_column_name_size = grn_obj_name(ctx, index_column,
+ index_column_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+
source_name_size = grn_obj_name(ctx, source,
source_name, GRN_TABLE_MAX_KEY_SIZE);
- if (GRN_OBJ_TABLEP(source)) {
+ if (grn_obj_is_table(ctx, source)) {
source_name[source_name_size] = '\0';
grn_strncat(source_name,
GRN_TABLE_MAX_KEY_SIZE,
@@ -7657,53 +8576,40 @@ grn_obj_set_info_source_validate_report_error(grn_ctx *ctx,
GRN_TABLE_MAX_KEY_SIZE - source_name_size - 1);
source_name_size = strlen(source_name);
}
- table_domain_name_size = grn_obj_name(ctx, table_domain,
- table_domain_name,
- GRN_TABLE_MAX_KEY_SIZE);
- source_type = grn_ctx_at(ctx, source_type_id);
- if (source_type) {
- source_type_name_size = grn_obj_name(ctx, source_type,
- source_type_name,
- GRN_TABLE_MAX_KEY_SIZE);
- grn_obj_unlink(ctx, source_type);
- } else {
- grn_strncpy(source_type_name,
- GRN_TABLE_MAX_KEY_SIZE,
- "(nil)",
- GRN_TABLE_MAX_KEY_SIZE);
- source_type_name_size = strlen(source_type_name);
- }
+
ERR(GRN_INVALID_ARGUMENT,
- "grn_obj_set_info(): GRN_INFO_SOURCE: "
- "source type must equal to index table's key type: "
- "source:<%.*s(%.*s)> index:<%.*s(%.*s)>",
- source_name_size, source_name,
- source_type_name_size, source_type_name,
- column_name_size, column_name,
- table_domain_name_size, table_domain_name);
- return ctx->rc;
+ "[column][index][source] %s: "
+ "<%.*s> -> <%.*s>: "
+ "index-column:<%.*s> "
+ "source:<%.*s>",
+ message,
+ actual_type_name_size, actual_type_name,
+ expected_type_name_size, expected_type_name,
+ index_column_name_size, index_column_name,
+ source_name_size, source_name);
}
inline static grn_rc
grn_obj_set_info_source_validate(grn_ctx *ctx, grn_obj *obj, grn_obj *value)
{
- grn_rc rc = GRN_SUCCESS;
- grn_id table_id;
- grn_obj *table = NULL;
- grn_id table_domain_id;
- grn_obj *table_domain = NULL;
+ grn_id lexicon_id;
+ grn_obj *lexicon = NULL;
+ grn_id lexicon_domain_id;
+ grn_obj *lexicon_domain = NULL;
+ grn_bool lexicon_domain_is_table;
+ grn_bool lexicon_have_tokenizer;
grn_id *source_ids;
int i, n_source_ids;
- table_id = obj->header.domain;
- table = grn_ctx_at(ctx, table_id);
- if (!table) {
+ lexicon_id = obj->header.domain;
+ lexicon = grn_ctx_at(ctx, lexicon_id);
+ if (!lexicon) {
goto exit;
}
- table_domain_id = table->header.domain;
- table_domain = grn_ctx_at(ctx, table_domain_id);
- if (!table_domain) {
+ lexicon_domain_id = lexicon->header.domain;
+ lexicon_domain = grn_ctx_at(ctx, lexicon_domain_id);
+ if (!lexicon_domain) {
goto exit;
}
@@ -7721,43 +8627,66 @@ grn_obj_set_info_source_validate(grn_ctx *ctx, grn_obj *obj, grn_obj *value)
goto exit;
}
- if (!GRN_OBJ_TABLEP(table_domain)) {
- goto exit;
+ lexicon_domain_is_table = grn_obj_is_table(ctx, lexicon_domain);
+ {
+ grn_obj *tokenizer;
+ grn_table_get_info(ctx, lexicon, NULL, NULL, &tokenizer, NULL, NULL);
+ lexicon_have_tokenizer = (tokenizer != NULL);
}
for (i = 0; i < n_source_ids; i++) {
grn_id source_id = source_ids[i];
grn_obj *source;
grn_id source_type_id;
+ grn_obj *source_type;
source = grn_ctx_at(ctx, source_id);
if (!source) {
continue;
}
- if (GRN_OBJ_TABLEP(source)) {
+ if (grn_obj_is_table(ctx, source)) {
source_type_id = source->header.domain;
} else {
source_type_id = DB_OBJ(source)->range;
}
- if (table_domain_id != source_type_id) {
- rc = grn_obj_set_info_source_validate_report_error(ctx,
- obj,
- table_domain,
- source,
- source_type_id);
+ source_type = grn_ctx_at(ctx, source_type_id);
+ if (!lexicon_have_tokenizer) {
+ if (grn_obj_is_table(ctx, source_type)) {
+ if (lexicon_id != source_type_id) {
+ grn_obj_set_info_source_invalid_lexicon_error(
+ ctx,
+ "index table must equal to source type",
+ lexicon,
+ source_type,
+ obj,
+ source);
+ }
+ } else {
+ if (!(lexicon_domain_id == source_type_id ||
+ (grn_type_id_is_text_family(ctx, lexicon_domain_id) &&
+ grn_type_id_is_text_family(ctx, source_type_id)))) {
+ grn_obj_set_info_source_invalid_lexicon_error(
+ ctx,
+ "index table's key must equal source type",
+ lexicon_domain,
+ source_type,
+ obj,
+ source);
+ }
+ }
}
grn_obj_unlink(ctx, source);
- if (rc != GRN_SUCCESS) {
+ if (ctx->rc != GRN_SUCCESS) {
goto exit;
}
}
exit:
- if (table) {
- grn_obj_unlink(ctx, table);
+ if (lexicon) {
+ grn_obj_unlink(ctx, lexicon);
}
- if (table_domain) {
- grn_obj_unlink(ctx, table_domain);
+ if (lexicon_domain) {
+ grn_obj_unlink(ctx, lexicon_domain);
}
return ctx->rc;
}
@@ -7768,7 +8697,11 @@ grn_obj_set_info_source_log(grn_ctx *ctx, grn_obj *obj, grn_obj *value)
grn_obj buf;
grn_id *vp = (grn_id *)GRN_BULK_HEAD(value);
uint32_t vs = GRN_BULK_VSIZE(value), s = 0;
- const char *n = _grn_table_key(ctx, ctx->impl->db, DB_OBJ(obj)->id, &s);
+ grn_id id;
+ const char *n;
+
+ id = DB_OBJ(obj)->id;
+ n = _grn_table_key(ctx, ctx->impl->db, id, &s);
GRN_TEXT_INIT(&buf, 0);
GRN_TEXT_PUT(ctx, &buf, n, s);
GRN_TEXT_PUTC(ctx, &buf, ' ');
@@ -7778,7 +8711,9 @@ grn_obj_set_info_source_log(grn_ctx *ctx, grn_obj *obj, grn_obj *value)
vs -= sizeof(grn_id);
if (vs) { GRN_TEXT_PUTC(ctx, &buf, ','); }
}
- GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:set_source %.*s",
+ GRN_LOG(ctx, GRN_LOG_NOTICE,
+ "DDL:%u:set_source %.*s",
+ id,
(int)GRN_BULK_VSIZE(&buf), GRN_BULK_HEAD(&buf));
GRN_OBJ_FIN(ctx, &buf);
}
@@ -7800,7 +8735,7 @@ grn_obj_set_info_source_update(grn_ctx *ctx, grn_obj *obj, grn_obj *value)
if (obj->header.type == GRN_COLUMN_INDEX) {
update_source_hook(ctx, obj);
- build_index(ctx, obj);
+ grn_index_column_build(ctx, obj);
}
} else {
DB_OBJ(obj)->source = NULL;
@@ -7883,7 +8818,8 @@ grn_obj_set_info_token_filters(grn_ctx *ctx,
token_filter_name_size);
}
if (n_token_filters > 0 || n_token_filters != n_current_token_filters) {
- GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:set_token_filters %.*s",
+ GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:%u:set_token_filters %.*s",
+ DB_OBJ(table)->id,
(int)GRN_BULK_VSIZE(&token_filter_names),
GRN_BULK_HEAD(&token_filter_names));
}
@@ -8013,7 +8949,7 @@ grn_obj_add_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry,
new->proc = (grn_proc *)proc;
new->hld_size = hld_size;
if (hld_size) {
- grn_memcpy(NEXT_ADDR(new), hld_value, hld_size);
+ grn_memcpy(GRN_NEXT_ADDR(new), hld_value, hld_size);
}
for (i = 0; i != offset && *last; i++) { last = &(*last)->next; }
new->next = *last;
@@ -8053,7 +8989,7 @@ grn_obj_get_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry,
if (!hook) { return NULL; }
}
res = (grn_obj *)hook->proc;
- grn_bulk_write(ctx, hldbuf, (char *)NEXT_ADDR(hook), hook->hld_size);
+ grn_bulk_write(ctx, hldbuf, (char *)GRN_NEXT_ADDR(hook), hook->hld_size);
}
GRN_API_RETURN(res);
}
@@ -8077,24 +9013,36 @@ grn_obj_delete_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, int offset
GRN_API_RETURN(GRN_SUCCESS);
}
-static void
+static grn_rc
remove_index(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry)
{
+ grn_rc rc = GRN_SUCCESS;
grn_hook *h0, *hooks = DB_OBJ(obj)->hooks[entry];
DB_OBJ(obj)->hooks[entry] = NULL; /* avoid mutual recursive call */
while (hooks) {
- default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks);
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
grn_obj *target = grn_ctx_at(ctx, data->target);
if (!target) {
char name[GRN_TABLE_MAX_KEY_SIZE];
int length;
+ char hook_name[GRN_TABLE_MAX_KEY_SIZE];
+ int hook_name_length;
+
length = grn_obj_name(ctx, obj, name, GRN_TABLE_MAX_KEY_SIZE);
- ERR(GRN_UNKNOWN_ERROR,
+ hook_name_length = grn_table_get_key(ctx,
+ ctx->impl->db,
+ data->target,
+ hook_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ ERR(GRN_OBJECT_CORRUPT,
"[column][remove][index] "
- "hook has a dangling reference: %.*s", length, name);
+ "hook has a dangling reference: <%.*s> -> <%.*s>",
+ length, name,
+ hook_name_length, hook_name);
+ rc = ctx->rc;
} else if (target->header.type == GRN_COLUMN_INDEX) {
//TODO: multicolumn MULTI_COLUMN_INDEXP
- _grn_obj_remove(ctx, target);
+ rc = _grn_obj_remove(ctx, target, GRN_FALSE);
} else {
//TODO: err
char fn[GRN_TABLE_MAX_KEY_SIZE];
@@ -8102,49 +9050,91 @@ remove_index(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry)
flen = grn_obj_name(ctx, target, fn, GRN_TABLE_MAX_KEY_SIZE);
fn[flen] = '\0';
ERR(GRN_UNKNOWN_ERROR, "column has unsupported hooks, col=%s",fn);
+ rc = ctx->rc;
+ }
+ if (rc != GRN_SUCCESS) {
+ DB_OBJ(obj)->hooks[entry] = hooks;
+ break;
}
h0 = hooks;
hooks = hooks->next;
GRN_FREE(h0);
}
+ return rc;
}
-static void
+static grn_rc
remove_columns(grn_ctx *ctx, grn_obj *obj)
{
+ grn_rc rc = GRN_SUCCESS;
grn_hash *cols;
if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) {
if (grn_table_columns(ctx, obj, "", 0, (grn_obj *)cols)) {
- grn_id *key;
- GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, {
- grn_obj *col = grn_ctx_at(ctx, *key);
- if (col) { _grn_obj_remove(ctx, col); }
- });
+ GRN_HASH_EACH_BEGIN(ctx, cols, cursor, id) {
+ grn_id *key;
+ grn_obj *col;
+
+ grn_hash_cursor_get_key(ctx, cursor, (void **)&key);
+ col = grn_ctx_at(ctx, *key);
+
+ if (!col) {
+ char name[GRN_TABLE_MAX_KEY_SIZE];
+ int name_size;
+ name_size = grn_table_get_key(ctx, ctx->impl->db, *key,
+ name, GRN_TABLE_MAX_KEY_SIZE);
+ if (ctx->rc == GRN_SUCCESS) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[object][remove] column is broken: <%.*s>",
+ name_size, name);
+ } else {
+ ERR(ctx->rc,
+ "[object][remove] column is broken: <%.*s>: %s",
+ name_size, name,
+ ctx->errbuf);
+ }
+ rc = ctx->rc;
+ break;
+ }
+
+ rc = _grn_obj_remove(ctx, col, GRN_FALSE);
+ if (rc != GRN_SUCCESS) {
+ grn_obj_unlink(ctx, col);
+ break;
+ }
+ } GRN_HASH_EACH_END(ctx, cursor);
}
grn_hash_close(ctx, cols);
}
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_db_index_columns(grn_ctx *ctx, grn_obj *db)
{
+ grn_rc rc = GRN_SUCCESS;
grn_table_cursor *cur;
if ((cur = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0))) {
grn_id id;
while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) {
grn_obj *obj = grn_ctx_at(ctx, id);
if (obj && obj->header.type == GRN_COLUMN_INDEX) {
- _grn_obj_remove(ctx, obj);
+ rc = _grn_obj_remove(ctx, obj, GRN_FALSE);
+ if (rc != GRN_SUCCESS) {
+ grn_obj_unlink(ctx, obj);
+ break;
+ }
}
}
grn_table_cursor_close(ctx, cur);
}
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_db_reference_columns(grn_ctx *ctx, grn_obj *db)
{
+ grn_rc rc = GRN_SUCCESS;
grn_table_cursor *cur;
if ((cur = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0))) {
grn_id id;
@@ -8169,23 +9159,29 @@ _grn_obj_remove_db_reference_columns(grn_ctx *ctx, grn_obj *db)
}
switch (range->header.type) {
- case GRN_TABLE_NO_KEY :
- case GRN_TABLE_HASH_KEY :
- case GRN_TABLE_PAT_KEY :
- case GRN_TABLE_DAT_KEY :
- _grn_obj_remove(ctx, obj);
- break;
+ case GRN_TABLE_NO_KEY :
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ rc = _grn_obj_remove(ctx, obj, GRN_FALSE);
+ break;
}
break;
}
+
+ if (rc != GRN_SUCCESS) {
+ break;
+ }
}
grn_table_cursor_close(ctx, cur);
}
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_db_reference_tables(grn_ctx *ctx, grn_obj *db)
{
+ grn_rc rc = GRN_SUCCESS;
grn_table_cursor *cur;
if ((cur = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0))) {
grn_id id;
@@ -8211,23 +9207,29 @@ _grn_obj_remove_db_reference_tables(grn_ctx *ctx, grn_obj *db)
}
switch (domain->header.type) {
- case GRN_TABLE_NO_KEY :
- case GRN_TABLE_HASH_KEY :
- case GRN_TABLE_PAT_KEY :
- case GRN_TABLE_DAT_KEY :
- _grn_obj_remove(ctx, obj);
- break;
+ case GRN_TABLE_NO_KEY :
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ rc = _grn_obj_remove(ctx, obj, GRN_FALSE);
+ break;
}
break;
}
+
+ if (rc != GRN_SUCCESS) {
+ break;
+ }
}
grn_table_cursor_close(ctx, cur);
}
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_db_all_tables(grn_ctx *ctx, grn_obj *db)
{
+ grn_rc rc = GRN_SUCCESS;
grn_table_cursor *cur;
if ((cur = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0))) {
grn_id id;
@@ -8243,28 +9245,43 @@ _grn_obj_remove_db_all_tables(grn_ctx *ctx, grn_obj *db)
case GRN_TABLE_HASH_KEY :
case GRN_TABLE_PAT_KEY :
case GRN_TABLE_DAT_KEY :
- _grn_obj_remove(ctx, obj);
+ rc = _grn_obj_remove(ctx, obj, GRN_FALSE);
+ break;
+ }
+
+ if (rc != GRN_SUCCESS) {
break;
}
}
grn_table_cursor_close(ctx, cur);
}
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_db(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id,
const char *path)
{
+ grn_rc rc = GRN_SUCCESS;
const char *io_spath;
char *spath;
grn_db *s = (grn_db *)db;
unsigned char key_type;
+ rc = _grn_obj_remove_db_index_columns(ctx, db);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = _grn_obj_remove_db_reference_columns(ctx, db);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = _grn_obj_remove_db_reference_tables(ctx, db);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = _grn_obj_remove_db_all_tables(ctx, db);
+ if (rc != GRN_SUCCESS) { return rc; }
+
if (s->specs &&
(io_spath = grn_obj_path(ctx, (grn_obj *)s->specs)) && *io_spath != '\0') {
if (!(spath = GRN_STRDUP(io_spath))) {
ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_spath);
- return;
+ return ctx->rc;
}
} else {
spath = NULL;
@@ -8272,39 +9289,53 @@ _grn_obj_remove_db(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id,
key_type = s->keys->header.type;
- _grn_obj_remove_db_index_columns(ctx, db);
- _grn_obj_remove_db_reference_columns(ctx, db);
- _grn_obj_remove_db_reference_tables(ctx, db);
- _grn_obj_remove_db_all_tables(ctx, db);
-
- grn_obj_close(ctx, obj);
+ rc = grn_obj_close(ctx, obj);
+ if (rc != GRN_SUCCESS) {
+ if (spath) {
+ GRN_FREE(spath);
+ }
+ return rc;
+ }
if (spath) {
- grn_ja_remove(ctx, spath);
+ rc = grn_ja_remove(ctx, spath);
GRN_FREE(spath);
+ if (rc != GRN_SUCCESS) { return rc; }
}
if (path) {
switch (key_type) {
case GRN_TABLE_PAT_KEY :
- grn_pat_remove(ctx, path);
+ rc = grn_pat_remove(ctx, path);
break;
case GRN_TABLE_DAT_KEY :
- grn_dat_remove(ctx, path);
+ rc = grn_dat_remove(ctx, path);
break;
}
+ if (rc == GRN_SUCCESS) {
+ rc = grn_db_config_remove(ctx, path);
+ } else {
+ grn_db_config_remove(ctx, path);
+ }
}
+
+ return rc;
}
-static grn_bool
-is_removable_table(grn_ctx *ctx, grn_obj *table, grn_obj *db)
+static grn_rc
+remove_reference_tables(grn_ctx *ctx, grn_obj *table, grn_obj *db)
{
- grn_bool removable = GRN_TRUE;
+ grn_rc rc = GRN_SUCCESS;
+ grn_bool is_close_opened_object_mode = GRN_FALSE;
grn_id table_id;
char table_name[GRN_TABLE_MAX_KEY_SIZE];
int table_name_size;
grn_table_cursor *cursor;
+ if (grn_thread_get_limit() == 1) {
+ is_close_opened_object_mode = GRN_TRUE;
+ }
+
table_id = DB_OBJ(table)->id;
table_name_size = grn_obj_name(ctx, table, table_name, GRN_TABLE_MAX_KEY_SIZE);
if ((cursor = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1,
@@ -8312,10 +9343,18 @@ is_removable_table(grn_ctx *ctx, grn_obj *table, grn_obj *db)
grn_id id;
while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
grn_obj *object;
+ grn_bool is_removed = GRN_FALSE;
+
+ if (is_close_opened_object_mode) {
+ grn_ctx_push_temporary_open_space(ctx);
+ }
object = grn_ctx_at(ctx, id);
if (!object) {
ERRCLR(ctx);
+ if (is_close_opened_object_mode) {
+ grn_ctx_pop_temporary_open_space(ctx);
+ }
continue;
}
@@ -8328,204 +9367,435 @@ is_removable_table(grn_ctx *ctx, grn_obj *table, grn_obj *db)
}
if (object->header.domain == table_id) {
- char reference_table_name[GRN_TABLE_MAX_KEY_SIZE];
- int reference_table_name_size;
- reference_table_name_size =
- grn_obj_name(ctx, object, reference_table_name,
- GRN_TABLE_MAX_KEY_SIZE);
- ERR(GRN_OPERATION_NOT_PERMITTED,
- "[table][remove] a table that references the table exists: "
- "<%.*s._key> -> <%.*s>",
- reference_table_name_size, reference_table_name,
- table_name_size, table_name);
- removable = GRN_FALSE;
+ rc = _grn_obj_remove(ctx, object, GRN_TRUE);
+ is_removed = (grn_table_at(ctx, db, id) == GRN_ID_NIL);
}
break;
+ case GRN_TABLE_NO_KEY :
+ break;
case GRN_COLUMN_VAR_SIZE :
case GRN_COLUMN_FIX_SIZE :
if (object->header.domain == table_id) {
break;
}
if (DB_OBJ(object)->range == table_id) {
- char column_name[GRN_TABLE_MAX_KEY_SIZE];
- int column_name_size;
- column_name_size = grn_obj_name(ctx, object, column_name,
- GRN_TABLE_MAX_KEY_SIZE);
- ERR(GRN_OPERATION_NOT_PERMITTED,
- "[table][remove] a column that references the table exists: "
- "<%.*s> -> <%.*s>",
- column_name_size, column_name,
- table_name_size, table_name);
- removable = GRN_FALSE;
+ rc = _grn_obj_remove(ctx, object, GRN_FALSE);
+ is_removed = (grn_table_at(ctx, db, id) == GRN_ID_NIL);
}
break;
+ case GRN_COLUMN_INDEX :
+ break;
default:
break;
}
- grn_obj_unlink(ctx, object);
- if (!removable) {
+ if (!is_removed) {
+ grn_obj_unlink(ctx, object);
+ }
+
+ if (is_close_opened_object_mode) {
+ grn_ctx_pop_temporary_open_space(ctx);
+ }
+
+ if (rc != GRN_SUCCESS) {
break;
}
}
grn_table_cursor_close(ctx, cursor);
}
- return removable;
+ return rc;
}
-static void
+static grn_bool
+is_removable_table(grn_ctx *ctx, grn_obj *table, grn_obj *db)
+{
+ grn_id table_id;
+ grn_id reference_object_id;
+
+ table_id = DB_OBJ(table)->id;
+ if (table_id & GRN_OBJ_TMP_OBJECT) {
+ return GRN_TRUE;
+ }
+
+ reference_object_id = grn_table_find_reference_object(ctx, table);
+ if (reference_object_id == GRN_ID_NIL) {
+ return GRN_TRUE;
+ }
+
+ {
+ grn_obj *db;
+ const char *table_name;
+ int table_name_size;
+ grn_obj *reference_object;
+ const char *reference_object_name;
+ int reference_object_name_size;
+
+ db = grn_ctx_db(ctx);
+
+ table_name = _grn_table_key(ctx, db, table_id,&table_name_size);
+
+ reference_object = grn_ctx_at(ctx, reference_object_id);
+ reference_object_name = _grn_table_key(ctx,
+ db,
+ reference_object_id,
+ &reference_object_name_size);
+ if (reference_object) {
+ if (grn_obj_is_table(ctx, reference_object)) {
+ ERR(GRN_OPERATION_NOT_PERMITTED,
+ "[table][remove] a table that references the table exists: "
+ "<%.*s._key> -> <%.*s>",
+ reference_object_name_size, reference_object_name,
+ table_name_size, table_name);
+ } else {
+ ERR(GRN_OPERATION_NOT_PERMITTED,
+ "[table][remove] a column that references the table exists: "
+ "<%.*s> -> <%.*s>",
+ reference_object_name_size, reference_object_name,
+ table_name_size, table_name);
+ }
+ } else {
+ ERR(GRN_OPERATION_NOT_PERMITTED,
+ "[table][remove] a dangling object that references the table exists: "
+ "<%.*s(%u)> -> <%.*s>",
+ reference_object_name_size,
+ reference_object_name,
+ reference_object_id,
+ table_name_size, table_name);
+ }
+ }
+
+ return GRN_FALSE;
+}
+
+static inline grn_rc
+_grn_obj_remove_spec(grn_ctx *ctx, grn_obj *db, grn_id id, uint8_t type)
+{
+ const char *name;
+ uint32_t name_size = 0;
+
+ name = _grn_table_key(ctx, db, id, &name_size);
+ /* TODO: reduce log level. */
+ GRN_LOG(ctx, GRN_LOG_NOTICE,
+ "spec:%u:remove:%.*s:%u(%s)",
+ id,
+ name_size, name,
+ type,
+ grn_obj_type_to_string(type));
+
+ return grn_ja_put(ctx, ((grn_db *)db)->specs, id, NULL, 0, GRN_OBJ_SET, NULL);
+}
+
+static grn_rc
_grn_obj_remove_pat(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id,
- const char *path)
+ const char *path, grn_bool dependent)
{
- if (!is_removable_table(ctx, obj, db)) {
- return;
+ grn_rc rc = GRN_SUCCESS;
+ uint8_t type;
+
+ type = obj->header.type;
+
+ if (dependent) {
+ rc = remove_reference_tables(ctx, obj, db);
+ if (rc != GRN_SUCCESS) {
+ return rc;
+ }
+ } else {
+ if (!is_removable_table(ctx, obj, db)) {
+ return ctx->rc;
+ }
}
- remove_index(ctx, obj, GRN_HOOK_INSERT);
- remove_columns(ctx, obj);
- grn_obj_close(ctx, obj);
+
+ rc = remove_index(ctx, obj, GRN_HOOK_INSERT);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = remove_columns(ctx, obj);
+ if (rc != GRN_SUCCESS) { return rc; }
+
+ rc = grn_obj_close(ctx, obj);
+ if (rc != GRN_SUCCESS) { return rc; }
+
if (path) {
- grn_ja_put(ctx, ((grn_db *)db)->specs, id, NULL, 0, GRN_OBJ_SET, NULL);
- grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
- grn_pat_remove(ctx, path);
+ rc = grn_pat_remove(ctx, path);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = _grn_obj_remove_spec(ctx, db, id, type);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
+ if (rc != GRN_SUCCESS) { return rc; }
}
+
grn_obj_touch(ctx, db, NULL);
+
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_dat(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id,
- const char *path)
+ const char *path, grn_bool dependent)
{
- if (!is_removable_table(ctx, obj, db)) {
- return;
+ grn_rc rc = GRN_SUCCESS;
+ uint8_t type;
+
+ type = obj->header.type;
+
+ if (dependent) {
+ rc = remove_reference_tables(ctx, obj, db);
+ if (rc != GRN_SUCCESS) {
+ return rc;
+ }
+ } else {
+ if (!is_removable_table(ctx, obj, db)) {
+ return ctx->rc;
+ }
}
- remove_index(ctx, obj, GRN_HOOK_INSERT);
- remove_columns(ctx, obj);
- grn_obj_close(ctx, obj);
+
+ rc = remove_index(ctx, obj, GRN_HOOK_INSERT);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = remove_columns(ctx, obj);
+ if (rc != GRN_SUCCESS) { return rc; }
+
+ rc = grn_obj_close(ctx, obj);
+ if (rc != GRN_SUCCESS) { return rc; }
+
if (path) {
- grn_ja_put(ctx, ((grn_db *)db)->specs, id, NULL, 0, GRN_OBJ_SET, NULL);
- grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
- grn_dat_remove(ctx, path);
+ rc = grn_dat_remove(ctx, path);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = _grn_obj_remove_spec(ctx, db, id, type);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
+ if (rc != GRN_SUCCESS) { return rc; }
}
+
grn_obj_touch(ctx, db, NULL);
+
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_hash(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id,
- const char *path)
+ const char *path, grn_bool dependent)
{
- if (!is_removable_table(ctx, obj, db)) {
- return;
+ grn_rc rc = GRN_SUCCESS;
+ uint8_t type;
+
+ type = obj->header.type;
+
+ if (dependent) {
+ rc = remove_reference_tables(ctx, obj, db);
+ if (rc != GRN_SUCCESS) {
+ return rc;
+ }
+ } else {
+ if (!is_removable_table(ctx, obj, db)) {
+ return ctx->rc;
+ }
}
- remove_index(ctx, obj, GRN_HOOK_INSERT);
- remove_columns(ctx, obj);
- grn_obj_close(ctx, obj);
+
+ rc = remove_index(ctx, obj, GRN_HOOK_INSERT);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = remove_columns(ctx, obj);
+ if (rc != GRN_SUCCESS) { return rc; }
+
+ rc = grn_obj_close(ctx, obj);
+ if (rc != GRN_SUCCESS) { return rc; }
+
if (path) {
- grn_ja_put(ctx, ((grn_db *)db)->specs, id, NULL, 0, GRN_OBJ_SET, NULL);
- grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
- grn_hash_remove(ctx, path);
+ rc = grn_hash_remove(ctx, path);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = _grn_obj_remove_spec(ctx, db, id, type);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
+ if (rc != GRN_SUCCESS) { return rc; }
}
+
grn_obj_touch(ctx, db, NULL);
+
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_array(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id,
- const char *path)
+ const char *path, grn_bool dependent)
{
- if (!is_removable_table(ctx, obj, db)) {
- return;
+ grn_rc rc = GRN_SUCCESS;
+ uint8_t type;
+
+ type = obj->header.type;
+
+ if (dependent) {
+ rc = remove_reference_tables(ctx, obj, db);
+ if (rc != GRN_SUCCESS) {
+ return rc;
+ }
+ } else {
+ if (!is_removable_table(ctx, obj, db)) {
+ return ctx->rc;
+ }
}
- remove_columns(ctx, obj);
- grn_obj_close(ctx, obj);
+
+ rc = remove_columns(ctx, obj);
+ if (rc != GRN_SUCCESS) { return rc; }
+
+ rc = grn_obj_close(ctx, obj);
+ if (rc != GRN_SUCCESS) { return rc; }
+
if (path) {
- grn_ja_put(ctx, ((grn_db *)db)->specs, id, NULL, 0, GRN_OBJ_SET, NULL);
- grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
- grn_array_remove(ctx, path);
+ rc = grn_array_remove(ctx, path);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = _grn_obj_remove_spec(ctx, db, id, type);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
+ if (rc != GRN_SUCCESS) { return rc; }
}
+
grn_obj_touch(ctx, db, NULL);
+
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_ja(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id,
const char *path)
{
- remove_index(ctx, obj, GRN_HOOK_SET);
- grn_obj_close(ctx, obj);
+ grn_rc rc = GRN_SUCCESS;
+ uint8_t type;
+
+ type = obj->header.type;
+
+ rc = remove_index(ctx, obj, GRN_HOOK_SET);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = grn_obj_close(ctx, obj);
+ if (rc != GRN_SUCCESS) { return rc; }
+
if (path) {
- grn_ja_put(ctx, ((grn_db *)db)->specs, id, NULL, 0, GRN_OBJ_SET, NULL);
- grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
- grn_ja_remove(ctx, path);
+ rc = grn_ja_remove(ctx, path);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = _grn_obj_remove_spec(ctx, db, id, type);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
+ if (rc != GRN_SUCCESS) { return rc; }
}
+
grn_obj_touch(ctx, db, NULL);
+
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_ra(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id,
const char *path)
{
- remove_index(ctx, obj, GRN_HOOK_SET);
- grn_obj_close(ctx, obj);
+ grn_rc rc = GRN_SUCCESS;
+ uint8_t type;
+
+ type = obj->header.type;
+
+ rc = remove_index(ctx, obj, GRN_HOOK_SET);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = grn_obj_close(ctx, obj);
+ if (rc != GRN_SUCCESS) { return rc; }
+
if (path) {
- grn_ja_put(ctx, ((grn_db *)db)->specs, id, NULL, 0, GRN_OBJ_SET, NULL);
- grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
- grn_ra_remove(ctx, path);
+ rc = grn_ra_remove(ctx, path);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = _grn_obj_remove_spec(ctx, db, id, type);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
+ if (rc != GRN_SUCCESS) { return rc; }
}
grn_obj_touch(ctx, db, NULL);
+
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_index(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id,
const char *path)
{
+ grn_rc rc = GRN_SUCCESS;
+ uint8_t type;
+
+ type = obj->header.type;
+
delete_source_hook(ctx, obj);
- grn_obj_close(ctx, obj);
+ rc = grn_obj_close(ctx, obj);
+ if (rc != GRN_SUCCESS) { return rc; }
+
if (path) {
- grn_ja_put(ctx, ((grn_db *)db)->specs, id, NULL, 0, GRN_OBJ_SET, NULL);
- grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
- grn_ii_remove(ctx, path);
+ rc = grn_ii_remove(ctx, path);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = _grn_obj_remove_spec(ctx, db, id, type);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
+ if (rc != GRN_SUCCESS) { return rc; }
}
+
grn_obj_touch(ctx, db, NULL);
+
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_db_obj(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id,
const char *path)
{
- grn_obj_close(ctx, obj);
- if (!(id & GRN_OBJ_TMP_OBJECT)) {
- grn_ja_put(ctx, ((grn_db *)db)->specs, id, NULL, 0, GRN_OBJ_SET, NULL);
- grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
- }
+ grn_rc rc = GRN_SUCCESS;
+ uint8_t type;
+
+ type = obj->header.type;
+
+ rc = grn_obj_close(ctx, obj);
+ if (rc != GRN_SUCCESS) { return rc; }
+
if (path) {
- grn_io_remove(ctx, path);
+ rc = grn_io_remove(ctx, path);
+ if (rc != GRN_SUCCESS) { return rc; }
+ }
+
+ if (!(id & GRN_OBJ_TMP_OBJECT)) {
+ rc = _grn_obj_remove_spec(ctx, db, id, type);
+ if (rc != GRN_SUCCESS) { return rc; }
+ rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
+ if (rc != GRN_SUCCESS) { return rc; }
}
+
grn_obj_touch(ctx, db, NULL);
+
+ return rc;
}
-static void
+static grn_rc
_grn_obj_remove_other(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id,
const char *path)
{
- grn_obj_close(ctx, obj);
+ return grn_obj_close(ctx, obj);
}
-static void
-_grn_obj_remove(grn_ctx *ctx, grn_obj *obj)
+static grn_rc
+_grn_obj_remove(grn_ctx *ctx, grn_obj *obj, grn_bool dependent)
{
+ grn_rc rc = GRN_SUCCESS;
grn_id id = GRN_ID_NIL;
grn_obj *db = NULL;
const char *io_path;
char *path;
+ grn_bool is_temporary_open_target = GRN_FALSE;
+
if (ctx->impl && ctx->impl->db) {
+ grn_id id;
uint32_t s = 0;
- const char *n = _grn_table_key(ctx, ctx->impl->db, DB_OBJ(obj)->id, &s);
- GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:obj_remove %.*s", s, n);
+ const char *n;
+
+ id = DB_OBJ(obj)->id;
+ n = _grn_table_key(ctx, ctx->impl->db, id, &s);
+ if (s > 0) {
+ GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:%u:obj_remove %.*s", id, s, n);
+ }
}
if (obj->header.type != GRN_PROC &&
(io_path = grn_obj_path(ctx, obj)) && *io_path != '\0') {
if (!(path = GRN_STRDUP(io_path))) {
ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_path);
- return;
+ return ctx->rc;
}
} else {
path = NULL;
@@ -8536,53 +9806,140 @@ _grn_obj_remove(grn_ctx *ctx, grn_obj *obj)
}
switch (obj->header.type) {
case GRN_DB :
- _grn_obj_remove_db(ctx, obj, db, id, path);
+ rc = _grn_obj_remove_db(ctx, obj, db, id, path);
break;
case GRN_TABLE_PAT_KEY :
- _grn_obj_remove_pat(ctx, obj, db, id, path);
+ rc = _grn_obj_remove_pat(ctx, obj, db, id, path, dependent);
+ is_temporary_open_target = GRN_TRUE;
break;
case GRN_TABLE_DAT_KEY :
- _grn_obj_remove_dat(ctx, obj, db, id, path);
+ rc = _grn_obj_remove_dat(ctx, obj, db, id, path, dependent);
+ is_temporary_open_target = GRN_TRUE;
break;
case GRN_TABLE_HASH_KEY :
- _grn_obj_remove_hash(ctx, obj, db, id, path);
+ rc = _grn_obj_remove_hash(ctx, obj, db, id, path, dependent);
+ is_temporary_open_target = GRN_TRUE;
break;
case GRN_TABLE_NO_KEY :
- _grn_obj_remove_array(ctx, obj, db, id, path);
+ rc = _grn_obj_remove_array(ctx, obj, db, id, path, dependent);
+ is_temporary_open_target = GRN_TRUE;
break;
case GRN_COLUMN_VAR_SIZE :
- _grn_obj_remove_ja(ctx, obj, db, id, path);
+ rc = _grn_obj_remove_ja(ctx, obj, db, id, path);
+ is_temporary_open_target = GRN_TRUE;
break;
case GRN_COLUMN_FIX_SIZE :
- _grn_obj_remove_ra(ctx, obj, db, id, path);
+ rc = _grn_obj_remove_ra(ctx, obj, db, id, path);
+ is_temporary_open_target = GRN_TRUE;
break;
case GRN_COLUMN_INDEX :
- _grn_obj_remove_index(ctx, obj, db, id, path);
+ rc = _grn_obj_remove_index(ctx, obj, db, id, path);
+ is_temporary_open_target = GRN_TRUE;
break;
default :
if (GRN_DB_OBJP(obj)) {
- _grn_obj_remove_db_obj(ctx, obj, db, id, path);
+ rc = _grn_obj_remove_db_obj(ctx, obj, db, id, path);
} else {
- _grn_obj_remove_other(ctx, obj, db, id, path);
+ rc = _grn_obj_remove_other(ctx, obj, db, id, path);
}
}
- if (path) { GRN_FREE(path); }
+ if (path) {
+ GRN_FREE(path);
+ } else {
+ is_temporary_open_target = GRN_FALSE;
+ }
+
+ if (is_temporary_open_target && rc == GRN_SUCCESS) {
+ grn_obj *space;
+ space = ctx->impl->temporary_open_spaces.current;
+ if (space) {
+ unsigned int i, n_elements;
+ n_elements = GRN_BULK_VSIZE(space) / sizeof(grn_obj *);
+ for (i = 0; i < n_elements; i++) {
+ if (GRN_PTR_VALUE_AT(space, i) == obj) {
+ GRN_PTR_SET_AT(ctx, space, i, NULL);
+ }
+ }
+ }
+ }
+
+ return rc;
}
grn_rc
grn_obj_remove(grn_ctx *ctx, grn_obj *obj)
{
+ grn_rc rc = GRN_SUCCESS;
GRN_API_ENTER;
if (ctx->impl && ctx->impl->db && ctx->impl->db != obj) {
- grn_io *io = grn_obj_io(ctx->impl->db);
- if (!grn_io_lock(ctx, io, grn_lock_timeout)) {
- _grn_obj_remove(ctx, obj);
+ grn_io *io = grn_obj_get_io(ctx, ctx->impl->db);
+ rc = grn_io_lock(ctx, io, grn_lock_timeout);
+ if (rc == GRN_SUCCESS) {
+ rc = _grn_obj_remove(ctx, obj, GRN_FALSE);
grn_io_unlock(io);
}
} else {
- _grn_obj_remove(ctx, obj);
+ rc = _grn_obj_remove(ctx, obj, GRN_FALSE);
}
- GRN_API_RETURN(ctx->rc);
+ GRN_API_RETURN(rc);
+}
+
+grn_rc
+grn_obj_remove_dependent(grn_ctx *ctx, grn_obj *obj)
+{
+ grn_rc rc = GRN_SUCCESS;
+ GRN_API_ENTER;
+ if (ctx->impl && ctx->impl->db && ctx->impl->db != obj) {
+ grn_io *io = grn_obj_get_io(ctx, ctx->impl->db);
+ rc = grn_io_lock(ctx, io, grn_lock_timeout);
+ if (rc == GRN_SUCCESS) {
+ rc = _grn_obj_remove(ctx, obj, GRN_TRUE);
+ grn_io_unlock(io);
+ }
+ } else {
+ rc = _grn_obj_remove(ctx, obj, GRN_TRUE);
+ }
+ GRN_API_RETURN(rc);
+}
+
+grn_rc
+grn_obj_remove_force(grn_ctx *ctx, const char *name, int name_size)
+{
+ grn_rc rc = GRN_SUCCESS;
+ grn_obj *db;
+ grn_id obj_id;
+ char path[PATH_MAX];
+
+ GRN_API_ENTER;
+
+ if (!(ctx->impl && ctx->impl->db)) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[object][remove][force] database isn't initialized");
+ rc = ctx->rc;
+ goto exit;
+ }
+
+ db = ctx->impl->db;
+ if (name_size == -1) {
+ name_size = strlen(name);
+ }
+ obj_id = grn_table_get(ctx, db, name, name_size);
+ if (obj_id == GRN_ID_NIL) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[object][remove][force] nonexistent object: <%.*s>",
+ name_size, name);
+ rc = ctx->rc;
+ goto exit;
+ }
+
+ grn_obj_delete_by_id(ctx, db, obj_id, GRN_TRUE);
+ grn_obj_path_by_id(ctx, db, obj_id, path);
+ grn_io_remove_if_exist(ctx, path);
+ grn_strcat(path, PATH_MAX, ".c");
+ grn_io_remove_if_exist(ctx, path);
+
+exit :
+ GRN_API_RETURN(rc);
}
grn_rc
@@ -8714,6 +10071,9 @@ grn_column_rename(grn_ctx *ctx, grn_obj *column, const char *name, unsigned int
grn_memcpy(fullname + len + 1, name, name_size);
name_size += len + 1;
rc = grn_obj_rename(ctx, column, fullname, name_size);
+ if (rc == GRN_SUCCESS) {
+ grn_obj_touch(ctx, column, NULL);
+ }
}
exit :
GRN_API_RETURN(rc);
@@ -8735,11 +10095,21 @@ grn_obj_register(grn_ctx *ctx, grn_obj *db, const char *name, unsigned int name_
grn_db *s = (grn_db *)db;
int added;
if (!(id = grn_table_add(ctx, s->keys, name, name_size, &added))) {
- ERR(GRN_NO_MEMORY_AVAILABLE,
- "grn_table_add failed: <%.*s>", name_size, name);
+ grn_rc rc;
+ rc = ctx->rc;
+ if (rc == GRN_SUCCESS) {
+ rc = GRN_NO_MEMORY_AVAILABLE;
+ }
+ ERR(rc,
+ "[object][register] failed to register a name: <%.*s>%s%s%s",
+ name_size, name,
+ ctx->rc == GRN_SUCCESS ? "" : ": <",
+ ctx->rc == GRN_SUCCESS ? "" : ctx->errbuf,
+ ctx->rc == GRN_SUCCESS ? "" : ">");
} else if (!added) {
ERR(GRN_INVALID_ARGUMENT,
- "already used name was assigned: <%.*s>", name_size, name);
+ "[object][register] already used name was assigned: <%.*s>",
+ name_size, name);
id = GRN_ID_NIL;
}
} else if (ctx->impl && ctx->impl->values) {
@@ -8755,9 +10125,19 @@ grn_obj_delete_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, grn_bool removep)
GRN_API_ENTER;
if (id) {
if (id & GRN_OBJ_TMP_OBJECT) {
- if (ctx->impl && ctx->impl->values) {
- rc = grn_array_delete_by_id(ctx, ctx->impl->values,
- id & ~GRN_OBJ_TMP_OBJECT, NULL);
+ if (ctx->impl) {
+ if (id & GRN_OBJ_TMP_COLUMN) {
+ if (ctx->impl->temporary_columns) {
+ rc = grn_pat_delete_by_id(ctx, ctx->impl->temporary_columns,
+ id & ~(GRN_OBJ_TMP_COLUMN | GRN_OBJ_TMP_OBJECT),
+ NULL);
+ }
+ } else {
+ if (ctx->impl->values) {
+ rc = grn_array_delete_by_id(ctx, ctx->impl->values,
+ id & ~GRN_OBJ_TMP_OBJECT, NULL);
+ }
+ }
}
} else {
db_value *vp;
@@ -8794,7 +10174,7 @@ grn_obj_path_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, char *buffer)
if (!GRN_DB_P(db) || !buffer) {
rc = GRN_INVALID_ARGUMENT;
} else {
- gen_pathname(grn_obj_io(db)->path, buffer, id);
+ grn_db_generate_pathname(ctx, db, id, buffer);
}
GRN_API_RETURN(rc);
}
@@ -8806,9 +10186,17 @@ grn_db_obj_init(grn_ctx *ctx, grn_obj *db, grn_id id, grn_db_obj *obj)
grn_rc rc = GRN_SUCCESS;
if (id) {
if (id & GRN_OBJ_TMP_OBJECT) {
- if (ctx->impl && ctx->impl->values) {
- rc = grn_array_set_value(ctx, ctx->impl->values,
- id & ~GRN_OBJ_TMP_OBJECT, &obj, GRN_OBJ_SET);
+ if (id & GRN_OBJ_TMP_COLUMN) {
+ if (ctx->impl && ctx->impl->temporary_columns) {
+ grn_id real_id = id & ~(GRN_OBJ_TMP_COLUMN | GRN_OBJ_TMP_OBJECT);
+ rc = grn_pat_set_value(ctx, ctx->impl->temporary_columns,
+ real_id, &obj, GRN_OBJ_SET);
+ }
+ } else {
+ if (ctx->impl && ctx->impl->values) {
+ rc = grn_array_set_value(ctx, ctx->impl->values,
+ id & ~GRN_OBJ_TMP_OBJECT, &obj, GRN_OBJ_SET);
+ }
}
} else {
db_value *vp;
@@ -8836,19 +10224,12 @@ grn_db_obj_init(grn_ctx *ctx, grn_obj *db, grn_id id, grn_db_obj *obj)
return rc;
}
-#define SERIALIZED_SPEC_INDEX_SPEC 0
-#define SERIALIZED_SPEC_INDEX_PATH 1
-#define SERIALIZED_SPEC_INDEX_SOURCE 2
-#define SERIALIZED_SPEC_INDEX_HOOK 3
-#define SERIALIZED_SPEC_INDEX_TOKEN_FILTERS 4
-#define SERIALIZED_SPEC_INDEX_EXPR 4
-
-#define GET_PATH(spec,buffer,s,id) do {\
+#define GET_PATH(spec,decoded_spec,buffer,s,id) do {\
if (spec->header.flags & GRN_OBJ_CUSTOM_NAME) {\
const char *path;\
unsigned int size = grn_vector_get_element(ctx,\
- &v,\
- SERIALIZED_SPEC_INDEX_PATH,\
+ decoded_spec,\
+ GRN_SERIALIZED_SPEC_INDEX_PATH,\
&path,\
NULL,\
NULL);\
@@ -8856,20 +10237,22 @@ grn_db_obj_init(grn_ctx *ctx, grn_obj *db, grn_id id, grn_db_obj *obj)
grn_memcpy(buffer, path, size);\
buffer[size] = '\0';\
} else {\
- gen_pathname(grn_obj_io(s->keys)->path, buffer, id); \
+ grn_db_generate_pathname(ctx, (grn_obj *)s, id, buffer);\
}\
} while (0)
-#define UNPACK_INFO() do {\
+#define UNPACK_INFO(spec,decoded_spec) do {\
if (vp->ptr) {\
+ const char *p;\
+ uint32_t size;\
grn_db_obj *r = DB_OBJ(vp->ptr);\
r->header = spec->header;\
r->id = id;\
r->range = spec->range;\
r->db = (grn_obj *)s;\
size = grn_vector_get_element(ctx,\
- &v,\
- SERIALIZED_SPEC_INDEX_SOURCE,\
+ decoded_spec,\
+ GRN_SERIALIZED_SPEC_INDEX_SOURCE,\
&p,\
NULL,\
NULL);\
@@ -8880,8 +10263,8 @@ grn_db_obj_init(grn_ctx *ctx, grn_obj *db, grn_id id, grn_db_obj *obj)
}\
}\
size = grn_vector_get_element(ctx,\
- &v,\
- SERIALIZED_SPEC_INDEX_HOOK,\
+ decoded_spec,\
+ GRN_SERIALIZED_SPEC_INDEX_HOOK,\
&p,\
NULL,\
NULL);\
@@ -8898,13 +10281,13 @@ grn_token_filters_unpack(grn_ctx *ctx,
unsigned int element_size;
unsigned int i, n_token_filter_ids;
- if (grn_vector_size(ctx, spec_vector) <= SERIALIZED_SPEC_INDEX_TOKEN_FILTERS) {
+ if (grn_vector_size(ctx, spec_vector) <= GRN_SERIALIZED_SPEC_INDEX_TOKEN_FILTERS) {
return;
}
element_size = grn_vector_get_element(ctx,
spec_vector,
- SERIALIZED_SPEC_INDEX_TOKEN_FILTERS,
+ GRN_SERIALIZED_SPEC_INDEX_TOKEN_FILTERS,
(const char **)(&token_filter_ids),
NULL,
NULL);
@@ -8923,6 +10306,62 @@ grn_token_filters_unpack(grn_ctx *ctx,
}
}
+grn_bool
+grn_db_spec_unpack(grn_ctx *ctx,
+ grn_id id,
+ void *encoded_spec,
+ uint32_t encoded_spec_size,
+ grn_obj_spec **spec,
+ grn_obj *decoded_spec,
+ const char *error_message_tag)
+{
+ grn_obj *db;
+ grn_db *db_raw;
+ grn_rc rc;
+ uint32_t spec_size;
+
+ db = ctx->impl->db;
+ db_raw = (grn_db *)db;
+
+ rc = grn_vector_decode(ctx,
+ decoded_spec,
+ encoded_spec,
+ encoded_spec_size);
+ if (rc != GRN_SUCCESS) {
+ const char *name;
+ uint32_t name_size;
+ name = _grn_table_key(ctx, db, id, &name_size);
+ GRN_LOG((ctx), GRN_LOG_ERROR,
+ "%s: failed to decode spec: <%u>(<%.*s>):<%u>: %s",
+ error_message_tag,
+ id,
+ name_size, name,
+ encoded_spec_size,
+ grn_rc_to_string(rc));
+ return GRN_FALSE;
+ }
+
+ spec_size = grn_vector_get_element(ctx,
+ decoded_spec,
+ GRN_SERIALIZED_SPEC_INDEX_SPEC,
+ (const char **)spec,
+ NULL,
+ NULL);
+ if (spec_size == 0) {
+ const char *name;
+ uint32_t name_size;
+ name = _grn_table_key(ctx, db, id, &name_size);
+ GRN_LOG(ctx, GRN_LOG_ERROR,
+ "%s: spec value is empty: <%u>(<%.*s>)",
+ error_message_tag,
+ id,
+ name_size, name);
+ return GRN_FALSE;
+ }
+
+ return GRN_TRUE;
+}
+
grn_obj *
grn_ctx_at(grn_ctx *ctx, grn_id id)
{
@@ -8930,11 +10369,27 @@ grn_ctx_at(grn_ctx *ctx, grn_id id)
if (!ctx || !ctx->impl || !id) { return res; }
GRN_API_ENTER;
if (id & GRN_OBJ_TMP_OBJECT) {
- if (ctx->impl->values) {
- grn_obj **tmp_obj;
- tmp_obj = _grn_array_get_value(ctx, ctx->impl->values, id & ~GRN_OBJ_TMP_OBJECT);
- if (tmp_obj) {
- res = *tmp_obj;
+ if (id & GRN_OBJ_TMP_COLUMN) {
+ if (ctx->impl->temporary_columns) {
+ grn_id real_id = id & ~(GRN_OBJ_TMP_COLUMN | GRN_OBJ_TMP_OBJECT);
+ grn_obj **tmp_obj;
+ uint32_t size;
+ tmp_obj = (grn_obj **)grn_pat_get_value_(ctx,
+ ctx->impl->temporary_columns,
+ real_id,
+ &size);
+ if (tmp_obj) {
+ res = *tmp_obj;
+ }
+ }
+ } else {
+ if (ctx->impl->values) {
+ grn_obj **tmp_obj;
+ tmp_obj = _grn_array_get_value(ctx, ctx->impl->values,
+ id & ~GRN_OBJ_TMP_OBJECT);
+ if (tmp_obj) {
+ res = *tmp_obj;
+ }
}
}
} else {
@@ -8971,107 +10426,128 @@ grn_ctx_at(grn_ctx *ctx, grn_id id)
}
#endif /* USE_NREF */
if (!l) {
- grn_io_win jw;
- uint32_t value_len;
- char *value = grn_ja_ref(ctx, s->specs, id, &jw, &value_len);
- if (value) {
- grn_obj v;
- GRN_OBJ_INIT(&v, GRN_VECTOR, 0, GRN_DB_TEXT);
- if (!grn_vector_decode(ctx, &v, value, value_len)) {
- const char *p;
- uint32_t size;
- grn_obj_spec *spec;
+ grn_io_win iw;
+ uint32_t encoded_spec_size;
+ void *encoded_spec;
+
+ encoded_spec = grn_ja_ref(ctx, s->specs, id, &iw, &encoded_spec_size);
+ if (encoded_spec) {
+ grn_bool success;
+ grn_obj_spec *spec;
+ grn_obj decoded_spec;
+
+ GRN_OBJ_INIT(&decoded_spec, GRN_VECTOR, 0, GRN_DB_TEXT);
+ success = grn_db_spec_unpack(ctx,
+ id,
+ encoded_spec,
+ encoded_spec_size,
+ &spec,
+ &decoded_spec,
+ "grn_ctx_at");
+ if (success) {
char buffer[PATH_MAX];
- size = grn_vector_get_element(ctx,
- &v,
- SERIALIZED_SPEC_INDEX_SPEC,
- (const char **)&spec,
- NULL,
- NULL);
- if (size) {
- switch (spec->header.type) {
- case GRN_TYPE :
- vp->ptr = (grn_obj *)grn_type_open(ctx, spec);
- UNPACK_INFO();
- break;
- case GRN_TABLE_HASH_KEY :
- GET_PATH(spec, buffer, s, id);
- vp->ptr = (grn_obj *)grn_hash_open(ctx, buffer);
- if (vp->ptr) {
- grn_hash *hash = (grn_hash *)(vp->ptr);
- grn_obj_flags flags = vp->ptr->header.flags;
- UNPACK_INFO();
- vp->ptr->header.flags = flags;
- grn_token_filters_unpack(ctx, &(hash->token_filters), &v);
- }
- break;
- case GRN_TABLE_PAT_KEY :
- GET_PATH(spec, buffer, s, id);
- vp->ptr = (grn_obj *)grn_pat_open(ctx, buffer);
- if (vp->ptr) {
- grn_pat *pat = (grn_pat *)(vp->ptr);
- grn_obj_flags flags = vp->ptr->header.flags;
- UNPACK_INFO();
- vp->ptr->header.flags = flags;
- grn_token_filters_unpack(ctx, &(pat->token_filters), &v);
- }
- break;
- case GRN_TABLE_DAT_KEY :
- GET_PATH(spec, buffer, s, id);
- vp->ptr = (grn_obj *)grn_dat_open(ctx, buffer);
- if (vp->ptr) {
- grn_dat *dat = (grn_dat *)(vp->ptr);
- grn_obj_flags flags = vp->ptr->header.flags;
- UNPACK_INFO();
- vp->ptr->header.flags = flags;
- grn_token_filters_unpack(ctx, &(dat->token_filters), &v);
- }
- break;
- case GRN_TABLE_NO_KEY :
- GET_PATH(spec, buffer, s, id);
- vp->ptr = (grn_obj *)grn_array_open(ctx, buffer);
- UNPACK_INFO();
- break;
- case GRN_COLUMN_VAR_SIZE :
- GET_PATH(spec, buffer, s, id);
- vp->ptr = (grn_obj *)grn_ja_open(ctx, buffer);
- UNPACK_INFO();
- break;
- case GRN_COLUMN_FIX_SIZE :
- GET_PATH(spec, buffer, s, id);
- vp->ptr = (grn_obj *)grn_ra_open(ctx, buffer);
- UNPACK_INFO();
- break;
- case GRN_COLUMN_INDEX :
- GET_PATH(spec, buffer, s, id);
- {
- grn_obj *table = grn_ctx_at(ctx, spec->header.domain);
- vp->ptr = (grn_obj *)grn_ii_open(ctx, buffer, table);
- }
- UNPACK_INFO();
- break;
- case GRN_PROC :
- GET_PATH(spec, buffer, s, id);
- grn_plugin_register(ctx, buffer);
- break;
- case GRN_EXPR :
- {
- uint8_t *u;
- size = grn_vector_get_element(ctx,
- &v,
- SERIALIZED_SPEC_INDEX_EXPR,
- &p,
- NULL,
- NULL);
- u = (uint8_t *)p;
- vp->ptr = grn_expr_open(ctx, spec, u, u + size);
- }
- break;
+ switch (spec->header.type) {
+ case GRN_TYPE :
+ vp->ptr = (grn_obj *)grn_type_open(ctx, spec);
+ UNPACK_INFO(spec, &decoded_spec);
+ break;
+ case GRN_TABLE_HASH_KEY :
+ GET_PATH(spec, &decoded_spec, buffer, s, id);
+ vp->ptr = (grn_obj *)grn_hash_open(ctx, buffer);
+ if (vp->ptr) {
+ grn_hash *hash = (grn_hash *)(vp->ptr);
+ grn_obj_flags flags = vp->ptr->header.flags;
+ UNPACK_INFO(spec, &decoded_spec);
+ vp->ptr->header.flags = flags;
+ grn_token_filters_unpack(ctx,
+ &(hash->token_filters),
+ &decoded_spec);
}
+ break;
+ case GRN_TABLE_PAT_KEY :
+ GET_PATH(spec, &decoded_spec, buffer, s, id);
+ vp->ptr = (grn_obj *)grn_pat_open(ctx, buffer);
+ if (vp->ptr) {
+ grn_pat *pat = (grn_pat *)(vp->ptr);
+ grn_obj_flags flags = vp->ptr->header.flags;
+ UNPACK_INFO(spec, &decoded_spec);
+ vp->ptr->header.flags = flags;
+ grn_token_filters_unpack(ctx,
+ &(pat->token_filters),
+ &decoded_spec);
+ }
+ break;
+ case GRN_TABLE_DAT_KEY :
+ GET_PATH(spec, &decoded_spec, buffer, s, id);
+ vp->ptr = (grn_obj *)grn_dat_open(ctx, buffer);
+ if (vp->ptr) {
+ grn_dat *dat = (grn_dat *)(vp->ptr);
+ grn_obj_flags flags = vp->ptr->header.flags;
+ UNPACK_INFO(spec, &decoded_spec);
+ vp->ptr->header.flags = flags;
+ grn_token_filters_unpack(ctx,
+ &(dat->token_filters),
+ &decoded_spec);
+ }
+ break;
+ case GRN_TABLE_NO_KEY :
+ GET_PATH(spec, &decoded_spec, buffer, s, id);
+ vp->ptr = (grn_obj *)grn_array_open(ctx, buffer);
+ UNPACK_INFO(spec, &decoded_spec);
+ break;
+ case GRN_COLUMN_VAR_SIZE :
+ GET_PATH(spec, &decoded_spec, buffer, s, id);
+ vp->ptr = (grn_obj *)grn_ja_open(ctx, buffer);
+ UNPACK_INFO(spec, &decoded_spec);
+ break;
+ case GRN_COLUMN_FIX_SIZE :
+ GET_PATH(spec, &decoded_spec, buffer, s, id);
+ vp->ptr = (grn_obj *)grn_ra_open(ctx, buffer);
+ UNPACK_INFO(spec, &decoded_spec);
+ break;
+ case GRN_COLUMN_INDEX :
+ GET_PATH(spec, &decoded_spec, buffer, s, id);
+ {
+ grn_obj *table = grn_ctx_at(ctx, spec->header.domain);
+ vp->ptr = (grn_obj *)grn_ii_open(ctx, buffer, table);
+ }
+ UNPACK_INFO(spec, &decoded_spec);
+ break;
+ case GRN_PROC :
+ GET_PATH(spec, &decoded_spec, buffer, s, id);
+ grn_plugin_register(ctx, buffer);
+ break;
+ case GRN_EXPR :
+ {
+ const char *p;
+ uint32_t size;
+ uint8_t *u;
+ size = grn_vector_get_element(ctx,
+ &decoded_spec,
+ GRN_SERIALIZED_SPEC_INDEX_EXPR,
+ &p,
+ NULL,
+ NULL);
+ u = (uint8_t *)p;
+ vp->ptr = grn_expr_open(ctx, spec, u, u + size);
+ }
+ break;
+ }
+ if (!vp->ptr) {
+ const char *name;
+ uint32_t name_size = 0;
+ name = _grn_table_key(ctx, (grn_obj *)s, id, &name_size);
+ GRN_LOG(ctx, GRN_LOG_ERROR,
+ "grn_ctx_at: failed to open object: "
+ "<%u>(<%.*s>):<%u>(<%s>)",
+ id,
+ name_size, name,
+ spec->header.type,
+ grn_obj_type_to_string(spec->header.type));
}
- grn_obj_close(ctx, &v);
}
- grn_ja_unref(ctx, &jw);
+ GRN_OBJ_FIN(ctx, &decoded_spec);
+ grn_ja_unref(ctx, &iw);
}
#ifndef USE_NREF
GRN_ATOMIC_ADD_EX(pl, -1, l);
@@ -9087,6 +10563,25 @@ grn_ctx_at(grn_ctx *ctx, grn_id id)
GRN_FUTEX_WAIT(&vp->ptr);
}
}
+ if (vp->ptr) {
+ switch (vp->ptr->header.type) {
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ case GRN_TABLE_NO_KEY :
+ case GRN_COLUMN_FIX_SIZE :
+ case GRN_COLUMN_VAR_SIZE :
+ case GRN_COLUMN_INDEX :
+ {
+ grn_obj *space;
+ space = ctx->impl->temporary_open_spaces.current;
+ if (space) {
+ GRN_PTR_PUT(ctx, space, vp->ptr);
+ }
+ }
+ break;
+ }
+ }
}
res = vp->ptr;
if (res && res->header.type == GRN_PROC) {
@@ -9098,6 +10593,38 @@ exit :
GRN_API_RETURN(res);
}
+grn_bool
+grn_ctx_is_opened(grn_ctx *ctx, grn_id id)
+{
+ grn_bool is_opened = GRN_FALSE;
+
+ if (!ctx || !ctx->impl || !id) {
+ return GRN_FALSE;
+ }
+
+ GRN_API_ENTER;
+ if (id & GRN_OBJ_TMP_OBJECT) {
+ if (ctx->impl->values) {
+ grn_obj **tmp_obj;
+ tmp_obj = _grn_array_get_value(ctx, ctx->impl->values,
+ id & ~GRN_OBJ_TMP_OBJECT);
+ if (tmp_obj) {
+ is_opened = GRN_TRUE;
+ }
+ }
+ } else {
+ grn_db *s = (grn_db *)ctx->impl->db;
+ if (s) {
+ db_value *vp;
+ vp = grn_tiny_array_at(&s->values, id);
+ if (vp && vp->ptr) {
+ is_opened = GRN_TRUE;
+ }
+ }
+ }
+ GRN_API_RETURN(is_opened);
+}
+
grn_obj *
grn_obj_open(grn_ctx *ctx, unsigned char type, grn_obj_flags flags, grn_id domain)
{
@@ -9126,11 +10653,75 @@ grn_obj_graft(grn_ctx *ctx, grn_obj *obj)
}
grn_rc
+grn_pvector_fin(grn_ctx *ctx, grn_obj *obj)
+{
+ grn_rc rc;
+ if (obj->header.impl_flags & GRN_OBJ_OWN) {
+ /*
+ * Note that GRN_OBJ_OWN should not be used outside the DB API function
+ * because grn_obj_close is a DB API function.
+ */
+ unsigned int i, n_elements;
+ n_elements = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *);
+ for (i = 0; i < n_elements; i++) {
+ grn_obj *element = GRN_PTR_VALUE_AT(obj, n_elements - i - 1);
+ if (element) {
+ grn_obj_close(ctx, element);
+ }
+ }
+ }
+ obj->header.type = GRN_VOID;
+ rc = grn_bulk_fin(ctx, obj);
+ if (obj->header.impl_flags & GRN_OBJ_ALLOCATED) {
+ GRN_FREE(obj);
+ }
+ return rc;
+}
+
+static void
+grn_table_close_columns(grn_ctx *ctx, grn_obj *table)
+{
+ grn_hash *columns;
+ int n_columns;
+
+ columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
+ GRN_OBJ_TABLE_HASH_KEY | GRN_HASH_TINY);
+ if (!columns) {
+ return;
+ }
+
+ n_columns = grn_table_columns(ctx, table, "", 0, (grn_obj *)columns);
+ if (n_columns > 0) {
+ grn_hash_cursor *cursor;
+ cursor = grn_hash_cursor_open(ctx, columns, NULL, 0, NULL, 0, 0, -1, 0);
+ if (cursor) {
+ while (grn_hash_cursor_next(ctx, cursor) != GRN_ID_NIL) {
+ grn_id *id;
+ grn_obj *column;
+
+ grn_hash_cursor_get_key(ctx, cursor, (void **)&id);
+ column = grn_ctx_at(ctx, *id);
+ if (column) {
+ grn_obj_close(ctx, column);
+ }
+ }
+ grn_hash_cursor_close(ctx, cursor);
+ }
+ }
+
+ grn_hash_close(ctx, columns);
+}
+
+grn_rc
grn_obj_close(grn_ctx *ctx, grn_obj *obj)
{
grn_rc rc = GRN_INVALID_ARGUMENT;
GRN_API_ENTER;
if (obj) {
+ if (grn_obj_is_table(ctx, obj) &&
+ (DB_OBJ(obj)->id & GRN_OBJ_TMP_OBJECT)) {
+ grn_table_close_columns(ctx, obj);
+ }
if (GRN_DB_OBJP(obj)) {
grn_hook_entry entry;
if (DB_OBJ(obj)->finalizer) {
@@ -9155,14 +10746,25 @@ grn_obj_close(grn_ctx *ctx, grn_obj *obj)
break;
case GRN_VOID :
case GRN_BULK :
- case GRN_PTR :
case GRN_UVECTOR :
- case GRN_PVECTOR :
case GRN_MSG :
obj->header.type = GRN_VOID;
rc = grn_bulk_fin(ctx, obj);
if (obj->header.impl_flags & GRN_OBJ_ALLOCATED) { GRN_FREE(obj); }
break;
+ case GRN_PTR :
+ if (obj->header.impl_flags & GRN_OBJ_OWN) {
+ if (GRN_BULK_VSIZE(obj) == sizeof(grn_obj *)) {
+ grn_obj_close(ctx, GRN_PTR_VALUE(obj));
+ }
+ }
+ obj->header.type = GRN_VOID;
+ rc = grn_bulk_fin(ctx, obj);
+ if (obj->header.impl_flags & GRN_OBJ_ALLOCATED) { GRN_FREE(obj); }
+ break;
+ case GRN_PVECTOR :
+ rc = grn_pvector_fin(ctx, obj);
+ break;
case GRN_ACCESSOR :
{
grn_accessor *p, *n;
@@ -9201,6 +10803,9 @@ grn_obj_close(grn_ctx *ctx, grn_obj *obj)
case GRN_CURSOR_COLUMN_GEO_INDEX :
grn_geo_cursor_close(ctx, obj);
break;
+ case GRN_CURSOR_CONFIG :
+ grn_config_cursor_close(ctx, (grn_config_cursor *)obj);
+ break;
case GRN_TYPE :
GRN_FREE(obj);
rc = GRN_SUCCESS;
@@ -9333,6 +10938,30 @@ grn_obj_reinit(grn_ctx *ctx, grn_obj *obj, grn_id domain, unsigned char flags)
if (!GRN_OBJ_MUTABLE(obj)) {
ERR(GRN_INVALID_ARGUMENT, "invalid obj assigned");
} else {
+ switch (obj->header.type) {
+ case GRN_PTR :
+ if (obj->header.impl_flags & GRN_OBJ_OWN) {
+ if (GRN_BULK_VSIZE(obj) == sizeof(grn_obj *)) {
+ grn_obj_close(ctx, GRN_PTR_VALUE(obj));
+ }
+ obj->header.impl_flags &= ~GRN_OBJ_OWN;
+ }
+ break;
+ case GRN_PVECTOR :
+ if (obj->header.impl_flags & GRN_OBJ_OWN) {
+ unsigned int i, n_elements;
+ n_elements = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *);
+ for (i = 0; i < n_elements; i++) {
+ grn_obj *element = GRN_PTR_VALUE_AT(obj, i);
+ grn_obj_close(ctx, element);
+ }
+ obj->header.impl_flags &= ~GRN_OBJ_OWN;
+ }
+ break;
+ default :
+ break;
+ }
+
switch (domain) {
case GRN_DB_VOID :
if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); }
@@ -9413,7 +11042,7 @@ grn_obj_reinit_for(grn_ctx *ctx, grn_obj *obj, grn_obj *domain_obj)
if (!GRN_DB_OBJP(domain_obj) && domain_obj->header.type != GRN_ACCESSOR) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
- limited_size_inspect(ctx, &inspected, domain_obj);
+ grn_inspect_limited(ctx, &inspected, domain_obj);
ERR(GRN_INVALID_ARGUMENT,
"[reinit] invalid domain object: <%.*s>",
(int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected));
@@ -9443,7 +11072,7 @@ grn_obj_path(grn_ctx *ctx, grn_obj *obj)
path = grn_plugin_path(ctx, DB_OBJ(obj)->range);
GRN_API_RETURN(path);
}
- io = grn_obj_io(obj);
+ io = grn_obj_get_io(ctx, obj);
if (io && !(io->flags & GRN_IO_TEMPORARY)) { path = io->path; }
GRN_API_RETURN(path);
}
@@ -9456,8 +11085,15 @@ grn_obj_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size)
if (GRN_DB_OBJP(obj)) {
if (DB_OBJ(obj)->id) {
grn_db *s = (grn_db *)DB_OBJ(obj)->db;
- if (!(DB_OBJ(obj)->id & GRN_OBJ_TMP_OBJECT)) {
- len = grn_table_get_key(ctx, s->keys, DB_OBJ(obj)->id, namebuf, buf_size);
+ grn_id id = DB_OBJ(obj)->id;
+ if (id & GRN_OBJ_TMP_OBJECT) {
+ if (id & GRN_OBJ_TMP_COLUMN) {
+ grn_id real_id = id & ~(GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN);
+ len = grn_pat_get_key(ctx, ctx->impl->temporary_columns,
+ real_id, namebuf, buf_size);
+ }
+ } else {
+ len = grn_table_get_key(ctx, s->keys, id, namebuf, buf_size);
}
}
}
@@ -9472,66 +11108,107 @@ grn_column_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size)
if (!obj) { return len; }
GRN_API_ENTER;
if (GRN_DB_OBJP(obj)) {
- if (DB_OBJ(obj)->id && DB_OBJ(obj)->id < GRN_ID_MAX) {
+ grn_id id = DB_OBJ(obj)->id;
+ if (id & GRN_OBJ_TMP_OBJECT) {
+ if (id & GRN_OBJ_TMP_COLUMN) {
+ grn_id real_id = id & ~(GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN);
+ len = grn_pat_get_key(ctx, ctx->impl->temporary_columns,
+ real_id, buf, GRN_TABLE_MAX_KEY_SIZE);
+ }
+ } else if (id && id < GRN_ID_MAX) {
grn_db *s = (grn_db *)DB_OBJ(obj)->db;
- len = grn_table_get_key(ctx, s->keys, DB_OBJ(obj)->id, buf, GRN_TABLE_MAX_KEY_SIZE);
- if (len) {
- int cl;
- char *p = buf, *p0 = p, *pe = p + len;
- for (; p < pe && (cl = grn_charlen(ctx, p, pe)); p += cl) {
- if (*p == GRN_DB_DELIMITER && cl == 1) { p0 = p + cl; }
- }
- len = pe - p0;
- if (len && len <= buf_size) {
- grn_memcpy(namebuf, p0, len);
- }
+ len = grn_table_get_key(ctx, s->keys, id, buf, GRN_TABLE_MAX_KEY_SIZE);
+ }
+ if (len) {
+ int cl;
+ char *p = buf, *p0 = p, *pe = p + len;
+ for (; p < pe && (cl = grn_charlen(ctx, p, pe)); p += cl) {
+ if (*p == GRN_DB_DELIMITER && cl == 1) { p0 = p + cl; }
+ }
+ len = pe - p0;
+ if (len && len <= buf_size) {
+ grn_memcpy(namebuf, p0, len);
}
}
} else if (obj->header.type == GRN_ACCESSOR) {
- const char *name = NULL;
+ grn_obj name;
grn_accessor *a;
+
+ GRN_TEXT_INIT(&name, 0);
+
+#define ADD_DELMITER() do { \
+ if (GRN_TEXT_LEN(&name) > 0) { \
+ GRN_TEXT_PUTC(ctx, &name, GRN_DB_DELIMITER); \
+ } \
+ } while (GRN_FALSE)
+
for (a = (grn_accessor *)obj; a; a = a->next) {
switch (a->action) {
case GRN_ACCESSOR_GET_ID :
- name = GRN_COLUMN_NAME_ID;
+ ADD_DELMITER();
+ GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_ID);
break;
case GRN_ACCESSOR_GET_KEY :
- name = GRN_COLUMN_NAME_KEY;
+ if (!a->next) {
+ ADD_DELMITER();
+ GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_KEY);
+ }
break;
case GRN_ACCESSOR_GET_VALUE :
- name = GRN_COLUMN_NAME_VALUE;
+ if (!a->next) {
+ ADD_DELMITER();
+ GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_VALUE);
+ }
break;
case GRN_ACCESSOR_GET_SCORE :
- name = GRN_COLUMN_NAME_SCORE;
+ ADD_DELMITER();
+ GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_SCORE);
break;
case GRN_ACCESSOR_GET_NSUBRECS :
- name = GRN_COLUMN_NAME_NSUBRECS;
+ ADD_DELMITER();
+ GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_NSUBRECS);
break;
case GRN_ACCESSOR_GET_MAX :
- name = GRN_COLUMN_NAME_MAX;
+ ADD_DELMITER();
+ GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_MAX);
break;
case GRN_ACCESSOR_GET_MIN :
- name = GRN_COLUMN_NAME_MIN;
+ ADD_DELMITER();
+ GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_MIN);
break;
case GRN_ACCESSOR_GET_SUM :
- name = GRN_COLUMN_NAME_SUM;
+ ADD_DELMITER();
+ GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_SUM);
break;
case GRN_ACCESSOR_GET_AVG :
- name = GRN_COLUMN_NAME_AVG;
+ ADD_DELMITER();
+ GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_AVG);
break;
case GRN_ACCESSOR_GET_COLUMN_VALUE :
+ ADD_DELMITER();
+ {
+ char column_name[GRN_TABLE_MAX_KEY_SIZE];
+ int column_name_size;
+ column_name_size = grn_column_name(ctx, a->obj,
+ column_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ GRN_TEXT_PUT(ctx, &name, column_name, column_name_size);
+ }
+ break;
case GRN_ACCESSOR_GET_DB_OBJ :
case GRN_ACCESSOR_LOOKUP :
case GRN_ACCESSOR_FUNCALL :
break;
}
}
- if (name) {
- len = strlen(name);
- if (len <= buf_size) {
- grn_memcpy(namebuf, name, len);
- }
+#undef ADD_DELIMITER
+
+ len = GRN_TEXT_LEN(&name);
+ if (len > 0 && len <= buf_size) {
+ grn_memcpy(namebuf, GRN_TEXT_VALUE(&name), len);
}
+
+ GRN_OBJ_FIN(ctx, &name);
}
GRN_API_RETURN(len);
}
@@ -9540,18 +11217,25 @@ grn_rc
grn_column_name_(grn_ctx *ctx, grn_obj *obj, grn_obj *buf)
{
if (GRN_DB_OBJP(obj)) {
- if (DB_OBJ(obj)->id && DB_OBJ(obj)->id < GRN_ID_MAX) {
- uint32_t len;
+ uint32_t len = 0;
+ const char *p = NULL;
+ grn_id id = DB_OBJ(obj)->id;
+ if (id & GRN_OBJ_TMP_OBJECT) {
+ if (id & GRN_OBJ_TMP_COLUMN) {
+ grn_id real_id = id & ~(GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN);
+ p = _grn_pat_key(ctx, ctx->impl->temporary_columns, real_id, &len);
+ }
+ } else if (id && id < GRN_ID_MAX) {
grn_db *s = (grn_db *)DB_OBJ(obj)->db;
- const char *p = _grn_table_key(ctx, s->keys, DB_OBJ(obj)->id, &len);
- if (len) {
- int cl;
- const char *p0 = p, *pe = p + len;
- for (; p < pe && (cl = grn_charlen(ctx, p, pe)); p += cl) {
- if (*p == GRN_DB_DELIMITER && cl == 1) { p0 = p + cl; }
- }
- GRN_TEXT_PUT(ctx, buf, p0, pe - p0);
+ p = _grn_table_key(ctx, s->keys, id, &len);
+ }
+ if (len) {
+ int cl;
+ const char *p0 = p, *pe = p + len;
+ for (; p < pe && (cl = grn_charlen(ctx, p, pe)); p += cl) {
+ if (*p == GRN_DB_DELIMITER && cl == 1) { p0 = p + cl; }
}
+ GRN_TEXT_PUT(ctx, buf, p0, pe - p0);
}
} else if (obj->header.type == GRN_ACCESSOR) {
grn_accessor *a;
@@ -9635,7 +11319,10 @@ grn_obj_lock(grn_ctx *ctx, grn_obj *obj, grn_id id, int timeout)
{
grn_rc rc = GRN_SUCCESS;
GRN_API_ENTER;
- rc = grn_io_lock(ctx, grn_obj_io(obj), timeout);
+ rc = grn_io_lock(ctx, grn_obj_get_io(ctx, obj), timeout);
+ if (rc == GRN_SUCCESS && obj && obj->header.type == GRN_COLUMN_INDEX) {
+ rc = grn_io_lock(ctx, ((grn_ii *)obj)->chunk, timeout);
+ }
GRN_API_RETURN(rc);
}
@@ -9643,7 +11330,10 @@ grn_rc
grn_obj_unlock(grn_ctx *ctx, grn_obj *obj, grn_id id)
{
GRN_API_ENTER;
- grn_io_unlock(grn_obj_io(obj));
+ if (obj && obj->header.type == GRN_COLUMN_INDEX) {
+ grn_io_unlock(((grn_ii *)obj)->chunk);
+ }
+ grn_io_unlock(grn_obj_get_io(ctx, obj));
GRN_API_RETURN(GRN_SUCCESS);
}
@@ -9692,7 +11382,13 @@ grn_obj_clear_lock(grn_ctx *ctx, grn_obj *obj)
grn_table_cursor_close(ctx, cur);
}
}
- grn_io_clear_lock(grn_obj_io(obj));
+ grn_io_clear_lock(grn_obj_get_io(ctx, obj));
+ {
+ grn_db *db = (grn_db *)obj;
+ if (db->specs) {
+ grn_obj_clear_lock(ctx, (grn_obj *)(db->specs));
+ }
+ }
break;
case GRN_TABLE_NO_KEY :
grn_array_queue_lock_clear(ctx, (grn_array *)obj);
@@ -9713,13 +11409,18 @@ grn_obj_clear_lock(grn_ctx *ctx, grn_obj *obj)
}
grn_hash_close(ctx, cols);
}
- grn_io_clear_lock(grn_obj_io(obj));
+ grn_io_clear_lock(grn_obj_get_io(ctx, obj));
}
break;
case GRN_COLUMN_FIX_SIZE:
case GRN_COLUMN_VAR_SIZE:
+ grn_io_clear_lock(grn_obj_get_io(ctx, obj));
+ break;
case GRN_COLUMN_INDEX:
- grn_io_clear_lock(grn_obj_io(obj));
+ grn_io_clear_lock(grn_obj_get_io(ctx, obj));
+ if (obj) {
+ grn_io_clear_lock(((grn_ii *)obj)->chunk);
+ }
break;
}
GRN_API_RETURN(GRN_SUCCESS);
@@ -9730,7 +11431,10 @@ grn_obj_is_locked(grn_ctx *ctx, grn_obj *obj)
{
unsigned int res = 0;
GRN_API_ENTER;
- res = grn_io_is_locked(grn_obj_io(obj));
+ res = grn_io_is_locked(grn_obj_get_io(ctx, obj));
+ if (obj && obj->header.type == GRN_COLUMN_INDEX) {
+ res += grn_io_is_locked(((grn_ii *)obj)->chunk);
+ }
GRN_API_RETURN(res);
}
@@ -9738,15 +11442,20 @@ grn_rc
grn_obj_flush(grn_ctx *ctx, grn_obj *obj)
{
grn_rc rc = GRN_SUCCESS;
+
GRN_API_ENTER;
+
switch (obj->header.type) {
case GRN_DB :
{
grn_db *db = (grn_db *)obj;
rc = grn_obj_flush(ctx, db->keys);
- if (rc == GRN_SUCCESS) {
+ if (rc == GRN_SUCCESS && db->specs) {
rc = grn_obj_flush(ctx, (grn_obj *)(db->specs));
}
+ if (rc == GRN_SUCCESS) {
+ rc = grn_obj_flush(ctx, (grn_obj *)(db->config));
+ }
}
break;
case GRN_TABLE_DAT_KEY :
@@ -9756,9 +11465,23 @@ grn_obj_flush(grn_ctx *ctx, grn_obj *obj)
rc = grn_ii_flush(ctx, (grn_ii *)obj);
break;
default :
- rc = grn_io_flush(ctx, grn_obj_io(obj));
+ {
+ grn_io *io;
+ io = grn_obj_get_io(ctx, obj);
+ if (io) {
+ rc = grn_io_flush(ctx, io);
+ }
+ }
break;
}
+
+ if (rc == GRN_SUCCESS &&
+ GRN_DB_OBJP(obj) &&
+ DB_OBJ(obj)->id != GRN_ID_NIL &&
+ !IS_TEMP(obj)) {
+ rc = grn_db_clean(ctx, DB_OBJ(obj)->db);
+ }
+
GRN_API_RETURN(rc);
}
@@ -10446,15 +12169,34 @@ grn_table_sort_value(grn_ctx *ctx, grn_obj *table,
static grn_bool
is_compressed_column(grn_ctx *ctx, grn_obj *obj)
{
+ grn_obj *target_obj;
+
if (!obj) {
return GRN_FALSE;
}
- if (obj->header.type != GRN_COLUMN_VAR_SIZE) {
+ if (obj->header.type == GRN_ACCESSOR) {
+ grn_accessor *a = (grn_accessor *)obj;
+ while (a->next) {
+ a = a->next;
+ }
+ target_obj = a->obj;
+ } else {
+ target_obj = obj;
+ }
+
+ if (target_obj->header.type != GRN_COLUMN_VAR_SIZE) {
return GRN_FALSE;
}
- return (obj->header.flags & (GRN_OBJ_COMPRESS_ZLIB | GRN_OBJ_COMPRESS_LZ4));
+ switch (target_obj->header.flags & GRN_OBJ_COMPRESS_MASK) {
+ case GRN_OBJ_COMPRESS_ZLIB :
+ case GRN_OBJ_COMPRESS_LZ4 :
+ case GRN_OBJ_COMPRESS_ZSTD :
+ return GRN_TRUE;
+ default :
+ return GRN_FALSE;
+ }
}
static grn_bool
@@ -10485,6 +12227,31 @@ is_sub_record_accessor(grn_ctx *ctx, grn_obj *obj)
return GRN_FALSE;
}
+static grn_bool
+is_encoded_pat_key_accessor(grn_ctx *ctx, grn_obj *obj)
+{
+ grn_accessor *accessor;
+
+ if (!grn_obj_is_accessor(ctx, obj)) {
+ return GRN_FALSE;
+ }
+
+ accessor = (grn_accessor *)obj;
+ while (accessor->next) {
+ accessor = accessor->next;
+ }
+
+ if (accessor->action != GRN_ACCESSOR_GET_KEY) {
+ return GRN_FALSE;
+ }
+
+ if (accessor->obj->header.type != GRN_TABLE_PAT_KEY) {
+ return GRN_FALSE;
+ }
+
+ return grn_pat_is_key_encoded(ctx, (grn_pat *)(accessor->obj));
+}
+
static int
range_is_idp(grn_obj *obj)
{
@@ -10525,7 +12292,12 @@ grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
e = offset + limit;
}
if (keys->flags & GRN_TABLE_SORT_GEO) {
- i = grn_geo_table_sort(ctx, table, offset, limit, result, keys, n_keys);
+ if (n_keys == 2) {
+ i = grn_geo_table_sort(ctx, table, offset, limit, result,
+ keys[0].key, keys[1].key);
+ } else {
+ i = 0;
+ }
goto exit;
}
if (n_keys == 1 && !GRN_ACCESSORP(keys->key) &&
@@ -10542,7 +12314,7 @@ grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
while (i < e && (tid = grn_pat_cursor_next(ctx, pc))) {
grn_ii_cursor *ic = grn_ii_cursor_open(ctx, (grn_ii *)index, tid, 0, 0, 1, 0);
if (ic) {
- grn_ii_posting *posting;
+ grn_posting *posting;
while (i < e && (posting = grn_ii_cursor_next(ctx, ic))) {
if (offset <= i) {
grn_id *v;
@@ -10560,6 +12332,7 @@ grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
int j;
grn_bool have_compressed_column = GRN_FALSE;
grn_bool have_sub_record_accessor = GRN_FALSE;
+ grn_bool have_encoded_pat_key_accessor = GRN_FALSE;
grn_bool have_index_value_get = GRN_FALSE;
grn_table_sort_key *kp;
for (kp = keys, j = n_keys; j; kp++, j--) {
@@ -10569,6 +12342,9 @@ grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
if (is_sub_record_accessor(ctx, kp->key)) {
have_sub_record_accessor = GRN_TRUE;
}
+ if (is_encoded_pat_key_accessor(ctx, kp->key)) {
+ have_encoded_pat_key_accessor = GRN_TRUE;
+ }
if (range_is_idp(kp->key)) {
kp->offset = KEY_ID;
} else {
@@ -10643,6 +12419,7 @@ grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
}
if (have_compressed_column ||
have_sub_record_accessor ||
+ have_encoded_pat_key_accessor ||
have_index_value_get) {
i = grn_table_sort_value(ctx, table, offset, limit, result,
keys, n_keys);
@@ -10741,7 +12518,8 @@ grn_db_init_builtin_types(grn_ctx *ctx)
grn_itoh(id, buf + 3, 2);
grn_obj_register(ctx, db, buf, 5);
}
- grn_db_init_builtin_query(ctx);
+ grn_db_init_builtin_commands(ctx);
+ grn_db_init_builtin_window_functions(ctx);
for (id = grn_db_curr_id(ctx, db) + 1; id < GRN_N_RESERVED_TYPES; id++) {
grn_itoh(id, buf + 3, 2);
grn_obj_register(ctx, db, buf, 5);
@@ -10751,7 +12529,31 @@ grn_db_init_builtin_types(grn_ctx *ctx)
#define MULTI_COLUMN_INDEXP(i) (DB_OBJ(i)->source_size > sizeof(grn_id))
-static inline int
+static grn_obj *
+grn_index_column_get_tokenizer(grn_ctx *ctx, grn_obj *index_column)
+{
+ grn_obj *tokenizer;
+ grn_obj *lexicon;
+
+ lexicon = grn_ctx_at(ctx, index_column->header.domain);
+ if (!lexicon) {
+ return NULL;
+ }
+
+ grn_table_get_info(ctx, lexicon, NULL, NULL, &tokenizer, NULL, NULL);
+ return tokenizer;
+}
+
+static grn_bool
+is_full_text_searchable_index(grn_ctx *ctx, grn_obj *index_column)
+{
+ grn_obj *tokenizer;
+
+ tokenizer = grn_index_column_get_tokenizer(ctx, index_column);
+ return tokenizer != NULL;
+}
+
+static int
grn_column_find_index_data_column_equal(grn_ctx *ctx, grn_obj *obj,
grn_operator op,
grn_index_datum *index_data,
@@ -10764,18 +12566,15 @@ grn_column_find_index_data_column_equal(grn_ctx *ctx, grn_obj *obj,
grn_hook *hooks;
for (hooks = DB_OBJ(obj)->hooks[GRN_HOOK_SET]; hooks; hooks = hooks->next) {
- default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks);
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
grn_obj *target = grn_ctx_at(ctx, data->target);
int section;
if (target->header.type != GRN_COLUMN_INDEX) { continue; }
- section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0;
- if (section_buf) { *section_buf = section; }
if (obj->header.type != GRN_COLUMN_FIX_SIZE) {
- grn_obj *tokenizer, *lexicon = grn_ctx_at(ctx, target->header.domain);
- if (!lexicon) { continue; }
- grn_table_get_info(ctx, lexicon, NULL, NULL, &tokenizer, NULL, NULL);
- if (tokenizer) { continue; }
+ if (is_full_text_searchable_index(ctx, target)) { continue; }
}
+ section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0;
+ if (section_buf) { *section_buf = section; }
if (n < buf_size) {
*ip++ = target;
}
@@ -10789,28 +12588,17 @@ grn_column_find_index_data_column_equal(grn_ctx *ctx, grn_obj *obj,
return n;
}
-static inline grn_bool
+static grn_bool
is_valid_regexp_index(grn_ctx *ctx, grn_obj *index_column)
{
grn_obj *tokenizer;
- grn_obj *lexicon;
-
- lexicon = grn_ctx_at(ctx, index_column->header.domain);
- if (!lexicon) {
- return GRN_FALSE;
- }
-
- grn_table_get_info(ctx, lexicon, NULL, NULL, &tokenizer, NULL, NULL);
- grn_obj_unlink(ctx, lexicon);
- if (!tokenizer) {
- return GRN_FALSE;
- }
+ tokenizer = grn_index_column_get_tokenizer(ctx, index_column);
/* TODO: Restrict to TokenRegexp? */
- return GRN_TRUE;
+ return tokenizer != NULL;
}
-static inline int
+static int
grn_column_find_index_data_column_match(grn_ctx *ctx, grn_obj *obj,
grn_operator op,
grn_index_datum *index_data,
@@ -10822,6 +12610,7 @@ grn_column_find_index_data_column_match(grn_ctx *ctx, grn_obj *obj,
grn_obj **ip = index_buf;
grn_hook_entry hook_entry;
grn_hook *hooks;
+ grn_bool prefer_full_text_search_index = GRN_FALSE;
switch (obj->header.type) {
case GRN_TABLE_HASH_KEY :
@@ -10835,14 +12624,44 @@ grn_column_find_index_data_column_match(grn_ctx *ctx, grn_obj *obj,
break;
}
+ if (op != GRN_OP_REGEXP && !grn_column_is_vector(ctx, obj)) {
+ prefer_full_text_search_index = GRN_TRUE;
+ }
+
+ if (prefer_full_text_search_index) {
+ for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) {
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
+ grn_obj *target = grn_ctx_at(ctx, data->target);
+ int section;
+ if (target->header.type != GRN_COLUMN_INDEX) { continue; }
+ if (!is_full_text_searchable_index(ctx, target)) { continue; }
+ section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0;
+ if (section_buf) { *section_buf = section; }
+ if (n < buf_size) {
+ *ip++ = target;
+ }
+ if (n < n_index_data) {
+ index_data[n].index = target;
+ index_data[n].section = section;
+ }
+ n++;
+ }
+ }
+
for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) {
- default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks);
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
grn_obj *target = grn_ctx_at(ctx, data->target);
int section;
+
if (target->header.type != GRN_COLUMN_INDEX) { continue; }
if (op == GRN_OP_REGEXP && !is_valid_regexp_index(ctx, target)) {
continue;
}
+
+ if (prefer_full_text_search_index) {
+ if (is_full_text_searchable_index(ctx, target)) { continue; }
+ }
+
section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0;
if (section_buf) { *section_buf = section; }
if (n < buf_size) {
@@ -10858,7 +12677,7 @@ grn_column_find_index_data_column_match(grn_ctx *ctx, grn_obj *obj,
return n;
}
-static inline int
+static int
grn_column_find_index_data_column_range(grn_ctx *ctx, grn_obj *obj,
grn_operator op,
grn_index_datum *index_data,
@@ -10884,9 +12703,10 @@ grn_column_find_index_data_column_range(grn_ctx *ctx, grn_obj *obj,
}
for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) {
- default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks);
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
grn_obj *target = grn_ctx_at(ctx, data->target);
int section;
+ if (!target) { continue; }
if (target->header.type != GRN_COLUMN_INDEX) { continue; }
section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0;
if (section_buf) { *section_buf = section; }
@@ -10911,13 +12731,13 @@ grn_column_find_index_data_column_range(grn_ctx *ctx, grn_obj *obj,
return n;
}
-static inline grn_bool
+static grn_bool
is_valid_match_index(grn_ctx *ctx, grn_obj *index_column)
{
return GRN_TRUE;
}
-static inline grn_bool
+static grn_bool
is_valid_range_index(grn_ctx *ctx, grn_obj *index_column)
{
grn_obj *tokenizer;
@@ -11030,7 +12850,50 @@ grn_column_find_index_data_accessor_index_column(grn_ctx *ctx, grn_accessor *a,
return 1;
}
-static inline int
+static grn_bool
+grn_column_find_index_data_accessor_is_key_search(grn_ctx *ctx,
+ grn_accessor *accessor,
+ grn_operator op)
+{
+ if (accessor->next) {
+ return GRN_FALSE;
+ }
+
+ if (accessor->action != GRN_ACCESSOR_GET_KEY) {
+ return GRN_FALSE;
+ }
+
+ if (!grn_obj_is_table(ctx, accessor->obj)) {
+ return GRN_FALSE;
+ }
+
+ switch (op) {
+ case GRN_OP_LESS :
+ case GRN_OP_GREATER :
+ case GRN_OP_LESS_EQUAL :
+ case GRN_OP_GREATER_EQUAL :
+ switch (accessor->obj->header.type) {
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ return GRN_TRUE;
+ default :
+ return GRN_FALSE;
+ }
+ case GRN_OP_EQUAL :
+ switch (accessor->obj->header.type) {
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ return GRN_TRUE;
+ default :
+ return GRN_FALSE;
+ }
+ default :
+ return GRN_FALSE;
+ }
+}
+
+static int
grn_column_find_index_data_accessor_match(grn_ctx *ctx, grn_obj *obj,
grn_operator op,
grn_index_datum *index_data,
@@ -11073,7 +12936,7 @@ grn_column_find_index_data_accessor_match(grn_ctx *ctx, grn_obj *obj,
}
for (hooks = DB_OBJ(a->obj)->hooks[entry]; hooks; hooks = hooks->next) {
- default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks);
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
grn_obj *target = grn_ctx_at(ctx, data->target);
if (target->header.type != GRN_COLUMN_INDEX) { continue; }
@@ -11101,6 +12964,52 @@ grn_column_find_index_data_accessor_match(grn_ctx *ctx, grn_obj *obj,
}
}
+ if (!found &&
+ grn_column_find_index_data_accessor_is_key_search(ctx, a, op)) {
+ grn_obj *index;
+ int section = 0;
+
+ if ((grn_obj *)a == obj) {
+ index = a->obj;
+ } else {
+ index = (grn_obj *)a;
+ }
+
+ found = GRN_TRUE;
+ if (section_buf) {
+ *section_buf = section;
+ }
+ if (n < buf_size) {
+ *ip++ = index;
+ }
+ if (n < n_index_data) {
+ index_data[n].index = index;
+ index_data[n].section = section;
+ }
+ n++;
+ }
+
+ if (!found &&
+ a->next &&
+ grn_obj_is_table(ctx, a->obj) &&
+ a->obj->header.domain == a->next->obj->header.domain) {
+ grn_obj *index = (grn_obj *)a;
+ int section = 0;
+
+ found = GRN_TRUE;
+ if (section_buf) {
+ *section_buf = section;
+ }
+ if (n < buf_size) {
+ *ip++ = index;
+ }
+ if (n < n_index_data) {
+ index_data[n].index = index;
+ index_data[n].section = section;
+ }
+ n++;
+ }
+
if (!found) {
break;
}
@@ -11110,7 +13019,7 @@ grn_column_find_index_data_accessor_match(grn_ctx *ctx, grn_obj *obj,
return n;
}
-static inline int
+static int
grn_column_find_index_data_accessor(grn_ctx *ctx, grn_obj *obj,
grn_operator op,
grn_index_datum *index_data,
@@ -11125,12 +13034,13 @@ grn_column_find_index_data_accessor(grn_ctx *ctx, grn_obj *obj,
}
switch (op) {
case GRN_OP_EQUAL :
+ case GRN_OP_NOT_EQUAL :
case GRN_OP_TERM_EXTRACT :
if (buf_size > 0) {
index_buf[n] = obj;
}
if (n_index_data > 0) {
- index_data[n].index = obj;
+ index_data[n].index = obj;
index_data[n].section = 0;
}
n++;
@@ -11144,7 +13054,7 @@ grn_column_find_index_data_accessor(grn_ctx *ctx, grn_obj *obj,
index_buf[n] = obj;
}
if (n_index_data > 0) {
- index_data[n].index = obj;
+ index_data[n].index = obj;
index_data[n].section = 0;
}
n++;
@@ -11160,10 +13070,10 @@ grn_column_find_index_data_accessor(grn_ctx *ctx, grn_obj *obj,
if (a->obj->header.type == GRN_TABLE_PAT_KEY &&
a->obj->header.flags & GRN_OBJ_KEY_WITH_SIS) {
if (buf_size > 0) {
- index_buf[n] = obj;
+ index_buf[n] = obj;
}
if (n_index_data > 0) {
- index_data[n].index = obj;
+ index_data[n].index = obj;
index_data[n].section = 0;
}
n++;
@@ -11181,6 +13091,7 @@ grn_column_find_index_data_accessor(grn_ctx *ctx, grn_obj *obj,
case GRN_OP_GREATER_EQUAL :
case GRN_OP_CALL :
case GRN_OP_REGEXP :
+ case GRN_OP_FUZZY :
n = grn_column_find_index_data_accessor_match(ctx, obj, op,
index_data, n_index_data,
index_buf, buf_size,
@@ -11202,6 +13113,7 @@ grn_column_index(grn_ctx *ctx, grn_obj *obj, grn_operator op,
if (GRN_DB_OBJP(obj)) {
switch (op) {
case GRN_OP_EQUAL :
+ case GRN_OP_NOT_EQUAL :
n = grn_column_find_index_data_column_equal(ctx, obj, op,
NULL, 0,
index_buf, buf_size,
@@ -11214,6 +13126,7 @@ grn_column_index(grn_ctx *ctx, grn_obj *obj, grn_operator op,
case GRN_OP_NEAR2 :
case GRN_OP_SIMILAR :
case GRN_OP_REGEXP :
+ case GRN_OP_FUZZY :
n = grn_column_find_index_data_column_match(ctx, obj, op,
NULL, 0,
index_buf, buf_size,
@@ -11251,6 +13164,7 @@ grn_column_find_index_data(grn_ctx *ctx, grn_obj *obj, grn_operator op,
if (GRN_DB_OBJP(obj)) {
switch (op) {
case GRN_OP_EQUAL :
+ case GRN_OP_NOT_EQUAL :
n = grn_column_find_index_data_column_equal(ctx, obj, op,
index_data, n_index_data,
NULL, 0, NULL);
@@ -11262,6 +13176,7 @@ grn_column_find_index_data(grn_ctx *ctx, grn_obj *obj, grn_operator op,
case GRN_OP_NEAR2 :
case GRN_OP_SIMILAR :
case GRN_OP_REGEXP :
+ case GRN_OP_FUZZY :
n = grn_column_find_index_data_column_match(ctx, obj, op,
index_data, n_index_data,
NULL, 0, NULL);
@@ -11286,31 +13201,182 @@ grn_column_find_index_data(grn_ctx *ctx, grn_obj *obj, grn_operator op,
GRN_API_RETURN(n);
}
-/* todo : refine */
-static int
-tokenize(const char *str, size_t str_len, const char **tokbuf, int buf_size, const char **rest)
+static uint32_t
+grn_column_get_all_index_data_column(grn_ctx *ctx,
+ grn_obj *obj,
+ grn_index_datum *index_data,
+ uint32_t n_index_data)
{
- const char **tok = tokbuf, **tok_end = tokbuf + buf_size;
- if (buf_size > 0) {
- const char *str_end = str + str_len;
- while (str < str_end && (' ' == *str || ',' == *str)) { str++; }
- for (;;) {
- if (str == str_end) {
- *tok++ = str;
- break;
+ uint32_t n = 0;
+ grn_hook_entry hook_entry;
+ grn_hook *hooks;
+
+ switch (obj->header.type) {
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ case GRN_TABLE_NO_KEY :
+ hook_entry = GRN_HOOK_INSERT;
+ break;
+ default :
+ hook_entry = GRN_HOOK_SET;
+ break;
+ }
+
+ for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) {
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
+ grn_obj *target = grn_ctx_at(ctx, data->target);
+ int section = 0;
+ if (!target) {
+ char name[GRN_TABLE_MAX_KEY_SIZE];
+ int length;
+ char hook_name[GRN_TABLE_MAX_KEY_SIZE];
+ int hook_name_length;
+
+ length = grn_obj_name(ctx, obj, name, GRN_TABLE_MAX_KEY_SIZE);
+ hook_name_length = grn_table_get_key(ctx,
+ ctx->impl->db,
+ data->target,
+ hook_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ ERR(GRN_OBJECT_CORRUPT,
+ "[column][indexes][all] "
+ "hook has a dangling reference: <%.*s> -> <%.*s>",
+ length, name,
+ hook_name_length, hook_name);
+ continue;
+ }
+ if (target->header.type != GRN_COLUMN_INDEX) {
+ continue;
+ }
+ if (MULTI_COLUMN_INDEXP(target)) {
+ section = data->section;
+ }
+ if (n < n_index_data) {
+ index_data[n].index = target;
+ index_data[n].section = section;
+ }
+ n++;
+ }
+
+ return n;
+}
+
+static uint32_t
+grn_column_get_all_index_data_accessor_index_column(grn_ctx *ctx,
+ grn_accessor *a,
+ grn_index_datum *index_data,
+ uint32_t n_index_data)
+{
+ grn_obj *index_column = a->obj;
+ int section = 0;
+
+ if (a->next) {
+ int specified_section;
+ grn_bool is_invalid_section;
+ if (a->next->next) {
+ return 0;
+ }
+ specified_section = find_section(ctx, index_column, a->next->obj);
+ is_invalid_section = (specified_section == 0);
+ if (is_invalid_section) {
+ return 0;
+ }
+ section = specified_section;
+ }
+ if (n_index_data > 0) {
+ index_data[0].index = index_column;
+ index_data[0].section = section;
+ }
+
+ return 1;
+}
+
+static uint32_t
+grn_column_get_all_index_data_accessor(grn_ctx *ctx,
+ grn_obj *obj,
+ grn_index_datum *index_data,
+ uint32_t n_index_data)
+{
+ uint32_t n = 0;
+ grn_accessor *a = (grn_accessor *)obj;
+
+ while (a) {
+ grn_hook *hooks;
+ grn_bool found = GRN_FALSE;
+ grn_hook_entry entry = (grn_hook_entry)-1;
+
+ if (a->action == GRN_ACCESSOR_GET_COLUMN_VALUE &&
+ GRN_OBJ_INDEX_COLUMNP(a->obj)) {
+ return grn_column_get_all_index_data_accessor_index_column(ctx,
+ a,
+ index_data,
+ n_index_data);
+ }
+
+ switch (a->action) {
+ case GRN_ACCESSOR_GET_KEY :
+ entry = GRN_HOOK_INSERT;
+ break;
+ case GRN_ACCESSOR_GET_COLUMN_VALUE :
+ entry = GRN_HOOK_SET;
+ break;
+ default :
+ break;
+ }
+
+ if (entry == (grn_hook_entry)-1) {
+ break;
+ }
+
+ for (hooks = DB_OBJ(a->obj)->hooks[entry]; hooks; hooks = hooks->next) {
+ grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks);
+ grn_obj *target = grn_ctx_at(ctx, data->target);
+
+ if (target->header.type != GRN_COLUMN_INDEX) {
+ continue;
}
- if (' ' == *str || ',' == *str) {
- // *str = '\0';
- *tok++ = str;
- if (tok == tok_end) { break; }
- do { str++; } while (str < str_end && (' ' == *str || ',' == *str));
- } else {
- str++;
+
+ found = GRN_TRUE;
+ if (!a->next) {
+ int section = 0;
+
+ if (MULTI_COLUMN_INDEXP(target)) {
+ section = data->section;
+ }
+ if (n < n_index_data) {
+ index_data[n].index = target;
+ index_data[n].section = section;
+ }
+ n++;
}
}
+
+ if (!found) {
+ break;
+ }
+ a = a->next;
+ }
+
+ return n;
+}
+
+uint32_t
+grn_column_get_all_index_data(grn_ctx *ctx,
+ grn_obj *obj,
+ grn_index_datum *index_data,
+ uint32_t n_index_data)
+{
+ uint32_t n = 0;
+ GRN_API_ENTER;
+ if (GRN_DB_OBJP(obj)) {
+ n = grn_column_get_all_index_data_column(ctx, obj,
+ index_data, n_index_data);
+ } else if (GRN_ACCESSORP(obj)) {
+ n = grn_column_get_all_index_data_accessor(ctx, obj,
+ index_data, n_index_data);
}
- if (rest) { *rest = str; }
- return tok - tokbuf;
+ GRN_API_RETURN(n);
}
grn_rc
@@ -11320,7 +13386,7 @@ grn_obj_columns(grn_ctx *ctx, grn_obj *table,
grn_obj *col;
const char *p = (char *)str, *q, *r, *pe = p + str_size, *tokbuf[256];
while (p < pe) {
- int i, n = tokenize(p, pe - p, tokbuf, 256, &q);
+ int i, n = grn_tokenize(p, pe - p, tokbuf, 256, &q);
for (i = 0; i < n; i++) {
r = tokbuf[i];
while (p < r && (' ' == *p || ',' == *p)) { p++; }
@@ -11344,19 +13410,24 @@ grn_obj_columns(grn_ctx *ctx, grn_obj *table,
GRN_COLUMN_NAME_ID_LEN);
if (ai) {
if (ai->header.type == GRN_ACCESSOR) {
- cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
- GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY);
- if (cols) {
- grn_id *key;
- grn_accessor *a, *ac;
- grn_obj *target_table = table;
- for (a = (grn_accessor *)ai; a; a = a->next) {
- target_table = a->obj;
+ grn_id *key;
+ grn_accessor *id_accessor;
+ for (id_accessor = ((grn_accessor *)ai)->next;
+ id_accessor;
+ id_accessor = id_accessor->next) {
+ grn_obj *target_table = id_accessor->obj;
+
+ cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
+ GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY);
+ if (!cols) {
+ continue;
}
grn_table_columns(ctx, target_table,
p, r - p - 1, (grn_obj *)cols);
GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, {
if ((col = grn_ctx_at(ctx, *key))) {
+ grn_accessor *a;
+ grn_accessor *ac;
ac = accessor_new(ctx);
GRN_PTR_PUT(ctx, res, (grn_obj *)ac);
for (a = (grn_accessor *)ai; a; a = a->next) {
@@ -11406,7 +13477,7 @@ grn_table_sort_key_from_str_geo(grn_ctx *ctx, const char *str, unsigned int str_
p = str;
if ((tokbuf = GRN_MALLOCN(const char *, str_size))) {
grn_id domain = GRN_ID_NIL;
- int i, n = tokenize(str, str_size, tokbuf, str_size, NULL);
+ int i, n = grn_tokenize(str, str_size, tokbuf, str_size, NULL);
if ((keys = GRN_MALLOCN(grn_table_sort_key, n))) {
k = keys;
for (i = 0; i < n; i++) {
@@ -11470,7 +13541,7 @@ grn_table_sort_key_from_str(grn_ctx *ctx, const char *str, unsigned int str_size
return keys;
}
if ((tokbuf = GRN_MALLOCN(const char *, str_size))) {
- int i, n = tokenize(str, str_size, tokbuf, str_size, NULL);
+ int i, n = grn_tokenize(str, str_size, tokbuf, str_size, NULL);
if ((keys = GRN_MALLOCN(grn_table_sort_key, n))) {
k = keys;
for (i = 0; i < n; i++) {
@@ -11490,13 +13561,37 @@ grn_table_sort_key_from_str(grn_ctx *ctx, const char *str, unsigned int str_size
} else {
if (r - p == GRN_COLUMN_NAME_SCORE_LEN &&
memcmp(p, GRN_COLUMN_NAME_SCORE, GRN_COLUMN_NAME_SCORE_LEN) == 0) {
+ char table_name[GRN_TABLE_MAX_KEY_SIZE];
+ int table_name_size;
+ table_name_size = grn_obj_name(ctx, table,
+ table_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ if (table_name_size == 0) {
+ grn_strcpy(table_name, GRN_TABLE_MAX_KEY_SIZE, "(anonymous)");
+ table_name_size = strlen(table_name);
+ }
GRN_LOG(ctx, GRN_WARN,
- "ignore invalid sort key: <%.*s>(<%.*s>)",
- (int)(r - p), p, str_size, str);
+ "ignore invalid sort key: <%.*s>: "
+ "table:<%*.s> keys:<%.*s>",
+ (int)(r - p), p,
+ table_name_size, table_name,
+ str_size, str);
} else {
+ char table_name[GRN_TABLE_MAX_KEY_SIZE];
+ int table_name_size;
+ table_name_size = grn_obj_name(ctx, table,
+ table_name,
+ GRN_TABLE_MAX_KEY_SIZE);
+ if (table_name_size == 0) {
+ grn_strcpy(table_name, GRN_TABLE_MAX_KEY_SIZE, "(anonymous)");
+ table_name_size = strlen(table_name);
+ }
WARN(GRN_INVALID_ARGUMENT,
- "invalid sort key: <%.*s>(<%.*s>)",
- (int)(r - p), p, str_size, str);
+ "invalid sort key: <%.*s>: "
+ "table:<%.*s> keys:<%.*s>",
+ (int)(r - p), p,
+ table_name_size, table_name,
+ str_size, str);
break;
}
}
@@ -11522,7 +13617,10 @@ grn_table_sort_key_close(grn_ctx *ctx, grn_table_sort_key *keys, unsigned int nk
int i;
if (keys) {
for (i = 0; i < nkeys; i++) {
- grn_obj_unlink(ctx, keys[i].key);
+ grn_obj *key = keys[i].key;
+ if (!grn_obj_is_column(ctx, key)) {
+ grn_obj_unlink(ctx, key);
+ }
}
GRN_FREE(keys);
}
@@ -11578,1014 +13676,39 @@ exit :
GRN_API_RETURN(buf);
}
-/* grn_load */
-
-static grn_obj *
-values_add(grn_ctx *ctx, grn_loader *loader)
-{
- grn_obj *res;
- uint32_t curr_size = loader->values_size * sizeof(grn_obj);
- if (curr_size < GRN_TEXT_LEN(&loader->values)) {
- res = (grn_obj *)(GRN_TEXT_VALUE(&loader->values) + curr_size);
- res->header.domain = GRN_DB_TEXT;
- GRN_BULK_REWIND(res);
- } else {
- if (grn_bulk_space(ctx, &loader->values, sizeof(grn_obj))) { return NULL; }
- res = (grn_obj *)(GRN_TEXT_VALUE(&loader->values) + curr_size);
- GRN_TEXT_INIT(res, 0);
- }
- loader->values_size++;
- loader->last = res;
- return res;
-}
-
-static grn_obj *
-values_next(grn_ctx *ctx, grn_obj *value)
-{
- if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET ||
- value->header.domain == GRN_JSON_LOAD_OPEN_BRACE) {
- value += GRN_UINT32_VALUE(value);
- }
- return value + 1;
-}
-
-static int
-values_len(grn_ctx *ctx, grn_obj *head, grn_obj *tail)
-{
- int len;
- for (len = 0; head < tail; head = values_next(ctx, head), len++) ;
- return len;
-}
-
-static grn_id
-loader_add(grn_ctx *ctx, grn_obj *key)
-{
- int added = 0;
- grn_loader *loader = &ctx->impl->loader;
- grn_id id = grn_table_add_by_key(ctx, loader->table, key, &added);
- if (!added && loader->ifexists) {
- grn_obj *v = grn_expr_get_var_by_offset(ctx, loader->ifexists, 0);
- grn_obj *result;
- unsigned int result_boolean;
- GRN_RECORD_SET(ctx, v, id);
- result = grn_expr_exec(ctx, loader->ifexists, 0);
- GRN_TRUEP(ctx, result, result_boolean);
- if (!result_boolean) { id = 0; }
- }
- return id;
-}
-
static void
-set_vector(grn_ctx *ctx, grn_obj *column, grn_id id, grn_obj *vector)
-{
- int n = GRN_UINT32_VALUE(vector);
- grn_obj buf, *v = vector + 1;
- grn_id range_id;
- grn_obj *range;
-
- range_id = DB_OBJ(column)->range;
- range = grn_ctx_at(ctx, range_id);
- if (GRN_OBJ_TABLEP(range)) {
- GRN_RECORD_INIT(&buf, GRN_OBJ_VECTOR, range_id);
- while (n--) {
- grn_bool cast_failed = GRN_FALSE;
- grn_obj record, *element = v;
- if (range_id != element->header.domain) {
- GRN_RECORD_INIT(&record, 0, range_id);
- if (grn_obj_cast(ctx, element, &record, GRN_TRUE)) {
- cast_failed = GRN_TRUE;
- ERR_CAST(column, range, element);
- }
- element = &record;
- }
- if (!cast_failed) {
- GRN_UINT32_PUT(ctx, &buf, GRN_RECORD_VALUE(element));
- }
- if (element == &record) { GRN_OBJ_FIN(ctx, element); }
- v = values_next(ctx, v);
- }
- } else {
- if (((struct _grn_type *)range)->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) {
- GRN_TEXT_INIT(&buf, GRN_OBJ_VECTOR);
- while (n--) {
- if (v->header.domain == GRN_DB_TEXT) {
- grn_bool cast_failed = GRN_FALSE;
- grn_obj casted_element, *element = v;
- if (range_id != element->header.domain) {
- GRN_OBJ_INIT(&casted_element, GRN_BULK, 0, range_id);
- if (grn_obj_cast(ctx, element, &casted_element, GRN_TRUE)) {
- cast_failed = GRN_TRUE;
- ERR_CAST(column, range, element);
- }
- element = &casted_element;
- }
- if (!cast_failed) {
- grn_vector_add_element(ctx, &buf,
- GRN_TEXT_VALUE(element),
- GRN_TEXT_LEN(element), 0,
- element->header.domain);
- }
- if (element == &casted_element) { GRN_OBJ_FIN(ctx, element); }
- } else {
- ERR(GRN_INVALID_ARGUMENT, "bad syntax.");
- }
- v = values_next(ctx, v);
- }
- } else {
- grn_id value_size = ((grn_db_obj *)range)->range;
- GRN_VALUE_FIX_SIZE_INIT(&buf, GRN_OBJ_VECTOR, range_id);
- while (n--) {
- grn_bool cast_failed = GRN_FALSE;
- grn_obj casted_element, *element = v;
- if (range_id != element->header.domain) {
- GRN_OBJ_INIT(&casted_element, GRN_BULK, 0, range_id);
- if (grn_obj_cast(ctx, element, &casted_element, GRN_TRUE)) {
- cast_failed = GRN_TRUE;
- ERR_CAST(column, range, element);
- }
- element = &casted_element;
- }
- if (!cast_failed) {
- grn_bulk_write(ctx, &buf, GRN_TEXT_VALUE(element), value_size);
- }
- if (element == &casted_element) { GRN_OBJ_FIN(ctx, element); }
- v = values_next(ctx, v);
- }
- }
- }
- grn_obj_set_value(ctx, column, id, &buf, GRN_OBJ_SET);
- GRN_OBJ_FIN(ctx, &buf);
-}
-
-static void
-set_weight_vector(grn_ctx *ctx, grn_obj *column, grn_id id, grn_obj *index_value)
-{
- if (!GRN_OBJ_WEIGHT_VECTOR_COLUMNP(column)) {
- char column_name[GRN_TABLE_MAX_KEY_SIZE];
- int column_name_size;
- column_name_size = grn_obj_name(ctx, column, column_name,
- GRN_TABLE_MAX_KEY_SIZE);
- ERR(GRN_INVALID_ARGUMENT,
- "<%.*s>: columns except weight vector column don't support object value",
- column_name_size, column_name);
- return;
- }
-
- {
- unsigned int i, n;
- grn_obj vector;
- grn_obj weight_buffer;
-
- n = GRN_UINT32_VALUE(index_value);
- GRN_TEXT_INIT(&vector, GRN_OBJ_VECTOR);
- GRN_UINT32_INIT(&weight_buffer, 0);
- for (i = 0; i < n; i += 2) {
- grn_rc rc;
- grn_obj *key, *weight;
-
- key = index_value + 1 + i;
- weight = key + 1;
-
- GRN_BULK_REWIND(&weight_buffer);
- rc = grn_obj_cast(ctx, weight, &weight_buffer, GRN_TRUE);
- if (rc != GRN_SUCCESS) {
- grn_obj *range;
- range = grn_ctx_at(ctx, weight_buffer.header.domain);
- ERR_CAST(column, range, weight);
- grn_obj_unlink(ctx, range);
- break;
- }
- grn_vector_add_element(ctx, &vector,
- GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key),
- GRN_UINT32_VALUE(&weight_buffer),
- key->header.domain);
- }
- grn_obj_set_value(ctx, column, id, &vector, GRN_OBJ_SET);
- GRN_OBJ_FIN(ctx, &vector);
- }
-}
-
-static inline int
-name_equal(const char *p, unsigned int size, const char *name)
-{
- if (strlen(name) != size) { return 0; }
- if (*p != GRN_DB_PSEUDO_COLUMN_PREFIX) { return 0; }
- return !memcmp(p + 1, name + 1, size - 1);
-}
-
-static void
-report_set_column_value_failure(grn_ctx *ctx,
- grn_obj *key,
- const char *column_name,
- unsigned int column_name_size,
- grn_obj *column_value)
-{
- grn_obj key_inspected, column_value_inspected;
-
- GRN_TEXT_INIT(&key_inspected, 0);
- GRN_TEXT_INIT(&column_value_inspected, 0);
- limited_size_inspect(ctx, &key_inspected, key);
- limited_size_inspect(ctx, &column_value_inspected, column_value);
- GRN_LOG(ctx, GRN_LOG_ERROR,
- "[table][load] failed to set column value: %s: "
- "key: <%.*s>, column: <%.*s>, value: <%.*s>",
- ctx->errbuf,
- (int)GRN_TEXT_LEN(&key_inspected),
- GRN_TEXT_VALUE(&key_inspected),
- column_name_size,
- column_name,
- (int)GRN_TEXT_LEN(&column_value_inspected),
- GRN_TEXT_VALUE(&column_value_inspected));
- GRN_OBJ_FIN(ctx, &key_inspected);
- GRN_OBJ_FIN(ctx, &column_value_inspected);
-}
-
-static void
-bracket_close(grn_ctx *ctx, grn_loader *loader)
-{
- grn_obj *value, *col, *ve;
- grn_id id = GRN_ID_NIL;
- grn_obj *key_value = NULL;
- grn_obj **cols = (grn_obj **)GRN_BULK_HEAD(&loader->columns);
- uint32_t begin, ndata, ncols = GRN_BULK_VSIZE(&loader->columns) / sizeof(grn_obj *);
- GRN_UINT32_POP(&loader->level, begin);
- value = ((grn_obj *)(GRN_TEXT_VALUE(&loader->values))) + begin;
- ve = ((grn_obj *)(GRN_TEXT_VALUE(&loader->values))) + loader->values_size;
- GRN_ASSERT(value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET);
- GRN_UINT32_SET(ctx, value, loader->values_size - begin - 1);
- value++;
- if (GRN_BULK_VSIZE(&loader->level) <= sizeof(uint32_t) * loader->emit_level) {
- ndata = values_len(ctx, value, ve);
- if (loader->table) {
- switch (loader->table->header.type) {
- case GRN_TABLE_HASH_KEY :
- case GRN_TABLE_PAT_KEY :
- case GRN_TABLE_DAT_KEY :
- if (loader->key_offset != -1 && ndata == ncols + 1) {
- key_value = value + loader->key_offset;
- id = loader_add(ctx, key_value);
- } else if (loader->key_offset == -1) {
- int i = 0;
- grn_obj *key_column_name = NULL;
- while (ndata--) {
- char *column_name = GRN_TEXT_VALUE(value);
- unsigned int column_name_size = GRN_TEXT_LEN(value);
- if (value->header.domain == GRN_DB_TEXT &&
- (name_equal(column_name, column_name_size,
- GRN_COLUMN_NAME_KEY) ||
- name_equal(column_name, column_name_size,
- GRN_COLUMN_NAME_ID))) {
- if (loader->key_offset != -1) {
- GRN_LOG(ctx, GRN_LOG_ERROR,
- "duplicated key columns: <%.*s> at %d and <%.*s> at %i",
- (int)GRN_TEXT_LEN(key_column_name),
- GRN_TEXT_VALUE(key_column_name),
- loader->key_offset,
- column_name_size, column_name, i);
- return;
- }
- key_column_name = value;
- loader->key_offset = i;
- } else {
- col = grn_obj_column(ctx, loader->table,
- column_name, column_name_size);
- if (!col) {
- ERR(GRN_INVALID_ARGUMENT,
- "nonexistent column: <%.*s>",
- column_name_size, column_name);
- return;
- }
- GRN_PTR_PUT(ctx, &loader->columns, col);
- }
- value++;
- i++;
- }
- }
- break;
- case GRN_TABLE_NO_KEY :
- if ((GRN_BULK_VSIZE(&loader->level)) > 0 &&
- (ndata == 0 || ndata == ncols)) {
- id = grn_table_add(ctx, loader->table, NULL, 0, NULL);
- } else if (!ncols) {
- while (ndata--) {
- if (value->header.domain == GRN_DB_TEXT) {
- char *column_name = GRN_TEXT_VALUE(value);
- unsigned int column_name_size = GRN_TEXT_LEN(value);
- col = grn_obj_column(ctx, loader->table,
- column_name, column_name_size);
- if (!col) {
- ERR(GRN_INVALID_ARGUMENT,
- "nonexistent column: <%.*s>",
- column_name_size, column_name);
- return;
- }
- GRN_PTR_PUT(ctx, &loader->columns, col);
- value++;
- } else {
- grn_obj buffer;
- GRN_TEXT_INIT(&buffer, 0);
- grn_inspect(ctx, &buffer, value);
- ERR(GRN_INVALID_ARGUMENT,
- "column name must be string: <%.*s>",
- (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
- GRN_OBJ_FIN(ctx, &buffer);
- return;
- }
- }
- }
- break;
- default :
- break;
- }
- if (id) {
- int i = 0;
- while (ndata--) {
- grn_obj *column;
- if ((loader->table->header.type == GRN_TABLE_HASH_KEY ||
- loader->table->header.type == GRN_TABLE_PAT_KEY ||
- loader->table->header.type == GRN_TABLE_DAT_KEY) &&
- i == loader->key_offset) {
- /* skip this value, because it's already used as key value */
- value = values_next(ctx, value);
- i++;
- continue;
- }
-
- column = *cols;
- if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET) {
- set_vector(ctx, column, id, value);
- } else if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACE) {
- set_weight_vector(ctx, column, id, value);
- } else {
- grn_obj_set_value(ctx, column, id, value, GRN_OBJ_SET);
- }
- if (ctx->rc != GRN_SUCCESS) {
- char column_name[GRN_TABLE_MAX_KEY_SIZE];
- unsigned int column_name_size;
- column_name_size = grn_obj_name(ctx, column, column_name,
- GRN_TABLE_MAX_KEY_SIZE);
- report_set_column_value_failure(ctx, key_value,
- column_name, column_name_size,
- value);
- ERRCLR(ctx);
- }
- value = values_next(ctx, value);
- cols++;
- i++;
- }
- if (loader->each) {
- grn_obj *v = grn_expr_get_var_by_offset(ctx, loader->each, 0);
- GRN_RECORD_SET(ctx, v, id);
- grn_expr_exec(ctx, loader->each, 0);
- }
- loader->nrecords++;
- }
- }
- loader->values_size = begin;
- }
-}
-
-static void
-brace_close(grn_ctx *ctx, grn_loader *loader)
+grn_db_recover_database_remove_orphan_inspect(grn_ctx *ctx, grn_obj *db)
{
- uint32_t begin;
- grn_obj *key_value = NULL;
- grn_obj *value, *ve;
- grn_id id = GRN_ID_NIL;
- GRN_UINT32_POP(&loader->level, begin);
- value = ((grn_obj *)(GRN_TEXT_VALUE(&loader->values))) + begin;
- ve = ((grn_obj *)(GRN_TEXT_VALUE(&loader->values))) + loader->values_size;
- GRN_ASSERT(value->header.domain == GRN_JSON_LOAD_OPEN_BRACE);
- GRN_UINT32_SET(ctx, value, loader->values_size - begin - 1);
- value++;
- if (GRN_BULK_VSIZE(&loader->level) <= sizeof(uint32_t) * loader->emit_level) {
- if (loader->table) {
- switch (loader->table->header.type) {
- case GRN_TABLE_HASH_KEY :
- case GRN_TABLE_PAT_KEY :
- case GRN_TABLE_DAT_KEY :
- {
- grn_obj *v, *key_column_name = NULL;
- for (v = value; v + 1 < ve; v = values_next(ctx, v)) {
- char *column_name = GRN_TEXT_VALUE(v);
- unsigned int column_name_size = GRN_TEXT_LEN(v);
- if (v->header.domain == GRN_DB_TEXT &&
- (name_equal(column_name, column_name_size,
- GRN_COLUMN_NAME_KEY) ||
- name_equal(column_name, column_name_size,
- GRN_COLUMN_NAME_ID))) {
- if (key_column_name) {
- GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated key columns: %.*s and %.*s",
- (int)GRN_TEXT_LEN(key_column_name),
- GRN_TEXT_VALUE(key_column_name),
- column_name_size, column_name);
- goto exit;
- }
- key_column_name = value;
- v++;
- key_value = v;
- id = loader_add(ctx, key_value);
- } else {
- v = values_next(ctx, v);
- }
- }
- }
- break;
- case GRN_TABLE_NO_KEY :
- {
- grn_obj *v;
- grn_bool found_id_column = GRN_FALSE;
- for (v = value; v + 1 < ve; v = values_next(ctx, v)) {
- char *column_name = GRN_TEXT_VALUE(v);
- unsigned int column_name_size = GRN_TEXT_LEN(v);
- if (v->header.domain == GRN_DB_TEXT &&
- (name_equal(column_name, column_name_size,
- GRN_COLUMN_NAME_ID))) {
- grn_obj *id_column;
- grn_obj *id_value;
- if (found_id_column) {
- GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated '_id' column");
- goto exit;
- }
- found_id_column = GRN_TRUE;
- id_column = v;
- v = values_next(ctx, v);
- id_value = v;
- switch (id_value->header.type) {
- case GRN_DB_UINT32 :
- id = GRN_UINT32_VALUE(id_value);
- break;
- case GRN_DB_INT32 :
- id = GRN_INT32_VALUE(id_value);
- break;
- default :
- {
- grn_obj casted_id_value;
- GRN_UINT32_INIT(&casted_id_value, 0);
- if (grn_obj_cast(ctx, id_value, &casted_id_value, GRN_FALSE)) {
- grn_obj inspected;
- GRN_TEXT_INIT(&inspected, 0);
- grn_inspect(ctx, &inspected, id_value);
- ERR(GRN_INVALID_ARGUMENT,
- "<%.*s>: failed to cast to <UInt32>: <%.*s>",
- (int)column_name_size, column_name,
- (int)GRN_TEXT_LEN(&inspected),
- GRN_TEXT_VALUE(&inspected));
- grn_obj_unlink(ctx, &inspected);
- goto exit;
- } else {
- id = GRN_UINT32_VALUE(&casted_id_value);
- }
- GRN_OBJ_FIN(ctx, &casted_id_value);
- }
- break;
- }
- } else {
- v = values_next(ctx, v);
- }
- }
- }
- if (id == GRN_ID_NIL) {
- id = grn_table_add(ctx, loader->table, NULL, 0, NULL);
- }
- break;
- default :
- break;
- }
- if (id) {
- grn_obj *col;
- const char *name;
- unsigned int name_size;
- while (value + 1 < ve) {
- if (value->header.domain != GRN_DB_TEXT) { break; /* error */ }
- name = GRN_TEXT_VALUE(value);
- name_size = GRN_TEXT_LEN(value);
- col = grn_obj_column(ctx, loader->table, name, name_size);
- value++;
- /* auto column create
- if (!col) {
- if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET) {
- grn_obj *v = value + 1;
- col = grn_column_create(ctx, loader->table, name, name_size,
- NULL, GRN_OBJ_PERSISTENT|GRN_OBJ_COLUMN_VECTOR,
- grn_ctx_at(ctx, v->header.domain));
- } else {
- col = grn_column_create(ctx, loader->table, name, name_size,
- NULL, GRN_OBJ_PERSISTENT,
- grn_ctx_at(ctx, value->header.domain));
- }
- }
- */
- if (col) {
- if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET) {
- set_vector(ctx, col, id, value);
- } else if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACE) {
- set_weight_vector(ctx, col, id, value);
- } else {
- grn_obj_set_value(ctx, col, id, value, GRN_OBJ_SET);
- }
- if (ctx->rc != GRN_SUCCESS) {
- report_set_column_value_failure(ctx, key_value,
- name, name_size, value);
- ERRCLR(ctx);
- }
- grn_obj_unlink(ctx, col);
- } else {
- GRN_LOG(ctx, GRN_LOG_ERROR, "invalid column('%.*s')", (int)name_size, name);
- }
- value = values_next(ctx, value);
- }
- if (loader->each) {
- grn_obj *v = grn_expr_get_var_by_offset(ctx, loader->each, 0);
- GRN_RECORD_SET(ctx, v, id);
- grn_expr_exec(ctx, loader->each, 0);
- }
- loader->nrecords++;
- } else {
- GRN_LOG(ctx, GRN_LOG_ERROR, "neither _key nor _id is assigned");
- }
- }
- exit:
- loader->values_size = begin;
- }
-}
-
-#define JSON_READ_OPEN_BRACKET() do {\
- GRN_UINT32_PUT(ctx, &loader->level, loader->values_size);\
- values_add(ctx, loader);\
- loader->last->header.domain = GRN_JSON_LOAD_OPEN_BRACKET;\
- loader->stat = GRN_LOADER_TOKEN;\
- str++;\
-} while (0)
-
-#define JSON_READ_OPEN_BRACE() do {\
- GRN_UINT32_PUT(ctx, &loader->level, loader->values_size);\
- values_add(ctx, loader);\
- loader->last->header.domain = GRN_JSON_LOAD_OPEN_BRACE;\
- loader->stat = GRN_LOADER_TOKEN;\
- str++;\
-} while (0)
+ GRN_TABLE_EACH_BEGIN_FLAGS(ctx, db, cursor, id, GRN_CURSOR_BY_ID) {
+ void *key;
+ int key_size;
-static void
-json_read(grn_ctx *ctx, grn_loader *loader, const char *str, unsigned int str_len)
-{
- const char *const beg = str;
- char c;
- int len;
- const char *se = str + str_len;
- while (str < se) {
- c = *str;
- switch (loader->stat) {
- case GRN_LOADER_BEGIN :
- if ((len = grn_isspace(str, ctx->encoding))) {
- str += len;
- continue;
- }
- switch (c) {
- case '[' :
- JSON_READ_OPEN_BRACKET();
- break;
- case '{' :
- JSON_READ_OPEN_BRACE();
- break;
- default :
- ERR(GRN_INVALID_ARGUMENT,
- "JSON must start with '[' or '{': <%.*s>", str_len, beg);
- loader->stat = GRN_LOADER_END;
- break;
- }
- break;
- case GRN_LOADER_TOKEN :
- if ((len = grn_isspace(str, ctx->encoding))) {
- str += len;
- continue;
- }
- switch (c) {
- case '"' :
- loader->stat = GRN_LOADER_STRING;
- values_add(ctx, loader);
- str++;
- break;
- case '[' :
- JSON_READ_OPEN_BRACKET();
- break;
- case '{' :
- JSON_READ_OPEN_BRACE();
- break;
- case ':' :
- str++;
- break;
- case ',' :
- str++;
- break;
- case ']' :
- bracket_close(ctx, loader);
- loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END;
- str++;
- break;
- case '}' :
- brace_close(ctx, loader);
- loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END;
- str++;
- break;
- case '+' : case '-' : case '0' : case '1' : case '2' : case '3' :
- case '4' : case '5' : case '6' : case '7' : case '8' : case '9' :
- loader->stat = GRN_LOADER_NUMBER;
- values_add(ctx, loader);
- break;
- default :
- if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('_' == c)) {
- loader->stat = GRN_LOADER_SYMBOL;
- values_add(ctx, loader);
- } else {
- if ((len = grn_charlen(ctx, str, se))) {
- GRN_LOG(ctx, GRN_LOG_ERROR, "ignored invalid char('%c') at", c);
- GRN_LOG(ctx, GRN_LOG_ERROR, "%.*s", (int)(str - beg) + len, beg);
- GRN_LOG(ctx, GRN_LOG_ERROR, "%*s", (int)(str - beg) + 1, "^");
- str += len;
- } else {
- GRN_LOG(ctx, GRN_LOG_ERROR, "ignored invalid char(\\x%.2x) after", c);
- GRN_LOG(ctx, GRN_LOG_ERROR, "%.*s", (int)(str - beg), beg);
- str = se;
- }
- }
- break;
- }
- break;
- case GRN_LOADER_SYMBOL :
- if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') ||
- ('0' <= c && c <= '9') || ('_' == c)) {
- GRN_TEXT_PUTC(ctx, loader->last, c);
- str++;
- } else {
- char *v = GRN_TEXT_VALUE(loader->last);
- switch (*v) {
- case 'n' :
- if (GRN_TEXT_LEN(loader->last) == 4 && !memcmp(v, "null", 4)) {
- loader->last->header.domain = GRN_DB_VOID;
- GRN_BULK_REWIND(loader->last);
- }
- break;
- case 't' :
- if (GRN_TEXT_LEN(loader->last) == 4 && !memcmp(v, "true", 4)) {
- loader->last->header.domain = GRN_DB_BOOL;
- GRN_BOOL_SET(ctx, loader->last, GRN_TRUE);
- }
- break;
- case 'f' :
- if (GRN_TEXT_LEN(loader->last) == 5 && !memcmp(v, "false", 5)) {
- loader->last->header.domain = GRN_DB_BOOL;
- GRN_BOOL_SET(ctx, loader->last, GRN_FALSE);
- }
- break;
- default :
- break;
- }
- loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END;
- }
- break;
- case GRN_LOADER_NUMBER :
- switch (c) {
- case '+' : case '-' : case '.' : case 'e' : case 'E' :
- case '0' : case '1' : case '2' : case '3' : case '4' :
- case '5' : case '6' : case '7' : case '8' : case '9' :
- GRN_TEXT_PUTC(ctx, loader->last, c);
- str++;
- break;
- default :
- {
- const char *cur, *str = GRN_BULK_HEAD(loader->last);
- const char *str_end = GRN_BULK_CURR(loader->last);
- int64_t i = grn_atoll(str, str_end, &cur);
- if (cur == str_end) {
- loader->last->header.domain = GRN_DB_INT64;
- GRN_INT64_SET(ctx, loader->last, i);
- } else if (cur != str) {
- double d;
- char *end;
- grn_obj buf;
- GRN_TEXT_INIT(&buf, 0);
- GRN_TEXT_PUT(ctx, &buf, str, GRN_BULK_VSIZE(loader->last));
- GRN_TEXT_PUTC(ctx, &buf, '\0');
- errno = 0;
- d = strtod(GRN_TEXT_VALUE(&buf), &end);
- if (!errno && end + 1 == GRN_BULK_CURR(&buf)) {
- loader->last->header.domain = GRN_DB_FLOAT;
- GRN_FLOAT_SET(ctx, loader->last, d);
- }
- GRN_OBJ_FIN(ctx, &buf);
- }
- }
- loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END;
- break;
- }
- break;
- case GRN_LOADER_STRING :
- switch (c) {
- case '\\' :
- loader->stat = GRN_LOADER_STRING_ESC;
- str++;
- break;
- case '"' :
- str++;
- loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END;
- /*
- *(GRN_BULK_CURR(loader->last)) = '\0';
- GRN_LOG(ctx, GRN_LOG_ALERT, "read str(%s)", GRN_TEXT_VALUE(loader->last));
- */
- break;
- default :
- if ((len = grn_charlen(ctx, str, se))) {
- GRN_TEXT_PUT(ctx, loader->last, str, len);
- str += len;
- } else {
- GRN_LOG(ctx, GRN_LOG_ERROR, "ignored invalid char(\\x%.2x) after", c);
- GRN_LOG(ctx, GRN_LOG_ERROR, "%.*s", (int)(str - beg), beg);
- str = se;
- }
- break;
- }
- break;
- case GRN_LOADER_STRING_ESC :
- switch (c) {
- case 'b' :
- GRN_TEXT_PUTC(ctx, loader->last, '\b');
- loader->stat = GRN_LOADER_STRING;
- break;
- case 'f' :
- GRN_TEXT_PUTC(ctx, loader->last, '\f');
- loader->stat = GRN_LOADER_STRING;
- break;
- case 'n' :
- GRN_TEXT_PUTC(ctx, loader->last, '\n');
- loader->stat = GRN_LOADER_STRING;
- break;
- case 'r' :
- GRN_TEXT_PUTC(ctx, loader->last, '\r');
- loader->stat = GRN_LOADER_STRING;
- break;
- case 't' :
- GRN_TEXT_PUTC(ctx, loader->last, '\t');
- loader->stat = GRN_LOADER_STRING;
- break;
- case 'u' :
- loader->stat = GRN_LOADER_UNICODE0;
- break;
- default :
- GRN_TEXT_PUTC(ctx, loader->last, c);
- loader->stat = GRN_LOADER_STRING;
- break;
- }
- str++;
- break;
- case GRN_LOADER_UNICODE0 :
- switch (c) {
- case '0' : case '1' : case '2' : case '3' : case '4' :
- case '5' : case '6' : case '7' : case '8' : case '9' :
- loader->unichar = (c - '0') * 0x1000;
- break;
- case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' :
- loader->unichar = (c - 'a' + 10) * 0x1000;
- break;
- case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' :
- loader->unichar = (c - 'A' + 10) * 0x1000;
- break;
- default :
- ;// todo : error
- }
- loader->stat = GRN_LOADER_UNICODE1;
- str++;
- break;
- case GRN_LOADER_UNICODE1 :
- switch (c) {
- case '0' : case '1' : case '2' : case '3' : case '4' :
- case '5' : case '6' : case '7' : case '8' : case '9' :
- loader->unichar += (c - '0') * 0x100;
- break;
- case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' :
- loader->unichar += (c - 'a' + 10) * 0x100;
- break;
- case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' :
- loader->unichar += (c - 'A' + 10) * 0x100;
- break;
- default :
- ;// todo : error
- }
- loader->stat = GRN_LOADER_UNICODE2;
- str++;
- break;
- case GRN_LOADER_UNICODE2 :
- switch (c) {
- case '0' : case '1' : case '2' : case '3' : case '4' :
- case '5' : case '6' : case '7' : case '8' : case '9' :
- loader->unichar += (c - '0') * 0x10;
- break;
- case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' :
- loader->unichar += (c - 'a' + 10) * 0x10;
- break;
- case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' :
- loader->unichar += (c - 'A' + 10) * 0x10;
- break;
- default :
- ;// todo : error
- }
- loader->stat = GRN_LOADER_UNICODE3;
- str++;
- break;
- case GRN_LOADER_UNICODE3 :
- switch (c) {
- case '0' : case '1' : case '2' : case '3' : case '4' :
- case '5' : case '6' : case '7' : case '8' : case '9' :
- loader->unichar += (c - '0');
- break;
- case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' :
- loader->unichar += (c - 'a' + 10);
- break;
- case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' :
- loader->unichar += (c - 'A' + 10);
- break;
- default :
- ;// todo : error
- }
- {
- uint32_t u = loader->unichar;
- if (u < 0x80) {
- GRN_TEXT_PUTC(ctx, loader->last, u);
- } else {
- if (u < 0x800) {
- GRN_TEXT_PUTC(ctx, loader->last, ((u >> 6) & 0x1f) | 0xc0);
- } else {
- GRN_TEXT_PUTC(ctx, loader->last, (u >> 12) | 0xe0);
- GRN_TEXT_PUTC(ctx, loader->last, ((u >> 6) & 0x3f) | 0x80);
- }
- GRN_TEXT_PUTC(ctx, loader->last, (u & 0x3f) | 0x80);
- }
+ key_size = grn_table_cursor_get_key(ctx, cursor, &key);
+#define INSPECT "inspect"
+#define INSPECT_LEN (sizeof(INSPECT) - 1)
+ if (key_size == INSPECT_LEN && memcmp(key, INSPECT, INSPECT_LEN) == 0) {
+ if (!grn_ctx_at(ctx, id)) {
+ ERRCLR(ctx);
+ grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
}
- loader->stat = GRN_LOADER_STRING;
- str++;
- break;
- case GRN_LOADER_END :
- str = se;
break;
}
- }
-}
-
-#undef JSON_READ_OPEN_BRACKET
-#undef JSON_READ_OPEN_BRACE
-
-static grn_rc
-parse_load_columns(grn_ctx *ctx, grn_obj *table,
- const char *str, unsigned int str_size, grn_obj *res)
-{
- const char *p = (char *)str, *q, *r, *pe = p + str_size, *tokbuf[256];
- while (p < pe) {
- int i, n = tokenize(p, pe - p, tokbuf, 256, &q);
- for (i = 0; i < n; i++) {
- grn_obj *col;
- r = tokbuf[i];
- while (p < r && (' ' == *p || ',' == *p)) { p++; }
- col = grn_obj_column(ctx, table, p, r - p);
- if (!col) {
- ERR(GRN_INVALID_ARGUMENT, "nonexistent column: <%.*s>", (int)(r - p), p);
- goto exit;
- }
- GRN_PTR_PUT(ctx, res, col);
- p = r;
- }
- p = q;
- }
-exit:
- return ctx->rc;
-}
-
-static grn_com_addr *addr;
-
-void
-grn_load_(grn_ctx *ctx, grn_content_type input_type,
- const char *table, unsigned int table_len,
- const char *columns, unsigned int columns_len,
- const char *values, unsigned int values_len,
- const char *ifexists, unsigned int ifexists_len,
- const char *each, unsigned int each_len,
- uint32_t emit_level)
-{
- grn_loader *loader;
- loader = &ctx->impl->loader;
- loader->emit_level = emit_level;
- if (ctx->impl->edge) {
- grn_edge *edge = grn_edges_add_communicator(ctx, addr);
- grn_obj *msg = grn_msg_open(ctx, edge->com, &ctx->impl->edge->send_old);
- /* build msg */
- grn_edge_dispatch(ctx, edge, msg);
- }
- if (table && table_len) {
- grn_ctx_loader_clear(ctx);
- loader->input_type = input_type;
- if (grn_db_check_name(ctx, table, table_len)) {
- GRN_DB_CHECK_NAME_ERR("[table][load]", table, table_len);
- loader->stat = GRN_LOADER_END;
- return;
- }
- loader->table = grn_ctx_get(ctx, table, table_len);
- if (!loader->table) {
- ERR(GRN_INVALID_ARGUMENT, "nonexistent table: <%.*s>", table_len, table);
- loader->stat = GRN_LOADER_END;
- return;
- }
- if (loader->table && columns && columns_len) {
- int i, n_columns;
- grn_obj parsed_columns;
-
- GRN_PTR_INIT(&parsed_columns, GRN_OBJ_VECTOR, GRN_ID_NIL);
- if (parse_load_columns(ctx, loader->table, columns, columns_len,
- &parsed_columns)) {
- loader->stat = GRN_LOADER_END;
- return;
- }
- n_columns = GRN_BULK_VSIZE(&parsed_columns) / sizeof(grn_obj *);
- for (i = 0; i < n_columns; i++) {
- grn_obj *column;
- column = GRN_PTR_VALUE_AT(&parsed_columns, i);
- if (column->header.type == GRN_ACCESSOR &&
- ((grn_accessor *)column)->action == GRN_ACCESSOR_GET_KEY) {
- loader->key_offset = i;
- grn_obj_unlink(ctx, column);
- } else {
- GRN_PTR_PUT(ctx, &loader->columns, column);
- }
- }
- GRN_OBJ_FIN(ctx, &parsed_columns);
- }
- if (ifexists && ifexists_len) {
- grn_obj *v;
- GRN_EXPR_CREATE_FOR_QUERY(ctx, loader->table, loader->ifexists, v);
- if (loader->ifexists && v) {
- grn_expr_parse(ctx, loader->ifexists, ifexists, ifexists_len,
- NULL, GRN_OP_EQUAL, GRN_OP_AND,
- GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE);
- }
- }
- if (each && each_len) {
- grn_obj *v;
- GRN_EXPR_CREATE_FOR_QUERY(ctx, loader->table, loader->each, v);
- if (loader->each && v) {
- grn_expr_parse(ctx, loader->each, each, each_len,
- NULL, GRN_OP_EQUAL, GRN_OP_AND,
- GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE);
- }
- }
- } else {
- if (!loader->table) {
- ERR(GRN_INVALID_ARGUMENT, "mandatory \"table\" parameter is absent");
- loader->stat = GRN_LOADER_END;
- return;
- }
- input_type = loader->input_type;
- }
- switch (input_type) {
- case GRN_CONTENT_JSON :
- json_read(ctx, loader, values, values_len);
- break;
- case GRN_CONTENT_NONE :
- case GRN_CONTENT_TSV :
- case GRN_CONTENT_XML :
- case GRN_CONTENT_MSGPACK :
- case GRN_CONTENT_GROONGA_COMMAND_LIST :
- ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "unsupported input_type");
- // todo
- break;
- }
-}
-
-grn_rc
-grn_load(grn_ctx *ctx, grn_content_type input_type,
- const char *table, unsigned int table_len,
- const char *columns, unsigned int columns_len,
- const char *values, unsigned int values_len,
- const char *ifexists, unsigned int ifexists_len,
- const char *each, unsigned int each_len)
-{
- if (!ctx || !ctx->impl) {
- ERR(GRN_INVALID_ARGUMENT, "db not initialized");
- return ctx->rc;
- }
- GRN_API_ENTER;
- grn_load_(ctx, input_type, table, table_len,
- columns, columns_len, values, values_len,
- ifexists, ifexists_len, each, each_len, 1);
- GRN_API_RETURN(ctx->rc);
+#undef INSPECT
+#undef INSPECT_LEN
+ } GRN_TABLE_EACH_END(ctx, cursor);
}
static void
grn_db_recover_database(grn_ctx *ctx, grn_obj *db)
{
- if (!grn_obj_is_locked(ctx, db)) {
+ if (grn_obj_is_locked(ctx, db)) {
+ ERR(GRN_OBJECT_CORRUPT,
+ "[db][recover] database may be broken. Please re-create the database");
return;
}
- ERR(GRN_OBJECT_CORRUPT,
- "[db][recover] database may be broken. Please re-create the database");
+ grn_db_clear_dirty(ctx, db);
+ grn_db_recover_database_remove_orphan_inspect(ctx, db);
}
static void
@@ -12629,14 +13752,39 @@ grn_db_recover_data_column(grn_ctx *ctx, grn_obj *data_column)
static void
grn_db_recover_index_column(grn_ctx *ctx, grn_obj *index_column)
{
- grn_ii *ii = (grn_ii *)index_column;
-
if (!grn_obj_is_locked(ctx, index_column)) {
return;
}
- grn_ii_truncate(ctx, ii);
- build_index(ctx, index_column);
+ grn_index_column_rebuild(ctx, index_column);
+}
+
+static grn_bool
+grn_db_recover_is_builtin(grn_ctx *ctx, grn_id id, grn_table_cursor *cursor)
+{
+ void *key;
+ const char *name;
+ int name_size;
+
+ if (id < GRN_N_RESERVED_TYPES) {
+ return GRN_TRUE;
+ }
+
+ name_size = grn_table_cursor_get_key(ctx, cursor, &key);
+ name = key;
+
+#define NAME_EQUAL(value) \
+ (name_size == strlen(value) && memcmp(name, value, strlen(value)) == 0)
+
+ if (NAME_EQUAL("inspect")) {
+ /* Just for compatibility. It's needed for users who used
+ Groonga master at between 2016-02-03 and 2016-02-26. */
+ return GRN_TRUE;
+ }
+
+#undef NAME_EQUAL
+
+ return GRN_FALSE;
}
grn_rc
@@ -12644,9 +13792,12 @@ grn_db_recover(grn_ctx *ctx, grn_obj *db)
{
grn_table_cursor *cursor;
grn_id id;
+ grn_bool is_close_opened_object_mode;
GRN_API_ENTER;
+ is_close_opened_object_mode = (grn_thread_get_limit() == 1);
+
grn_db_recover_database(ctx, db);
if (ctx->rc != GRN_SUCCESS) {
GRN_API_RETURN(ctx->rc);
@@ -12663,6 +13814,10 @@ grn_db_recover(grn_ctx *ctx, grn_obj *db)
while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
grn_obj *object;
+ if (is_close_opened_object_mode) {
+ grn_ctx_push_temporary_open_space(ctx);
+ }
+
if ((object = grn_ctx_at(ctx, id))) {
switch (object->header.type) {
case GRN_TABLE_NO_KEY :
@@ -12683,7 +13838,13 @@ grn_db_recover(grn_ctx *ctx, grn_obj *db)
}
grn_obj_unlink(ctx, object);
} else {
- ERRCLR(ctx);
+ if (grn_db_recover_is_builtin(ctx, id, cursor)) {
+ ERRCLR(ctx);
+ }
+ }
+
+ if (is_close_opened_object_mode) {
+ grn_ctx_pop_temporary_open_space(ctx);
}
if (ctx->rc != GRN_SUCCESS) {
@@ -12696,7 +13857,38 @@ grn_db_recover(grn_ctx *ctx, grn_obj *db)
}
grn_rc
-grn_ctx_get_all_tables(grn_ctx *ctx, grn_obj *tables_buffer)
+grn_db_unmap(grn_ctx *ctx, grn_obj *db)
+{
+ grn_id id;
+ db_value *vp;
+ grn_db *s = (grn_db *)db;
+
+ GRN_API_ENTER;
+
+ GRN_TINY_ARRAY_EACH(&s->values, 1, grn_db_curr_id(ctx, db), id, vp, {
+ grn_obj *obj = vp->ptr;
+
+ if (obj) {
+ switch (obj->header.type) {
+ case GRN_TABLE_HASH_KEY :
+ case GRN_TABLE_PAT_KEY :
+ case GRN_TABLE_DAT_KEY :
+ case GRN_TABLE_NO_KEY :
+ case GRN_COLUMN_FIX_SIZE :
+ case GRN_COLUMN_VAR_SIZE :
+ case GRN_COLUMN_INDEX :
+ grn_obj_close(ctx, obj);
+ break;
+ }
+ }
+ });
+
+ GRN_API_RETURN(ctx->rc);
+}
+
+static grn_rc
+grn_ctx_get_all_objects(grn_ctx *ctx, grn_obj *objects_buffer,
+ grn_bool (*predicate)(grn_ctx *ctx, grn_obj *object))
{
grn_obj *db;
grn_table_cursor *cursor;
@@ -12719,8 +13911,8 @@ grn_ctx_get_all_tables(grn_ctx *ctx, grn_obj *tables_buffer)
grn_obj *object;
if ((object = grn_ctx_at(ctx, id))) {
- if (grn_obj_is_table(ctx, object)) {
- GRN_PTR_PUT(ctx, tables_buffer, object);
+ if (predicate(ctx, object)) {
+ GRN_PTR_PUT(ctx, objects_buffer, object);
} else {
grn_obj_unlink(ctx, object);
}
@@ -12734,3 +13926,126 @@ grn_ctx_get_all_tables(grn_ctx *ctx, grn_obj *tables_buffer)
GRN_API_RETURN(ctx->rc);
}
+
+grn_rc
+grn_ctx_get_all_tables(grn_ctx *ctx, grn_obj *tables_buffer)
+{
+ return grn_ctx_get_all_objects(ctx, tables_buffer, grn_obj_is_table);
+}
+
+grn_rc
+grn_ctx_get_all_types(grn_ctx *ctx, grn_obj *types_buffer)
+{
+ return grn_ctx_get_all_objects(ctx, types_buffer, grn_obj_is_type);
+}
+
+grn_rc
+grn_ctx_get_all_tokenizers(grn_ctx *ctx, grn_obj *tokenizers_buffer)
+{
+ return grn_ctx_get_all_objects(ctx, tokenizers_buffer,
+ grn_obj_is_tokenizer_proc);
+}
+
+grn_rc
+grn_ctx_get_all_normalizers(grn_ctx *ctx, grn_obj *normalizers_buffer)
+{
+ return grn_ctx_get_all_objects(ctx, normalizers_buffer,
+ grn_obj_is_normalizer_proc);
+}
+
+grn_rc
+grn_ctx_get_all_token_filters(grn_ctx *ctx, grn_obj *token_filters_buffer)
+{
+ return grn_ctx_get_all_objects(ctx, token_filters_buffer,
+ grn_obj_is_token_filter_proc);
+}
+
+grn_rc
+grn_ctx_push_temporary_open_space(grn_ctx *ctx)
+{
+ grn_obj *stack;
+ grn_obj *space;
+ grn_obj buffer;
+
+ GRN_API_ENTER;
+
+ stack = &(ctx->impl->temporary_open_spaces.stack);
+ GRN_VOID_INIT(&buffer);
+ grn_bulk_write(ctx, stack, (const char *)&buffer, sizeof(grn_obj));
+ space = ((grn_obj *)GRN_BULK_CURR(stack)) - 1;
+ GRN_PTR_INIT(space, GRN_OBJ_VECTOR | GRN_OBJ_OWN, GRN_ID_NIL);
+
+ ctx->impl->temporary_open_spaces.current = space;
+
+ GRN_API_RETURN(ctx->rc);
+}
+
+grn_rc
+grn_ctx_pop_temporary_open_space(grn_ctx *ctx)
+{
+ grn_obj *stack;
+ grn_obj *space;
+
+ GRN_API_ENTER;
+
+ stack = &(ctx->impl->temporary_open_spaces.stack);
+ if (GRN_BULK_EMPTYP(stack)) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[ctx][temporary-open-spaces][pop] too much pop");
+ GRN_API_RETURN(ctx->rc);
+ }
+
+ space = ctx->impl->temporary_open_spaces.current;
+ GRN_OBJ_FIN(ctx, space);
+ grn_bulk_truncate(ctx, stack, GRN_BULK_VSIZE(stack) - sizeof(grn_obj));
+
+ if (GRN_BULK_EMPTYP(stack)) {
+ space = NULL;
+ } else {
+ space = ((grn_obj *)GRN_BULK_CURR(stack)) - 1;
+ }
+ ctx->impl->temporary_open_spaces.current = space;
+
+ GRN_API_RETURN(ctx->rc);
+}
+
+grn_rc
+grn_ctx_merge_temporary_open_space(grn_ctx *ctx)
+{
+ grn_obj *stack;
+ grn_obj *space;
+ grn_obj *next_space;
+
+ GRN_API_ENTER;
+
+ stack = &(ctx->impl->temporary_open_spaces.stack);
+ if (GRN_BULK_VSIZE(stack) < sizeof(grn_obj) * 2) {
+ ERR(GRN_INVALID_ARGUMENT,
+ "[ctx][temporary-open-spaces][merge] "
+ "merge requires at least two spaces");
+ GRN_API_RETURN(ctx->rc);
+ }
+
+ space = ctx->impl->temporary_open_spaces.current;
+ next_space = ctx->impl->temporary_open_spaces.current - 1;
+ {
+ unsigned int i, n_elements;
+ n_elements = GRN_BULK_VSIZE(space) / sizeof(grn_obj *);
+ for (i = 0; i < n_elements; i++) {
+ grn_obj *element = GRN_PTR_VALUE_AT(space, i);
+ GRN_PTR_PUT(ctx, next_space, element);
+ }
+ }
+ GRN_BULK_REWIND(space);
+ GRN_OBJ_FIN(ctx, space);
+ grn_bulk_truncate(ctx, stack, GRN_BULK_VSIZE(stack) - sizeof(grn_obj));
+
+ if (GRN_BULK_EMPTYP(stack)) {
+ space = NULL;
+ } else {
+ space = ((grn_obj *)GRN_BULK_CURR(stack)) - 1;
+ }
+ ctx->impl->temporary_open_spaces.current = space;
+
+ GRN_API_RETURN(ctx->rc);
+}