void test_accessor(void) { int i; grn_obj *t1, *t2, *c1, *c2, r1, r2; t1 = grn_table_create(context, "t1", 2, NULL, GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT, NULL, NULL); cut_assert_not_null(t1); t2 = grn_table_create(context, "t2", 2, NULL, GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT, NULL, NULL); cut_assert_not_null(t2); c1 = grn_column_create(context, t1, "c1", 2, NULL, GRN_OBJ_PERSISTENT, t2); cut_assert_not_null(c1); c2 = grn_column_create(context, t2, "c2", 2, NULL, GRN_OBJ_PERSISTENT, t1); cut_assert_not_null(c2); GRN_RECORD_INIT(&r1, 0, grn_obj_id(context, t1)); GRN_RECORD_INIT(&r2, 0, grn_obj_id(context, t2)); for (i = 0; i < NRECORDS; i++) { grn_id i1, i2; i1 = grn_table_add(context, t1, NULL, 0, NULL); i2 = grn_table_add(context, t2, NULL, 0, NULL); GRN_RECORD_SET(context, &r1, i1); GRN_RECORD_SET(context, &r2, i2); grn_obj_set_value(context, c1, i1, &r2, GRN_OBJ_SET); grn_obj_set_value(context, c2, i2, &r1, GRN_OBJ_SET); } { grn_id id; uint64_t et; int nerr = 0; struct timeval tvb, tve; grn_obj *a = grn_obj_column(context, t1, "c1.c2.c1", 8); grn_table_cursor *tc = grn_table_cursor_open(context, t1, NULL, 0, NULL, 0, 0, -1, 0); cut_assert_not_null(a); cut_assert_not_null(tc); gettimeofday(&tvb, NULL); while ((id = grn_table_cursor_next(context, tc))) { GRN_BULK_REWIND(&r2); grn_obj_get_value(context, a, id, &r2); if (GRN_RECORD_VALUE(&r2) != id) { nerr++; } } gettimeofday(&tve, NULL); et = (tve.tv_sec - tvb.tv_sec) * 1000000 + (tve.tv_usec - tvb.tv_usec); // printf("et=%zu\n", et); cut_assert_equal_uint(0, nerr); grn_test_assert(grn_table_cursor_close(context, tc)); grn_test_assert(grn_obj_close(context, a)); } grn_test_assert(grn_obj_close(context, &r1)); grn_test_assert(grn_obj_close(context, &r2)); }
void test_array_set_data(void) { grn_obj *table; grn_id record_id; gchar value[] = "sample value"; grn_obj *record_value; grn_obj *retrieved_record_value; const gchar *dupped_retrieved_record_value; const gchar *value_type_name = "value_type"; grn_obj *value_type; value_type = grn_type_create(context, value_type_name, strlen(value_type_name), 0, sizeof(value)); table = grn_table_create(context, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY, NULL, value_type); record_id = grn_table_add(context, table, NULL, 0, NULL); record_value = grn_obj_open(context, GRN_BULK, 0, GRN_DB_TEXT); grn_bulk_write(context, record_value, value, sizeof(value)); grn_test_assert(grn_obj_set_value(context, table, record_id, record_value, GRN_OBJ_SET)); grn_obj_unlink(context, record_value); retrieved_record_value = grn_obj_get_value(context, table, record_id, NULL); dupped_retrieved_record_value = cut_take_strdup(GRN_BULK_HEAD(retrieved_record_value)); grn_obj_unlink(context, retrieved_record_value); cut_assert_equal_string(value, dupped_retrieved_record_value); }
int table_put_allocate(void) { int i; grn_obj *buf; grn_obj *key_type = grn_ctx_at(&ctx, GRN_DB_SHORT_TEXT); grn_obj *table = grn_table_create(&ctx, "<t1>", 4, NULL, GRN_OBJ_TABLE_HASH_KEY|GRN_OBJ_PERSISTENT, key_type, value_type); if (!table) { return -1; } for (i = 0; i < nloops; i++) { int key = GENKEY(i); buf = grn_obj_open(&ctx, GRN_BULK, 0, 0); grn_text_itoh(&ctx, buf, key, key_size); { grn_id rid = grn_table_add(&ctx, table, GRN_BULK_HEAD(buf), key_size, NULL); if (!rid) { fprintf(stderr, "table_lookup failed"); } else { grn_obj *value_buf; value_buf = grn_obj_open(&ctx, GRN_BULK, 0, 0); grn_text_itoh(&ctx, value_buf, key, key_size); if (grn_obj_set_value(&ctx, table, rid, value_buf, GRN_OBJ_SET)) { fprintf(stderr, "grn_obj_set_value failed"); } grn_obj_close(&ctx, value_buf); } } grn_obj_close(&ctx, buf); } return 0; }
void test_unsequantial_records_in_table_with_keys(void) { grn_obj *table; grn_id id, expected_id = 1; const gchar *keys[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; int i, n_keys = sizeof(keys) / sizeof(keys[0]); table = table_create("Weekdays", GRN_OBJ_TABLE_HASH_KEY, "ShortText", NULL); grn_test_assert_context(context); for (i = 0; i < n_keys; ++i) { id = grn_table_add(context, table, keys[i], strlen(keys[i]), NULL); cut_assert_equal_int(expected_id++, id); grn_test_assert_context(context); } grn_table_delete_by_id(context, table, 3); grn_table_delete_by_id(context, table, 6); cut_assert_equal_string("table_create Weekdays TABLE_HASH_KEY ShortText\n" "load --table Weekdays\n" "[\n" "[\"_key\"],\n" "[\"Sun\"],\n" "[\"Mon\"],\n" "[\"Wed\"],\n" "[\"Thu\"],\n" "[\"Sat\"]\n" "]", send_command("dump")); }
void test_read_write(gconstpointer *data) { gint i; int added; grn_ctx *context; grn_obj *table; const gchar *path; const gchar *value_string; gint process_number = 0; const gchar *process_number_string; const gchar table_name[] = "performance-read-write"; grn_obj value; grn_obj *retrieved_value; grn_id id; grn_rc rc; i = GPOINTER_TO_INT(data); process_number_string = g_getenv(GRN_TEST_ENV_PROCESS_NUMBER); if (process_number_string) process_number = atoi(process_number_string); rc = grn_ctx_init(&contexts[i], GRN_CTX_USE_QL); grn_test_assert(rc, cut_set_message("context: %d (%d)", i, process_number)); context = &contexts[i]; path = g_getenv(GRN_TEST_ENV_TABLE_PATH); cut_assert_not_null(path); tables[i] = grn_table_open(context, table_name, strlen(table_name), path); cut_assert_not_null(tables[i], cut_message("table: %d (%d)", i, process_number)); table = tables[i]; grn_test_assert_nil(grn_table_get(context, table, &i, sizeof(grn_id)), cut_message("lookup - fail: (%d:%d)", i, process_number)); value_string = cut_take_printf("value: (%d:%d)", i, process_number); id = grn_table_add(context, table, &i, sizeof(grn_id), &added); grn_test_assert_not_nil(id); cut_assert_equal_int(1, added); GRN_TEXT_INIT(&value, GRN_OBJ_DO_SHALLOW_COPY); GRN_TEXT_SET_REF(&value, value_string, strlen(value_string)); grn_obj_set_value(context, table, id, &value, GRN_OBJ_SET); retrieved_value = grn_obj_get_value(context, table, id, NULL); grn_test_assert_not_nil( id, cut_message("lookup - success: (%d:%d)", i, process_number)); GRN_TEXT_PUTC(context, retrieved_value, '\0'); cut_assert_equal_string(value_string, GRN_BULK_HEAD(retrieved_value)); tables[i] = NULL; grn_test_assert(grn_obj_close(context, table)); // contexts[i] = NULL; grn_test_assert(grn_ctx_fin(context)); }
static void add_groonga_bookmark(void) { gchar key[] = "groonga"; groonga_bookmark_id = grn_table_add(&context, bookmarks, &key, strlen(key), NULL); grn_test_assert_context(&context); cut_set_message("%s", cut_take_string(grn_collect_logger_to_string(logger))); grn_test_assert_not_nil(groonga_bookmark_id); }
static void insert_and_search(grn_obj *users, grn_obj *items, grn_obj *checks, grn_obj *checked) { grn_id user1 = grn_table_add(context, users, NULL, 0, NULL); grn_id user2 = grn_table_add(context, users, NULL, 0, NULL); grn_id item = grn_table_add(context, items, NULL, 0, NULL); grn_obj value, *res; GRN_TEXT_INIT(&value, 0); res = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_HASH_KEY, users, 0); cut_assert_not_null(res); grn_bulk_write(context, &value, (void *)&item, sizeof(grn_id)); value.header.domain = grn_obj_id(context, items); grn_test_assert(grn_obj_set_value(context, checks, user1, &value, GRN_OBJ_SET)); grn_test_assert(grn_obj_search(context, checked, &value, res, GRN_OP_OR, NULL)); cut_assert_equal_int(grn_table_size(context, res), 1); grn_test_assert(grn_obj_set_value(context, checks, user2, &value, GRN_OBJ_SET)); grn_test_assert(grn_obj_search(context, checked, &value, res, GRN_OP_OR, NULL)); cut_assert_equal_int(grn_table_size(context, res), 2); grn_obj_close(context, &value); grn_obj_close(context, res); }
static grn_id add_record(const gchar *table_name, const gchar *key) { grn_obj *table; grn_id record_id; table = grn_ctx_get(&context, table_name, strlen(table_name)); record_id = grn_table_add(&context, table, key, key ? strlen(key) : 0, NULL); grn_obj_unlink(&context, table); grn_test_assert_not_nil(record_id); return record_id; }
void test_temporary_table_add(gpointer data) { grn_obj *table; grn_obj_flags flags = GPOINTER_TO_INT(data); gchar key[] = "key"; if ((flags & GRN_OBJ_TABLE_TYPE_MASK) == GRN_OBJ_TABLE_NO_KEY) { table = grn_table_create(context, NULL, 0, NULL, flags, NULL, NULL); grn_table_add(context, table, NULL, 0, NULL); } else { table = grn_table_create(context, NULL, 0, NULL, flags, get_object("ShortText"), NULL); grn_table_add(context, table, key, strlen(key), NULL); } cut_assert_equal_int(1, grn_table_size(context, table)); }
// <cmd> {<len> <column id>} <types> <#kvs> [{<len> <key>} {<len> <value>}]... void put_or_set(server_t *s, grn_ctx *ctx, int set) { uint32_t len; HOG_RECV(s, &len, sizeof(len), return); len = ntohl(len); char *buf = hog_alloc(NULL, len); HOG_RECV(s, buf, len, goto cleanup); grn_obj *col, *table; col = grn_ctx_get(ctx, buf, len); if(grn_obj_is_table(ctx, col)) table = col; else table = grn_column_table(ctx, col); // get key and value types char types[2]; HOG_RECV(s, types, 2, goto cleanup); // receive keys and values uint32_t nkeys; HOG_RECV(s, &nkeys, sizeof(nkeys), goto cleanup); nkeys = ntohl(nkeys); grn_obj value; GRN_OBJ_INIT(&value, GRN_BULK, 0, types[1]); for(uint32_t i = 0; i < nkeys; ++i){ HOG_RECV(s, &len, sizeof(len), goto value_fin); len = ntohl(len); buf = hog_alloc(buf, len); HOG_RECV(s, buf, len, goto value_fin); ntoh_buf(buf, len, types[0]); grn_id id; if(set){ id = grn_table_get(ctx, table, buf, len); }else{ id = grn_table_add(ctx, table, buf, len, NULL); } HOG_RECV(s, &len, sizeof(len), goto value_fin); len = ntohl(len); buf = hog_alloc(buf, len); HOG_RECV(s, buf, len, goto value_fin); if(id == GRN_ID_NIL) continue; ntoh_buf(buf, len, types[1]); GRN_BULK_REWIND(&value); grn_bulk_write(ctx, &value, buf, len); grn_obj_set_value(ctx, col, id, &value, GRN_OBJ_SET); } submit_one(s->socket); value_fin: GRN_OBJ_FIN(ctx, &value); cleanup: free(buf); }
static grn_obj * func_highlight_html_create_keywords_table(grn_ctx *ctx, grn_obj *expression) { grn_obj *keywords; grn_obj *condition_ptr = NULL; grn_obj *condition = NULL; keywords = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_PAT_KEY, grn_ctx_at(ctx, GRN_DB_SHORT_TEXT), NULL); { grn_obj *normalizer; normalizer = grn_ctx_get(ctx, "NormalizerAuto", -1); grn_obj_set_info(ctx, keywords, GRN_INFO_NORMALIZER, normalizer); grn_obj_unlink(ctx, normalizer); } condition_ptr = grn_expr_get_var(ctx, expression, GRN_SELECT_INTERNAL_VAR_CONDITION, strlen(GRN_SELECT_INTERNAL_VAR_CONDITION)); if (condition_ptr) { condition = GRN_PTR_VALUE(condition_ptr); } if (condition) { size_t i, n_keywords; grn_obj current_keywords; GRN_PTR_INIT(¤t_keywords, GRN_OBJ_VECTOR, GRN_ID_NIL); grn_expr_get_keywords(ctx, condition, ¤t_keywords); n_keywords = GRN_BULK_VSIZE(¤t_keywords) / sizeof(grn_obj *); for (i = 0; i < n_keywords; i++) { grn_obj *keyword; keyword = GRN_PTR_VALUE_AT(¤t_keywords, i); grn_table_add(ctx, keywords, GRN_TEXT_VALUE(keyword), GRN_TEXT_LEN(keyword), NULL); } grn_obj_unlink(ctx, ¤t_keywords); } return keywords; }
void test_vector_column(gconstpointer data) { const gchar *expected; grn_id id, type_id; grn_obj vector; grn_obj *elements; grn_obj *table, *column; const gchar *type_name; type_name = gcut_data_get_string(data, "type_name"); type_id = grn_obj_id(context, get_object(type_name)); table = table_create("Table", GRN_OBJ_TABLE_NO_KEY, NULL, NULL); grn_test_assert_context(context); column = column_create("Table", "Column", GRN_OBJ_COLUMN_VECTOR, type_name, NULL); grn_test_assert_context(context); id = grn_table_add(context, table, NULL, 0, NULL); grn_test_assert_context(context); cut_assert_equal_int(1, id); elements = construct_elements(data); GRN_TEXT_INIT(&vector, GRN_OBJ_VECTOR); grn_vector_add_element(context, &vector, GRN_TEXT_VALUE(&elements[0]), GRN_TEXT_LEN(&elements[0]), 0, type_id); grn_vector_add_element(context, &vector, GRN_TEXT_VALUE(&elements[1]), GRN_TEXT_LEN(&elements[1]), 0, type_id); grn_vector_add_element(context, &vector, GRN_TEXT_VALUE(&elements[2]), GRN_TEXT_LEN(&elements[2]), 0, type_id); grn_obj_set_value(context, column, id, &vector, GRN_OBJ_SET); expected = cut_take_printf("table_create Table TABLE_NO_KEY\n" "column_create Table Column COLUMN_VECTOR %s\n" "load --table Table\n" "[\n" "[\"_id\",\"Column\"],\n" "[1,%s]\n" "]", type_name, gcut_data_get_string(data, "expected")); cut_assert_equal_string(expected, send_command("dump")); GRN_OBJ_FIN(context, &vector); }
grn_rc grn_index_upd(grn_ctx *ctx, grn_index *index, const char *key, const char *oldvalue, unsigned int oldvalue_len, const char *newvalue, unsigned int newvalue_len) { grn_id rid = grn_table_add(ctx, index->keys, key, strlen(key), NULL); if (rid) { grn_obj old, new; GRN_TEXT_INIT(&old, GRN_OBJ_DO_SHALLOW_COPY); GRN_TEXT_INIT(&new, GRN_OBJ_DO_SHALLOW_COPY); GRN_TEXT_SET_REF(&old, oldvalue, oldvalue_len); GRN_TEXT_SET_REF(&new, newvalue, newvalue_len); grn_column_index_update(ctx, index->inv, rid, 1, &old, &new); grn_obj_close(ctx, &old); grn_obj_close(ctx, &new); } return ctx->rc; }
/* * call-seq: * array.add(values=nil) -> Groonga::Recordまたはnil * * レコード追加し、追加したレコードを返す。レコードの追加に失 * 敗した場合は+nil+を返す。 * * _values_にはレコードのカラムに設定する値を指定する。省略 * した場合または+nil+を指定した場合はカラムは設定しない。カ * ラムの値は<tt>{:カラム名1 => 値1, :カラム名2 => 値2, * ...}</tt>と指定する。 * * 使用例では、以下のようなユーザを格納するGroonga::Arrayが * 定義されているものとする。 * users = Groonga::Array.create(:name => "Users") * users.define_column("name", "ShortText") * users.define_column("uri", "ShortText") * * ユーザを追加する。 * user = users.add * * daijiroユーザを追加する。 * daijiro = users.add(:name => "daijiro") * * gunyara-kunユーザを追加する。 * gunyara_kun = users.add(:name => "gunyara-kun", * :uri => "http://d.hatena.ne.jp/tasukuchan/") */ static VALUE rb_grn_array_add (int argc, VALUE *argv, VALUE self) { grn_ctx *context = NULL; grn_obj *table; grn_id id; VALUE values; rb_scan_args(argc, argv, "01", &values); table = SELF(self, &context); id = grn_table_add(context, table, NULL, 0, NULL); rb_grn_context_check(context, self); if (GRN_ID_NIL == id) return Qnil; else return rb_grn_record_new(self, id, values); }
static void insert_document(const gchar *author_content, const gchar *body_content) { uint32_t s = (uint32_t)strlen(body_content); grn_id docid = grn_table_add(&context, docs, NULL, 0, NULL); if (author_content) { GRN_TEXT_SET(&context, &text_buf, author_content, strlen(author_content)); grn_test_assert(grn_obj_set_value(&context, author, docid, &text_buf, GRN_OBJ_SET)); } GRN_TEXT_SET(&context, &text_buf, body_content, s); grn_test_assert(grn_obj_set_value(&context, body, docid, &text_buf, GRN_OBJ_SET)); GRN_UINT32_SET(&context, &int_buf, s); grn_test_assert(grn_obj_set_value(&context, size, docid, &int_buf, GRN_OBJ_SET)); }
static grn_id rb_grn_table_key_support_add_raw (VALUE self, VALUE rb_key, int *added) { grn_ctx *context; grn_obj *table; grn_id id, domain_id; grn_obj *key, *domain; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, &key, &domain_id, &domain, NULL, NULL, NULL, NULL); GRN_BULK_REWIND(key); RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self); id = grn_table_add(context, table, GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key), added); rb_grn_context_check(context, self); return id; }
int column_put(void) { int i, s = 0; grn_obj buf; grn_obj *key_type = grn_ctx_at(&ctx, GRN_DB_SHORT_TEXT); grn_obj *table = grn_table_create(&ctx, "<t1>", 4, NULL, GRN_OBJ_TABLE_HASH_KEY|GRN_OBJ_PERSISTENT, key_type, NULL); grn_obj *value_type = grn_ctx_at(&ctx, GRN_DB_TEXT); grn_obj *column = grn_column_create(&ctx, table, "c1", 2, NULL, GRN_OBJ_PERSISTENT, value_type); if (!table || !column) { return -1; } GRN_TEXT_INIT(&buf, 0); for (i = 0; i < nloops; i++) { int key = GENKEY(i); GRN_BULK_REWIND(&buf); grn_text_itoh(&ctx, &buf, key, key_size); { grn_id rid = grn_table_add(&ctx, table, GRN_BULK_HEAD(&buf), key_size, NULL); if (!rid) { fprintf(stderr, "table_lookup failed"); } else { unsigned int v = key % value_size; GRN_BULK_REWIND(&buf); if (v) { grn_bulk_space(&ctx, &buf, v -1); GRN_TEXT_PUTC(&ctx, &buf, GRN_BULK_HEAD(&buf)[0]); s += v; } if (grn_obj_set_value(&ctx, column, rid, &buf, GRN_OBJ_SET)) { fprintf(stderr, "grn_obj_set_value failed"); } } } } grn_obj_close(&ctx, &buf); printf("total size: %d\n", s); return 0; }
void test_array_truncate(void) { grn_obj *table; gchar value[] = "sample value"; gchar *value_type_name = "value_type"; grn_obj *value_type; cut_omit("grn_table_truncate() is still buggy."); value_type = grn_type_create(context, value_type_name, strlen(value_type_name), 0, sizeof(value)); table = grn_table_create(context, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY, NULL, value_type); grn_test_assert_not_nil(grn_table_add(context, table, NULL, 0, NULL)); cut_assert_equal_uint(1, grn_table_size(context, table)); grn_test_assert(grn_table_truncate(context, table)); cut_assert_equal_uint(0, grn_table_size(context, table)); }
static void insert_document(const gchar *body_content) { uint32_t s = (uint32_t)strlen(body_content); grn_id docid = grn_table_add(&context, docs, NULL, 0, NULL); const gchar *size_string; struct tm time; GRN_TEXT_SET(&context, &textbuf, body_content, s); grn_test_assert(grn_obj_set_value(&context, body, docid, &textbuf, GRN_OBJ_SET)); GRN_UINT32_SET(&context, &intbuf, s); grn_test_assert(grn_obj_set_value(&context, size, docid, &intbuf, GRN_OBJ_SET)); size_string = cut_take_printf("%u", s); GRN_TEXT_SET(&context, &textbuf, size_string, strlen(size_string)); grn_test_assert(grn_obj_set_value(&context, size_in_string, docid, &textbuf, GRN_OBJ_SET)); GRN_FLOAT_SET(&context, &floatbuf, s); grn_test_assert(grn_obj_set_value(&context, size_in_float, docid, &floatbuf, GRN_OBJ_SET)); time.tm_sec = s; time.tm_min = 16; time.tm_hour = 15; time.tm_mday = 2; time.tm_mon = 11; time.tm_year = 109; time.tm_wday = 3; time.tm_yday = 336; time.tm_isdst = 0; GRN_TIME_SET(&context, &timebuf, GRN_TIME_PACK(mktime(&time), 0)); grn_test_assert(grn_obj_set_value(&context, created_at, docid, &timebuf, GRN_OBJ_SET)); }
void test_truncate_anonymous(gconstpointer data) { grn_obj_flags flags; const gchar *key; grn_obj *key_type; unsigned key_size; grn_bool array_p; int added; flags = gcut_data_get_int(data, "flags"); array_p = ((flags & GRN_OBJ_TABLE_TYPE_MASK) == GRN_OBJ_TABLE_NO_KEY); if (array_p) { key = NULL; key_size = 0; key_type = NULL; } else { key = "groonga"; key_size = strlen(key); key_type = grn_ctx_at(context, GRN_DB_SHORT_TEXT); } table = grn_table_create(context, NULL, 0, NULL, flags, key_type, NULL); if (key_type) { grn_obj_unlink(context, key_type); } grn_test_assert_not_nil(grn_table_add(context, table, key, key_size, &added)); cut_assert_true(added); cut_assert_equal_uint(1, grn_table_size(context, table)); grn_test_assert(grn_table_truncate(context, table)); cut_assert_equal_uint(0, grn_table_size(context, table)); }
static void brace_close(grn_ctx *ctx, grn_loader *loader) { grn_id id = GRN_ID_NIL; grn_obj *value, *value_begin, *value_end; grn_obj *id_value = NULL, *key_value = NULL; uint32_t begin; GRN_UINT32_POP(&loader->level, begin); value_begin = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + begin; value_end = (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_begin, loader->values_size - begin - 1); value_begin++; if (GRN_BULK_VSIZE(&loader->level) > sizeof(uint32_t) * loader->emit_level) { return; } if (!loader->table) { goto exit; } /* Scan values to find _id or _key. */ for (value = value_begin; value + 1 < value_end; value = values_next(ctx, value)) { const char *name = GRN_TEXT_VALUE(value); unsigned int name_size = GRN_TEXT_LEN(value); if (value->header.domain != GRN_DB_TEXT) { grn_obj buffer; GRN_TEXT_INIT(&buffer, 0); grn_inspect(ctx, &buffer, value); GRN_LOG(ctx, GRN_LOG_ERROR, "column name must be string: <%.*s>", (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); GRN_OBJ_FIN(ctx, &buffer); goto exit; } value++; if (name_equal(name, name_size, GRN_COLUMN_NAME_ID)) { if (id_value || key_value) { if (loader->table->header.type == GRN_TABLE_NO_KEY) { GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated '_id' column"); goto exit; } else { GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated key columns: %s and %s", id_value ? GRN_COLUMN_NAME_ID : GRN_COLUMN_NAME_KEY, GRN_COLUMN_NAME_ID); goto exit; } } id_value = value; } else if (name_equal(name, name_size, GRN_COLUMN_NAME_KEY)) { if (id_value || key_value) { GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated key columns: %s and %s", id_value ? GRN_COLUMN_NAME_ID : GRN_COLUMN_NAME_KEY, GRN_COLUMN_NAME_KEY); goto exit; } key_value = value; } } switch (loader->table->header.type) { case GRN_TABLE_HASH_KEY : case GRN_TABLE_PAT_KEY : case GRN_TABLE_DAT_KEY : /* The target table requires _id or _key. */ if (!id_value && !key_value) { GRN_LOG(ctx, GRN_LOG_ERROR, "neither _key nor _id is assigned"); goto exit; } break; default : /* The target table does not have _key. */ if (key_value) { GRN_LOG(ctx, GRN_LOG_ERROR, "nonexistent key value"); goto exit; } break; } if (id_value) { id = parse_id_value(ctx, id_value); if (grn_table_at(ctx, loader->table, id) == GRN_ID_NIL) { if (ctx->rc == GRN_SUCCESS) { id = grn_table_add(ctx, loader->table, NULL, 0, NULL); } } } else if (key_value) { id = loader_add(ctx, key_value); } else { id = grn_table_add(ctx, loader->table, NULL, 0, NULL); } if (id == GRN_ID_NIL) { /* Target record is not available. */ goto exit; } for (value = value_begin; value + 1 < value_end; value = values_next(ctx, value)) { grn_obj *col; const char *name = GRN_TEXT_VALUE(value); unsigned int name_size = GRN_TEXT_LEN(value); value++; if (value == id_value || value == key_value) { /* Skip _id and _key, because it's already used to get id. */ continue; } col = grn_obj_column(ctx, loader->table, name, name_size); if (!col) { GRN_LOG(ctx, GRN_LOG_ERROR, "invalid column('%.*s')", (int)name_size, name); /* Automatic column creation is disabled. */ /* 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)); } */ } else { 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) { grn_loader_save_error(ctx, loader); report_set_column_value_failure(ctx, key_value, name, name_size, value); loader->n_column_errors++; ERRCLR(ctx); } grn_obj_unlink(ctx, col); } } if (loader->each) { value = grn_expr_get_var_by_offset(ctx, loader->each, 0); GRN_RECORD_SET(ctx, value, id); grn_expr_exec(ctx, loader->each, 0); } loader->nrecords++; exit: if (ctx->rc != GRN_SUCCESS) { loader->n_record_errors++; } if (loader->output_ids) { GRN_UINT32_PUT(ctx, &(loader->ids), id); } if (loader->output_errors) { GRN_INT32_PUT(ctx, &(loader->return_codes), ctx->rc); grn_vector_add_element(ctx, &(loader->error_messages), ctx->errbuf, strlen(ctx->errbuf), 0, GRN_DB_TEXT); } loader->values_size = begin; ERRCLR(ctx); }
void test_array_sort(gpointer data) { const gint32 values[] = { 5, 6, 18, 9, 0, 4, 13, 12, 8, 14, 19, 11, 7, 3, 1, 10, 15, 2, 17, 16 }; const int n_values = sizeof(values) / sizeof(values[0]); const gchar table_name[] = "Store"; const gchar column_name[] = "sample_column"; const int n_keys = 1; grn_table_sort_key keys[n_keys]; grn_obj *table, *column, *result; grn_table_cursor *cursor; int n_results; guint i; guint n_expected_values; GList *expected_values, *sorted_values = NULL; table = grn_table_create(context, table_name, strlen(table_name), NULL, GRN_OBJ_TABLE_NO_KEY | GRN_OBJ_PERSISTENT, NULL, NULL); column = grn_column_create(context, table, column_name, strlen(column_name), NULL, 0, get_object("Int32")); keys[0].key = column; keys[0].flags = GRN_TABLE_SORT_ASC; for(i = 0; i < n_values; ++i) { grn_obj record_value; grn_id record_id; record_id = grn_table_add(context, table, NULL, 0, NULL); GRN_INT32_INIT(&record_value, 0); GRN_INT32_SET(context, &record_value, values[i]); grn_test_assert(grn_obj_set_value(context, column, record_id, &record_value, GRN_OBJ_SET)); GRN_OBJ_FIN(context, &record_value); } cut_assert_equal_int(n_values, grn_table_size(context, table)); result = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_NO_KEY, NULL, table); n_results = grn_table_sort(context, table, gcut_data_get_int(data, "offset"), gcut_data_get_int(data, "limit"), result, keys, n_keys); expected_values = (GList *)gcut_data_get_pointer(data, "expected_values"); n_expected_values = g_list_length(expected_values); cut_assert_equal_int(n_expected_values, n_results); cut_assert_equal_int(n_expected_values, grn_table_size(context, result)); cursor = grn_table_cursor_open(context, result, NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_ASCENDING); while (grn_table_cursor_next(context, cursor) != GRN_ID_NIL) { void *value; grn_id *id; grn_obj record_value; grn_table_cursor_get_value(context, cursor, &value); id = value; GRN_INT32_INIT(&record_value, 0); grn_obj_get_value(context, column, *id, &record_value); sorted_values = g_list_append(sorted_values, GINT_TO_POINTER(GRN_INT32_VALUE(&record_value))); GRN_OBJ_FIN(context, &record_value); } gcut_take_list(sorted_values, NULL); gcut_assert_equal_list_int(expected_values, sorted_values); grn_table_cursor_close(context, cursor); grn_obj_close(context, result); }
void test_truncate_named(gconstpointer data) { grn_obj_flags flags; const gchar *table_name = "SearchEngines"; const gchar *key; grn_obj *key_type; unsigned key_size; const gchar *column_name = "description"; grn_obj *column_type; const gchar *column_value = "An open-source fulltext search engine"; grn_bool array_p; grn_id record_id; int added; flags = gcut_data_get_int(data, "flags"); array_p = ((flags & GRN_OBJ_TABLE_TYPE_MASK) == GRN_OBJ_TABLE_NO_KEY); if (array_p) { key = NULL; key_size = 0; key_type = NULL; } else { key = "groonga"; key_size = strlen(key); key_type = grn_ctx_at(context, GRN_DB_SHORT_TEXT); } table = grn_table_create(context, table_name, strlen(table_name), NULL, flags | GRN_OBJ_PERSISTENT, key_type, NULL); if (key_type) { grn_obj_unlink(context, key_type); } grn_test_assert_context(context); column_type = grn_ctx_at(context, GRN_DB_SHORT_TEXT); column = grn_column_create(context, table, column_name, strlen(column_name), NULL, GRN_OBJ_COLUMN_SCALAR | GRN_OBJ_PERSISTENT, column_type); grn_obj_unlink(context, column_type); grn_test_assert_context(context); record_id = grn_table_add(context, table, key, key_size, &added); grn_test_assert_not_nil(record_id); cut_assert_true(added); grn_obj_reinit(context, &buffer, GRN_DB_SHORT_TEXT, 0); GRN_TEXT_PUTS(context, &buffer, column_value); grn_test_assert(grn_obj_set_value(context, column, record_id, &buffer, GRN_OBJ_SET)); GRN_BULK_REWIND(&buffer); grn_obj_get_value(context, column, record_id, &buffer); GRN_TEXT_PUTC(context, &buffer, '\0'); cut_assert_equal_string(column_value, GRN_TEXT_VALUE(&buffer)); cut_assert_equal_uint(1, grn_table_size(context, table)); grn_test_assert(grn_table_truncate(context, table)); GRN_BULK_REWIND(&buffer); grn_obj_get_value(context, column, record_id, &buffer); GRN_TEXT_PUTC(context, &buffer, '\0'); cut_assert_equal_string("", GRN_TEXT_VALUE(&buffer)); cut_assert_equal_uint(0, grn_table_size(context, table)); }
static grn_obj * func_highlight(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) { grn_obj *highlighted = NULL; #define N_REQUIRED_ARGS 1 if (nargs > N_REQUIRED_ARGS) { grn_obj *string = args[0]; grn_bool use_html_escape = GRN_FALSE; grn_obj *keywords; const char *normalizer_name = "NormalizerAuto"; unsigned int normalizer_name_length = 14; const char *default_open_tag = NULL; unsigned int default_open_tag_length = 0; const char *default_close_tag = NULL; unsigned int default_close_tag_length = 0; grn_obj *end_arg = args[nargs - 1]; int n_args_without_option = nargs; if (end_arg->header.type == GRN_TABLE_HASH_KEY) { grn_obj *options = end_arg; grn_hash_cursor *cursor; void *key; grn_obj *value; int key_size; n_args_without_option--; cursor = grn_hash_cursor_open(ctx, (grn_hash *)options, NULL, 0, NULL, 0, 0, -1, 0); if (!cursor) { GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE, "highlight(): couldn't open cursor"); goto exit; } while (grn_hash_cursor_next(ctx, cursor) != GRN_ID_NIL) { grn_hash_cursor_get_key_value(ctx, cursor, &key, &key_size, (void **)&value); if (key_size == 10 && !memcmp(key, "normalizer", 10)) { normalizer_name = GRN_TEXT_VALUE(value); normalizer_name_length = GRN_TEXT_LEN(value); } else if (key_size == 11 && !memcmp(key, "html_escape", 11)) { if (GRN_BOOL_VALUE(value)) { use_html_escape = GRN_TRUE; } } else if (key_size == 16 && !memcmp(key, "default_open_tag", 16)) { default_open_tag = GRN_TEXT_VALUE(value); default_open_tag_length = GRN_TEXT_LEN(value); } else if (key_size == 17 && !memcmp(key, "default_close_tag", 17)) { default_close_tag = GRN_TEXT_VALUE(value); default_close_tag_length = GRN_TEXT_LEN(value); } else { GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "invalid option name: <%.*s>", key_size, (char *)key); grn_hash_cursor_close(ctx, cursor); goto exit; } } grn_hash_cursor_close(ctx, cursor); } keywords = func_highlight_create_keywords_table(ctx, user_data, normalizer_name, normalizer_name_length); if (keywords) { grn_obj **keyword_args = args + N_REQUIRED_ARGS; unsigned int n_keyword_args = n_args_without_option - N_REQUIRED_ARGS; if (default_open_tag_length == 0 && default_close_tag_length == 0) { highlighted = highlight_keyword_sets(ctx, user_data, keyword_args, n_keyword_args, string, keywords, use_html_escape); } else { unsigned int i; for (i = 0; i < n_keyword_args; i++) { grn_table_add(ctx, keywords, GRN_TEXT_VALUE(keyword_args[i]), GRN_TEXT_LEN(keyword_args[i]), NULL); } highlighted = highlight_keywords(ctx, user_data, string, keywords, use_html_escape, default_open_tag, default_open_tag_length, default_close_tag, default_close_tag_length); } } } #undef N_REQUIRED_ARGS exit : if (!highlighted) { highlighted = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_VOID, 0); } return highlighted; }
static grn_obj * highlight_keyword_sets(grn_ctx *ctx, grn_user_data *user_data, grn_obj **keyword_set_args, unsigned int n_keyword_args, grn_obj *string, grn_obj *keywords, grn_bool use_html_escape) { grn_obj *highlighted = NULL; #define KEYWORD_SET_SIZE 3 { unsigned int i; unsigned int n_keyword_sets; grn_obj open_tags; grn_obj open_tag_lengths; grn_obj close_tags; grn_obj close_tag_lengths; n_keyword_sets = n_keyword_args / KEYWORD_SET_SIZE; GRN_OBJ_INIT(&open_tags, GRN_BULK, 0, GRN_DB_VOID); GRN_OBJ_INIT(&open_tag_lengths, GRN_BULK, 0, GRN_DB_VOID); GRN_OBJ_INIT(&close_tags, GRN_BULK, 0, GRN_DB_VOID); GRN_OBJ_INIT(&close_tag_lengths, GRN_BULK, 0, GRN_DB_VOID); for (i = 0; i < n_keyword_sets; i++) { grn_obj *keyword = keyword_set_args[i * KEYWORD_SET_SIZE + 0]; grn_obj *open_tag = keyword_set_args[i * KEYWORD_SET_SIZE + 1]; grn_obj *close_tag = keyword_set_args[i * KEYWORD_SET_SIZE + 2]; grn_table_add(ctx, keywords, GRN_TEXT_VALUE(keyword), GRN_TEXT_LEN(keyword), NULL); { const char *open_tag_content = GRN_TEXT_VALUE(open_tag); grn_bulk_write(ctx, &open_tags, (const char *)(&open_tag_content), sizeof(char *)); } { unsigned int open_tag_length = GRN_TEXT_LEN(open_tag); grn_bulk_write(ctx, &open_tag_lengths, (const char *)(&open_tag_length), sizeof(unsigned int)); } { const char *close_tag_content = GRN_TEXT_VALUE(close_tag); grn_bulk_write(ctx, &close_tags, (const char *)(&close_tag_content), sizeof(char *)); } { unsigned int close_tag_length = GRN_TEXT_LEN(close_tag); grn_bulk_write(ctx, &close_tag_lengths, (const char *)(&close_tag_length), sizeof(unsigned int)); } } highlighted = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_TEXT, 0); grn_pat_tag_keys(ctx, keywords, GRN_TEXT_VALUE(string), GRN_TEXT_LEN(string), (const char **)GRN_BULK_HEAD(&open_tags), (unsigned int *)GRN_BULK_HEAD(&open_tag_lengths), (const char **)GRN_BULK_HEAD(&close_tags), (unsigned int *)GRN_BULK_HEAD(&close_tag_lengths), n_keyword_sets, highlighted, use_html_escape); grn_obj_unlink(ctx, &open_tags); grn_obj_unlink(ctx, &open_tag_lengths); grn_obj_unlink(ctx, &close_tags); grn_obj_unlink(ctx, &close_tag_lengths); } #undef KEYWORD_SET_SIZE return highlighted; }
void test_expr_query(void) { grn_obj *t1, *c1, *lc, *ft, *v, *expr; grn_obj textbuf, intbuf; grn_id r1, r2, r3, r4; /* actual table */ t1 = grn_table_create(&context, "t1", 2, NULL, GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT, NULL, 0); cut_assert_not_null(t1); /* lexicon table */ lc = grn_table_create(&context, "lc", 2, NULL, GRN_OBJ_TABLE_PAT_KEY|GRN_OBJ_PERSISTENT, grn_ctx_at(&context, GRN_DB_SHORTTEXT), 0); cut_assert_not_null(lc); grn_test_assert(grn_obj_set_info(&context, lc, GRN_INFO_DEFAULT_TOKENIZER, grn_ctx_at(&context, GRN_DB_BIGRAM))); /* actual column */ c1 = grn_column_create(&context, t1, "c1", 2, NULL, GRN_OBJ_COLUMN_SCALAR|GRN_OBJ_PERSISTENT, grn_ctx_at(&context, GRN_DB_TEXT)); cut_assert_not_null(c1); /* fulltext index */ ft = grn_column_create(&context, lc, "ft", 2, NULL, GRN_OBJ_COLUMN_INDEX|GRN_OBJ_PERSISTENT|GRN_OBJ_WITH_POSITION, t1); cut_assert_not_null(ft); GRN_TEXT_INIT(&textbuf, 0); GRN_UINT32_INIT(&intbuf, 0); /* link between actual column and fulltext index */ GRN_UINT32_SET(&context, &intbuf, grn_obj_id(&context, c1)); grn_obj_set_info(&context, ft, GRN_INFO_SOURCE, &intbuf); /* need to use grn_id */ /* insert row */ r1 = grn_table_add(&context, t1, NULL, 0, NULL); cut_assert_equal_int(1, r1); GRN_TEXT_SETS(&context, &textbuf, "abhij"); grn_test_assert(grn_obj_set_value(&context, c1, r1, &textbuf, GRN_OBJ_SET)); r2 = grn_table_add(&context, t1, NULL, 0, NULL); cut_assert_equal_int(2, r2); GRN_TEXT_SETS(&context, &textbuf, "fghij"); grn_test_assert(grn_obj_set_value(&context, c1, r2, &textbuf, GRN_OBJ_SET)); r3 = grn_table_add(&context, t1, NULL, 0, NULL); cut_assert_equal_int(3, r3); GRN_TEXT_SETS(&context, &textbuf, "11 22 33"); grn_test_assert(grn_obj_set_value(&context, c1, r3, &textbuf, GRN_OBJ_SET)); r4 = grn_table_add(&context, t1, NULL, 0, NULL); cut_assert_equal_int(4, r4); GRN_TEXT_SETS(&context, &textbuf, "44 22 55"); grn_test_assert(grn_obj_set_value(&context, c1, r4, &textbuf, GRN_OBJ_SET)); /* confirm record are inserted in both column and index */ cut_assert_equal_int(4, grn_table_size(&context, t1)); cut_assert_equal_int(17, grn_table_size(&context, lc)); cut_assert_not_null((expr = grn_expr_create(&context, NULL, 0))); v = grn_expr_add_var(&context, expr, NULL, 0); GRN_BULK_REWIND(&textbuf); grn_expr_append_const(&context, expr, &textbuf); GRN_UINT32_SET(&context, &intbuf, GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC); grn_expr_append_const(&context, expr, &intbuf); grn_expr_append_obj(&context, expr, t1); GRN_UINT32_SET(&context, &intbuf, 0); grn_expr_append_const(&context, expr, &intbuf); grn_expr_append_op(&context, expr, GRN_OP_TABLE_CREATE, 4); grn_expr_append_obj(&context, expr, v); grn_expr_append_op(&context, expr, GRN_OP_VAR_SET_VALUE, 2); grn_expr_append_obj(&context, expr, ft); GRN_TEXT_SETS(&context, &textbuf, "hij"); grn_expr_append_const(&context, expr, &textbuf); grn_expr_append_obj(&context, expr, v); GRN_UINT32_SET(&context, &intbuf, GRN_SEL_OR); grn_expr_append_const(&context, expr, &intbuf); grn_expr_append_op(&context, expr, GRN_OP_OBJ_SEARCH, 4); grn_expr_append_obj(&context, expr, v); GRN_TEXT_SETS(&context, &textbuf, ".c1 .:score"); grn_expr_append_const(&context, expr, &textbuf); GRN_BULK_REWIND(&textbuf); grn_expr_append_obj(&context, expr, &textbuf); grn_expr_append_op(&context, expr, GRN_OP_JSON_PUT, 3); grn_expr_compile(&context, expr); grn_expr_exec(&context, expr); cut_assert_equal_uint(0, grn_obj_close(&context, expr)); cut_assert_equal_substring("[[\"abhij\", 1], [\"fghij\", 1]]", GRN_TEXT_VALUE(&textbuf), GRN_TEXT_LEN(&textbuf)); grn_obj_close(&context, &textbuf); grn_obj_close(&context, ft); grn_obj_close(&context, c1); grn_obj_close(&context, lc); grn_obj_close(&context, t1); }
void test_persistent_expr(void) { int i; grn_obj *t1, *t2, *c1, *c2, buf; t1 = grn_table_create(&context, "t1", 2, NULL, GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT, NULL, 0); cut_assert_not_null(t1); t2 = grn_table_create(&context, "t2", 2, NULL, GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT, NULL, 0); cut_assert_not_null(t2); c1 = grn_column_create(&context, t1, "c1", 2, NULL, GRN_OBJ_PERSISTENT, t2); cut_assert_not_null(c1); c2 = grn_column_create(&context, t2, "c2", 2, NULL, GRN_OBJ_PERSISTENT, t1); cut_assert_not_null(c2); GRN_TEXT_INIT(&buf, 0); for (i = 0; i < NRECORDS; i++) { grn_id i1, i2; i1 = grn_table_add(&context, t1, NULL, 0, NULL); i2 = grn_table_add(&context, t2, NULL, 0, NULL); GRN_BULK_REWIND(&buf); grn_bulk_write(&context, &buf, (char *)&i2, sizeof(grn_id)); grn_obj_set_value(&context, c1, i1, &buf, GRN_OBJ_SET); grn_obj_set_value(&context, c2, i2, &buf, GRN_OBJ_SET); } { grn_obj *expr = grn_expr_create(&context, "test", 4); grn_obj *v; cut_assert_not_null(expr); v = grn_expr_add_var(&context, expr, "foo", 3); GRN_RECORD_INIT(v, 0, grn_obj_id(&context, t1)); grn_expr_append_obj(&context, expr, v); GRN_TEXT_SETS(&context, &buf, "c1"); grn_expr_append_const(&context, expr, &buf); grn_expr_append_op(&context, expr, GRN_OP_OBJ_GET_VALUE, 2); GRN_TEXT_SETS(&context, &buf, "c2"); grn_expr_append_const(&context, expr, &buf); grn_expr_append_op(&context, expr, GRN_OP_OBJ_GET_VALUE, 2); GRN_TEXT_SETS(&context, &buf, "c1"); grn_expr_append_const(&context, expr, &buf); /* GRN_TEXT_SETS(&context, &buf, "c1.c2.c1"); grn_expr_append_const(&context, expr, &buf); */ grn_expr_append_op(&context, expr, GRN_OP_OBJ_GET_VALUE, 2); grn_expr_compile(&context, expr); } cut_assert_equal_uint(0, grn_obj_close(&context, &buf)); grn_db_close(&context, database); database = grn_db_open(&context, path); GRN_TEXT_INIT(&buf, 0); { grn_id id; uint64_t et; int nerr = 0; grn_obj *r, *v; grn_table_cursor *tc; struct timeval tvb, tve; grn_obj *expr = grn_ctx_get(&context, "test", 4); v = grn_expr_get_var(&context, expr, "foo", 3); t1 = grn_ctx_get(&context, "t1", 2); tc = grn_table_cursor_open(&context, t1, NULL, 0, NULL, 0, 0); cut_assert_not_null(tc); gettimeofday(&tvb, NULL); while ((id = grn_table_cursor_next(&context, tc))) { GRN_RECORD_SET(&context, v, id); r = grn_expr_exec(&context, expr); if (GRN_RECORD_VALUE(r) != id) { nerr++; } } gettimeofday(&tve, NULL); et = (tve.tv_sec - tvb.tv_sec) * 1000000 + (tve.tv_usec - tvb.tv_usec); // printf("et=%zu\n", et); cut_assert_equal_uint(0, nerr); cut_assert_equal_uint(0, grn_table_cursor_close(&context, tc)); } cut_assert_equal_uint(0, grn_obj_close(&context, &buf)); }
static grn_obj * yangram_next(grn_ctx *ctx, GNUC_UNUSED int nargs, GNUC_UNUSED grn_obj **args, grn_user_data *user_data) { grn_yangram_tokenizer *tokenizer = user_data->ptr; const unsigned char *string_end = tokenizer->end; const unsigned char *token_top = tokenizer->next; const unsigned char *token_next = token_top; const unsigned char *token_tail = token_top; int token_size = 0; grn_bool is_token_grouped = GRN_FALSE; const unsigned char *token_ctypes = NULL; unsigned int ctypes_skip_size; int char_length = 0; grn_tokenizer_status status = 0; grn_bool is_token_hit = GRN_FALSE; grn_obj *lexicon = args[0]; if (tokenizer->phrase_table) { if (tokenizer->nhits > 0 && token_top - (const unsigned char *)tokenizer->scan_start > tokenizer->hits[tokenizer->current_hit].offset) { tokenizer->current_hit++; } if (tokenizer->current_hit >= tokenizer->nhits) { tokenizer->scan_start = tokenizer->scan_rest; unsigned int scan_rest_length = tokenizer->end - (const unsigned char *)tokenizer->scan_rest; if (scan_rest_length > 0) { tokenizer->nhits = grn_pat_scan(ctx, (grn_pat *)tokenizer->phrase_table, tokenizer->scan_rest, scan_rest_length, tokenizer->hits, MAX_N_HITS, &(tokenizer->scan_rest)); tokenizer->current_hit = 0; } } if (tokenizer->nhits > 0 && tokenizer->current_hit < tokenizer->nhits && token_top - (const unsigned char *)tokenizer->scan_start == tokenizer->hits[tokenizer->current_hit].offset) { is_token_hit = GRN_TRUE; } } if (tokenizer->ctypes) { token_ctypes = tokenizer->ctypes + tokenizer->ctypes_next; } else { token_ctypes = NULL; } if (is_token_hit) { token_size = forward_scan_hit_token_tail(ctx, tokenizer, &token_tail, tokenizer->hits[tokenizer->current_hit].length); token_next = token_tail; tokenizer->current_hit++; } else { is_token_grouped = is_token_group(tokenizer, token_ctypes); if (is_token_grouped) { token_size = forward_grouped_token_tail(ctx, tokenizer, token_ctypes, &token_tail); token_next = token_tail; } else { token_size = forward_ngram_token_tail(ctx, tokenizer, token_ctypes, &token_tail); char_length = grn_plugin_charlen(ctx, (char *)token_next, tokenizer->rest_length, tokenizer->query->encoding); token_next += char_length; } } if (token_top == token_tail || token_next == string_end) { ctypes_skip_size = 0; } else { if (is_token_grouped || is_token_hit) { ctypes_skip_size = token_size; } else { ctypes_skip_size = 1; } } if (tokenizer->use_vgram > 0 && !is_token_grouped) { grn_bool maybe_vgram = GRN_FALSE; grn_id id; id = grn_table_get(ctx, tokenizer->vgram_table, (const char *)token_top, token_tail - token_top); if (id) { maybe_vgram = GRN_TRUE; } if (tokenizer->use_vgram >= VGRAM_BOTH && !maybe_vgram) { if (token_tail < string_end && !is_group_border(ctx, tokenizer, token_tail, token_ctypes, token_size)) { grn_id id; const unsigned char *token_next_tail; char_length = grn_plugin_charlen(ctx, (char *)token_tail, tokenizer->rest_length, tokenizer->query->encoding); token_next_tail = token_tail + char_length; id = grn_table_get(ctx, tokenizer->vgram_table, (const char *)token_next, token_next_tail - token_next); if (id) { maybe_vgram = GRN_TRUE; } } else if (token_tail == string_end && tokenizer->query->tokenize_mode == GRN_TOKENIZE_GET) { maybe_vgram = GRN_TRUE; } } if (maybe_vgram) { if (token_tail < string_end && !is_group_border(ctx, tokenizer, token_tail, token_ctypes, token_size)) { char_length = grn_plugin_charlen(ctx, (char *)token_tail, tokenizer->rest_length, tokenizer->query->encoding); token_size++; token_tail += char_length; if (tokenizer->use_vgram == VGRAM_QUAD) { if (token_tail < string_end && !is_group_border(ctx, tokenizer, token_tail, token_ctypes, token_size)) { id = grn_table_get(ctx, tokenizer->vgram_table, (const char *)token_top, token_tail - token_top); if (id) { char_length = grn_plugin_charlen(ctx, (char *)token_tail, tokenizer->rest_length, tokenizer->query->encoding); token_size++; token_tail += char_length; } } else { if (tokenizer->query->tokenize_mode == GRN_TOKENIZE_GET) { grn_id tid; tid = grn_table_get(ctx, lexicon, (const char *)token_top, token_tail - token_top); if (tid == GRN_ID_NIL) { int added; grn_table_add(ctx, lexicon, (const char *)token_top, token_tail - token_top, &added); } status |= GRN_TOKEN_FORCE_PREFIX; } } } } else { if (tokenizer->query->tokenize_mode == GRN_TOKENIZE_GET) { grn_id tid; tid = grn_table_get(ctx, lexicon, (const char *)token_top, token_tail - token_top); if (tid == GRN_ID_NIL) { int added; grn_table_add(ctx, lexicon, (const char *)token_top, token_tail - token_top, &added); } status |= GRN_TOKEN_FORCE_PREFIX; } } } } if (token_top == token_tail || token_next == string_end) { status |= GRN_TOKEN_LAST; } if (token_tail == string_end) { status |= GRN_TOKEN_REACH_END; } if (!is_token_grouped && !is_token_hit && token_size < tokenizer->ngram_unit) { status |= GRN_TOKEN_UNMATURED; } if (tokenizer->pushed_token_tail && token_top < tokenizer->pushed_token_tail) { status |= GRN_TOKEN_OVERLAP; if (tokenizer->skip_overlap && !grn_ii_overlap_token_skip_enable && !(status & GRN_TOKEN_REACH_END) && !(status & GRN_TOKEN_SKIP_WITH_POSITION) && tokenizer->query->tokenize_mode == GRN_TOKENIZE_GET) { if (token_tail <= tokenizer->pushed_token_tail) { status |= GRN_TOKEN_SKIP; } else { if (!is_group_border(ctx, tokenizer, token_tail, token_ctypes, token_size)) { status |= GRN_TOKEN_SKIP; } } } } if (!(status & GRN_TOKEN_SKIP) && !(status & GRN_TOKEN_SKIP_WITH_POSITION)) { tokenizer->pushed_token_tail = token_tail; } tokenizer->next = token_next; tokenizer->rest_length = string_end - token_next; tokenizer->ctypes_next = tokenizer->ctypes_next + ctypes_skip_size; grn_tokenizer_token_push(ctx, &(tokenizer->token), (const char *)token_top, token_tail - token_top, status); return NULL; }
static void bracket_close(grn_ctx *ctx, grn_loader *loader) { grn_id id = GRN_ID_NIL; grn_obj *value, *value_end, *id_value = NULL, *key_value = NULL; grn_obj *col, **cols; /* Columns except _id and _key. */ uint32_t i, begin; uint32_t ncols; /* Number of columns except _id and _key. */ uint32_t nvalues; /* Number of values in brackets. */ uint32_t depth; grn_bool is_record_load = GRN_FALSE; cols = (grn_obj **)GRN_BULK_HEAD(&loader->columns); ncols = GRN_BULK_VSIZE(&loader->columns) / sizeof(grn_obj *); GRN_UINT32_POP(&loader->level, begin); value = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + begin; value_end = (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++; depth = GRN_BULK_VSIZE(&loader->level); if (depth > sizeof(uint32_t) * loader->emit_level) { return; } if (depth == 0 || !loader->table || loader->columns_status == GRN_LOADER_COLUMNS_BROKEN) { goto exit; } nvalues = values_len(ctx, value, value_end); if (loader->columns_status == GRN_LOADER_COLUMNS_UNSET) { /* * Target columns and _id or _key are not specified yet and values are * handled as column names and "_id" or "_key". */ for (i = 0; i < nvalues; i++) { const char *col_name; unsigned int col_name_size; if (value->header.domain != GRN_DB_TEXT) { 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_loader_save_error(ctx, loader); GRN_OBJ_FIN(ctx, &buffer); loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; goto exit; } col_name = GRN_TEXT_VALUE(value); col_name_size = GRN_TEXT_LEN(value); col = grn_obj_column(ctx, loader->table, col_name, col_name_size); if (!col) { ERR(GRN_INVALID_ARGUMENT, "nonexistent column: <%.*s>", col_name_size, col_name); grn_loader_save_error(ctx, loader); loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; goto exit; } if (name_equal(col_name, col_name_size, GRN_COLUMN_NAME_ID)) { grn_obj_unlink(ctx, col); if (loader->id_offset != -1 || loader->key_offset != -1) { /* _id and _key must not appear more than once. */ if (loader->id_offset != -1) { ERR(GRN_INVALID_ARGUMENT, "duplicated id and key columns: <%s> at %d and <%s> at %d", GRN_COLUMN_NAME_ID, i, GRN_COLUMN_NAME_ID, loader->id_offset); } else { ERR(GRN_INVALID_ARGUMENT, "duplicated id and key columns: <%s> at %d and <%s> at %d", GRN_COLUMN_NAME_ID, i, GRN_COLUMN_NAME_KEY, loader->key_offset); } grn_loader_save_error(ctx, loader); loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; goto exit; } loader->id_offset = i; } else if (name_equal(col_name, col_name_size, GRN_COLUMN_NAME_KEY)) { grn_obj_unlink(ctx, col); if (loader->id_offset != -1 || loader->key_offset != -1) { /* _id and _key must not appear more than once. */ if (loader->id_offset != -1) { ERR(GRN_INVALID_ARGUMENT, "duplicated id and key columns: <%s> at %d and <%s> at %d", GRN_COLUMN_NAME_KEY, i, GRN_COLUMN_NAME_ID, loader->id_offset); } else { ERR(GRN_INVALID_ARGUMENT, "duplicated id and key columns: <%s> at %d and <%s> at %d", GRN_COLUMN_NAME_KEY, i, GRN_COLUMN_NAME_KEY, loader->key_offset); } grn_loader_save_error(ctx, loader); loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; goto exit; } loader->key_offset = i; } else { GRN_PTR_PUT(ctx, &loader->columns, col); } value++; } switch (loader->table->header.type) { case GRN_TABLE_HASH_KEY : case GRN_TABLE_PAT_KEY : case GRN_TABLE_DAT_KEY : if (loader->id_offset == -1 && loader->key_offset == -1) { ERR(GRN_INVALID_ARGUMENT, "missing id or key column"); grn_loader_save_error(ctx, loader); loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; goto exit; } break; } loader->columns_status = GRN_LOADER_COLUMNS_SET; goto exit; } is_record_load = GRN_TRUE; /* Target columns and _id or _key are already specified. */ if (!nvalues) { /* * Accept empty arrays because a dump command may output a load command * which contains empty arrays for a table with deleted records. */ id = grn_table_add(ctx, loader->table, NULL, 0, NULL); } else { uint32_t expected_nvalues = ncols; if (loader->id_offset != -1 || loader->key_offset != -1) { expected_nvalues++; } if (nvalues != expected_nvalues) { ERR(GRN_INVALID_ARGUMENT, "unexpected #values: expected:%u, actual:%u", expected_nvalues, nvalues); grn_loader_save_error(ctx, loader); goto exit; } if (loader->id_offset != -1) { id_value = value + loader->id_offset; id = parse_id_value(ctx, id_value); if (grn_table_at(ctx, loader->table, id) == GRN_ID_NIL) { id = grn_table_add(ctx, loader->table, NULL, 0, NULL); } } else if (loader->key_offset != -1) { key_value = value + loader->key_offset; id = loader_add(ctx, key_value); } else { id = grn_table_add(ctx, loader->table, NULL, 0, NULL); } } if (id == GRN_ID_NIL) { /* Target record is not available. */ goto exit; } for (i = 0; i < nvalues; i++, value = values_next(ctx, value)) { if (i == loader->id_offset || i == loader->key_offset) { /* Skip _id and _key, because it's already used to get id. */ continue; } col = *cols; 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) { char column_name[GRN_TABLE_MAX_KEY_SIZE]; unsigned int column_name_size; grn_loader_save_error(ctx, loader); column_name_size = grn_obj_name(ctx, col, column_name, GRN_TABLE_MAX_KEY_SIZE); report_set_column_value_failure(ctx, key_value, column_name, column_name_size, value); loader->n_column_errors++; ERRCLR(ctx); } cols++; } 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++; exit: if (is_record_load) { if (ctx->rc != GRN_SUCCESS) { loader->n_record_errors++; } if (loader->output_ids) { GRN_UINT32_PUT(ctx, &(loader->ids), id); } if (loader->output_errors) { GRN_INT32_PUT(ctx, &(loader->return_codes), ctx->rc); grn_vector_add_element(ctx, &(loader->error_messages), ctx->errbuf, strlen(ctx->errbuf), 0, GRN_DB_TEXT); } } loader->values_size = begin; ERRCLR(ctx); }
void test_expr(void) { int i; grn_obj *t1, *t2, *c1, *c2, r1, r2, buf; t1 = grn_table_create(context, "t1", 2, NULL, GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT, NULL, NULL); cut_assert_not_null(t1); t2 = grn_table_create(context, "t2", 2, NULL, GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT, NULL, NULL); cut_assert_not_null(t2); c1 = grn_column_create(context, t1, "c1", 2, NULL, GRN_OBJ_PERSISTENT, t2); cut_assert_not_null(c1); c2 = grn_column_create(context, t2, "c2", 2, NULL, GRN_OBJ_PERSISTENT, t1); cut_assert_not_null(c2); GRN_TEXT_INIT(&buf, 0); GRN_RECORD_INIT(&r1, 0, grn_obj_id(context, t1)); GRN_RECORD_INIT(&r2, 0, grn_obj_id(context, t2)); for (i = 0; i < NRECORDS; i++) { grn_id i1, i2; i1 = grn_table_add(context, t1, NULL, 0, NULL); i2 = grn_table_add(context, t2, NULL, 0, NULL); GRN_RECORD_SET(context, &r1, i1); GRN_RECORD_SET(context, &r2, i2); grn_obj_set_value(context, c1, i1, &r2, GRN_OBJ_SET); grn_obj_set_value(context, c2, i2, &r1, GRN_OBJ_SET); } { grn_obj *r, *v; expr = grn_expr_create(context, NULL, 0); cut_assert_not_null(expr); v = grn_expr_add_var(context, expr, NULL, 0); GRN_RECORD_INIT(v, 0, grn_obj_id(context, t1)); grn_expr_append_obj(context, expr, v, GRN_OP_PUSH, 1); GRN_TEXT_SETS(context, &buf, "c1"); grn_expr_append_const(context, expr, &buf, GRN_OP_PUSH, 1); grn_expr_append_op(context, expr, GRN_OP_GET_VALUE, 2); GRN_TEXT_SETS(context, &buf, "c2"); grn_expr_append_const(context, expr, &buf, GRN_OP_PUSH, 1); grn_expr_append_op(context, expr, GRN_OP_GET_VALUE, 2); GRN_TEXT_SETS(context, &buf, "c1"); grn_expr_append_const(context, expr, &buf, GRN_OP_PUSH, 1); // GRN_TEXT_SETS(context, &buf, "c1.c2.c1"); // grn_expr_append_const(context, expr, &buf); grn_expr_append_op(context, expr, GRN_OP_GET_VALUE, 2); grn_expr_compile(context, expr); { grn_id id; uint64_t et; int nerr = 0; grn_table_cursor *tc; struct timeval tvb, tve; tc = grn_table_cursor_open(context, t1, NULL, 0, NULL, 0, 0, -1, 0); cut_assert_not_null(tc); gettimeofday(&tvb, NULL); while ((id = grn_table_cursor_next(context, tc))) { GRN_RECORD_SET(context, v, id); grn_expr_exec(context, expr, 0); r = grn_ctx_pop(context); if (GRN_RECORD_VALUE(r) != id) { nerr++; } } gettimeofday(&tve, NULL); et = (tve.tv_sec - tvb.tv_sec) * 1000000 + (tve.tv_usec - tvb.tv_usec); // printf("et=%zu\n", et); cut_assert_equal_uint(0, nerr); grn_test_assert(grn_table_cursor_close(context, tc)); } } grn_test_assert(grn_obj_close(context, &r1)); grn_test_assert(grn_obj_close(context, &r2)); grn_test_assert(grn_obj_close(context, &buf)); }