int rb_grn_table_cursor_order_by_to_flag (unsigned char table_type, VALUE rb_table, VALUE rb_order_by) { int flag = 0; if (NIL_P(rb_order_by)) { if (table_type == GRN_TABLE_PAT_KEY) { flag |= GRN_CURSOR_BY_KEY; } else { flag |= GRN_CURSOR_BY_ID; } } else if (rb_grn_equal_option(rb_order_by, "id")) { flag |= GRN_CURSOR_BY_ID; } else if (rb_grn_equal_option(rb_order_by, "key")) { if (table_type != GRN_TABLE_PAT_KEY) { rb_raise(rb_eArgError, "order_by => :key is available " "only for Groonga::PatriciaTrie: %s", rb_grn_inspect(rb_table)); } flag |= GRN_CURSOR_BY_KEY; } else { rb_raise(rb_eArgError, "order_by should be one of [:id%s]: %s", table_type == GRN_TABLE_PAT_KEY ? ", :key" : "", rb_grn_inspect(rb_order_by)); } return flag; }
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; }
grn_id rb_grn_id_from_ruby_object (VALUE object, grn_ctx *context, grn_obj *table, VALUE related_object) { VALUE rb_id; if (NIL_P(object)) return Qnil; if (RVAL2CBOOL(rb_obj_is_kind_of(object, rb_cGrnRecord))) { VALUE rb_table; rb_table = rb_funcall(object, rb_intern("table"), 0); if (table && RVAL2GRNOBJECT(rb_table, &context) != table) { VALUE rb_expected_table; rb_expected_table = GRNOBJECT2RVAL(Qnil, context, table, GRN_FALSE); rb_raise(rb_eGrnError, "wrong table: expected <%s>: actual <%s>", rb_grn_inspect(rb_expected_table), rb_grn_inspect(rb_table)); } rb_id = rb_funcall(object, rb_intern("id"), 0); } else { rb_id = object; } if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_id, rb_cInteger))) rb_raise(rb_eGrnError, "should be unsigned integer or Groogna::Record: <%s>: <%s>", rb_grn_inspect(object), rb_grn_inspect(related_object)); return NUM2UINT(rb_id); }
/* * 名前が _name_ の型を作成する。 * * @overload new(name, options={}) * @param name [String] 作成する型の名前 * @param options [::Hash] The name and value * pairs. Omitted names are initialized as the default value * @option options [Symbol] :type (:variable) * :integer(符号付き整数)、:int(:integerの省略 * 形)、:unsigned_integer(符号なし整 * 数)、:uint(:unsigned_integerの省略形)、:float(浮動小数点 * 数)、:variable(可変長文字列)のいずれかを指定する。省略した場 * 合は:variableを指定したものと扱う。 * :variableを指定した場合は必ず +:size+ を指定しなければいけない。 * @option options [Context] :context * 型の作成時に利用するGroonga::Contextを指定する。省略すると * Groonga::Context.defaultを用いる。 * @option options [Integer] :size * +:option+ が:variableの場合は最大長、それ以外の場合は長さを * 指定する(単位:byte)。 */ static VALUE rb_grn_type_initialize (int argc, VALUE *argv, VALUE self) { grn_ctx *context; grn_obj *type; const char *name = NULL; unsigned name_size, size = 0; grn_obj_flags flags = 0; VALUE rb_name, options, rb_context, rb_type, rb_size; rb_scan_args(argc, argv, "11", &rb_name, &options); rb_grn_scan_options(options, "context", &rb_context, "type", &rb_type, "size", &rb_size, NULL); name = StringValuePtr(rb_name); name_size = RSTRING_LEN(rb_name); context = rb_grn_context_ensure(&rb_context); if (NIL_P(rb_type) || rb_grn_equal_option(rb_type, "variable")) { flags = GRN_OBJ_KEY_VAR_SIZE; } else if (rb_grn_equal_option(rb_type, "integer") || rb_grn_equal_option(rb_type, "int")) { flags = GRN_OBJ_KEY_INT; size = sizeof(int); } else if (rb_grn_equal_option(rb_type, "unsigned_integer") || rb_grn_equal_option(rb_type, "uint")) { flags = GRN_OBJ_KEY_UINT; size = sizeof(unsigned int); } else if (rb_grn_equal_option(rb_type, "float")) { flags = GRN_OBJ_KEY_FLOAT; size = sizeof(double); } else { rb_raise(rb_eArgError, ":type should be one of " "[:integer, :int, :unsigned_integer, :uint, " ":float, :variable]: %s", rb_grn_inspect(options)); } if (NIL_P(rb_size)) { if (size == 0) rb_raise(rb_eArgError, "size is missing: %s", rb_grn_inspect(options)); } else { size = NUM2UINT(rb_size); } type = grn_type_create(context, name, name_size, flags, size); rb_grn_object_assign(Qnil, self, rb_context, context, type); rb_grn_context_check(context, rb_ary_new4(argc, argv)); return Qnil; }
static void rb_grn_uvector_from_ruby_object_reference (UVectorFromRubyData *data) { VALUE object; grn_ctx *context; grn_obj *uvector; VALUE related_object; VALUE *rb_values; int i, n; object = data->object; context = data->context; uvector = data->uvector; related_object = data->related_object; n = RARRAY_LEN(object); rb_values = RARRAY_PTR(object); for (i = 0; i < n; i++) { VALUE rb_value; grn_id id; void *grn_value; ID id_record_raw_id; rb_value = rb_values[i]; switch (TYPE(rb_value)) { case T_FIXNUM: id = NUM2UINT(rb_value); break; default: CONST_ID(id_record_raw_id, "record_raw_id"); if (rb_respond_to(rb_value, id_record_raw_id)) { id = NUM2UINT(rb_funcall(rb_value, id_record_raw_id, 0)); } else { rb_raise(rb_eArgError, "uvector value should be one of " "[Fixnum or object that has #record_raw_id]: " "%s (%s): %s", rb_grn_inspect(rb_value), rb_grn_inspect(object), rb_grn_inspect(related_object)); } break; } grn_value = &id; grn_bulk_write(context, uvector, grn_value, sizeof(grn_id)); } data->succeeded = GRN_TRUE; }
void rb_grn_scan_options (VALUE options, ...) { VALUE original_options = options; VALUE available_keys; const char *key; VALUE *value; va_list args; options = rb_grn_check_convert_to_hash(options); if (NIL_P(options)) { if (NIL_P(original_options)) { options = rb_hash_new(); } else { rb_raise(rb_eArgError, "options must be Hash: %s", rb_grn_inspect(original_options)); } } else if (options == original_options) { options = rb_funcall(options, rb_intern("dup"), 0); } available_keys = rb_ary_new(); va_start(args, options); key = va_arg(args, const char *); while (key) { VALUE rb_key; value = va_arg(args, VALUE *); rb_key = RB_GRN_INTERN(key); rb_ary_push(available_keys, rb_key); *value = rb_funcall(options, rb_intern("delete"), 1, rb_key); if (NIL_P(*value)) { rb_key = rb_str_new_cstr(key); *value = rb_funcall(options, rb_intern("delete"), 1, rb_key); } key = va_arg(args, const char *); } va_end(args); if (RVAL2CBOOL(rb_funcall(options, rb_intern("empty?"), 0))) return; rb_raise(rb_eArgError, "unexpected key(s) exist: %s: available keys: %s", rb_grn_inspect(rb_funcall(options, rb_intern("keys"), 0)), rb_grn_inspect(available_keys)); }
VALUE rb_grn_context_to_exception (grn_ctx *context, VALUE related_object) { VALUE exception, exception_class; const char *message; grn_obj bulk; if (context->rc == GRN_SUCCESS) return Qnil; exception_class = rb_grn_rc_to_exception(context->rc); message = rb_grn_rc_to_message(context->rc); GRN_OBJ_INIT(&bulk, GRN_BULK, 0, GRN_ID_NIL); GRN_TEXT_PUTS(context, &bulk, message); GRN_TEXT_PUTS(context, &bulk, ": "); GRN_TEXT_PUTS(context, &bulk, context->errbuf); if (!NIL_P(related_object)) { GRN_TEXT_PUTS(context, &bulk, ": "); GRN_TEXT_PUTS(context, &bulk, rb_grn_inspect(related_object)); } GRN_TEXT_PUTS(context, &bulk, "\n"); GRN_TEXT_PUTS(context, &bulk, context->errfile); GRN_TEXT_PUTS(context, &bulk, ":"); grn_text_itoa(context, &bulk, context->errline); GRN_TEXT_PUTS(context, &bulk, ": "); GRN_TEXT_PUTS(context, &bulk, context->errfunc); GRN_TEXT_PUTS(context, &bulk, "()"); exception = rb_funcall(exception_class, rb_intern("new"), 1, rb_str_new(GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk))); grn_obj_unlink(context, &bulk); return exception; }
static grn_table_cursor * rb_grn_patricia_trie_open_grn_rk_cursor (int argc, VALUE *argv, VALUE self, grn_ctx **context) { grn_obj *table; grn_table_cursor *cursor; void *prefix = NULL; unsigned prefix_size = 0; int offset = 0, limit = -1; int flags = GRN_CURSOR_PREFIX | GRN_CURSOR_RK; VALUE options, rb_prefix, rb_key_bytes, rb_key_bits; VALUE rb_greater_than, rb_less_than, rb_offset, rb_limit; rb_grn_table_deconstruct((RbGrnTable *)SELF(self), &table, context, NULL, NULL, NULL, NULL, NULL, NULL); rb_scan_args(argc, argv, "11", &rb_prefix, &options); rb_grn_scan_options(options, "key_bytes", &rb_key_bytes, "key_bites", &rb_key_bits, "offset", &rb_offset, "limit", &rb_limit, "greater_than", &rb_greater_than, "less_than", &rb_less_than, NULL); prefix = StringValuePtr(rb_prefix); if (!NIL_P(rb_key_bytes) && !NIL_P(rb_key_bits)) { rb_raise(rb_eArgError, "should not specify both :key_bytes and :key_bits once: %s", rb_grn_inspect(rb_ary_new4(argc, argv))); } else if (!NIL_P(rb_key_bytes)) { prefix_size = NUM2UINT(rb_key_bytes); } else if (!NIL_P(rb_key_bits)) { prefix_size = NUM2UINT(rb_key_bits); flags |= GRN_CURSOR_SIZE_BY_BIT; } else { prefix_size = RSTRING_LEN(rb_prefix); } if (!NIL_P(rb_offset)) offset = NUM2INT(rb_offset); if (!NIL_P(rb_limit)) limit = NUM2INT(rb_limit); if (RVAL2CBOOL(rb_greater_than)) flags |= GRN_CURSOR_GT; if (RVAL2CBOOL(rb_less_than)) flags |= GRN_CURSOR_LT; cursor = grn_table_cursor_open(*context, table, prefix, prefix_size, NULL, 0, offset, limit, flags); rb_grn_context_check(*context, self); return cursor; }
/* * Flush memory mapped data to disk. * * @overload flush(options={}) * @param [::Hash] options * @option options [Boolean] :recursive (true) Whether to flush objects * which a target object has recursively. * @return [void] */ static VALUE rb_grn_flushable_flush (int argc, VALUE *argv, VALUE self) { grn_ctx *context = NULL; grn_obj *object = NULL; VALUE rb_recursive_p; VALUE rb_options; rb_scan_args(argc, argv, "01", &rb_options); rb_grn_scan_options(rb_options, "recursive", &rb_recursive_p, NULL); if (NIL_P(rb_recursive_p)) { rb_recursive_p = Qtrue; } rb_grn_object_deconstruct(SELF(self), &object, &context, NULL, NULL, NULL, NULL); if (!object) { rb_raise(rb_eGrnClosed, "can't access already closed Groonga object: <%s>", rb_grn_inspect(self)); } if (RVAL2CBOOL(rb_recursive_p)) { grn_obj_flush_recursive(context, object); } else { grn_obj_flush(context, object); } rb_grn_context_check(context, self); return Qnil; }
/* * _table_ の _key_ に対応するカラム _column_name_ の値を設定する。 * _key_ に対応するレコードがない場合は新しく作成される。 * * 0.9.0から値ではなくカラムの値を設定するようになった。 * * @overload []=(key, values) * @param [::Hash] values * keyに対応させるカラムの値。{ :column_name => value, ... }の形で設定する。 */ static VALUE rb_grn_table_key_support_array_set (VALUE self, VALUE rb_key, VALUE rb_values) { grn_id id; SetValueData data; grn_ctx *context; grn_obj *table; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, NULL, NULL, NULL, NULL); id = rb_grn_table_key_support_add_raw(self, rb_key, NULL); if (id == GRN_ID_NIL) { rb_raise(rb_eGrnError, "failed to add record: %s", rb_grn_inspect(rb_ary_new3(3, self, rb_key, rb_values))); } data.self = self; data.id = id; data.table = table; data.rb_grn_object.context = context; rb_iterate(rb_each, rb_values, set_value, (VALUE)&data); return Qnil; }
/* * _table_ の _key_ に対応するカラム _name_ の値を設定する。 * _key_ に対応するレコードがない場合は新しく作成される。 * * @overload set_column_value(key, name, value) * @overload set_column_value(id, name, value, {:id=>true}) */ static VALUE rb_grn_table_key_support_set_column_value (int argc, VALUE *argv, VALUE self) { grn_id id; VALUE rb_key, rb_id_or_key, rb_name, rb_value, rb_options; rb_scan_args(argc, argv, "31", &rb_id_or_key, &rb_name, &rb_value, &rb_options); if (!NIL_P(rb_options)) { VALUE rb_option_id; rb_grn_scan_options(rb_options, "id", &rb_option_id, NULL); if (RVAL2CBOOL(rb_option_id)) { VALUE rb_id = rb_id_or_key; return rb_grn_table_set_column_value(self, rb_id, rb_name, rb_value); } } rb_key = rb_id_or_key; id = rb_grn_table_key_support_add_raw(self, rb_key, NULL); if (id == GRN_ID_NIL) { rb_raise(rb_eGrnError, "failed to add record: %s", rb_grn_inspect(rb_ary_new3(4, self, rb_key, rb_name, rb_value))); } return rb_grn_table_set_column_value_raw(self, id, rb_name, rb_value); }
grn_operator rb_grn_operator_from_ruby_object (VALUE rb_operator) { grn_operator operator = GRN_OP_OR; if (NIL_P(rb_operator) || rb_grn_equal_option(rb_operator, "or") || rb_grn_equal_option(rb_operator, "||")) { operator = GRN_OP_OR; } else if (rb_grn_equal_option(rb_operator, "and") || rb_grn_equal_option(rb_operator, "+") || rb_grn_equal_option(rb_operator, "&&")) { operator = GRN_OP_AND; } else if (rb_grn_equal_option(rb_operator, "but") || rb_grn_equal_option(rb_operator, "not") || rb_grn_equal_option(rb_operator, "-")) { operator = GRN_OP_BUT; } else if (rb_grn_equal_option(rb_operator, "adjust") || rb_grn_equal_option(rb_operator, ">")) { operator = GRN_OP_ADJUST; } else { rb_raise(rb_eArgError, "operator should be one of " "[:or, :||, :and, :+, :&&, :but, :not, :-, :adjust, :>]: <%s>", rb_grn_inspect(rb_operator)); } return operator; }
grn_obj * rb_grn_uvector_from_ruby_object (VALUE object, grn_ctx *context, grn_obj *uvector, VALUE related_object) { UVectorFromRubyData data; if (NIL_P(object)) return NULL; data.domain = grn_ctx_at(context, uvector->header.domain); if (!data.domain) { rb_raise(rb_eArgError, "unknown domain uvector can't be converted: <%s>", rb_grn_inspect(related_object)); } GRN_OBJ_INIT(&(data.element_buffer), GRN_BULK, 0, uvector->header.domain); data.object = object; data.context = context; data.uvector = uvector; data.related_object = related_object; data.succeeded = GRN_FALSE; rb_ensure(rb_grn_uvector_from_ruby_object_body, (VALUE)(&data), rb_grn_uvector_from_ruby_object_ensure, (VALUE)(&data)); if (!data.succeeded) { return NULL; } return uvector; }
static VALUE rb_grn_uvector_from_ruby_object_body (VALUE user_data) { UVectorFromRubyData *data = (UVectorFromRubyData *)user_data; grn_obj *domain; domain = data->domain; switch (domain->header.type) { case GRN_TYPE: rb_grn_uvector_from_ruby_object_type(data); break; case GRN_TABLE_HASH_KEY: case GRN_TABLE_PAT_KEY: case GRN_TABLE_DAT_KEY: case GRN_TABLE_NO_KEY: rb_grn_uvector_from_ruby_object_reference(data); break; default: rb_raise(rb_eTypeError, "can't convert to unknown domain uvector: %s(%#x): <%s>", rb_grn_inspect_type(domain->header.type), domain->header.type, rb_grn_inspect(data->related_object)); break; } return Qnil; }
/* * Returns whether the column is compressed or not. If * @type@ is specified, it returns whether the column is * compressed by @type@ or not. * @overload compressed? * @return [Boolean] whether the column is compressed or not. * @overload compressed?(type) * @param [:zlib, :lz4] type (nil) * @return [Boolean] whether specified compressed type is used or not. * @since 1.3.1 */ static VALUE rb_grn_variable_size_column_compressed_p (int argc, VALUE *argv, VALUE self) { RbGrnVariableSizeColumn *rb_grn_column; grn_ctx *context = NULL; grn_obj *column; grn_obj_flags flags; VALUE type; grn_bool compressed_p = GRN_FALSE; grn_bool accept_any_type = GRN_FALSE; grn_bool need_zlib_check = GRN_FALSE; grn_bool need_lz4_check = GRN_FALSE; rb_scan_args(argc, argv, "01", &type); if (NIL_P(type)) { accept_any_type = GRN_TRUE; } else { if (rb_grn_equal_option(type, "zlib")) { need_zlib_check = GRN_TRUE; } else if (rb_grn_equal_option(type, "lzo")) { /* TODO: for backward compatibility */ need_lz4_check = GRN_TRUE; } else if (rb_grn_equal_option(type, "lz4")) { need_lz4_check = GRN_TRUE; } else { rb_raise(rb_eArgError, "compressed type should be <:zlib> or <:lz4>: <%s>", rb_grn_inspect(type)); } } rb_grn_column = SELF(self); rb_grn_object_deconstruct(RB_GRN_OBJECT(rb_grn_column), &column, &context, NULL, NULL, NULL, NULL); flags = column->header.flags; switch (flags & GRN_OBJ_COMPRESS_MASK) { case GRN_OBJ_COMPRESS_ZLIB: if (accept_any_type || need_zlib_check) { grn_obj support_p; GRN_BOOL_INIT(&support_p, 0); grn_obj_get_info(context, NULL, GRN_INFO_SUPPORT_ZLIB, &support_p); compressed_p = GRN_BOOL_VALUE(&support_p); } break; case GRN_OBJ_COMPRESS_LZ4: if (accept_any_type || need_lz4_check) { grn_obj support_p; GRN_BOOL_INIT(&support_p, 0); grn_obj_get_info(context, NULL, GRN_INFO_SUPPORT_LZ4, &support_p); compressed_p = GRN_BOOL_VALUE(&support_p); } break; } return CBOOL2RVAL(compressed_p); }
/* * call-seq: * table.find(key) -> Groonga::Record * * テーブルの_key_に対応するレコードを返す。 * * 0.9.0から非推奨。代わりにtable[key]を使うこと。 */ static VALUE rb_grn_table_key_support_find (VALUE self, VALUE rb_key) { rb_warn("#find is deprecated. Use #[] instead: %s", rb_grn_inspect(self)); return rb_grn_table_key_support_array_reference(self, rb_key); }
VALUE rb_grn_obj_to_ruby_object (VALUE klass, grn_ctx *context, grn_obj *obj, VALUE related_object) { if (!obj) return Qnil; /* if (NIL_P(klass)) */ /* klass = GRNOBJECT2RCLASS(obj); */ switch (obj->header.type) { case GRN_VOID: if (GRN_BULK_VSIZE(obj) > 0) return rb_str_new(GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj)); else return Qnil; break; case GRN_BULK: return GRNBULK2RVAL(context, obj, NULL, related_object); break; /* case GRN_PTR: */ /* case GRN_UVECTOR: */ /* case GRN_PVECTOR: */ case GRN_VECTOR: return GRNVECTOR2RVAL(context, obj); break; /* case GRN_MSG: */ /* case GRN_QUERY: */ /* case GRN_ACCESSOR: */ /* case GRN_SNIP: */ /* case GRN_PATSNIP: */ /* case GRN_CURSOR_TABLE_HASH_KEY: */ /* case GRN_CURSOR_TABLE_PAT_KEY: */ /* case GRN_CURSOR_TABLE_NO_KEY: */ /* case GRN_CURSOR_COLUMN_INDEX: */ /* case GRN_TYPE: */ /* case GRN_PROC: */ /* case GRN_EXPR: */ /* case GRN_TABLE_HASH_KEY: */ /* case GRN_TABLE_PAT_KEY: */ /* case GRN_TABLE_DAT_KEY: */ /* case GRN_TABLE_NO_KEY: */ /* case GRN_DB: */ /* case GRN_COLUMN_FIX_SIZE: */ /* case GRN_COLUMN_VAR_SIZE: */ /* case GRN_COLUMN_INDEX: */ default: rb_raise(rb_eTypeError, "unsupported groonga object: %s(%#x): <%s>", rb_grn_inspect_type(obj->header.type), obj->header.type, rb_grn_inspect(related_object)); break; } return Qnil; }
VALUE rb_grn_value_to_ruby_object (grn_ctx *context, grn_obj *value, grn_obj *range, VALUE related_object) { if (!value) return Qnil; switch (value->header.type) { case GRN_VOID: return Qnil; break; case GRN_BULK: if (GRN_BULK_EMPTYP(value)) return Qnil; if (value->header.domain == GRN_ID_NIL && range) value->header.domain = grn_obj_id(context, range); return GRNBULK2RVAL(context, value, range, related_object); break; case GRN_UVECTOR: { VALUE rb_value, rb_range = Qnil; grn_id *uvector, *uvector_end; rb_value = rb_ary_new(); if (range) rb_range = GRNTABLE2RVAL(context, range, GRN_FALSE); uvector = (grn_id *)GRN_BULK_HEAD(value); uvector_end = (grn_id *)GRN_BULK_CURR(value); for (; uvector < uvector_end; uvector++) { VALUE record = Qnil; if (*uvector != GRN_ID_NIL) record = rb_grn_record_new(rb_range, *uvector, Qnil); rb_ary_push(rb_value, record); } return rb_value; } break; case GRN_VECTOR: return GRNVECTOR2RVAL(context, value); break; default: rb_raise(rb_eGrnError, "unsupported value type: %s(%#x): %s", rb_grn_inspect_type(value->header.type), value->header.type, rb_grn_inspect(related_object)); break; } if (!range) return GRNOBJECT2RVAL(Qnil, context, value, GRN_FALSE); return Qnil; }
grn_obj * rb_grn_uvector_from_ruby_object (VALUE object, grn_ctx *context, grn_obj *uvector, VALUE related_object) { VALUE *values; int i, n; if (NIL_P(object)) return NULL; n = RARRAY_LEN(object); values = RARRAY_PTR(object); for (i = 0; i < n; i++) { VALUE value; grn_id id; void *grn_value; value = values[i]; switch (TYPE(value)) { case T_FIXNUM: id = NUM2UINT(value); break; default: if (rb_respond_to(value, rb_intern("record_raw_id"))) { id = NUM2UINT(rb_funcall(value, rb_intern("record_raw_id"), 0)); } else { grn_obj_unlink(context, uvector); rb_raise(rb_eArgError, "uvector value should be one of " "[Fixnum or object that has #record_raw_id]: " "%s (%s): %s", rb_grn_inspect(value), rb_grn_inspect(object), rb_grn_inspect(related_object)); } break; } grn_value = &id; grn_bulk_write(context, uvector, grn_value, sizeof(grn_id)); } return uvector; }
static VALUE set_value (VALUE args, SetValueData *data) { VALUE rb_name, rb_value, rb_column; RbGrnObject *rb_grn_object; rb_name = rb_ary_entry(args, 0); rb_value = rb_ary_entry(args, 1); rb_column = rb_grn_table_get_column(data->self, rb_name); if (NIL_P(rb_column)) { rb_raise(rb_eGrnNoSuchColumn, "no such column: <%s>: <%s>", rb_grn_inspect(rb_name), rb_grn_inspect(data->self)); } rb_grn_object = RB_GRN_OBJECT(DATA_PTR(rb_column)); return rb_grn_object_set_raw(rb_grn_object, data->id, rb_value, GRN_OBJ_SET, data->self); }
void rb_grn_scan_options (VALUE options, ...) { VALUE available_keys; const char *key; VALUE *value; va_list args; if (NIL_P(options)) options = rb_hash_new(); else options = rb_funcall(options, rb_intern("dup"), 0); Check_Type(options, T_HASH); available_keys = rb_ary_new(); va_start(args, options); key = va_arg(args, const char *); while (key) { VALUE rb_key; value = va_arg(args, VALUE *); rb_key = RB_GRN_INTERN(key); rb_ary_push(available_keys, rb_key); *value = rb_funcall(options, rb_intern("delete"), 1, rb_key); key = va_arg(args, const char *); } va_end(args); if (RVAL2CBOOL(rb_funcall(options, rb_intern("empty?"), 0))) return; rb_raise(rb_eArgError, "unexpected key(s) exist: %s: available keys: %s", rb_grn_inspect(rb_funcall(options, rb_intern("keys"), 0)), rb_grn_inspect(available_keys)); }
static VALUE rb_grn_table_key_support_set_value_by_key (VALUE self, VALUE rb_key, VALUE rb_value) { grn_ctx *context; grn_obj *table; grn_id id; grn_obj *value; grn_rc rc; if (NIL_P(rb_key)) { rb_raise(rb_eArgError, "key should not be nil: <%s>", rb_grn_inspect(self)); } rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, &value, NULL, NULL, NULL); id = rb_grn_table_key_support_add_raw(self, rb_key, NULL); if (GRN_ID_NIL == id) { rb_raise(rb_eGrnError, "failed to add new record with key: <%s>: <%s>", rb_grn_inspect(rb_key), rb_grn_inspect(self)); } GRN_BULK_REWIND(value); RVAL2GRNBULK(rb_value, context, value); rc = grn_obj_set_value(context, table, id, value, GRN_OBJ_SET); rb_grn_context_check(context, self); rb_grn_rc_check(rc, self); return rb_value; }
void rb_grn_rc_check (grn_rc rc, VALUE related_object) { VALUE exception; const char *message; exception = rb_grn_rc_to_exception(rc); if (NIL_P(exception)) return; message = rb_grn_rc_to_message(rc); if (NIL_P(related_object)) rb_raise(exception, "%s", message); else rb_raise(exception, "%s: %s", rb_grn_inspect(related_object), message); }
/* * call-seq: * snippet.execute(string) -> スニペットの配列 * * _string_を走査し、スニペットを作成する。 */ static VALUE rb_grn_snippet_execute (VALUE self, VALUE rb_string) { RbGrnSnippet *rb_grn_snippet; grn_rc rc; grn_ctx *context; grn_snip *snippet; char *string; unsigned int string_length; unsigned int i, n_results, max_tagged_length; VALUE rb_results; char *result; if (TYPE(rb_string) != T_STRING) { rb_raise(rb_eGrnInvalidArgument, "snippet text must be String: <%s>", rb_grn_inspect(rb_string)); } rb_grn_snippet = SELF(self); context = rb_grn_snippet->context; snippet = rb_grn_snippet->snippet; #ifdef HAVE_RUBY_ENCODING_H rb_string = rb_grn_context_rb_string_encode(context, rb_string); #endif string = StringValuePtr(rb_string); string_length = RSTRING_LEN(rb_string); rc = grn_snip_exec(context, snippet, string, string_length, &n_results, &max_tagged_length); rb_grn_rc_check(rc, self); rb_results = rb_ary_new2(n_results); result = ALLOCA_N(char, max_tagged_length); for (i = 0; i < n_results; i++) { VALUE rb_result; unsigned result_length; rc = grn_snip_get_result(context, snippet, i, result, &result_length); rb_grn_rc_check(rc, self); rb_result = rb_grn_context_rb_string_new(context, result, result_length); rb_ary_push(rb_results, rb_result); } return rb_results; }
int rb_grn_table_cursor_order_to_flag (VALUE rb_order) { int flag = 0; if (NIL_P(rb_order) || rb_grn_equal_option(rb_order, "asc") || rb_grn_equal_option(rb_order, "ascending")) { flag |= GRN_CURSOR_ASCENDING; } else if (rb_grn_equal_option(rb_order, "desc") || rb_grn_equal_option(rb_order, "descending")) { flag |= GRN_CURSOR_DESCENDING; } else { rb_raise(rb_eArgError, "order should be one of " "[:asc, :ascending, :desc, :descending]: %s", rb_grn_inspect(rb_order)); } return flag; }
VALUE rb_grn_value_to_ruby_object (grn_ctx *context, grn_obj *value, grn_obj *range, VALUE related_object) { if (!value) return Qnil; switch (value->header.type) { case GRN_VOID: return Qnil; break; case GRN_BULK: if (GRN_BULK_EMPTYP(value)) return Qnil; if (value->header.domain == GRN_ID_NIL && range) value->header.domain = grn_obj_id(context, range); return GRNBULK2RVAL(context, value, range, related_object); break; case GRN_UVECTOR: return GRNUVECTOR2RVAL(context, value, range, related_object); break; case GRN_VECTOR: return GRNVECTOR2RVAL(context, value); break; default: rb_raise(rb_eGrnError, "unsupported value type: %s(%#x): %s", rb_grn_inspect_type(value->header.type), value->header.type, rb_grn_inspect(related_object)); break; } if (!range) return GRNOBJECT2RVAL(Qnil, context, value, GRN_FALSE); return Qnil; }
static grn_log_level rb_grn_log_level_from_ruby_object (VALUE rb_level) { grn_log_level level = GRN_LOG_NONE; if (NIL_P(rb_level)) { level = GRN_LOG_DEFAULT_LEVEL; } else if (rb_grn_equal_option(rb_level, "none")) { level = GRN_LOG_NONE; } else if (rb_grn_equal_option(rb_level, "emergency")) { level = GRN_LOG_EMERG; } else if (rb_grn_equal_option(rb_level, "alert")) { level = GRN_LOG_ALERT; } else if (rb_grn_equal_option(rb_level, "critical")) { level = GRN_LOG_CRIT; } else if (rb_grn_equal_option(rb_level, "error")) { level = GRN_LOG_ERROR; } else if (rb_grn_equal_option(rb_level, "warning")) { level = GRN_LOG_WARNING; } else if (rb_grn_equal_option(rb_level, "notice")) { level = GRN_LOG_NOTICE; } else if (rb_grn_equal_option(rb_level, "info")) { level = GRN_LOG_INFO; } else if (rb_grn_equal_option(rb_level, "debug")) { level = GRN_LOG_DEBUG; } else if (rb_grn_equal_option(rb_level, "dump")) { level = GRN_LOG_DUMP; } else { rb_raise(rb_eArgError, "log level should be one of " "[nil, :none, :emergency, :alert, :critical, :error, " ":warning, :notice, :info, :debug, :dump]: %s", rb_grn_inspect(rb_level)); } return level; }
/* * call-seq: * context[name] -> Groonga::Object or nil * context[id] -> Groonga::Object or nil * * コンテキスト管理下にあるオブジェクトを返す。 * * _name_として文字列を指定した場合はオブジェクト名でオブジェ * クトを検索する。 * * _id_として数値を指定した場合はオブジェクトIDでオブジェク * トを検索する。 */ static VALUE rb_grn_context_array_reference (VALUE self, VALUE name_or_id) { grn_ctx *context; grn_obj *object; const char *name; unsigned int name_size; grn_id id; context = SELF(self); switch (TYPE(name_or_id)) { case T_SYMBOL: name = rb_id2name(SYM2ID(name_or_id)); name_size = strlen(name); object = rb_grn_context_get_backward_compatibility(context, name, name_size); break; case T_STRING: name = StringValuePtr(name_or_id); name_size = RSTRING_LEN(name_or_id); object = rb_grn_context_get_backward_compatibility(context, name, name_size); break; case T_FIXNUM: id = NUM2UINT(name_or_id); object = grn_ctx_at(context, id); break; default: rb_raise(rb_eArgError, "should be String, Symbol or unsigned integer: %s", rb_grn_inspect(name_or_id)); break; } return GRNOBJECT2RVAL(Qnil, context, object, RB_GRN_FALSE); }
/* FIXME: DON'T WORK!!! */ static VALUE rb_grn_view_sort (int argc, VALUE *argv, VALUE self) { VALUE rb_result = Qnil; #ifdef WIN32 rb_raise(rb_eNotImpError, "grn_view_add() isn't available on Windows."); #else grn_ctx *context = NULL; grn_obj *view; grn_obj *result; grn_table_sort_key *keys; int i, n_keys; int n_records, offset = 0, limit = -1; VALUE rb_keys, options; VALUE rb_offset, rb_limit; VALUE *rb_sort_keys; grn_table_cursor *cursor; VALUE exception; grn_obj id; rb_grn_table_deconstruct(SELF(self), &view, &context, NULL, NULL, NULL, NULL, NULL, NULL); rb_scan_args(argc, argv, "11", &rb_keys, &options); if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_keys, rb_cArray))) rb_raise(rb_eArgError, "keys should be an array of key: <%s>", rb_grn_inspect(rb_keys)); n_keys = RARRAY_LEN(rb_keys); rb_sort_keys = RARRAY_PTR(rb_keys); keys = ALLOCA_N(grn_table_sort_key, n_keys); for (i = 0; i < n_keys; i++) { VALUE rb_sort_options, rb_key, rb_resolved_key, rb_order; if (RVAL2CBOOL(rb_obj_is_kind_of(rb_sort_keys[i], rb_cHash))) { rb_sort_options = rb_sort_keys[i]; } else if (RVAL2CBOOL(rb_obj_is_kind_of(rb_sort_keys[i], rb_cArray))) { rb_sort_options = rb_hash_new(); rb_hash_aset(rb_sort_options, RB_GRN_INTERN("key"), rb_ary_entry(rb_sort_keys[i], 0)); rb_hash_aset(rb_sort_options, RB_GRN_INTERN("order"), rb_ary_entry(rb_sort_keys[i], 1)); } else { rb_sort_options = rb_hash_new(); rb_hash_aset(rb_sort_options, RB_GRN_INTERN("key"), rb_sort_keys[i]); } rb_grn_scan_options(rb_sort_options, "key", &rb_key, "order", &rb_order, NULL); if (RVAL2CBOOL(rb_obj_is_kind_of(rb_key, rb_cString))) { rb_resolved_key = rb_grn_table_get_column(self, rb_key); } else { rb_resolved_key = rb_key; } keys[i].key = RVAL2GRNOBJECT(rb_resolved_key, &context); if (!keys[i].key) { rb_raise(rb_eGrnNoSuchColumn, "no such column: <%s>: <%s>", rb_grn_inspect(rb_key), rb_grn_inspect(self)); } if (NIL_P(rb_order)) { keys[i].flags = 0; } else if (rb_grn_equal_option(rb_order, "desc") || rb_grn_equal_option(rb_order, "descending")) { keys[i].flags = GRN_TABLE_SORT_DESC; } else if (rb_grn_equal_option(rb_order, "asc") || rb_grn_equal_option(rb_order, "ascending")) { keys[i].flags = GRN_TABLE_SORT_ASC; } else { rb_raise(rb_eArgError, "order should be one of " "[nil, :desc, :descending, :asc, :ascending]: %s", rb_grn_inspect(rb_order)); } } rb_grn_scan_options(options, "offset", &rb_offset, "limit", &rb_limit, NULL); if (!NIL_P(rb_offset)) offset = NUM2INT(rb_offset); if (!NIL_P(rb_limit)) limit = NUM2INT(rb_limit); result = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_VIEW, NULL, NULL); grn_view_add(context, result, grn_table_create(context, NULL, 0, NULL, GRN_TABLE_NO_KEY, NULL, grn_ctx_get(context, "People", strlen("People")))); grn_view_add(context, result, grn_table_create(context, NULL, 0, NULL, GRN_TABLE_NO_KEY, NULL, grn_ctx_get(context, "People", strlen("People")))); n_records = grn_table_sort(context, view, offset, limit, result, keys, n_keys); exception = rb_grn_context_to_exception(context, self); if (!NIL_P(exception)) { grn_obj_unlink(context, result); rb_exc_raise(exception); } rb_result = rb_ary_new(); cursor = grn_table_cursor_open(context, result, NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_ASCENDING); GRN_TEXT_INIT(&id, 0); while (grn_table_cursor_next_o(context, cursor, &id) == GRN_SUCCESS) { rb_ary_push(rb_result, rb_grn_view_record_new(self, &id)); } GRN_OBJ_FIN(context, &id); grn_table_cursor_close(context, cursor); grn_obj_unlink(context, result); #endif return rb_result; }
/* * call-seq: * column.select(options) {|record| ...} -> Groonga::Hash * column.select(query, options) -> Groonga::Hash * column.select(expression, options) -> Groonga::Hash * * カラムが所属するテーブルからブロックまたは文字列で指定し * た条件にマッチするレコードを返す。返されたテーブルには * +expression+という特異メソッドがあり、指定した条件を表し * ているGroonga::Expressionを取得できる。 * Groonga::Expression#snippetを使うことにより、指定した条件 * 用のスニペットを簡単に生成できる。 * * results = description_column.select do |column| * column =~ "groonga" * end * snippet = results.expression.snippet([["<em>", "</em>"]]) * results.each do |record| * puts "#{record['name']}の説明文の中で「groonga」が含まれる部分" * snippet.execute(record["description"].each do |snippet| * puts "---" * puts "#{snippet}..." * puts "---" * end * end * * 出力例 * Ruby/groongaの説明文の中で「groonga」が含まれる部分 * --- * Ruby/<em>groonga</em>は<em>groonga</em>のいわゆるDB-APIの層の... * --- * * _query_には「[カラム名]:[演算子][値]」という書式で条件を * 指定する。演算子は以下の通り。 * * [なし] * [カラム値] == [値] * [<tt>!</tt>] * [カラム値] != [値] * [<tt><</tt>] * [カラム値] < [値] * [<tt>></tt>] * [カラム値] > [値] * [<tt><=</tt>] * [カラム値] <= [値] * [<tt>>=</tt>] * [カラム値] >= [値] * [<tt>@</tt>] * [カラム値]が[値]を含んでいるかどうか * * 例: * "groonga" # _column_カラムの値が"groonga"のレコードにマッチ * "name:daijiro" # _column_カラムが属しているテーブルの * # "name"カラムの値が"daijiro"のレコードにマッチ * "description:@groonga" # _column_カラムが属しているテーブルの * # "description"カラムが * # "groonga"を含んでいるレコードにマッチ * * _expression_には既に作成済みのGroonga::Expressionを渡す * * ブロックで条件を指定する場合は * Groonga::ColumnExpressionBuilderを参照。 * * _options_に指定可能な値は以下の通り。 * * [+:operator+] * マッチしたレコードをどのように扱うか。指定可能な値は以 * 下の通り。省略した場合はGroonga::Operation::OR。 * * [Groonga::Operation::OR] * マッチしたレコードを追加。すでにレコードが追加され * ている場合は何もしない。 * [Groonga::Operation::AND] * マッチしたレコードのスコアを増加。マッチしなかった * レコードを削除。 * [Groonga::Operation::BUT] * マッチしたレコードを削除。 * [Groonga::Operation::ADJUST] * マッチしたレコードのスコアを増加。 * * [+:result+] * 検索結果を格納するテーブル。マッチしたレコードが追加さ * れていく。省略した場合は新しくテーブルを作成して返す。 * * [+:name+] * 条件の名前。省略した場合は名前を付けない。 * * [+:syntax+] * _query_の構文。省略した場合は+:query+。 * * 参考: Groonga::Expression#parse. * * [+:allow_pragma+] * query構文時にプラグマを利用するかどうか。省略した場合は * 利用する。 * * 参考: Groonga::Expression#parse. * * [+:allow_column+] * query構文時にカラム指定を利用するかどうか。省略した場合 * は利用する。 * * 参考: Groonga::Expression#parse. * * [+:allow_update+] * script構文時に更新操作を利用するかどうか。省略した場合 * は利用する。 * * 参考: Groonga::Expression#parse. */ static VALUE rb_grn_column_select (int argc, VALUE *argv, VALUE self) { grn_ctx *context; grn_obj *table, *column, *result, *expression; grn_operator operator = GRN_OP_OR; VALUE options; VALUE rb_query, condition_or_options; VALUE rb_name, rb_operator, rb_result, rb_syntax; VALUE rb_allow_pragma, rb_allow_column, rb_allow_update; VALUE builder; VALUE rb_expression = Qnil; rb_query = Qnil; rb_scan_args(argc, argv, "02", &condition_or_options, &options); rb_grn_column_deconstruct(SELF(self), &column, &context, NULL, NULL, NULL, NULL, NULL); table = grn_column_table(context, column); if (RVAL2CBOOL(rb_obj_is_kind_of(condition_or_options, rb_cString))) { rb_query = condition_or_options; } else if (RVAL2CBOOL(rb_obj_is_kind_of(condition_or_options, rb_cGrnExpression))) { rb_expression = condition_or_options; } else { if (!NIL_P(options)) rb_raise(rb_eArgError, "should be [query_string, option_hash], " "[expression, option_hash] " "or [option_hash]: %s", rb_grn_inspect(rb_ary_new4(argc, argv))); options = condition_or_options; } rb_grn_scan_options(options, "operator", &rb_operator, "result", &rb_result, "name", &rb_name, "syntax", &rb_syntax, "allow_pragma", &rb_allow_pragma, "allow_column", &rb_allow_column, "allow_update", &rb_allow_update, NULL); if (!NIL_P(rb_operator)) operator = NUM2INT(rb_operator); if (NIL_P(rb_result)) { result = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC, table, 0); rb_result = GRNTABLE2RVAL(context, result, RB_GRN_TRUE); } else { result = RVAL2GRNTABLE(rb_result, &context); } if (NIL_P(rb_expression)) { builder = rb_grn_column_expression_builder_new(self, rb_name, rb_query); rb_funcall(builder, rb_intern("syntax="), 1, rb_syntax); rb_funcall(builder, rb_intern("allow_pragma="), 1, rb_allow_pragma); rb_funcall(builder, rb_intern("allow_column="), 1, rb_allow_column); rb_funcall(builder, rb_intern("allow_update="), 1, rb_allow_update); rb_expression = rb_grn_column_expression_builder_build(builder); } rb_grn_object_deconstruct(RB_GRN_OBJECT(DATA_PTR(rb_expression)), &expression, NULL, NULL, NULL, NULL, NULL); grn_table_select(context, table, expression, result, operator); rb_grn_context_check(context, self); rb_attr(rb_singleton_class(rb_result), rb_intern("expression"), RB_GRN_TRUE, RB_GRN_FALSE, RB_GRN_FALSE); rb_iv_set(rb_result, "@expression", rb_expression); return rb_result; }