Пример #1
0
/*
 * Document-method: reference?
 *
 * call-seq:
 *   column.reference? -> true/false
 *
 * _column_ の値がテーブルのレコードとなる場合は +true+ を返し、
 * そうでない場合は +false+ を返す。
 *
 * @since 1.0.5
 */
static VALUE
rb_grn_column_reference_p (VALUE self)
{
    grn_ctx *context;
    grn_obj *column;
    grn_id range_id;
    grn_obj *range;
    unsigned short int type;

    rb_grn_column_deconstruct(SELF(self), &column, &context,
			     NULL, NULL,
			     NULL, NULL, NULL);

    range_id = grn_obj_get_range(context, column);
    range = grn_ctx_at(context, range_id);
    type = range->header.type;
    grn_obj_unlink(context, range);
    switch (type) {
      case GRN_TABLE_HASH_KEY:
      case GRN_TABLE_PAT_KEY:
      case GRN_TABLE_NO_KEY:
	return Qtrue;
      default:
	return Qfalse;
    }
}
Пример #2
0
/*
 * Document-method: clear_lock
 *
 * call-seq:
 *   column.clear_lock(options={})
 *
 * _column_のロックを強制的に解除する。
 *
 * 利用可能なオプションは以下の通り。
 *
 * [_:id_]
 *   _:id_で指定したレコードのロックを強制的に解除する。
 *   (注: groonga側が未実装のため、現在は無視される。実装さ
 *   れるのではないかと思っているが、実装されないかもしれな
 *   い。)
 */
static VALUE
rb_grn_column_clear_lock (int argc, VALUE *argv, VALUE self)
{
    grn_id id = GRN_ID_NIL;
    grn_ctx *context;
    grn_obj *column;
    VALUE options, rb_id;

    rb_scan_args(argc, argv, "01",  &options);

    rb_grn_column_deconstruct(SELF(self), &column, &context,
			     NULL, NULL,
			     NULL, NULL, NULL);

    rb_grn_scan_options(options,
			"id", &rb_id,
			NULL);

    if (!NIL_P(rb_id))
	id = NUM2UINT(rb_id);

    grn_obj_clear_lock(context, column);

    return Qnil;
}
Пример #3
0
void
rb_grn_index_column_deconstruct (RbGrnIndexColumn *rb_grn_index_column,
                                 grn_obj **column,
                                 grn_ctx **context,
                                 grn_id *domain_id,
                                 grn_obj **domain,
                                 grn_obj **value,
                                 grn_obj **old_value,
                                 grn_id *range_id,
                                 grn_obj **range,
                                 grn_obj **id_query,
                                 grn_obj **string_query)
{
    RbGrnObject *rb_grn_object;

    rb_grn_object = RB_GRN_OBJECT(rb_grn_index_column);
    rb_grn_column_deconstruct(RB_GRN_COLUMN(rb_grn_object), column, context,
                              domain_id, domain, value,
                              range_id, range);

    if (old_value)
        *old_value = rb_grn_index_column->old_value;
    if (id_query)
        *id_query = rb_grn_index_column->id_query;
    if (string_query)
        *string_query = rb_grn_index_column->string_query;
}
Пример #4
0
/*
 * Document-method: index?
 *
 * call-seq:
 *   column.index? -> true/false
 *
 * _column_ がGroonga::IndexColumnの場合は +true+ を返し、
 * そうでない場合は +false+ を返す。
 *
 * @since 1.0.5
 */
static VALUE
rb_grn_column_index_p (VALUE self)
{
    grn_ctx *context;
    grn_obj *column;

    rb_grn_column_deconstruct(SELF(self), &column, &context,
			     NULL, NULL,
			     NULL, NULL, NULL);

    if (column->header.type == GRN_COLUMN_INDEX) {
	return Qtrue;
    } else {
	return Qfalse;
    }
}
Пример #5
0
/*
 * Document-method: vector?
 *
 * call-seq:
 *   column.vector? -> true/false
 *
 * _column_ がベクターカラムの場合は +true+ を返し、
 * そうでない場合は +false+ を返す。
 *
 * @since 1.0.5
 */
static VALUE
rb_grn_column_vector_p (VALUE self)
{
    grn_ctx *context;
    grn_obj *column;

    rb_grn_column_deconstruct(SELF(self), &column, &context,
			     NULL, NULL,
			     NULL, NULL, NULL);

    if (column->header.type == GRN_COLUMN_VAR_SIZE &&
	((column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) ==
	 GRN_OBJ_COLUMN_VECTOR)) {
	return Qtrue;
    } else {
	return Qfalse;
    }
}
Пример #6
0
static void
rb_grn_variable_size_column_deconstruct (RbGrnVariableSizeColumn *rb_column,
                                         grn_obj **column,
                                         grn_ctx **context,
                                         grn_id *domain_id,
                                         grn_obj **domain,
                                         grn_obj **value,
                                         grn_obj **element_value,
                                         grn_id *range_id,
                                         grn_obj **range)
{
    RbGrnColumn *rb_grn_column;

    rb_grn_column = RB_GRN_COLUMN(rb_column);
    rb_grn_column_deconstruct(rb_grn_column, column, context,
                              domain_id, domain, value,
                              range_id, range);

    if (element_value)
        *element_value = rb_column->element_value;
}
Пример #7
0
/*
 * Document-method: rename
 *
 * call-seq:
 *   table.rename(name)
 *
 * Renames the table to name.
 *
 * @param name [String] the new name
 * @since 1.3.0
 */
static VALUE
rb_grn_column_rename (VALUE self, VALUE rb_name)
{
    int rc;
    grn_ctx *context;
    grn_obj *column;
    char *name;
    int name_size;

    rb_grn_column_deconstruct(SELF(self), &column, &context,
			      NULL, NULL,
			      NULL, NULL, NULL);

    name = StringValueCStr(rb_name);
    name_size = RSTRING_LEN(rb_name);

    rc = grn_column_rename(context, column, name, name_size);
    rb_grn_context_check(context, self);
    rb_grn_rc_check(rc, self);

    return self;
}
Пример #8
0
/*
 * Document-method: indexes
 *
 * call-seq:
 *   column.indexes(operator=Groonga::Operator::MATCH) -> [index_column, ...]
 *
 * _operation_ を実行できる _column_ のインデックスを返す。
 *
 * @since 1.0.9
 */
static VALUE
rb_grn_column_get_indexes (int argc, VALUE *argv, VALUE self)
{
    grn_ctx *context;
    grn_obj *column;
    grn_obj **indexes = NULL;
    int i, n_indexes;
    grn_operator operator = GRN_OP_MATCH;
    VALUE rb_operator, rb_indexes;

    rb_scan_args(argc, argv, "01", &rb_operator);

    rb_grn_column_deconstruct(SELF(self), &column, &context,
			     NULL, NULL,
			     NULL, NULL, NULL);

    if (!NIL_P(rb_operator)) {
	operator = RVAL2GRNOPERATOR(rb_operator);
    }

    rb_indexes = rb_ary_new();
    n_indexes = grn_column_index(context, column, operator,
				 NULL, 0, NULL);
    if (n_indexes == 0)
	return rb_indexes;

    indexes = xmalloc(sizeof(grn_obj *) * n_indexes);
    n_indexes = grn_column_index(context, column, operator,
				 indexes, n_indexes, NULL);
    for (i = 0; i < n_indexes; i++) {
	VALUE rb_index;
	rb_index = GRNOBJECT2RVAL(Qnil, context, indexes[i], GRN_FALSE);
	rb_ary_push(rb_indexes, rb_index);
	grn_obj_unlink(context, indexes[i]);
    }
    xfree(indexes);
    return rb_indexes;
}
Пример #9
0
/*
 * Document-method: lock
 *
 * call-seq:
 *   column.lock(options={})
 *   column.lock(options={}) {...}
 *
 * _column_をロックする。ロックに失敗した場合は
 * Groonga::ResourceDeadlockAvoided例外が発生する。
 *
 * ブロックを指定した場合はブロックを抜けたときにunlockする。
 *
 * 利用可能なオプションは以下の通り。
 *
 * [_:timeout_]
 *   ロックを獲得できなかった場合は_:timeout_秒間ロックの獲
 *   得を試みる。_:timeout_秒以内にロックを獲得できなかった
 *   場合は例外が発生する。
 * [_:id_]
 *   _:id_で指定したレコードをロックする。(注: groonga側が
 *   未実装のため、現在は無視される)
 */
static VALUE
rb_grn_column_lock (int argc, VALUE *argv, VALUE self)
{
    grn_id id = GRN_ID_NIL;
    grn_ctx *context;
    grn_obj *column;
    int timeout = 0;
    grn_rc rc;
    VALUE options, rb_timeout, rb_id;

    rb_scan_args(argc, argv, "01",  &options);

    rb_grn_column_deconstruct(SELF(self), &column, &context,
			     NULL, NULL,
			     NULL, NULL, NULL);

    rb_grn_scan_options(options,
			"timeout", &rb_timeout,
			"id", &rb_id,
			NULL);

    if (!NIL_P(rb_timeout))
	timeout = NUM2UINT(rb_timeout);

    if (!NIL_P(rb_id))
	id = NUM2UINT(rb_id);

    rc = grn_obj_lock(context, column, id, timeout);
    rb_grn_context_check(context, self);
    rb_grn_rc_check(rc, self);

    if (rb_block_given_p()) {
	return rb_ensure(rb_yield, Qnil, rb_grn_column_unlock_ensure, self);
    } else {
	return Qnil;
    }
}
Пример #10
0
/*
 * Document-method: scalar?
 *
 * call-seq:
 *   column.scalar? -> true/false
 *
 * _column_ がスカラーカラムの場合は +true+ を返し、
 * そうでない場合は +false+ を返す。
 *
 * @since 1.0.5
 */
static VALUE
rb_grn_column_scalar_p (VALUE self)
{
    grn_ctx *context;
    grn_obj *column;

    rb_grn_column_deconstruct(SELF(self), &column, &context,
			     NULL, NULL,
			     NULL, NULL, NULL);

    switch (column->header.type) {
      case GRN_COLUMN_FIX_SIZE:
	return Qtrue;
      case GRN_COLUMN_VAR_SIZE:
	if ((column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) ==
	    GRN_OBJ_COLUMN_SCALAR) {
	    return Qtrue;
	} else {
	    return Qfalse;
	}
      default:
	return Qfalse;
    }
}
Пример #11
0
/*
 * 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;
}