groonga 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/NEWS.ja.rdoc +11 -0
- data/NEWS.rdoc +11 -0
- data/README.ja.rdoc +4 -3
- data/README.rdoc +4 -3
- data/Rakefile +1 -1
- data/TUTORIAL.ja.rdoc +168 -44
- data/benchmark/common.rb +49 -0
- data/benchmark/read-write-small-many-items.rb +156 -0
- data/benchmark/write-small-many-items.rb +145 -0
- data/example/bookmark.rb +68 -20
- data/ext/rb-grn-array-cursor.c +8 -0
- data/ext/rb-grn-array.c +40 -11
- data/ext/rb-grn-column.c +38 -209
- data/ext/rb-grn-context.c +203 -56
- data/ext/rb-grn-database.c +119 -5
- data/ext/rb-grn-encoding-support.c +64 -0
- data/ext/rb-grn-encoding.c +58 -1
- data/ext/rb-grn-fix-size-column.c +220 -0
- data/ext/rb-grn-hash-cursor.c +8 -0
- data/ext/rb-grn-hash.c +244 -2
- data/ext/rb-grn-index-column.c +474 -0
- data/ext/rb-grn-object.c +143 -265
- data/ext/rb-grn-patricia-trie.c +148 -2
- data/ext/rb-grn-query.c +5 -3
- data/ext/rb-grn-record.c +3 -2
- data/ext/rb-grn-snippet.c +5 -3
- data/ext/rb-grn-table-cursor-key-support.c +3 -3
- data/ext/rb-grn-table-cursor.c +106 -112
- data/ext/rb-grn-table-key-support.c +220 -118
- data/ext/rb-grn-table.c +336 -80
- data/ext/rb-grn-type.c +5 -4
- data/ext/rb-grn-utils.c +62 -63
- data/ext/rb-grn.h +215 -14
- data/ext/rb-groonga.c +7 -16
- data/extconf.rb +3 -1
- data/html/favicon.ico +0 -0
- data/html/favicon.xcf +0 -0
- data/html/index.html +1 -7
- data/lib/groonga/record.rb +6 -1
- data/test/groonga-test-utils.rb +1 -0
- data/test/test-array.rb +81 -0
- data/test/test-column.rb +22 -12
- data/test/test-context.rb +1 -29
- data/test/test-database.rb +30 -0
- data/test/test-hash.rb +194 -0
- data/test/test-index-column.rb +57 -0
- data/test/test-patricia-trie.rb +82 -0
- data/test/test-record.rb +10 -10
- data/test/test-table.rb +37 -130
- data/test/test-type.rb +4 -3
- metadata +15 -4
- data/benchmark/small-many-items.rb +0 -175
| @@ -0,0 +1,474 @@ | |
| 1 | 
            +
            /* -*- c-file-style: "ruby" -*- */
         | 
| 2 | 
            +
            /*
         | 
| 3 | 
            +
              Copyright (C) 2009  Kouhei Sutou <kou@clear-code.com>
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              This library is free software; you can redistribute it and/or
         | 
| 6 | 
            +
              modify it under the terms of the GNU Lesser General Public
         | 
| 7 | 
            +
              License version 2.1 as published by the Free Software Foundation.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              This library is distributed in the hope that it will be useful,
         | 
| 10 | 
            +
              but WITHOUT ANY WARRANTY; without even the implied warranty of
         | 
| 11 | 
            +
              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
         | 
| 12 | 
            +
              Lesser General Public License for more details.
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              You should have received a copy of the GNU Lesser General Public
         | 
| 15 | 
            +
              License along with this library; if not, write to the Free Software
         | 
| 16 | 
            +
              Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
         | 
| 17 | 
            +
            */
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            #include "rb-grn.h"
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            #define SELF(object) ((RbGrnIndexColumn *)DATA_PTR(object))
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            VALUE rb_cGrnIndexColumn;
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            /*
         | 
| 26 | 
            +
             * Document-class: Groonga::IndexColumn < Groonga::Column
         | 
| 27 | 
            +
             *
         | 
| 28 | 
            +
             * 転置索引エントリを格納するカラム。このカラムを利用するこ
         | 
| 29 | 
            +
             * とにより高速な全文検索を実現できる。
         | 
| 30 | 
            +
             *
         | 
| 31 | 
            +
             * テーブルにGroonga::IndexColumnを定義する方法は
         | 
| 32 | 
            +
             * Groonga::Table#define_index_columnを参照。
         | 
| 33 | 
            +
             */
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            void
         | 
| 36 | 
            +
            rb_grn_index_column_unbind (RbGrnIndexColumn *rb_grn_index_column)
         | 
| 37 | 
            +
            {
         | 
| 38 | 
            +
                RbGrnObject *rb_grn_object;
         | 
| 39 | 
            +
                grn_ctx *context;
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                rb_grn_object = RB_GRN_OBJECT(rb_grn_index_column);
         | 
| 42 | 
            +
                context = rb_grn_object->context;
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                if (context) {
         | 
| 45 | 
            +
            	grn_obj_close(context, rb_grn_index_column->id_query);
         | 
| 46 | 
            +
            	grn_obj_close(context, rb_grn_index_column->string_query);
         | 
| 47 | 
            +
            	grn_obj_close(context, rb_grn_index_column->value);
         | 
| 48 | 
            +
            	grn_obj_close(context, rb_grn_index_column->old_value);
         | 
| 49 | 
            +
                }
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                rb_grn_object_unbind(rb_grn_object);
         | 
| 52 | 
            +
            }
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            static void
         | 
| 55 | 
            +
            rb_grn_index_column_free (void *object)
         | 
| 56 | 
            +
            {
         | 
| 57 | 
            +
                RbGrnIndexColumn *rb_grn_index_column = object;
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                rb_grn_index_column_unbind(rb_grn_index_column);
         | 
| 60 | 
            +
                xfree(rb_grn_index_column);
         | 
| 61 | 
            +
            }
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            VALUE
         | 
| 64 | 
            +
            rb_grn_index_column_alloc (VALUE klass)
         | 
| 65 | 
            +
            {
         | 
| 66 | 
            +
                return Data_Wrap_Struct(klass, NULL, rb_grn_index_column_free, NULL);
         | 
| 67 | 
            +
            }
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            void
         | 
| 70 | 
            +
            rb_grn_index_column_bind (RbGrnIndexColumn *rb_grn_index_column,
         | 
| 71 | 
            +
            			  grn_ctx *context, grn_obj *column,
         | 
| 72 | 
            +
            			  rb_grn_boolean owner)
         | 
| 73 | 
            +
            {
         | 
| 74 | 
            +
                RbGrnObject *rb_grn_object;
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                rb_grn_object = RB_GRN_OBJECT(rb_grn_index_column);
         | 
| 77 | 
            +
                rb_grn_object_bind(rb_grn_object, context, column, owner);
         | 
| 78 | 
            +
                rb_grn_object->unbind = RB_GRN_UNBIND_FUNCTION(rb_grn_index_column_unbind);
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                rb_grn_index_column->value = grn_obj_open(context, GRN_BULK, 0,
         | 
| 81 | 
            +
            					      rb_grn_object->range_id);
         | 
| 82 | 
            +
                rb_grn_index_column->old_value = grn_obj_open(context, GRN_BULK, 0,
         | 
| 83 | 
            +
            						  rb_grn_object->range_id);
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                rb_grn_index_column->id_query = grn_obj_open(context, GRN_BULK, 0,
         | 
| 86 | 
            +
            						 rb_grn_object->domain_id);
         | 
| 87 | 
            +
                rb_grn_index_column->string_query = grn_obj_open(context, GRN_BULK,
         | 
| 88 | 
            +
            						     GRN_OBJ_DO_SHALLOW_COPY,
         | 
| 89 | 
            +
            						     GRN_ID_NIL);
         | 
| 90 | 
            +
            }
         | 
| 91 | 
            +
             | 
| 92 | 
            +
            void
         | 
| 93 | 
            +
            rb_grn_index_column_assign (VALUE self, VALUE rb_context,
         | 
| 94 | 
            +
            			    grn_ctx *context, grn_obj *column,
         | 
| 95 | 
            +
            			    rb_grn_boolean owner)
         | 
| 96 | 
            +
            {
         | 
| 97 | 
            +
                RbGrnIndexColumn *rb_grn_index_column;
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                rb_grn_index_column = ALLOC(RbGrnIndexColumn);
         | 
| 100 | 
            +
                DATA_PTR(self) = rb_grn_index_column;
         | 
| 101 | 
            +
                rb_grn_index_column_bind(rb_grn_index_column, context, column, owner);
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                rb_iv_set(self, "context", rb_context);
         | 
| 104 | 
            +
            }
         | 
| 105 | 
            +
             | 
| 106 | 
            +
            void
         | 
| 107 | 
            +
            rb_grn_index_column_deconstruct (RbGrnIndexColumn *rb_grn_index_column,
         | 
| 108 | 
            +
            				 grn_obj **column,
         | 
| 109 | 
            +
            				 grn_ctx **context,
         | 
| 110 | 
            +
            				 grn_id *domain_id,
         | 
| 111 | 
            +
            				 grn_obj **domain,
         | 
| 112 | 
            +
            				 grn_obj **value,
         | 
| 113 | 
            +
            				 grn_obj **old_value,
         | 
| 114 | 
            +
            				 grn_id *range_id,
         | 
| 115 | 
            +
            				 grn_obj **range,
         | 
| 116 | 
            +
            				 grn_obj **id_query,
         | 
| 117 | 
            +
            				 grn_obj **string_query)
         | 
| 118 | 
            +
            {
         | 
| 119 | 
            +
                RbGrnObject *rb_grn_object;
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                rb_grn_object = RB_GRN_OBJECT(rb_grn_index_column);
         | 
| 122 | 
            +
                rb_grn_object_deconstruct(rb_grn_object, column, context,
         | 
| 123 | 
            +
            			      domain_id, domain,
         | 
| 124 | 
            +
            			      range_id, range);
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                if (value)
         | 
| 127 | 
            +
            	*value = rb_grn_index_column->value;
         | 
| 128 | 
            +
                if (old_value)
         | 
| 129 | 
            +
            	*old_value = rb_grn_index_column->old_value;
         | 
| 130 | 
            +
                if (id_query)
         | 
| 131 | 
            +
            	*id_query = rb_grn_index_column->id_query;
         | 
| 132 | 
            +
                if (string_query)
         | 
| 133 | 
            +
            	*string_query = rb_grn_index_column->string_query;
         | 
| 134 | 
            +
            }
         | 
| 135 | 
            +
             | 
| 136 | 
            +
            /*
         | 
| 137 | 
            +
             * call-seq:
         | 
| 138 | 
            +
             *   column[id] = value
         | 
| 139 | 
            +
             *   column[id] = options
         | 
| 140 | 
            +
             *
         | 
| 141 | 
            +
             * IDが_id_であるレコードを高速に全文検索するため転置索引を作
         | 
| 142 | 
            +
             * 成する。多くの場合、Groonga::Table#define_index_columnで
         | 
| 143 | 
            +
             * +:source+オプションを指定することにより、自動的に全文検索
         | 
| 144 | 
            +
             * 用の索引は更新されるので、明示的にこのメソッドを使うこと
         | 
| 145 | 
            +
             * は少ない。
         | 
| 146 | 
            +
             *
         | 
| 147 | 
            +
             * _value_には文字列を指定する。
         | 
| 148 | 
            +
             *
         | 
| 149 | 
            +
             * _options_を指定することにより、より索引の作成を制御できる。
         | 
| 150 | 
            +
             * _options_に指定可能な値は以下の通り。
         | 
| 151 | 
            +
             *
         | 
| 152 | 
            +
             * [+:section+]
         | 
| 153 | 
            +
             *   段落番号を指定する。省略した場合は1を指定したとみなされ
         | 
| 154 | 
            +
             *   る。
         | 
| 155 | 
            +
             *
         | 
| 156 | 
            +
             *   Groonga::Table#define_index_columnで
         | 
| 157 | 
            +
             *   <tt>{:with_section => true}</tt>を指定していなければい
         | 
| 158 | 
            +
             *   けない。
         | 
| 159 | 
            +
             *
         | 
| 160 | 
            +
             * [+:old_value+]
         | 
| 161 | 
            +
             *   以前の値を指定する。省略した場合は現在の値が用いられる。
         | 
| 162 | 
            +
             *   通常は指定する必要はない。
         | 
| 163 | 
            +
             *
         | 
| 164 | 
            +
             * [+:value+]
         | 
| 165 | 
            +
             *   新しい値を指定する。_value_を指定した場合と_options_で
         | 
| 166 | 
            +
             *   <tt>{:value => value}</tt>を指定した場合は同じ動作とな
         | 
| 167 | 
            +
             *   る。
         | 
| 168 | 
            +
             *
         | 
| 169 | 
            +
             * 記事の段落毎に索引を作成する。
         | 
| 170 | 
            +
             *   articles = Groonga::Array.create(:name => "<articles>")
         | 
| 171 | 
            +
             *   articles.define_column("title", "<shottext>")
         | 
| 172 | 
            +
             *   articles.define_column("content", "<text>")
         | 
| 173 | 
            +
             *
         | 
| 174 | 
            +
             *   terms = Groonga::Hash.create(:name => "<terms>",
         | 
| 175 | 
            +
             *                                :with_section => true,
         | 
| 176 | 
            +
             *                                :default_tokenizer => "<token:bigram>")
         | 
| 177 | 
            +
             *   content_index = terms.define_index_column("content", articles)
         | 
| 178 | 
            +
             *
         | 
| 179 | 
            +
             *   content = <<-EOC
         | 
| 180 | 
            +
             *   groonga は組み込み型の全文検索エンジンライブラリです。
         | 
| 181 | 
            +
             *   DBMSやスクリプト言語処理系等に組み込むことによって、その
         | 
| 182 | 
            +
             *   全文検索機能を強化することができます。また、リレーショナ
         | 
| 183 | 
            +
             *   ルモデルに基づくデータストア機能を内包しており、groonga
         | 
| 184 | 
            +
             *   単体でも高速なデータストアサーバとして使用することができ
         | 
| 185 | 
            +
             *   ます。
         | 
| 186 | 
            +
             *
         | 
| 187 | 
            +
             *   ■全文検索方式
         | 
| 188 | 
            +
             *   転置索引型の全文検索エンジンです。転置索引は圧縮されてファ
         | 
| 189 | 
            +
             *   イルに格納され、検索時のディスク読み出し量を小さく、かつ
         | 
| 190 | 
            +
             *   局所的に抑えるように設計されています。用途に応じて以下の
         | 
| 191 | 
            +
             *   索引タイプを選択できます。
         | 
| 192 | 
            +
             *   EOC
         | 
| 193 | 
            +
             *
         | 
| 194 | 
            +
             *   groonga = articles.add(:title => "groonga", :content => content)
         | 
| 195 | 
            +
             *
         | 
| 196 | 
            +
             *   content.split(/\n{2,}/).each_with_index do |sentence, i|
         | 
| 197 | 
            +
             *     content_index[groonga] = {:value => sentence, :section => i + 1}
         | 
| 198 | 
            +
             *   end
         | 
| 199 | 
            +
             *
         | 
| 200 | 
            +
             *   content.search("エンジン").collect do |record|
         | 
| 201 | 
            +
             *     p record.key["title"] # -> "groonga"
         | 
| 202 | 
            +
             *   end
         | 
| 203 | 
            +
             */
         | 
| 204 | 
            +
            static VALUE
         | 
| 205 | 
            +
            rb_grn_index_column_array_set (VALUE self, VALUE rb_id, VALUE rb_value)
         | 
| 206 | 
            +
            {
         | 
| 207 | 
            +
                grn_ctx *context = NULL;
         | 
| 208 | 
            +
                grn_obj *column, *range;
         | 
| 209 | 
            +
                grn_rc rc;
         | 
| 210 | 
            +
                grn_id id;
         | 
| 211 | 
            +
                unsigned int section;
         | 
| 212 | 
            +
                grn_obj *old_value, *new_value;
         | 
| 213 | 
            +
                VALUE original_rb_value, rb_section, rb_old_value, rb_new_value;
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                original_rb_value = rb_value;
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                rb_grn_index_column_deconstruct(SELF(self), &column, &context,
         | 
| 218 | 
            +
            				    NULL, NULL,
         | 
| 219 | 
            +
            				    &new_value, &old_value,
         | 
| 220 | 
            +
            				    NULL, &range,
         | 
| 221 | 
            +
            				    NULL, NULL);
         | 
| 222 | 
            +
             | 
| 223 | 
            +
                id = RVAL2GRNID(rb_id, context, range, self);
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_value, rb_cHash))) {
         | 
| 226 | 
            +
            	VALUE hash_value;
         | 
| 227 | 
            +
            	hash_value = rb_hash_new();
         | 
| 228 | 
            +
            	rb_hash_aset(hash_value, RB_GRN_INTERN("value"), rb_value);
         | 
| 229 | 
            +
            	rb_value = hash_value;
         | 
| 230 | 
            +
                }
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                rb_grn_scan_options(rb_value,
         | 
| 233 | 
            +
            			"section", &rb_section,
         | 
| 234 | 
            +
            			"old_value", &rb_old_value,
         | 
| 235 | 
            +
            			"value", &rb_new_value,
         | 
| 236 | 
            +
            			NULL);
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                if (NIL_P(rb_section))
         | 
| 239 | 
            +
            	section = 1;
         | 
| 240 | 
            +
                else
         | 
| 241 | 
            +
            	section = NUM2UINT(rb_section);
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                if (NIL_P(rb_old_value)) {
         | 
| 244 | 
            +
            	old_value = NULL;
         | 
| 245 | 
            +
                } else {
         | 
| 246 | 
            +
            	GRN_BULK_REWIND(old_value);
         | 
| 247 | 
            +
            	RVAL2GRNBULK(rb_old_value, context, old_value);
         | 
| 248 | 
            +
                }
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                if (NIL_P(rb_new_value)) {
         | 
| 251 | 
            +
            	new_value = NULL;
         | 
| 252 | 
            +
                } else {
         | 
| 253 | 
            +
            	GRN_BULK_REWIND(new_value);
         | 
| 254 | 
            +
            	RVAL2GRNBULK(rb_new_value, context, new_value);
         | 
| 255 | 
            +
                }
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                rc = grn_column_index_update(context, column,
         | 
| 258 | 
            +
            				 id, section, old_value, new_value);
         | 
| 259 | 
            +
                rb_grn_context_check(context, self);
         | 
| 260 | 
            +
                rb_grn_rc_check(rc, self);
         | 
| 261 | 
            +
             | 
| 262 | 
            +
                return original_rb_value;
         | 
| 263 | 
            +
            }
         | 
| 264 | 
            +
             | 
| 265 | 
            +
            static VALUE
         | 
| 266 | 
            +
            rb_grn_index_column_get_sources (VALUE self)
         | 
| 267 | 
            +
            {
         | 
| 268 | 
            +
                grn_ctx *context = NULL;
         | 
| 269 | 
            +
                grn_obj *column;
         | 
| 270 | 
            +
                grn_obj sources;
         | 
| 271 | 
            +
                grn_id *source_ids;
         | 
| 272 | 
            +
                VALUE rb_sources;
         | 
| 273 | 
            +
                int i, n;
         | 
| 274 | 
            +
             | 
| 275 | 
            +
                rb_grn_index_column_deconstruct(SELF(self), &column, &context,
         | 
| 276 | 
            +
            				    NULL, NULL,
         | 
| 277 | 
            +
            				    NULL, NULL, NULL, NULL,
         | 
| 278 | 
            +
            				    NULL, NULL);
         | 
| 279 | 
            +
             | 
| 280 | 
            +
                GRN_OBJ_INIT(&sources, GRN_BULK, 0, GRN_ID_NIL);
         | 
| 281 | 
            +
                grn_obj_get_info(context, column, GRN_INFO_SOURCE, &sources);
         | 
| 282 | 
            +
                rb_grn_context_check(context, self);
         | 
| 283 | 
            +
             | 
| 284 | 
            +
                n = GRN_BULK_VSIZE(&sources) / sizeof(grn_id);
         | 
| 285 | 
            +
                source_ids = (grn_id *)GRN_BULK_HEAD(&sources);
         | 
| 286 | 
            +
                rb_sources = rb_ary_new2(n);
         | 
| 287 | 
            +
                for (i = 0; i < n; i++) {
         | 
| 288 | 
            +
            	grn_obj *source;
         | 
| 289 | 
            +
            	VALUE rb_source;
         | 
| 290 | 
            +
             | 
| 291 | 
            +
            	source = grn_ctx_at(context, *source_ids);
         | 
| 292 | 
            +
            	rb_source = GRNOBJECT2RVAL(Qnil, context, source, RB_GRN_FALSE);
         | 
| 293 | 
            +
            	rb_ary_push(rb_sources, rb_source);
         | 
| 294 | 
            +
            	source_ids++;
         | 
| 295 | 
            +
                }
         | 
| 296 | 
            +
                grn_obj_close(context, &sources);
         | 
| 297 | 
            +
             | 
| 298 | 
            +
                return rb_sources;
         | 
| 299 | 
            +
            }
         | 
| 300 | 
            +
             | 
| 301 | 
            +
            static VALUE
         | 
| 302 | 
            +
            rb_grn_index_column_set_sources (VALUE self, VALUE rb_sources)
         | 
| 303 | 
            +
            {
         | 
| 304 | 
            +
                VALUE exception;
         | 
| 305 | 
            +
                grn_ctx *context = NULL;
         | 
| 306 | 
            +
                grn_obj *column;
         | 
| 307 | 
            +
                int i, n;
         | 
| 308 | 
            +
                VALUE *rb_source_values;
         | 
| 309 | 
            +
                grn_id *sources;
         | 
| 310 | 
            +
                grn_rc rc;
         | 
| 311 | 
            +
             | 
| 312 | 
            +
                rb_grn_index_column_deconstruct(SELF(self), &column, &context,
         | 
| 313 | 
            +
            				    NULL, NULL,
         | 
| 314 | 
            +
            				    NULL, NULL, NULL, NULL,
         | 
| 315 | 
            +
            				    NULL, NULL);
         | 
| 316 | 
            +
             | 
| 317 | 
            +
                n = RARRAY_LEN(rb_sources);
         | 
| 318 | 
            +
                rb_source_values = RARRAY_PTR(rb_sources);
         | 
| 319 | 
            +
                sources = ALLOCA_N(grn_id, n);
         | 
| 320 | 
            +
                for (i = 0; i < n; i++) {
         | 
| 321 | 
            +
            	VALUE rb_source_id;
         | 
| 322 | 
            +
            	grn_obj *source;
         | 
| 323 | 
            +
            	grn_id source_id;
         | 
| 324 | 
            +
             | 
| 325 | 
            +
            	rb_source_id = rb_source_values[i];
         | 
| 326 | 
            +
            	if (CBOOL2RVAL(rb_obj_is_kind_of(rb_source_id, rb_cInteger))) {
         | 
| 327 | 
            +
            	    source_id = NUM2UINT(rb_source_id);
         | 
| 328 | 
            +
            	} else {
         | 
| 329 | 
            +
            	    source = RVAL2GRNOBJECT(rb_source_id, &context);
         | 
| 330 | 
            +
            	    rb_grn_context_check(context, rb_source_id);
         | 
| 331 | 
            +
            	    source_id = grn_obj_id(context, source);
         | 
| 332 | 
            +
            	}
         | 
| 333 | 
            +
            	sources[i] = source_id;
         | 
| 334 | 
            +
                }
         | 
| 335 | 
            +
             | 
| 336 | 
            +
                {
         | 
| 337 | 
            +
            	grn_obj bulk_sources;
         | 
| 338 | 
            +
            	GRN_OBJ_INIT(&bulk_sources, GRN_BULK, 0, GRN_ID_NIL);
         | 
| 339 | 
            +
            	GRN_TEXT_SET(context, &bulk_sources, sources, n * sizeof(grn_id));
         | 
| 340 | 
            +
            	rc = grn_obj_set_info(context, column, GRN_INFO_SOURCE, &bulk_sources);
         | 
| 341 | 
            +
            	exception = rb_grn_context_to_exception(context, self);
         | 
| 342 | 
            +
            	grn_obj_close(context, &bulk_sources);
         | 
| 343 | 
            +
                }
         | 
| 344 | 
            +
             | 
| 345 | 
            +
                if (!NIL_P(exception))
         | 
| 346 | 
            +
            	rb_exc_raise(exception);
         | 
| 347 | 
            +
                rb_grn_rc_check(rc, self);
         | 
| 348 | 
            +
             | 
| 349 | 
            +
                return Qnil;
         | 
| 350 | 
            +
            }
         | 
| 351 | 
            +
             | 
| 352 | 
            +
            static VALUE
         | 
| 353 | 
            +
            rb_grn_index_column_set_source (VALUE self, VALUE rb_source)
         | 
| 354 | 
            +
            {
         | 
| 355 | 
            +
                if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_source, rb_cArray)))
         | 
| 356 | 
            +
            	rb_source = rb_ary_new3(1, rb_source);
         | 
| 357 | 
            +
             | 
| 358 | 
            +
                return rb_grn_index_column_set_sources(self, rb_source);
         | 
| 359 | 
            +
            }
         | 
| 360 | 
            +
             | 
| 361 | 
            +
            /*
         | 
| 362 | 
            +
             * Document-method: search
         | 
| 363 | 
            +
             *
         | 
| 364 | 
            +
             * call-seq:
         | 
| 365 | 
            +
             *   column.search(query, options={}) -> Groonga::Hash
         | 
| 366 | 
            +
             *
         | 
| 367 | 
            +
             * _object_から_query_に対応するオブジェクトを検索し、見つかっ
         | 
| 368 | 
            +
             * たオブジェクトのIDがキーになっているGroonga::Hashを返す。
         | 
| 369 | 
            +
             *
         | 
| 370 | 
            +
             * 利用可能なオプションは以下の通り。
         | 
| 371 | 
            +
             *
         | 
| 372 | 
            +
             * [_:result_]
         | 
| 373 | 
            +
             *   結果を格納するGroonga::Hash。指定しない場合は新しく
         | 
| 374 | 
            +
             *   Groonga::Hashを生成し、それに結果を格納して返す。
         | 
| 375 | 
            +
             * [_:operator_]
         | 
| 376 | 
            +
             *   以下のどれかの値を指定する。+nil+, <tt>"or"</tt>, <tt>"||"</tt>,
         | 
| 377 | 
            +
             *   <tt>"and"</tt>, <tt>"+"</tt>, <tt>"&&"</tt>, <tt>"but"</tt>,
         | 
| 378 | 
            +
             *   <tt>"not"</tt>, <tt>"-"</tt>, <tt>"adjust"</tt>, <tt>">"</tt>。
         | 
| 379 | 
            +
             *   それぞれ以下のようになる。(FIXME: 「以下」)
         | 
| 380 | 
            +
             * [_:exact_]
         | 
| 381 | 
            +
             *   +true+を指定すると完全一致で検索する
         | 
| 382 | 
            +
             * [_:longest_common_prefix_]
         | 
| 383 | 
            +
             *   +true+を指定すると_query_と同じ接頭辞をもつエントリのう
         | 
| 384 | 
            +
             *   ち、もっとも長いエントリを検索する
         | 
| 385 | 
            +
             * [_:suffix_]
         | 
| 386 | 
            +
             *   +true+を指定すると_query_が後方一致するエントリを検索す
         | 
| 387 | 
            +
             *   る
         | 
| 388 | 
            +
             * [_:prefix_]
         | 
| 389 | 
            +
             *   +true+を指定すると_query_が前方一致するレコードを検索す
         | 
| 390 | 
            +
             *   る
         | 
| 391 | 
            +
             * [_:near_]
         | 
| 392 | 
            +
             *   +true+を指定すると_query_に指定した複数の語が近傍に含ま
         | 
| 393 | 
            +
             *   れるレコードを検索する
         | 
| 394 | 
            +
             * [...]
         | 
| 395 | 
            +
             *   ...
         | 
| 396 | 
            +
             */
         | 
| 397 | 
            +
            static VALUE
         | 
| 398 | 
            +
            rb_grn_index_column_search (int argc, VALUE *argv, VALUE self)
         | 
| 399 | 
            +
            {
         | 
| 400 | 
            +
                grn_ctx *context;
         | 
| 401 | 
            +
                grn_obj *column;
         | 
| 402 | 
            +
                grn_obj *range;
         | 
| 403 | 
            +
                grn_obj *query = NULL, *id_query = NULL, *string_query = NULL;
         | 
| 404 | 
            +
                grn_obj *result;
         | 
| 405 | 
            +
                grn_sel_operator operator;
         | 
| 406 | 
            +
                grn_rc rc;
         | 
| 407 | 
            +
                VALUE rb_query, options, rb_result, rb_operator;
         | 
| 408 | 
            +
             | 
| 409 | 
            +
                rb_grn_index_column_deconstruct(SELF(self), &column, &context,
         | 
| 410 | 
            +
            				    NULL, NULL,
         | 
| 411 | 
            +
            				    NULL, NULL, NULL, &range,
         | 
| 412 | 
            +
            				    &id_query, &string_query);
         | 
| 413 | 
            +
             | 
| 414 | 
            +
                rb_scan_args(argc, argv, "11", &rb_query, &options);
         | 
| 415 | 
            +
             | 
| 416 | 
            +
                if (CBOOL2RVAL(rb_obj_is_kind_of(rb_query, rb_cGrnQuery))) {
         | 
| 417 | 
            +
            	grn_query *_query;
         | 
| 418 | 
            +
            	_query = RVAL2GRNQUERY(rb_query);
         | 
| 419 | 
            +
            	query = (grn_obj *)_query;
         | 
| 420 | 
            +
                } else if (CBOOL2RVAL(rb_obj_is_kind_of(rb_query, rb_cInteger))) {
         | 
| 421 | 
            +
            	grn_id id;
         | 
| 422 | 
            +
            	id = NUM2UINT(rb_query);
         | 
| 423 | 
            +
            	GRN_TEXT_SET(context, id_query, &id, sizeof(grn_id));
         | 
| 424 | 
            +
            	query = id_query;
         | 
| 425 | 
            +
                } else {
         | 
| 426 | 
            +
            	const char *_query;
         | 
| 427 | 
            +
            	_query = StringValuePtr(rb_query);
         | 
| 428 | 
            +
            	GRN_TEXT_SET(context, string_query, _query, RSTRING_LEN(rb_query));
         | 
| 429 | 
            +
            	query = string_query;
         | 
| 430 | 
            +
                }
         | 
| 431 | 
            +
             | 
| 432 | 
            +
                rb_grn_scan_options(options,
         | 
| 433 | 
            +
            			"result", &rb_result,
         | 
| 434 | 
            +
            			"operator", &rb_operator,
         | 
| 435 | 
            +
            			NULL);
         | 
| 436 | 
            +
             | 
| 437 | 
            +
                if (NIL_P(rb_result)) {
         | 
| 438 | 
            +
            	result = grn_table_create(context, NULL, 0, NULL,
         | 
| 439 | 
            +
            				  GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
         | 
| 440 | 
            +
            				  range, 0);
         | 
| 441 | 
            +
            	rb_grn_context_check(context, self);
         | 
| 442 | 
            +
            	rb_result = GRNOBJECT2RVAL(Qnil, context, result, RB_GRN_TRUE);
         | 
| 443 | 
            +
                } else {
         | 
| 444 | 
            +
            	result = RVAL2GRNOBJECT(rb_result, &context);
         | 
| 445 | 
            +
                }
         | 
| 446 | 
            +
             | 
| 447 | 
            +
                operator = RVAL2GRNSELECTOPERATOR(rb_operator);
         | 
| 448 | 
            +
             | 
| 449 | 
            +
                rc = grn_obj_search(context, column, query, result, operator, NULL);
         | 
| 450 | 
            +
                rb_grn_rc_check(rc, self);
         | 
| 451 | 
            +
             | 
| 452 | 
            +
                return rb_result;
         | 
| 453 | 
            +
            }
         | 
| 454 | 
            +
             | 
| 455 | 
            +
            void
         | 
| 456 | 
            +
            rb_grn_init_index_column (VALUE mGrn)
         | 
| 457 | 
            +
            {
         | 
| 458 | 
            +
                rb_cGrnIndexColumn =
         | 
| 459 | 
            +
            	rb_define_class_under(mGrn, "IndexColumn", rb_cGrnColumn);
         | 
| 460 | 
            +
                rb_define_alloc_func(rb_cGrnIndexColumn, rb_grn_index_column_alloc);
         | 
| 461 | 
            +
             | 
| 462 | 
            +
                rb_define_method(rb_cGrnIndexColumn, "[]=",
         | 
| 463 | 
            +
            		     rb_grn_index_column_array_set, 2);
         | 
| 464 | 
            +
             | 
| 465 | 
            +
                rb_define_method(rb_cGrnIndexColumn, "sources",
         | 
| 466 | 
            +
            		     rb_grn_index_column_get_sources, 0);
         | 
| 467 | 
            +
                rb_define_method(rb_cGrnIndexColumn, "sources=",
         | 
| 468 | 
            +
            		     rb_grn_index_column_set_sources, 1);
         | 
| 469 | 
            +
                rb_define_method(rb_cGrnIndexColumn, "source=",
         | 
| 470 | 
            +
            		     rb_grn_index_column_set_source, 1);
         | 
| 471 | 
            +
             | 
| 472 | 
            +
                rb_define_method(rb_cGrnIndexColumn, "search",
         | 
| 473 | 
            +
            		     rb_grn_index_column_search, -1);
         | 
| 474 | 
            +
            }
         |