/* * Document-method: search * * call-seq: * column.search(query, options={}) -> Groonga::Hash * * _object_から_query_に対応するオブジェクトを検索し、見つかっ * たオブジェクトのIDがキーになっているGroonga::Hashを返す。 * * 利用可能なオプションは以下の通り。 * * [_:result_] * 結果を格納するGroonga::Hash。指定しない場合は新しく * Groonga::Hashを生成し、それに結果を格納して返す。 * [_:operator_] * 以下のどれかの値を指定する。+nil+, <tt>"or"</tt>, <tt>"||"</tt>, * <tt>"and"</tt>, <tt>"+"</tt>, <tt>"&&"</tt>, <tt>"but"</tt>, * <tt>"not"</tt>, <tt>"-"</tt>, <tt>"adjust"</tt>, <tt>">"</tt>。 * それぞれ以下のようになる。(FIXME: 「以下」) * [_:exact_] * +true+を指定すると完全一致で検索する * [_:longest_common_prefix_] * +true+を指定すると_query_と同じ接頭辞をもつエントリのう * ち、もっとも長いエントリを検索する * [_:suffix_] * +true+を指定すると_query_が後方一致するエントリを検索す * る * [_:prefix_] * +true+を指定すると_query_が前方一致するレコードを検索す * る * [_:near_] * +true+を指定すると_query_に指定した複数の語が近傍に含ま * れるレコードを検索する * [...] * ... */ static VALUE rb_grn_index_column_search (int argc, VALUE *argv, VALUE self) { grn_ctx *context; grn_obj *column; grn_obj *range; grn_obj *query = NULL, *id_query = NULL, *string_query = NULL; grn_obj *result; grn_operator operator; grn_rc rc; VALUE rb_query, options, rb_result, rb_operator; rb_grn_index_column_deconstruct(SELF(self), &column, &context, NULL, NULL, NULL, NULL, NULL, &range, &id_query, &string_query); rb_scan_args(argc, argv, "11", &rb_query, &options); if (CBOOL2RVAL(rb_obj_is_kind_of(rb_query, rb_cGrnQuery))) { grn_query *_query; _query = RVAL2GRNQUERY(rb_query); query = (grn_obj *)_query; } else if (CBOOL2RVAL(rb_obj_is_kind_of(rb_query, rb_cInteger))) { grn_id id; id = NUM2UINT(rb_query); GRN_TEXT_SET(context, id_query, &id, sizeof(grn_id)); query = id_query; } else { const char *_query; _query = StringValuePtr(rb_query); GRN_TEXT_SET(context, string_query, _query, RSTRING_LEN(rb_query)); query = string_query; } rb_grn_scan_options(options, "result", &rb_result, "operator", &rb_operator, NULL); if (NIL_P(rb_result)) { result = grn_table_create(context, NULL, 0, NULL, GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC, range, 0); rb_grn_context_check(context, self); rb_result = GRNOBJECT2RVAL(Qnil, context, result, RB_GRN_TRUE); } else { result = RVAL2GRNOBJECT(rb_result, &context); } operator = RVAL2GRNOPERATOR(rb_operator); rc = grn_obj_search(context, column, query, result, operator, NULL); rb_grn_rc_check(rc, self); return rb_result; }
static int grn_token_cursor_next_apply_token_filters(grn_ctx *ctx, grn_token_cursor *token_cursor, grn_obj *current_token_data, grn_obj *status) { grn_obj *token_filters = token_cursor->token_filter.objects; unsigned int i, n_token_filters; grn_token current_token; grn_token next_token; if (token_filters) { n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); } else { n_token_filters = 0; } GRN_TEXT_INIT(&(current_token.data), GRN_OBJ_DO_SHALLOW_COPY); GRN_TEXT_SET(ctx, &(current_token.data), GRN_TEXT_VALUE(current_token_data), GRN_TEXT_LEN(current_token_data)); current_token.status = GRN_INT32_VALUE(status); GRN_TEXT_INIT(&(next_token.data), GRN_OBJ_DO_SHALLOW_COPY); GRN_TEXT_SET(ctx, &(next_token.data), GRN_TEXT_VALUE(&(current_token.data)), GRN_TEXT_LEN(&(current_token.data))); next_token.status = current_token.status; for (i = 0; i < n_token_filters; i++) { grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i); grn_proc *token_filter = (grn_proc *)token_filter_object; void *data = token_cursor->token_filter.data[i]; #define SKIP_FLAGS\ (GRN_TOKEN_SKIP |\ GRN_TOKEN_SKIP_WITH_POSITION) if (current_token.status & SKIP_FLAGS) { break; } #undef SKIP_FLAGS token_filter->callbacks.token_filter.filter(ctx, ¤t_token, &next_token, data); GRN_TEXT_SET(ctx, &(current_token.data), GRN_TEXT_VALUE(&(next_token.data)), GRN_TEXT_LEN(&(next_token.data))); current_token.status = next_token.status; } token_cursor->curr = (const unsigned char *)GRN_TEXT_VALUE(&(current_token.data)); token_cursor->curr_size = GRN_TEXT_LEN(&(current_token.data)); return current_token.status; }
grn_obj * grn_mrb_value_to_bulk(mrb_state *mrb, mrb_value mrb_value_, grn_obj *bulk) { grn_ctx *ctx = (grn_ctx *)mrb->ud; switch (mrb_type(mrb_value_)) { case MRB_TT_FALSE : if (mrb_nil_p(mrb_value_)) { grn_obj_reinit(ctx, bulk, GRN_DB_VOID, 0); } else { grn_obj_reinit(ctx, bulk, GRN_DB_BOOL, 0); GRN_BOOL_SET(ctx, bulk, GRN_FALSE); } break; case MRB_TT_TRUE : grn_obj_reinit(ctx, bulk, GRN_DB_BOOL, 0); GRN_BOOL_SET(ctx, bulk, GRN_TRUE); break; case MRB_TT_FIXNUM : grn_obj_reinit(ctx, bulk, GRN_DB_INT64, 0); GRN_INT64_SET(ctx, bulk, mrb_fixnum(mrb_value_)); break; case MRB_TT_SYMBOL : { const char *name; mrb_int name_length; grn_obj_reinit(ctx, bulk, GRN_DB_TEXT, 0); name = mrb_sym2name_len(mrb, mrb_symbol(mrb_value_), &name_length); GRN_TEXT_SET(ctx, bulk, name, name_length); } break; case MRB_TT_FLOAT : grn_obj_reinit(ctx, bulk, GRN_DB_FLOAT, 0); GRN_FLOAT_SET(ctx, bulk, mrb_float(mrb_value_)); break; case MRB_TT_STRING : grn_obj_reinit(ctx, bulk, GRN_DB_TEXT, 0); GRN_TEXT_SET(ctx, bulk, RSTRING_PTR(mrb_value_), RSTRING_LEN(mrb_value_)); break; default : mrb_raisef(mrb, E_ARGUMENT_ERROR, "unsupported object to convert to bulk: %S", mrb_value_); break; } return bulk; }
grn_rc grn_token_copy(grn_ctx *ctx, grn_token *token, grn_token *source) { GRN_API_ENTER; if (!token) { ERR(GRN_INVALID_ARGUMENT, "[token][copy] token must not be NULL"); goto exit; } GRN_TEXT_SET(ctx, &(token->data), GRN_TEXT_VALUE(&(source->data)), GRN_TEXT_LEN(&(source->data))); token->status = source->status; token->source_offset = source->source_offset; token->source_length = source->source_length; token->source_first_character_length = source->source_first_character_length; token->have_overlap = source->have_overlap; grn_token_metadata_reset(ctx, &(token->metadata)); grn_token_metadata_copy(ctx, &(token->metadata), &(source->metadata)); token->force_prefix_search = source->force_prefix_search; token->position = source->position; exit: GRN_API_RETURN(ctx->rc); }
static void query_expand(mrn::QueryExpandInfo *info, UDF_ARGS *args) { grn_ctx *ctx = info->ctx; const char *query = args->args[3]; unsigned int query_length = args->lengths[3]; mrn::QueryParser query_parser(info->ctx, current_thd, NULL, NULL, 0, NULL); const char *raw_query; size_t raw_query_length; grn_operator default_operator; grn_expr_flags flags; query_parser.parse_pragma(query, query_length, &raw_query, &raw_query_length, &default_operator, &flags); GRN_TEXT_SET(info->ctx, &(info->expanded_query), query, raw_query - query); grn_expr_syntax_expand_query_by_table(ctx, raw_query, raw_query_length, flags, info->term_column, info->expanded_term_column, &(info->expanded_query)); }
static mrb_value mrb_grn_expression_allocate_constant(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; grn_obj *expr; mrb_value mrb_object; grn_obj *grn_object; mrb_get_args(mrb, "o", &mrb_object); expr = DATA_PTR(self); switch (mrb_type(mrb_object)) { case MRB_TT_STRING: grn_object = grn_expr_alloc_const(ctx, expr); if (!grn_object) { grn_mrb_ctx_check(mrb); } GRN_TEXT_INIT(grn_object, 0); GRN_TEXT_SET(ctx, grn_object, RSTRING_PTR(mrb_object), RSTRING_LEN(mrb_object)); break; default: mrb_raisef(mrb, E_ARGUMENT_ERROR, "unsupported type: %S", mrb_object); break; } return grn_mrb_value_from_grn_obj(mrb, grn_object); }
grn_obj * rb_grn_key_from_ruby_object (VALUE rb_key, grn_ctx *context, grn_obj *key, grn_id domain_id, grn_obj *domain, VALUE related_object) { grn_id id; if (!domain) return RVAL2GRNBULK(rb_key, context, key); switch (domain->header.type) { case GRN_TYPE: return RVAL2GRNBULK_WITH_TYPE(rb_key, context, key, domain_id, domain); break; case GRN_TABLE_HASH_KEY: case GRN_TABLE_PAT_KEY: case GRN_TABLE_DAT_KEY: case GRN_TABLE_NO_KEY: id = RVAL2GRNID(rb_key, context, domain, related_object); break; default: if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_key, rb_cInteger))) rb_raise(rb_eGrnError, "should be unsigned integer: <%s>: <%s>", rb_grn_inspect(rb_key), rb_grn_inspect(related_object)); id = NUM2UINT(rb_key); break; } GRN_TEXT_SET(context, key, &id, sizeof(id)); return key; }
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)); }
VALUE rb_grn_key_to_ruby_object (grn_ctx *context, const void *key, int key_size, grn_obj *table, VALUE related_object) { grn_obj bulk; GRN_OBJ_INIT(&bulk, GRN_BULK, GRN_OBJ_DO_SHALLOW_COPY, table->header.domain); GRN_TEXT_SET(context, &bulk, key, key_size); return GRNBULK2RVAL(context, &bulk, NULL, related_object); }
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 ConditionConverter::append_const_item(const Item_field *field_item, Item *const_item, grn_obj *expression) { MRN_DBUG_ENTER_METHOD(); enum_field_types field_type = field_item->field_type(); NormalizedType normalized_type = normalize_field_type(field_type); switch (normalized_type) { case STRING_TYPE: grn_obj_reinit(ctx_, &value_, GRN_DB_TEXT, 0); { String *string; string = const_item->val_str(NULL); GRN_TEXT_SET(ctx_, &value_, string->ptr(), string->length()); } break; case INT_TYPE: grn_obj_reinit(ctx_, &value_, GRN_DB_INT64, 0); GRN_INT64_SET(ctx_, &value_, const_item->val_int()); break; case TIME_TYPE: grn_obj_reinit(ctx_, &value_, GRN_DB_TIME, 0); { MYSQL_TIME mysql_time; get_time_value(field_item, const_item, &mysql_time); bool truncated = false; TimeConverter time_converter; long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); GRN_TIME_SET(ctx_, &value_, time); } break; case UNSUPPORTED_TYPE: // Should not be occurred. DBUG_PRINT("error", ("mroonga: append_const_item: unsupported type: <%d> " "This case should not be occurred.", field_type)); grn_obj_reinit(ctx_, &value_, GRN_DB_VOID, 0); break; } grn_expr_append_const(ctx_, expression, &value_, GRN_OP_PUSH, 1); DBUG_VOID_RETURN; }
grn_rc grn_token_set_data(grn_ctx *ctx, grn_token *token, const char *str_ptr, int str_length) { GRN_API_ENTER; if (!token) { ERR(GRN_INVALID_ARGUMENT, "token must not be NULL"); goto exit; } if (str_length == -1) { str_length = strlen(str_ptr); } GRN_TEXT_SET(ctx, &(token->data), str_ptr, str_length); exit: GRN_API_RETURN(ctx->rc); }
/* * インデックス対象となる複数のカラムを配列で設定する。 * * @overload sources=(columns) * @param [::Array<Groonga::Column>] columns インデックス対象となるカラムの配列 */ static VALUE rb_grn_index_column_set_sources (VALUE self, VALUE rb_sources) { VALUE exception; grn_ctx *context = NULL; grn_obj *column; int i, n; VALUE *rb_source_values; grn_id range_id; grn_id *sources; grn_rc rc; rb_grn_index_column_deconstruct(SELF(self), &column, &context, NULL, NULL, NULL, NULL, &range_id, NULL, NULL, NULL); n = RARRAY_LEN(rb_sources); rb_source_values = RARRAY_PTR(rb_sources); sources = ALLOCA_N(grn_id, n); for (i = 0; i < n; i++) { sources[i] = resolve_source_id(context, column, range_id, rb_source_values[i]); } { grn_obj bulk_sources; GRN_OBJ_INIT(&bulk_sources, GRN_BULK, 0, GRN_ID_NIL); GRN_TEXT_SET(context, &bulk_sources, sources, n * sizeof(grn_id)); rc = grn_obj_set_info(context, column, GRN_INFO_SOURCE, &bulk_sources); exception = rb_grn_context_to_exception(context, self); grn_obj_unlink(context, &bulk_sources); } if (!NIL_P(exception)) rb_exc_raise(exception); rb_grn_rc_check(rc, self); return Qnil; }
static mrb_value mrb_grn_cache_update(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; grn_cache *cache; char *key; mrb_int key_size; char *value; mrb_int value_size; grn_obj value_buffer; cache = DATA_PTR(self); mrb_get_args(mrb, "ss", &key, &key_size, &value, &value_size); GRN_TEXT_INIT(&value_buffer, GRN_OBJ_DO_SHALLOW_COPY); GRN_TEXT_SET(ctx, &value_buffer, value, value_size); grn_cache_update(ctx, cache, key, key_size, &value_buffer); GRN_OBJ_FIN(ctx, &value_buffer); return mrb_nil_value(); }
VALUE rb_grn_uvector_to_ruby_object (grn_ctx *context, grn_obj *uvector, grn_obj *range, VALUE related_object) { VALUE array = Qnil; if (!uvector) return Qnil; if (!range) { rb_raise(rb_eTypeError, "unknown range uvector can't be converted: <%s>", rb_grn_inspect(related_object)); } switch (range->header.type) { case GRN_TYPE: { const char *current, *end; grn_id range_id; grn_obj value; int value_size; value_size = grn_obj_get_range(context, range); array = rb_ary_new(); current = GRN_BULK_HEAD(uvector); end = GRN_BULK_CURR(uvector); range_id = grn_obj_id(context, range); GRN_OBJ_INIT(&value, GRN_BULK, GRN_OBJ_DO_SHALLOW_COPY, range_id); while (current < end) { VALUE rb_value; GRN_TEXT_SET(context, &value, current, value_size); rb_value = GRNBULK2RVAL(context, &value, range, related_object); rb_ary_push(array, rb_value); current += value_size; } GRN_OBJ_FIN(context, &value); break; } case GRN_TABLE_HASH_KEY: case GRN_TABLE_PAT_KEY: case GRN_TABLE_DAT_KEY: case GRN_TABLE_NO_KEY: { grn_id *current, *end; VALUE rb_range = Qnil; array = rb_ary_new(); rb_range = GRNTABLE2RVAL(context, range, GRN_FALSE); current = (grn_id *)GRN_BULK_HEAD(uvector); end = (grn_id *)GRN_BULK_CURR(uvector); while (current < end) { VALUE record = Qnil; if (*current != GRN_ID_NIL) { record = rb_grn_record_new(rb_range, *current, Qnil); } rb_ary_push(array, record); current++; } break; } default: rb_raise(rb_eTypeError, "unknown range uvector can't be converted: %s(%#x): <%s>", rb_grn_inspect_type(range->header.type), range->header.type, rb_grn_inspect(related_object)); break; } return array; }
grn_obj * rb_grn_bulk_from_ruby_object_with_type (VALUE object, grn_ctx *context, grn_obj *bulk, grn_id type_id, grn_obj *type) { const char *string; unsigned int size; union { int8_t int8_value; uint8_t uint8_value; int16_t int16_value; uint16_t uint16_value; int32_t int32_value; uint32_t uint32_value; int64_t int64_value; uint64_t uint64_value; int64_t time_value; double double_value; grn_geo_point geo_point_value; grn_id record_id; } value; grn_id range; VALUE rb_type_object; grn_obj_flags flags = 0; grn_bool string_p, table_type_p; string_p = rb_type(object) == T_STRING; table_type_p = (GRN_TABLE_HASH_KEY <= type->header.type && type->header.type <= GRN_TABLE_NO_KEY); switch (type_id) { case GRN_DB_INT8: value.int8_value = NUM2SHORT(object); string = (const char *)&(value.int8_value); size = sizeof(value.int8_value); break; case GRN_DB_UINT8: value.uint8_value = NUM2USHORT(object); string = (const char *)&(value.uint8_value); size = sizeof(value.uint8_value); break; case GRN_DB_INT16: value.int16_value = NUM2SHORT(object); string = (const char *)&(value.int16_value); size = sizeof(value.int16_value); break; case GRN_DB_UINT16: value.uint16_value = NUM2USHORT(object); string = (const char *)&(value.uint16_value); size = sizeof(value.uint16_value); break; case GRN_DB_INT32: value.int32_value = NUM2INT(object); string = (const char *)&(value.int32_value); size = sizeof(value.int32_value); break; case GRN_DB_UINT32: value.uint32_value = NUM2UINT(object); string = (const char *)&(value.uint32_value); size = sizeof(value.uint32_value); break; case GRN_DB_INT64: value.int64_value = NUM2LL(object); string = (const char *)&(value.int64_value); size = sizeof(value.int64_value); break; case GRN_DB_UINT64: value.uint64_value = NUM2ULL(object); string = (const char *)&(value.uint64_value); size = sizeof(value.uint64_value); break; case GRN_DB_FLOAT: value.double_value = NUM2DBL(object); string = (const char *)&(value.double_value); size = sizeof(value.double_value); break; case GRN_DB_TIME: { VALUE rb_sec, rb_usec; int64_t sec; int32_t usec; if (string_p) { ID id_parse; CONST_ID(id_parse, "parse"); object = rb_funcall(rb_cTime, id_parse, 1, object); } switch (TYPE(object)) { case T_FIXNUM: case T_BIGNUM: sec = NUM2LL(object); usec = 0; break; case T_FLOAT: rb_sec = rb_funcall(object, rb_intern("to_i"), 0); rb_usec = rb_funcall(object, rb_intern("remainder"), 1, INT2NUM(1)); sec = NUM2LL(rb_sec); usec = (int32_t)(NUM2DBL(rb_usec) * 1000000); break; case T_NIL: sec = 0; usec = 0; break; default: sec = NUM2LL(rb_funcall(object, rb_intern("to_i"), 0)); usec = NUM2INT(rb_funcall(object, rb_intern("usec"), 0)); break; } value.time_value = GRN_TIME_PACK(sec, usec); string = (const char *)&(value.time_value); size = sizeof(value.time_value); break; } case GRN_DB_SHORT_TEXT: case GRN_DB_TEXT: case GRN_DB_LONG_TEXT: string = StringValuePtr(object); size = RSTRING_LEN(object); range = grn_obj_get_range(context, type); if (size > range) rb_raise(rb_eArgError, "string is too large: expected: %u <= %u", size, range); flags |= GRN_OBJ_DO_SHALLOW_COPY; break; case GRN_DB_TOKYO_GEO_POINT: case GRN_DB_WGS84_GEO_POINT: { VALUE rb_geo_point; VALUE rb_latitude, rb_longitude; if (type_id == GRN_DB_TOKYO_GEO_POINT) { rb_geo_point = rb_funcall(rb_cGrnTokyoGeoPoint, rb_intern("new"), 1, object); } else { rb_geo_point = rb_funcall(rb_cGrnWGS84GeoPoint, rb_intern("new"), 1, object); } rb_geo_point = rb_funcall(rb_geo_point, rb_intern("to_msec"), 0); rb_latitude = rb_funcall(rb_geo_point, rb_intern("latitude"), 0); rb_longitude = rb_funcall(rb_geo_point, rb_intern("longitude"), 0); value.geo_point_value.latitude = NUM2INT(rb_latitude); value.geo_point_value.longitude = NUM2INT(rb_longitude); string = (const char *)&(value.geo_point_value); size = sizeof(value.geo_point_value); break; } case GRN_DB_VOID: case GRN_DB_DELIMIT: case GRN_DB_UNIGRAM: case GRN_DB_BIGRAM: case GRN_DB_TRIGRAM: case GRN_DB_MECAB: rb_type_object = GRNOBJECT2RVAL(Qnil, context, type, GRN_FALSE); rb_raise(rb_eArgError, "unbulkable type: %s", rb_grn_inspect(rb_type_object)); break; default: if (table_type_p && (NIL_P(object) || (string_p && RSTRING_LEN(object) == 0))) { value.record_id = GRN_ID_NIL; string = (const char *)&(value.record_id); size = sizeof(value.record_id); if (bulk && bulk->header.domain != type_id) { grn_obj_reinit(context, bulk, type_id, 0); } } else { return RVAL2GRNBULK(object, context, bulk); } break; } if (!bulk) { bulk = grn_obj_open(context, GRN_BULK, flags, GRN_ID_NIL); rb_grn_context_check(context, object); } GRN_TEXT_SET(context, bulk, string, size); return bulk; }
void test_mroonga_index(void) { grn_obj *t1,*c1,*lc,*ft; grn_obj buff; grn_id c1_id,r1,r2,r3,r4; const gchar *mrn_dir; mrn_dir = cut_build_path(tmp_directory, "mrn", NULL); g_mkdir_with_parents(mrn_dir, 0700); grn_obj_close(context, db); db = grn_db_create(context, cut_build_path(mrn_dir, "mroonga.grn", NULL), NULL); cut_assert_not_null(db); /* actual table */ t1 = grn_table_create(context, "t1", 2, cut_build_path(mrn_dir, "t1.grn", 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, cut_build_path(mrn_dir, "lc.grn", NULL), GRN_OBJ_TABLE_PAT_KEY|GRN_OBJ_PERSISTENT, grn_ctx_at(context, GRN_DB_SHORT_TEXT), 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, cut_build_path(mrn_dir, "t1.c1.grn", 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, cut_build_path(mrn_dir, "lc.ft.grn", NULL), GRN_OBJ_COLUMN_INDEX|GRN_OBJ_PERSISTENT, t1); cut_assert_not_null(ft); GRN_TEXT_INIT(&buff,0); /* link between actual column and fulltext index */ c1_id = grn_obj_id(context, c1); GRN_TEXT_SET(context, &buff, (char*)&c1_id, sizeof(grn_id)); grn_obj_set_info(context, ft, GRN_INFO_SOURCE, &buff); /* need to use grn_id */ /* insert row */ r1 = grn_table_add(context, t1, NULL, 0, NULL); cut_assert_equal_int(1,r1); GRN_TEXT_SET(context, &buff, "abcde", 5); grn_test_assert(grn_obj_set_value(context, c1, r1, &buff, GRN_OBJ_SET)); r2 = grn_table_add(context, t1, NULL, 0, NULL); cut_assert_equal_int(2,r2); GRN_TEXT_SET(context, &buff, "fghij", 5); grn_test_assert(grn_obj_set_value(context, c1, r2, &buff, GRN_OBJ_SET)); r3 = grn_table_add(context, t1, NULL, 0, NULL); cut_assert_equal_int(3,r3); GRN_TEXT_SET(context, &buff, "11 22 33", 8); grn_test_assert(grn_obj_set_value(context, c1, r3, &buff, GRN_OBJ_SET)); r4 = grn_table_add(context, t1, NULL, 0, NULL); cut_assert_equal_int(4,r4); GRN_TEXT_SET(context, &buff, "44 22 55", 8); grn_test_assert(grn_obj_set_value(context, c1, r4, &buff, 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(23,grn_table_size(context,lc)); /* nlq search */ { grn_id id, docid; grn_obj *res; grn_table_cursor *tc; res = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_HASH_KEY, t1, 0); GRN_BULK_REWIND(&buff); GRN_TEXT_SET(context, &buff, "hi", 2); grn_obj_search(context, ft, &buff, res, GRN_OP_OR, NULL); cut_assert_equal_int(1, grn_table_size(context, res)); tc = grn_table_cursor_open(context, res, NULL, 0, NULL, 0, 0, -1, 0); while ((id = grn_table_cursor_next(context, tc))) { GRN_BULK_REWIND(&buff); grn_table_get_key(context, res, id, &docid, sizeof(grn_id)); cut_assert_equal_int(2, docid); cut_assert_not_null(grn_obj_get_value(context, c1, docid, &buff)); cut_assert_equal_int(5 ,GRN_TEXT_LEN(&buff)); cut_assert_equal_substring("fghij", (char*) GRN_BULK_HEAD(&buff),GRN_TEXT_LEN(&buff)); } grn_table_cursor_close(context, tc); grn_obj_close(context, res); } /* boolean search */ { grn_id id, docid; grn_obj *match_columns, *match_columns_variable; grn_obj *expression, *expression_variable; grn_obj *res; grn_table_cursor *tc; const char *match_columns_expression = "c1"; const char *qstr = "+22 -55"; GRN_EXPR_CREATE_FOR_QUERY(context, t1, match_columns, match_columns_variable); grn_expr_parse(context, match_columns, match_columns_expression, strlen(match_columns_expression), NULL, GRN_OP_MATCH, GRN_OP_AND, GRN_EXPR_SYNTAX_SCRIPT); GRN_EXPR_CREATE_FOR_QUERY(context, t1, expression, expression_variable); res = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_HASH_KEY, t1, 0); grn_test_assert(grn_expr_parse(context, expression, qstr, strlen(qstr), match_columns, GRN_OP_MATCH, GRN_OP_OR, GRN_EXPR_SYNTAX_QUERY)); grn_table_select(context, t1, expression, res, GRN_OP_OR); cut_assert_equal_int(1, grn_table_size(context, res)); tc = grn_table_cursor_open(context, res, NULL, 0, NULL, 0, 0, -1, 0); while ((id = grn_table_cursor_next(context, tc))) { GRN_BULK_REWIND(&buff); grn_table_get_key(context, res, id, &docid, sizeof(grn_id)); cut_assert_equal_int(3, docid); cut_assert_not_null(grn_obj_get_value(context, c1, docid, &buff)); cut_assert_equal_int(8 ,GRN_TEXT_LEN(&buff)); cut_assert_equal_substring("11 22 33", (char*) GRN_BULK_HEAD(&buff),GRN_TEXT_LEN(&buff)); } grn_obj_close(context, expression); grn_obj_close(context, match_columns); grn_table_cursor_close(context ,tc); grn_obj_close(context, res); } grn_obj_close(context, &buff); grn_obj_close(context, ft); grn_obj_close(context, c1); grn_obj_close(context, lc); grn_obj_close(context, t1); }
void test_mroonga_index(void) { grn_obj *t1,*c1,*lc,*ft; grn_obj buff; grn_id c1_id,r1,r2,r3,r4; remove_tmp_directory(); g_mkdir_with_parents(tmp_directory,0700); g_chdir(tmp_directory); g_mkdir_with_parents("mrn",0700); db = grn_db_create(context,"mroonga.grn",NULL); cut_assert_not_null(db); /* actual table */ t1 = grn_table_create(context,"t1",2,"mrn/t1.grn", GRN_OBJ_TABLE_NO_KEY|GRN_OBJ_PERSISTENT,NULL,0); cut_assert_not_null(t1); /* lexicon table */ lc = grn_table_create(context,"lc",2,"mrn/lc.grn", GRN_OBJ_TABLE_PAT_KEY|GRN_OBJ_PERSISTENT, grn_ctx_at(context, GRN_DB_SHORT_TEXT), 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,"mrn/t1.c1.grn", 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,"mrn/lc.ft.grn", GRN_OBJ_COLUMN_INDEX|GRN_OBJ_PERSISTENT,t1); cut_assert_not_null(ft); GRN_TEXT_INIT(&buff,0); /* link between actual column and fulltext index */ c1_id = grn_obj_id(context, c1); GRN_TEXT_SET(context, &buff, (char*)&c1_id, sizeof(grn_id)); grn_obj_set_info(context, ft, GRN_INFO_SOURCE, &buff); /* need to use grn_id */ /* insert row */ r1 = grn_table_add(context, t1, NULL, 0, NULL); cut_assert_equal_int(1,r1); GRN_TEXT_SET(context, &buff, "abcde", 5); grn_test_assert(grn_obj_set_value(context, c1, r1, &buff, GRN_OBJ_SET)); r2 = grn_table_add(context, t1, NULL, 0, NULL); cut_assert_equal_int(2,r2); GRN_TEXT_SET(context, &buff, "fghij", 5); grn_test_assert(grn_obj_set_value(context, c1, r2, &buff, GRN_OBJ_SET)); r3 = grn_table_add(context, t1, NULL, 0, NULL); cut_assert_equal_int(3,r3); GRN_TEXT_SET(context, &buff, "11 22 33", 8); grn_test_assert(grn_obj_set_value(context, c1, r3, &buff, GRN_OBJ_SET)); r4 = grn_table_add(context, t1, NULL, 0, NULL); cut_assert_equal_int(4,r4); GRN_TEXT_SET(context, &buff, "44 22 55", 8); grn_test_assert(grn_obj_set_value(context, c1, r4, &buff, 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(23,grn_table_size(context,lc)); /* nlq search */ { grn_id id, docid; grn_obj *res; grn_table_cursor *tc; res = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_HASH_KEY, t1, 0); GRN_BULK_REWIND(&buff); GRN_TEXT_SET(context, &buff, "hi", 2); grn_obj_search(context, ft, &buff, res, GRN_OP_OR, NULL); cut_assert_equal_int(1, grn_table_size(context, res)); tc = grn_table_cursor_open(context, res, NULL, 0, NULL, 0, 0, 0, 0); while ((id = grn_table_cursor_next(context, tc))) { GRN_BULK_REWIND(&buff); grn_table_get_key(context, res, id, &docid, sizeof(grn_id)); cut_assert_equal_int(2, docid); cut_assert_not_null(grn_obj_get_value(context, c1, docid, &buff)); cut_assert_equal_int(5 ,GRN_TEXT_LEN(&buff)); cut_assert_equal_substring("fghij", (char*) GRN_BULK_HEAD(&buff),GRN_TEXT_LEN(&buff)); } grn_table_cursor_close(context, tc); grn_obj_close(context, res); } /* boolean search */ { grn_id id, docid; grn_obj *res; grn_query *query; grn_table_cursor *tc; const char *qstr = "+22 -55"; res = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_HASH_KEY, t1, 0); query = grn_query_open(context, qstr, strlen(qstr), GRN_OP_OR, 32); grn_obj_search(context, ft, (grn_obj*) query, res, GRN_OP_OR, NULL); cut_assert_equal_int(1, grn_table_size(context, res)); tc = grn_table_cursor_open(context, res, NULL, 0, NULL, 0, 0, 0, 0); while ((id = grn_table_cursor_next(context, tc))) { GRN_BULK_REWIND(&buff); grn_table_get_key(context, res, id, &docid, sizeof(grn_id)); cut_assert_equal_int(3, docid); cut_assert_not_null(grn_obj_get_value(context, c1, docid, &buff)); cut_assert_equal_int(8 ,GRN_TEXT_LEN(&buff)); cut_assert_equal_substring("11 22 33", (char*) GRN_BULK_HEAD(&buff),GRN_TEXT_LEN(&buff)); } grn_query_close(context, query); grn_table_cursor_close(context ,tc); grn_obj_close(context, res); } grn_obj_close(context, &buff); grn_obj_close(context, ft); grn_obj_close(context, c1); grn_obj_close(context, lc); grn_obj_close(context, t1); }
grn_obj * rb_grn_bulk_from_ruby_object_with_type (VALUE object, grn_ctx *context, grn_obj *bulk, grn_id type_id, grn_obj *type) { const char *string; unsigned int size; int32_t int32_value; uint32_t uint32_value; int64_t int64_value; uint64_t uint64_value; int64_t time_value; double double_value; grn_id record_id, range; VALUE rb_type_object; grn_obj_flags flags = 0; grn_bool string_p, table_type_p; string_p = rb_type(object) == T_STRING; table_type_p = (GRN_TABLE_HASH_KEY <= type->header.type && type->header.type <= GRN_TABLE_VIEW); if (string_p && !table_type_p) { return RVAL2GRNBULK(object, context, bulk); } switch (type_id) { case GRN_DB_INT32: int32_value = NUM2INT(object); string = (const char *)&int32_value; size = sizeof(int32_value); break; case GRN_DB_UINT32: uint32_value = NUM2UINT(object); string = (const char *)&uint32_value; size = sizeof(uint32_value); break; case GRN_DB_INT64: int64_value = NUM2LL(object); string = (const char *)&int64_value; size = sizeof(int64_value); break; case GRN_DB_UINT64: uint64_value = NUM2ULL(object); string = (const char *)&uint64_value; size = sizeof(uint64_value); break; case GRN_DB_FLOAT: double_value = NUM2DBL(object); string = (const char *)&double_value; size = sizeof(double_value); break; case GRN_DB_TIME: { VALUE rb_sec, rb_usec; int64_t sec; int32_t usec; switch (TYPE(object)) { case T_FIXNUM: case T_BIGNUM: sec = NUM2LL(object); usec = 0; break; case T_FLOAT: rb_sec = rb_funcall(object, rb_intern("to_i"), 0); rb_usec = rb_funcall(object, rb_intern("remainder"), 1, INT2NUM(1)); sec = NUM2LL(rb_sec); usec = (int32_t)(NUM2DBL(rb_usec) * 1000000); break; case T_NIL: sec = 0; usec = 0; break; default: sec = NUM2LL(rb_funcall(object, rb_intern("to_i"), 0)); usec = NUM2INT(rb_funcall(object, rb_intern("usec"), 0)); break; } time_value = GRN_TIME_PACK(sec, usec); } string = (const char *)&time_value; size = sizeof(time_value); break; case GRN_DB_SHORT_TEXT: case GRN_DB_TEXT: case GRN_DB_LONG_TEXT: string = StringValuePtr(object); size = RSTRING_LEN(object); range = grn_obj_get_range(context, type); if (size > range) rb_raise(rb_eArgError, "string is too large: expected: %u <= %u", size, range); flags |= GRN_OBJ_DO_SHALLOW_COPY; break; case GRN_DB_VOID: case GRN_DB_DELIMIT: case GRN_DB_UNIGRAM: case GRN_DB_BIGRAM: case GRN_DB_TRIGRAM: case GRN_DB_MECAB: rb_type_object = GRNOBJECT2RVAL(Qnil, context, type, GRN_FALSE); rb_raise(rb_eArgError, "unbulkable type: %s", rb_grn_inspect(rb_type_object)); break; default: if (table_type_p && (NIL_P(object) || (string_p && RSTRING_LEN(object) == 0))) { record_id = GRN_ID_NIL; string = (const char *)&record_id; size = sizeof(record_id); if (bulk && bulk->header.domain != type_id) { grn_obj_reinit(context, bulk, type_id, 0); } } else { return RVAL2GRNBULK(object, context, bulk); } break; } if (!bulk) { bulk = grn_obj_open(context, GRN_BULK, flags, GRN_ID_NIL); rb_grn_context_check(context, object); } GRN_TEXT_SET(context, bulk, string, size); return bulk; }
void rb_grn_context_text_set (grn_ctx *context, grn_obj *bulk, VALUE rb_string) { rb_string = rb_grn_context_rb_string_encode(context, rb_string); GRN_TEXT_SET(context, bulk, RSTRING_PTR(rb_string), RSTRING_LEN(rb_string)); }