void test_score_set(void) { grn_obj *v, *res2; prepare_data(); GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v); cut_assert_not_null(cond); cut_assert_not_null(v); PARSE(cond, "size:>0", GRN_EXPR_SYNTAX_QUERY|GRN_EXPR_ALLOW_PRAGMA|GRN_EXPR_ALLOW_COLUMN); res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR); cut_assert_not_null(res); grn_test_assert_select_all(res); grn_test_assert(grn_obj_close(&context, cond)); cond = NULL; GRN_EXPR_CREATE_FOR_QUERY(&context, res, expr, v); PARSE(expr, "_score = size", GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE); GRN_TABLE_EACH(&context, res, 0, 0, id, NULL, 0, NULL, { GRN_RECORD_SET(&context, v, id); grn_expr_exec(&context, expr, 0); });
void test_set_value(void) { grn_obj *v; prepare_data(); GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v); cut_assert_not_null(cond); cut_assert_not_null(v); PARSE(cond, "size:14", GRN_EXPR_SYNTAX_QUERY|GRN_EXPR_ALLOW_PRAGMA|GRN_EXPR_ALLOW_COLUMN); res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR); cut_assert_not_null(res); grn_test_assert_select(&context, gcut_take_new_list_string("moge moge moge", "hoge fuga fuga", "moge hoge hoge", NULL), res, "body"); grn_test_assert(grn_obj_close(&context, res)); res = NULL; GRN_EXPR_CREATE_FOR_QUERY(&context, docs, expr, v); grn_expr_append_obj(&context, expr, v, GRN_OP_PUSH, 1); GRN_TEXT_SETS(&context, &textbuf, "size"); grn_expr_append_const(&context, expr, &textbuf, GRN_OP_PUSH, 1); grn_expr_append_op(&context, expr, GRN_OP_GET_VALUE, 2); GRN_UINT32_SET(&context, &intbuf, 14); grn_expr_append_const(&context, expr, &intbuf, GRN_OP_PUSH, 1); grn_expr_append_op(&context, expr, GRN_OP_ASSIGN, 2); { grn_id id; grn_table_cursor *tc; tc = grn_table_cursor_open(&context, docs, NULL, 0, NULL, 0, 0, -1, 0); cut_assert_not_null(tc); while ((id = grn_table_cursor_next(&context, tc))) { GRN_RECORD_SET(&context, v, id); grn_expr_exec(&context, expr, 0); } grn_test_assert(grn_table_cursor_close(&context, tc)); } res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR); cut_assert_not_null(res); grn_test_assert_select_all(res); }
/* * _expression_ ćå®č”ććå®č”ććēµęćčæćć * * @overload execute * @return [å¤] */ static VALUE rb_grn_expression_execute (VALUE self) { grn_ctx *context = NULL; grn_obj *expression; grn_obj *result; rb_grn_expression_deconstruct(SELF(self), &expression, &context, NULL, NULL, NULL, NULL, NULL); result = grn_expr_exec(context, expression, 0); rb_grn_context_check(context, self); return GRNOBJ2RVAL(Qnil, context, result, self); }
/* * call-seq: * expression.execute * * _expression_ćå®č”ććć */ static VALUE rb_grn_expression_execute (VALUE self) { grn_ctx *context = NULL; grn_obj *expression; grn_rc rc; rb_grn_expression_deconstruct(SELF(self), &expression, &context, NULL, NULL, NULL, NULL, NULL); rc = grn_expr_exec(context, expression, 0); rb_grn_context_check(context, self); rb_grn_rc_check(rc, self); return Qnil; }
void test_proc_call(void) { grn_obj *v; prepare_data(); GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v); cut_assert_not_null(cond); cut_assert_not_null(v); PARSE(cond, "size:>14", GRN_EXPR_SYNTAX_QUERY|GRN_EXPR_ALLOW_PRAGMA|GRN_EXPR_ALLOW_COLUMN); res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR); cut_assert_not_null(res); grn_test_assert_select(&context, gcut_take_new_list_string("hoge moge moge moge", "moge hoge fuga fuga", "moge hoge moge moge moge", "poyo moge hoge " "moge moge moge", NULL), res, "body"); grn_test_assert(grn_obj_close(&context, res)); res = NULL; GRN_EXPR_CREATE_FOR_QUERY(&context, docs, expr, v); PARSE(expr, "size = rand(14)", GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE); { grn_id id; grn_table_cursor *tc; tc = grn_table_cursor_open(&context, docs, NULL, 0, NULL, 0, 0, -1, 0); cut_assert_not_null(tc); while ((id = grn_table_cursor_next(&context, tc))) { GRN_RECORD_SET(&context, v, id); grn_expr_exec(&context, expr, 0); } grn_test_assert(grn_table_cursor_close(&context, tc)); } res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR); cut_assert_not_null(res); grn_test_assert_select_none(res); }
void test_op_table_scan(void) { grn_obj *cond, *expr, *v, *res, textbuf, intbuf; GRN_TEXT_INIT(&textbuf, 0); GRN_UINT32_INIT(&intbuf, 0); prepare_data(&textbuf, &intbuf); cut_assert_not_null((cond = grn_expr_create(&context, NULL, 0))); v = grn_expr_add_var(&context, cond, NULL, 0); GRN_RECORD_INIT(v, 0, grn_obj_id(&context, docs)); grn_expr_append_obj(&context, cond, v); GRN_TEXT_SETS(&context, &textbuf, "size"); grn_expr_append_const(&context, cond, &textbuf); grn_expr_append_op(&context, cond, GRN_OP_OBJ_GET_VALUE, 2); GRN_UINT32_SET(&context, &intbuf, 14); grn_expr_append_const(&context, cond, &intbuf); grn_expr_append_op(&context, cond, GRN_OP_EQUAL, 2); grn_expr_compile(&context, cond); res = grn_table_create(&context, NULL, 0, NULL, GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, docs, 0); cut_assert_not_null(res); cut_assert_not_null((expr = grn_expr_create(&context, NULL, 0))); grn_expr_append_obj(&context, expr, docs); grn_expr_append_obj(&context, expr, cond); grn_expr_append_obj(&context, expr, res); GRN_UINT32_SET(&context, &intbuf, GRN_SEL_OR); grn_expr_append_const(&context, expr, &intbuf); grn_expr_append_op(&context, expr, GRN_OP_TABLE_SCAN, 4); grn_expr_exec(&context, expr); cut_assert_equal_uint(3, grn_table_size(&context, res)); grn_test_assert(grn_obj_close(&context, expr)); grn_test_assert(grn_obj_close(&context, res)); grn_test_assert(grn_obj_close(&context, cond)); grn_test_assert(grn_obj_close(&context, &textbuf)); grn_test_assert(grn_obj_close(&context, &intbuf)); }
void test_select(void) { grn_obj *v; prepare_data(); cut_assert_not_null((cond = grn_expr_create(&context, NULL, 0))); v = grn_expr_add_var(&context, cond, NULL, 0); GRN_RECORD_INIT(v, 0, grn_obj_id(&context, docs)); grn_expr_append_obj(&context, cond, v, GRN_OP_PUSH, 1); GRN_TEXT_SETS(&context, &text_buf, "size"); grn_expr_append_const(&context, cond, &text_buf, GRN_OP_PUSH, 1); grn_expr_append_op(&context, cond, GRN_OP_GET_VALUE, 2); GRN_UINT32_SET(&context, &int_buf, 14); grn_expr_append_const(&context, cond, &int_buf, GRN_OP_PUSH, 1); grn_expr_append_op(&context, cond, GRN_OP_EQUAL, 2); grn_expr_compile(&context, cond); res = grn_table_create(&context, NULL, 0, NULL, GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, docs, NULL); cut_assert_not_null(res); cut_assert_not_null((expr = grn_expr_create(&context, NULL, 0))); grn_expr_append_obj(&context, expr, docs, GRN_OP_PUSH, 1); grn_expr_append_obj(&context, expr, cond, GRN_OP_PUSH, 1); grn_expr_append_obj(&context, expr, res, GRN_OP_PUSH, 1); GRN_UINT32_SET(&context, &int_buf, GRN_OP_OR); grn_expr_append_const(&context, expr, &int_buf, GRN_OP_PUSH, 1); grn_expr_append_op(&context, expr, GRN_OP_TABLE_SELECT, 4); grn_expr_exec(&context, expr, 0); grn_test_assert_select(&context, gcut_take_new_list_string("moge moge moge", "hoge fuga fuga", "moge hoge hoge", NULL), res, "body"); }
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 (id == GRN_ID_NIL) { grn_loader_save_error(ctx, loader); return id; } if (!added && loader->ifexists) { grn_obj *v = grn_expr_get_var_by_offset(ctx, loader->ifexists, 0); grn_obj *result; GRN_RECORD_SET(ctx, v, id); result = grn_expr_exec(ctx, loader->ifexists, 0); if (!grn_obj_is_true(ctx, result)) { id = 0; } } return id; }
void test_select_search(void) { grn_obj *v; prepare_data(); cut_assert_not_null((cond = grn_expr_create(&context, NULL, 0))); v = grn_expr_add_var(&context, cond, NULL, 0); GRN_RECORD_INIT(v, 0, grn_obj_id(&context, docs)); grn_expr_append_obj(&context, cond, v, GRN_OP_PUSH, 1); GRN_TEXT_SETS(&context, &text_buf, "size"); grn_expr_append_const(&context, cond, &text_buf, GRN_OP_PUSH, 1); grn_expr_append_op(&context, cond, GRN_OP_GET_VALUE, 2); GRN_UINT32_SET(&context, &int_buf, 14); grn_expr_append_const(&context, cond, &int_buf, GRN_OP_PUSH, 1); grn_expr_append_op(&context, cond, GRN_OP_EQUAL, 2); grn_expr_compile(&context, cond); cut_assert_not_null((expr = grn_expr_create(&context, NULL, 0))); v = grn_expr_add_var(&context, expr, NULL, 0); grn_expr_append_obj(&context, expr, v, GRN_OP_PUSH, 1); GRN_BULK_REWIND(&text_buf); grn_expr_append_const(&context, expr, &text_buf, GRN_OP_PUSH, 1); GRN_UINT32_SET(&context, &int_buf, GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC); grn_expr_append_const(&context, expr, &int_buf, GRN_OP_PUSH, 1); grn_expr_append_obj(&context, expr, docs, GRN_OP_PUSH, 1); GRN_PTR_SET(&context, &ptr_buf, NULL); grn_expr_append_obj(&context, expr, &ptr_buf, GRN_OP_PUSH, 1); grn_expr_append_op(&context, expr, GRN_OP_TABLE_CREATE, 4); grn_expr_append_op(&context, expr, GRN_OP_ASSIGN, 2); grn_expr_append_obj(&context, expr, docs, GRN_OP_PUSH, 1); grn_expr_append_obj(&context, expr, cond, GRN_OP_PUSH, 1); grn_expr_append_obj(&context, expr, v, GRN_OP_PUSH, 1); GRN_UINT32_SET(&context, &int_buf, GRN_OP_OR); grn_expr_append_const(&context, expr, &int_buf, GRN_OP_PUSH, 1); grn_expr_append_op(&context, expr, GRN_OP_TABLE_SELECT, 4); grn_expr_append_obj(&context, expr, index_body, GRN_OP_PUSH, 1); GRN_TEXT_SETS(&context, &text_buf, "moge"); grn_expr_append_const(&context, expr, &text_buf, GRN_OP_PUSH, 1); grn_expr_append_obj(&context, expr, v, GRN_OP_PUSH, 1); GRN_UINT32_SET(&context, &int_buf, GRN_OP_AND); grn_expr_append_const(&context, expr, &int_buf, GRN_OP_PUSH, 1); grn_expr_append_op(&context, expr, GRN_OP_OBJ_SEARCH, 4); grn_expr_append_obj(&context, expr, v, GRN_OP_PUSH, 1); GRN_TEXT_SETS(&context, &text_buf, ".size ._score .body"); grn_expr_append_const(&context, expr, &text_buf, GRN_OP_PUSH, 1); GRN_BULK_REWIND(&text_buf); grn_expr_append_obj(&context, expr, &text_buf, GRN_OP_PUSH, 1); grn_expr_append_op(&context, expr, GRN_OP_JSON_PUT, 3); grn_expr_exec(&context, expr, 0); cut_assert_equal_substring("[[2],[14,4,\"moge moge moge\"],[14,2,\"moge hoge hoge\"]]", GRN_TEXT_VALUE(&text_buf), GRN_TEXT_LEN(&text_buf)); }
static mrb_value mrb_grn_index_cursor_select(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; mrb_value mrb_result_set; mrb_value mrb_options; grn_obj *index_cursor; grn_obj *expr = NULL; grn_obj *expr_variable = NULL; int offset = 0; int limit = 10; int n_matched_records = 0; mrb_value mrb_index; grn_obj *index; grn_obj *lexicon; grn_obj *data_table; grn_hash *result_set; grn_posting *posting; grn_id term_id; grn_operator op = GRN_OP_OR; mrb_get_args(mrb, "o|H", &mrb_result_set, &mrb_options); index_cursor = DATA_PTR(self); result_set = DATA_PTR(mrb_result_set); if (!mrb_nil_p(mrb_options)) { mrb_value mrb_expr; mrb_value mrb_offset; mrb_value mrb_limit; mrb_expr = grn_mrb_options_get_lit(mrb, mrb_options, "expression"); if (!mrb_nil_p(mrb_expr)) { expr = DATA_PTR(mrb_expr); expr_variable = grn_expr_get_var_by_offset(ctx, expr, 0); } mrb_offset = grn_mrb_options_get_lit(mrb, mrb_options, "offset"); if (!mrb_nil_p(mrb_offset)) { offset = mrb_fixnum(mrb_offset); } mrb_limit = grn_mrb_options_get_lit(mrb, mrb_options, "limit"); if (!mrb_nil_p(mrb_limit)) { limit = mrb_fixnum(mrb_limit); } } if (limit <= 0) { return mrb_fixnum_value(n_matched_records); } mrb_index = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@index")); index = DATA_PTR(mrb_index); lexicon = ((grn_ii *)index)->lexicon; data_table = grn_ctx_at(ctx, grn_obj_get_range(ctx, index)); while ((posting = grn_index_cursor_next(ctx, index_cursor, &term_id))) { if (expr) { grn_bool matched_raw; grn_obj *matched; GRN_RECORD_SET(ctx, expr_variable, posting->rid); matched = grn_expr_exec(ctx, expr, 0); if (!matched) { grn_mrb_ctx_check(mrb); continue; } GRN_TRUEP(ctx, matched, matched_raw); if (!matched_raw) { continue; } } n_matched_records++; if (offset > 0) { offset--; continue; } grn_ii_posting_add(ctx, (grn_ii_posting *)posting, result_set, op); limit--; if (limit == 0) { break; } } grn_ii_resolve_sel_and(ctx, result_set, op); return mrb_fixnum_value(n_matched_records); }
void test_scan_search(void) { grn_obj *cond, *expr, *v, textbuf, intbuf; GRN_TEXT_INIT(&textbuf, 0); GRN_UINT32_INIT(&intbuf, 0); prepare_data(&textbuf, &intbuf); cut_assert_not_null((cond = grn_expr_create(&context, NULL, 0))); v = grn_expr_add_var(&context, cond, NULL, 0); GRN_RECORD_INIT(v, 0, grn_obj_id(&context, docs)); grn_expr_append_obj(&context, cond, v); GRN_TEXT_SETS(&context, &textbuf, "size"); grn_expr_append_const(&context, cond, &textbuf); grn_expr_append_op(&context, cond, GRN_OP_OBJ_GET_VALUE, 2); GRN_UINT32_SET(&context, &intbuf, 14); grn_expr_append_const(&context, cond, &intbuf); grn_expr_append_op(&context, cond, GRN_OP_EQUAL, 2); grn_expr_compile(&context, cond); 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, docs); 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, docs); grn_expr_append_obj(&context, expr, cond); 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_TABLE_SCAN, 4); grn_expr_append_obj(&context, expr, index_body); GRN_TEXT_SETS(&context, &textbuf, "moge"); grn_expr_append_const(&context, expr, &textbuf); grn_expr_append_obj(&context, expr, v); GRN_UINT32_SET(&context, &intbuf, GRN_SEL_AND); 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, ".size .:score .body"); 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_exec(&context, expr); cut_assert_equal_substring("[[14, 4, \"moge moge moge\"], [14, 2, \"moge hoge hoge\"]]", GRN_TEXT_VALUE(&textbuf), GRN_TEXT_LEN(&textbuf)); grn_test_assert(grn_obj_close(&context, expr)); grn_test_assert(grn_obj_close(&context, cond)); grn_test_assert(grn_obj_close(&context, &textbuf)); grn_test_assert(grn_obj_close(&context, &intbuf)); }
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)); }
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)); }
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); }
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); }