/* * _constant_ を追加し、 _n_arguments_ 個の引数を取る _operation_ を追加する。 * * @overload append_constant(constant, operation=Groonga::Operator::PUSH, n_arguments=1) * @param [Object] constant 追加する _constant_ * @param [Groonga::Operator::XXX] operation 追加する _operation_ * @param [Integer] n_arguments _operation_ の取る引数 * @return [Self] self */ static VALUE rb_grn_expression_append_constant (int argc, VALUE *argv, VALUE self) { VALUE rb_constant, rb_operator, rb_n_arguments; VALUE exception; grn_ctx *context = NULL; grn_obj *expression, *constant = NULL; grn_operator operator = GRN_OP_PUSH; int n_arguments = 1; rb_scan_args(argc, argv, "12", &rb_constant, &rb_operator, &rb_n_arguments); if (!NIL_P(rb_operator)) operator = RVAL2GRNOPERATOR(rb_operator); if (!NIL_P(rb_n_arguments)) n_arguments = NUM2INT(rb_n_arguments); rb_grn_expression_deconstruct(SELF(self), &expression, &context, NULL, NULL, NULL, NULL, NULL); RVAL2GRNOBJ(rb_constant, context, &constant); grn_expr_append_const(context, expression, constant, operator, n_arguments); exception = rb_grn_context_to_exception(context, self); grn_obj_unlink(context, constant); if (!NIL_P(exception)) rb_exc_raise(exception); return self; }
/* * データベース内のオブジェクトを順番にブロックに渡す。 * * @example すべてのオブジェクトの名前を表示する: * database.each do |object| * p object.name * end * * @example すべてのオブジェクトの名前をID順で表示する: * database.each(:order_by => :id) do |object| * p object.name * end * * @example すべてのオブジェクトの名前をキー名の降順で表示する: * database.each(:order_by => :key, :order => :desc) do |object| * p object.name * end * * @overload each(options=nil) * @macro [new] database.each.options * @param options [::Hash] * @yield [object] * @option options :order * +:asc+ または +:ascending+ を指定すると昇順にレコードを取 * り出す。(デフォルト) * +:desc+ または +:descending+ を指定すると降順にレコードを * 取り出す。 * @option options :order_by (:key) * +:id+ を指定するとID順にレコードを取り出す。 * +:key+ 指定するとキー順にレコードを取り出す。(デフォル * ト) * @macro database.each.options * * @overload each(options=nil) * @macro database.each.options * @option options :ignore_missing_object (false) * Specify +true+ to ignore missing object. Otherwise, an exception is * raised for missing object. * * @since 2.0.5 */ static VALUE rb_grn_database_each (int argc, VALUE *argv, VALUE self) { grn_ctx *context = NULL; grn_obj *database; grn_table_cursor *cursor; VALUE rb_cursor, rb_options, rb_order, rb_order_by; VALUE rb_ignore_missing_object; int flags = 0; grn_id id; VALUE exception; RETURN_ENUMERATOR(self, argc, argv); rb_grn_database_deconstruct(SELF(self), &database, &context, NULL, NULL, NULL, NULL); rb_scan_args(argc, argv, "01", &rb_options); rb_grn_scan_options(rb_options, "order", &rb_order, "order_by", &rb_order_by, "ignore_missing_object", &rb_ignore_missing_object, NULL); flags |= rb_grn_table_cursor_order_to_flag(rb_order); flags |= rb_grn_table_cursor_order_by_to_flag(GRN_TABLE_PAT_KEY, self, rb_order_by); cursor = grn_table_cursor_open(context, database, NULL, 0, NULL, 0, 0, -1, flags); rb_cursor = GRNTABLECURSOR2RVAL(Qnil, context, cursor); rb_iv_set(self, "cursor", rb_cursor); while ((id = grn_table_cursor_next(context, cursor)) != GRN_ID_NIL) { grn_obj *object; object = grn_ctx_at(context, id); if (!object && RTEST(rb_ignore_missing_object)) { context->rc = GRN_SUCCESS; continue; } exception = rb_grn_context_to_exception(context, self); if (!NIL_P(exception)) { rb_grn_object_close(rb_cursor); rb_iv_set(self, "cursor", Qnil); rb_exc_raise(exception); } if (object) { rb_yield(GRNOBJECT2RVAL(Qnil, context, object, GRN_FALSE)); } } rb_grn_object_close(rb_cursor); rb_iv_set(self, "cursor", Qnil); return Qnil; }
void rb_grn_context_check (grn_ctx *context, VALUE related_object) { VALUE exception; exception = rb_grn_context_to_exception(context, related_object); if (NIL_P(exception)) return; rb_exc_raise(exception); }
/* * インデックス対象となっている {Groonga::Column} の配列を返す。 * * @overload sources * @return [::Array<Groonga::Column>] */ static VALUE rb_grn_index_column_get_sources (VALUE self) { grn_ctx *context = NULL; grn_obj *column; grn_obj sources; grn_id *source_ids; VALUE rb_sources; int i, n; VALUE exception; rb_grn_index_column_deconstruct(SELF(self), &column, &context, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); GRN_OBJ_INIT(&sources, GRN_BULK, 0, GRN_ID_NIL); grn_obj_get_info(context, column, GRN_INFO_SOURCE, &sources); rb_grn_context_check(context, self); n = GRN_BULK_VSIZE(&sources) / sizeof(grn_id); source_ids = (grn_id *)GRN_BULK_HEAD(&sources); rb_sources = rb_ary_new2(n); for (i = 0; i < n; i++) { grn_obj *source; VALUE rb_source; source = grn_ctx_at(context, *source_ids); exception = rb_grn_context_to_exception(context, self); if (!NIL_P(exception)) { grn_obj_unlink(context, &sources); rb_exc_raise(exception); } rb_source = GRNOBJECT2RVAL(Qnil, context, source, GRN_FALSE); rb_ary_push(rb_sources, rb_source); source_ids++; } grn_obj_unlink(context, &sources); return rb_sources; }
/* * インデックス対象となる複数のカラムを配列で設定する。 * * @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; }
/* 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; }
/* * 文字列 _query_ をパースする。 * @overload parse(query, options={}) * @param [String] query パースする文字列 * @param [::Hash] options The name and value * pairs. Omitted names are initialized as the default value. * @option options :default_column * "column_name:hoge"ではなく"hoge"のようにcolumn_nameが指 * 定されない条件の検索対象となるカラムを指定する。 * @option options :default_operator (Groonga::Operator::AND) * "+"や"OR"で繋がれず、ただ列挙された複数の条件があった時、 * _expression_ 全体として各レコードをヒットとみなすかの論理 * 条件を指定する。省略した場合はGroonga::Operator::AND。 * * - Groonga::Operator::OR := * レコードはいずれかの条件にマッチすればいい。 =: * - Groonga::Operator::AND := * レコードは全ての条件にマッチしなければならない。 =: * - Groonga::Operator::AND_NOT := * 最初の条件にレコードはマッチし、残りの条件にレコードは * マッチしてはならない。 =: * * @option options :default_mode (Groonga::Operator::MATCH) * 検索時のモードを指定する。省略した場合はGroonga::Operator::MATCH。 * (FIXME: モードによってどういう動作になるかを書く。) * @option options :syntax (:query) * _query_ の構文を指定する。指定可能な値は以下の通り。省略 * した場合は +:query+ 。 * * - +:query+ := * 「文字列1 OR 文字列2」で「"文字列1"あるいは"文字列2" * にマッチという検索エンジンで利用できるような構文を使 * う。 * 参考: "Groongaのクエリ構文のドキュメント":http://groonga.org/ja/docs/reference/grn_expr/query_syntax.html =: * - +nil+ := * +:query+と同様 =: * - +:script+ := * 「[カラム名] == [値]」というようにECMAScript風の構文を使う。 * 参考: "Groongaのscript構文のドキュメント":http://groonga.org/ja/docs/reference/grn_expr/script_syntax.html =: * @option options :allow_pragma * _query_ の構文に query を用いているとき( +:syntax+ * オプション参照)、「*E-1」というようにクエリの先頭で * pragmaを利用できるようにする。script構文を用いている * ときはこのオプションを利用できない。 * * デフォルトではプラグマを利用できる。 * * 参考: "Groongaのクエリ構文のドキュメント":http://groonga.org/ja/docs/reference/grn_expr/query_syntax.html * @option options :allow_column * _query_ の構文にqueryを用いているとき( +:syntax+ オプショ * ン参照)、「カラム名:値」というようにカラム名を指定した * 条件式を利用できるようにする。script構文を用いていると * きはこのオプションを利用できない。 * * デフォルトではカラム名を指定した条件式を利用できる。 * * 参考: "Groongaのクエリ構文のドキュメント":http://groonga.org/ja/docs/reference/grn_expr/query_syntax.html * @option options :allow_update * _query_ の構文にscriptを用いているとき( +:syntax+ オプショ * ン参照)、「カラム名 = 値」というように更新操作を利用で * きるようにする。query構文を用いているときはこのオプショ * ンを利用できない。 * * デフォルトでは更新操作を利用できる。 * * 参考: "Groongaのクエリ構文のドキュメント":http://groonga.org/ja/docs/reference/grn_expr/query_syntax.html */ static VALUE rb_grn_expression_parse (int argc, VALUE *argv, VALUE self) { grn_ctx *context = NULL; grn_obj *expression, *default_column; grn_bool default_column_is_created = GRN_FALSE; grn_operator default_operator = GRN_OP_AND; grn_operator default_mode = GRN_OP_MATCH; grn_rc rc; char *query = NULL; unsigned query_size = 0; grn_expr_flags flags = 0; VALUE options, rb_query, rb_default_column, rb_default_operator; VALUE rb_default_mode, rb_syntax; VALUE rb_allow_pragma, rb_allow_column, rb_allow_update, rb_allow_leading_not; VALUE exception = Qnil; rb_scan_args(argc, argv, "11", &rb_query, &options); rb_grn_scan_options(options, "default_column", &rb_default_column, "default_operator", &rb_default_operator, "default_mode", &rb_default_mode, "syntax", &rb_syntax, "allow_pragma", &rb_allow_pragma, "allow_column", &rb_allow_column, "allow_update", &rb_allow_update, "allow_leading_not", &rb_allow_leading_not, NULL); query = StringValuePtr(rb_query); query_size = RSTRING_LEN(rb_query); rb_grn_expression_deconstruct(SELF(self), &expression, &context, NULL, NULL, NULL, NULL, NULL); if (NIL_P(rb_default_column)) { default_column = NULL; } else if (RVAL2CBOOL(rb_obj_is_kind_of(rb_default_column, rb_cGrnObject))) { default_column = RVAL2GRNOBJECT(rb_default_column, &context); } else { default_column = RVAL2GRNBULK(rb_default_column, context, NULL); default_column_is_created = GRN_TRUE; } if (!NIL_P(rb_default_mode)) default_mode = RVAL2GRNOPERATOR(rb_default_mode); if (!NIL_P(rb_default_operator)) default_operator = RVAL2GRNSETOPERATOR(rb_default_operator); if (NIL_P(rb_syntax) || rb_grn_equal_option(rb_syntax, "query")) { flags = GRN_EXPR_SYNTAX_QUERY; } else if (rb_grn_equal_option(rb_syntax, "script")) { flags = GRN_EXPR_SYNTAX_SCRIPT; } else { rb_raise(rb_eArgError, "syntax should be one of " "[nil, :query, :script]: %s", rb_grn_inspect(rb_syntax)); } if (NIL_P(rb_allow_pragma)) { if (!(flags & GRN_EXPR_SYNTAX_SCRIPT)) flags |= GRN_EXPR_ALLOW_PRAGMA; } else { if ((flags & GRN_EXPR_SYNTAX_SCRIPT)) rb_raise(rb_eArgError, ":allow_pragma isn't allowed in script syntax"); if (RVAL2CBOOL(rb_allow_pragma)) flags |= GRN_EXPR_ALLOW_PRAGMA; } if (NIL_P(rb_allow_column)) { if (!(flags & GRN_EXPR_SYNTAX_SCRIPT)) flags |= GRN_EXPR_ALLOW_COLUMN; } else { if ((flags & GRN_EXPR_SYNTAX_SCRIPT)) rb_raise(rb_eArgError, ":allow_column isn't allowed in script syntax"); if (RVAL2CBOOL(rb_allow_column)) flags |= GRN_EXPR_ALLOW_COLUMN; } if (NIL_P(rb_allow_update)) { flags |= GRN_EXPR_ALLOW_UPDATE; } else { if (RVAL2CBOOL(rb_allow_update)) flags |= GRN_EXPR_ALLOW_UPDATE; } if (!NIL_P(rb_allow_leading_not)) { if (RVAL2CBOOL(rb_allow_leading_not)) flags |= GRN_EXPR_ALLOW_LEADING_NOT; } rc = grn_expr_parse(context, expression, query, query_size, default_column, default_mode, default_operator, flags); if (rc != GRN_SUCCESS) { VALUE related_object; related_object = rb_ary_new_from_args(2, self, rb_ary_new_from_values(argc, argv)); exception = rb_grn_context_to_exception(context, related_object); } if (default_column_is_created) grn_obj_unlink(context, default_column); if (!NIL_P(exception)) rb_exc_raise(exception); return Qnil; }