groonga 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/NEWS.ja.rdoc +11 -0
  2. data/NEWS.rdoc +11 -0
  3. data/README.ja.rdoc +4 -3
  4. data/README.rdoc +4 -3
  5. data/Rakefile +1 -1
  6. data/TUTORIAL.ja.rdoc +168 -44
  7. data/benchmark/common.rb +49 -0
  8. data/benchmark/read-write-small-many-items.rb +156 -0
  9. data/benchmark/write-small-many-items.rb +145 -0
  10. data/example/bookmark.rb +68 -20
  11. data/ext/rb-grn-array-cursor.c +8 -0
  12. data/ext/rb-grn-array.c +40 -11
  13. data/ext/rb-grn-column.c +38 -209
  14. data/ext/rb-grn-context.c +203 -56
  15. data/ext/rb-grn-database.c +119 -5
  16. data/ext/rb-grn-encoding-support.c +64 -0
  17. data/ext/rb-grn-encoding.c +58 -1
  18. data/ext/rb-grn-fix-size-column.c +220 -0
  19. data/ext/rb-grn-hash-cursor.c +8 -0
  20. data/ext/rb-grn-hash.c +244 -2
  21. data/ext/rb-grn-index-column.c +474 -0
  22. data/ext/rb-grn-object.c +143 -265
  23. data/ext/rb-grn-patricia-trie.c +148 -2
  24. data/ext/rb-grn-query.c +5 -3
  25. data/ext/rb-grn-record.c +3 -2
  26. data/ext/rb-grn-snippet.c +5 -3
  27. data/ext/rb-grn-table-cursor-key-support.c +3 -3
  28. data/ext/rb-grn-table-cursor.c +106 -112
  29. data/ext/rb-grn-table-key-support.c +220 -118
  30. data/ext/rb-grn-table.c +336 -80
  31. data/ext/rb-grn-type.c +5 -4
  32. data/ext/rb-grn-utils.c +62 -63
  33. data/ext/rb-grn.h +215 -14
  34. data/ext/rb-groonga.c +7 -16
  35. data/extconf.rb +3 -1
  36. data/html/favicon.ico +0 -0
  37. data/html/favicon.xcf +0 -0
  38. data/html/index.html +1 -7
  39. data/lib/groonga/record.rb +6 -1
  40. data/test/groonga-test-utils.rb +1 -0
  41. data/test/test-array.rb +81 -0
  42. data/test/test-column.rb +22 -12
  43. data/test/test-context.rb +1 -29
  44. data/test/test-database.rb +30 -0
  45. data/test/test-hash.rb +194 -0
  46. data/test/test-index-column.rb +57 -0
  47. data/test/test-patricia-trie.rb +82 -0
  48. data/test/test-record.rb +10 -10
  49. data/test/test-table.rb +37 -130
  50. data/test/test-type.rb +4 -3
  51. metadata +15 -4
  52. data/benchmark/small-many-items.rb +0 -175
@@ -22,7 +22,51 @@
22
22
  * Document-module: Groonga::Encoding
23
23
  *
24
24
  * groongaがサポートしてるエンコーディングが定義されてい
25
- * るモジュールです。
25
+ * るモジュール。
26
+ *
27
+ * エンコーディングの指定方法は以下の通り。
28
+ *
29
+ * [+nil+]
30
+ * コンテキストと関連付けられているオブジェクトの場合(多
31
+ * くの場合)はコンテキストのエンコーディングを使用。
32
+ *
33
+ * それ以外のオブジェクトの場合(コンテキスト自身など)は
34
+ * groongaのビルド時に指定したエンコーディング
35
+ * (Groonga::Encoding::DEFAULT)を使用
36
+ *
37
+ * [+:default+]
38
+ * groongaのビルド時に指定したエンコーディングを使用。
39
+ * Groonga::Encoding::DEFAULT
40
+ *
41
+ * [+:none+]
42
+ * エンコーディングを指定しない。Groonga::Encoding::NONE
43
+ *
44
+ * [+:euc_jp+]
45
+ * EUC-JPを使用。Groonga::Encoding::EUC_JP
46
+ *
47
+ * [<tt>"euc-jp"</tt>]
48
+ * +:euc_jp+と同じ。
49
+ *
50
+ * [+:utf8+]
51
+ * UTF-8を使用。Groonga::Encoding::UTF8
52
+ *
53
+ * [<tt>"utf-8"</tt>]
54
+ * +:utf8+と同じ。
55
+ *
56
+ * [+:sjis+]
57
+ * Shift_JISを使用。Groonga::Encoding::SJIS
58
+ *
59
+ * [+:shift_jis+]
60
+ * +:sjis+と同じ。
61
+ *
62
+ * [<tt>"shift-jis"</tt>]
63
+ * +:sjis+と同じ。
64
+ *
65
+ * [+:latin1+]
66
+ * Latin-1を使用。Groonga::Encoding::LATIN1
67
+ *
68
+ * [+:koi8r+]
69
+ * KOI8-Rを使用。Groonga::Encoding::KOI8R
26
70
  */
27
71
 
28
72
  static VALUE mGrnEncoding;
@@ -104,12 +148,25 @@ rb_grn_encoding_to_ruby_object (grn_encoding encoding)
104
148
  return rb_encoding;
105
149
  }
106
150
 
151
+ /*
152
+ * call-seq:
153
+ * Groonga::Encoding.default -> エンコーディング
154
+ *
155
+ * デフォルトのエンコーディングを返す。
156
+ */
107
157
  static VALUE
108
158
  rb_grn_encoding_s_get_default (VALUE self)
109
159
  {
110
160
  return GRNENCODING2RVAL(grn_get_default_encoding());
111
161
  }
112
162
 
163
+ /*
164
+ * call-seq:
165
+ * Groonga::Encoding.default(encoding)
166
+ *
167
+ * デフォルトのエンコーディングを設定する。エンコーディング
168
+ * の指定方法はGroonga::Encodingを参照。
169
+ */
113
170
  static VALUE
114
171
  rb_grn_encoding_s_set_default (VALUE self, VALUE rb_encoding)
115
172
  {
@@ -0,0 +1,220 @@
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) ((RbGrnFixSizeColumn *)DATA_PTR(object))
22
+
23
+ VALUE rb_cGrnFixSizeColumn;
24
+
25
+ /*
26
+ * Document-class: Groonga::FixSizeColumn < Groonga::Column
27
+ *
28
+ * 固定長データ用のカラム。
29
+ */
30
+
31
+ void
32
+ rb_grn_fix_size_column_unbind (RbGrnFixSizeColumn *rb_grn_fix_size_column)
33
+ {
34
+ RbGrnObject *rb_grn_object;
35
+ grn_ctx *context;
36
+
37
+ rb_grn_object = RB_GRN_OBJECT(rb_grn_fix_size_column);
38
+ context = rb_grn_object->context;
39
+
40
+ if (context)
41
+ grn_obj_close(context, rb_grn_fix_size_column->value);
42
+
43
+ rb_grn_object_unbind(rb_grn_object);
44
+ }
45
+
46
+ static void
47
+ rb_grn_fix_size_column_free (void *object)
48
+ {
49
+ RbGrnFixSizeColumn *rb_grn_fix_size_column = object;
50
+
51
+ rb_grn_fix_size_column_unbind(rb_grn_fix_size_column);
52
+ xfree(rb_grn_fix_size_column);
53
+ }
54
+
55
+ VALUE
56
+ rb_grn_fix_size_column_alloc (VALUE klass)
57
+ {
58
+ return Data_Wrap_Struct(klass, NULL, rb_grn_fix_size_column_free, NULL);
59
+ }
60
+
61
+ void
62
+ rb_grn_fix_size_column_bind (RbGrnFixSizeColumn *rb_grn_fix_size_column,
63
+ grn_ctx *context, grn_obj *column,
64
+ rb_grn_boolean owner)
65
+ {
66
+ RbGrnObject *rb_grn_object;
67
+
68
+ rb_grn_object = RB_GRN_OBJECT(rb_grn_fix_size_column);
69
+ rb_grn_object_bind(rb_grn_object, context, column, owner);
70
+ rb_grn_object->unbind =
71
+ RB_GRN_UNBIND_FUNCTION(rb_grn_fix_size_column_unbind);
72
+
73
+ rb_grn_fix_size_column->value = grn_obj_open(context, GRN_BULK, 0,
74
+ rb_grn_object->range_id);
75
+ }
76
+
77
+ void
78
+ rb_grn_fix_size_column_assign (VALUE self, VALUE rb_context,
79
+ grn_ctx *context, grn_obj *column,
80
+ rb_grn_boolean owner)
81
+ {
82
+ RbGrnFixSizeColumn *rb_grn_fix_size_column;
83
+
84
+ rb_grn_fix_size_column = ALLOC(RbGrnFixSizeColumn);
85
+ DATA_PTR(self) = rb_grn_fix_size_column;
86
+ rb_grn_fix_size_column_bind(rb_grn_fix_size_column, context, column, owner);
87
+
88
+ rb_iv_set(self, "context", rb_context);
89
+ }
90
+
91
+ void
92
+ rb_grn_fix_size_column_deconstruct (RbGrnFixSizeColumn *rb_grn_fix_size_column,
93
+ grn_obj **column,
94
+ grn_ctx **context,
95
+ grn_id *domain_id,
96
+ grn_obj **domain,
97
+ grn_obj **value,
98
+ grn_id *range_id,
99
+ grn_obj **range)
100
+ {
101
+ RbGrnObject *rb_grn_object;
102
+
103
+ rb_grn_object = RB_GRN_OBJECT(rb_grn_fix_size_column);
104
+ rb_grn_object_deconstruct(rb_grn_object, column, context,
105
+ domain_id, domain,
106
+ range_id, range);
107
+
108
+ if (value)
109
+ *value = rb_grn_fix_size_column->value;
110
+ }
111
+
112
+ /*
113
+ * call-seq:
114
+ * column[id] -> 値
115
+ *
116
+ * _column_の_id_に対応する値を返す。
117
+ */
118
+ VALUE
119
+ rb_grn_fix_size_column_array_reference (VALUE self, VALUE rb_id)
120
+ {
121
+ grn_id id;
122
+ grn_ctx *context;
123
+ grn_obj *fix_size_column;
124
+ grn_obj *range;
125
+ grn_obj *value;
126
+
127
+ rb_grn_fix_size_column_deconstruct(SELF(self), &fix_size_column, &context,
128
+ NULL, NULL,
129
+ &value, NULL, &range);
130
+
131
+ id = NUM2UINT(rb_id);
132
+ GRN_BULK_REWIND(value);
133
+ grn_obj_get_value(context, fix_size_column, id, value);
134
+ rb_grn_context_check(context, self);
135
+
136
+ return GRNVALUE2RVAL(context, value, range, self);
137
+ }
138
+
139
+ /*
140
+ * call-seq:
141
+ * column[id] = value
142
+ *
143
+ * _column_の_id_に対応する値を設定する。
144
+ */
145
+ static VALUE
146
+ rb_grn_fix_size_column_array_set (VALUE self, VALUE rb_id, VALUE rb_value)
147
+ {
148
+ grn_ctx *context = NULL;
149
+ grn_obj *column;
150
+ grn_id domain_id, range_id;
151
+ grn_obj *domain, *range;
152
+ grn_obj *value;
153
+ grn_rc rc;
154
+ grn_id id;
155
+
156
+ rb_grn_fix_size_column_deconstruct(SELF(self), &column, &context,
157
+ &domain_id, &domain,
158
+ &value, &range_id, &range);
159
+
160
+ id = NUM2UINT(rb_id);
161
+
162
+ if (RVAL2CBOOL(rb_obj_is_kind_of(rb_value, rb_cGrnRecord))) {
163
+ VALUE rb_id, rb_table;
164
+ grn_obj *table;
165
+
166
+ if (!range)
167
+ rb_raise(rb_eArgError,
168
+ "%s isn't associated with any table: %s",
169
+ rb_grn_inspect(self), rb_grn_inspect(rb_value));
170
+
171
+ rb_id = rb_funcall(rb_value, rb_intern("id"), 0);
172
+ rb_table = rb_funcall(rb_value, rb_intern("table"), 0);
173
+ table = RVAL2GRNTABLE(rb_table, &context);
174
+ if (grn_obj_id(context, table) != range_id)
175
+ rb_raise(rb_eArgError,
176
+ "%s isn't associated with passed record's table: %s",
177
+ rb_grn_inspect(self),
178
+ rb_grn_inspect(rb_value));
179
+
180
+ rb_value = rb_id;
181
+ } else if (range) {
182
+ switch (range->header.type) {
183
+ case GRN_TABLE_HASH_KEY:
184
+ case GRN_TABLE_PAT_KEY:
185
+ if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_value, rb_cFixnum))) {
186
+ VALUE rb_range;
187
+ grn_id id;
188
+
189
+ rb_range = GRNOBJECT2RVAL(Qnil, context, range, RB_GRN_FALSE);
190
+ id = rb_grn_table_key_support_get(rb_range, rb_value);
191
+ rb_value = UINT2NUM(id);
192
+ }
193
+ break;
194
+ default:
195
+ break;
196
+ }
197
+ }
198
+
199
+ GRN_BULK_REWIND(value);
200
+ RVAL2GRNBULK(rb_value, context, value);
201
+
202
+ rc = grn_obj_set_value(context, column, id, value, GRN_OBJ_SET);
203
+ rb_grn_context_check(context, self);
204
+ rb_grn_rc_check(rc, self);
205
+
206
+ return Qnil;
207
+ }
208
+
209
+ void
210
+ rb_grn_init_fix_size_column (VALUE mGrn)
211
+ {
212
+ rb_cGrnFixSizeColumn =
213
+ rb_define_class_under(mGrn, "FixSizeColumn", rb_cGrnColumn);
214
+ rb_define_alloc_func(rb_cGrnFixSizeColumn, rb_grn_fix_size_column_alloc);
215
+
216
+ rb_define_method(rb_cGrnFixSizeColumn, "[]",
217
+ rb_grn_fix_size_column_array_reference, 1);
218
+ rb_define_method(rb_cGrnFixSizeColumn, "[]=",
219
+ rb_grn_fix_size_column_array_set, 2);
220
+ }
@@ -20,6 +20,14 @@
20
20
 
21
21
  VALUE rb_cGrnHashCursor;
22
22
 
23
+ /*
24
+ * Document-class: Groonga::HashCursor < Groonga::TableCursor
25
+ *
26
+ * Groonga::Hashに登録されているレコードを順番に取り出すため
27
+ * のオブジェクト。利用できるメソッドはGroonga::TableCursor
28
+ * とGroonga::TableCursorKeySupportを参照。
29
+ */
30
+
23
31
  void
24
32
  rb_grn_init_hash_cursor (VALUE mGrn)
25
33
  {
data/ext/rb-grn-hash.c CHANGED
@@ -18,23 +18,265 @@
18
18
 
19
19
  #include "rb-grn.h"
20
20
 
21
- #define SELF(object) (RVAL2GRNTABLE(object))
21
+ #define SELF(object) ((RbGrnTableKeySupport *)DATA_PTR(object))
22
22
 
23
23
  VALUE rb_cGrnHash;
24
24
 
25
+ /*
26
+ * Document-class: Groonga::Hash < Groonga::Table
27
+ *
28
+ * 各レコードをキーで管理するテーブル。キーと完全一致するレ
29
+ * コードを非常に高速に検索できる。
30
+ */
31
+
32
+ /*
33
+ * call-seq:
34
+ * Groonga::Hash.create(options={}) -> Groonga::Hash
35
+ * Groonga::Hash.create(options={}) {|table| ... }
36
+ *
37
+ * 各レコードをキーで管理するテーブルを生成する。ブロックを指
38
+ * 定すると、そのブロックに生成したテーブルが渡され、ブロック
39
+ * を抜けると自動的にテーブルが破棄される。
40
+ *
41
+ * _options_に指定可能な値は以下の通り。
42
+ *
43
+ * [+:context+]
44
+ * テーブルが利用するGroonga::Context。省略すると
45
+ * Groonga::Context.defaultを用いる。
46
+ *
47
+ * [+:name+]
48
+ * テーブルの名前。名前をつけると、Groonga::Context#[]に名
49
+ * 前を指定してテーブルを取得することができる。省略すると
50
+ * 無名テーブルになり、テーブルIDでのみ取得できる。
51
+ *
52
+ * [+:path+]
53
+ * テーブルを保存するパス。パスを指定すると永続テーブルとな
54
+ * り、プロセス終了後もレコードは保持される。次回起動時に
55
+ * Groonga::Hash.openで保存されたレコードを利用することが
56
+ * できる。省略すると一時テーブルになり、プロセスが終了する
57
+ * とレコードは破棄される。
58
+ *
59
+ * [+:persistent+]
60
+ * +true+を指定すると永続テーブルとなる。+path+を省略した
61
+ * 場合は自動的にパスが付加される。+:context+で指定した
62
+ * Groonga::Contextに結びついているデータベースが一時デー
63
+ * タベースの場合は例外が発生する。
64
+ *
65
+ * [+:key_type+]
66
+ * キーの種類を示すオブジェクトを指定する。キーの種類には
67
+ * Groonga::Typeまたはテーブル(Groonga::Array、
68
+ * Groonga::Hash、Groonga::PatriciaTrieのどれか)を指定する。
69
+ *
70
+ * Groonga::Typeを指定した場合は、その型が示す範囲の値をキー
71
+ * として使用する。ただし、キーの最大サイズは4096バイトで
72
+ * あるため、Groonga::Type::TEXTやGroonga::Type::LONG_TEXT
73
+ * は使用できない。
74
+ *
75
+ * テーブルを指定した場合はレコードIDをキーとして使用する。
76
+ * 指定したテーブルのGroonga::Recordをキーとして使用するこ
77
+ * ともでき、その場合は自動的にGroonga::Recordからレコード
78
+ * IDを取得する。
79
+ *
80
+ * 省略した場合は文字列をキーとして使用する。この場合、
81
+ * 4096バイトまで使用可能である。
82
+ *
83
+ * [+:value_size+]
84
+ * 値の大きさを指定する。省略すると0になる。
85
+ *
86
+ * [+:default_tokenizer+]
87
+ * Groonga::IndexColumnで使用するトークナイザを指定する。
88
+ * デフォルトでは何も設定されていないので、テーブルに
89
+ * Groonga::IndexColumnを定義する場合は
90
+ * <tt>"<token:bigram>"</tt>などを指定する必要がある。
91
+ *
92
+ * 使用例:
93
+ *
94
+ * 無名一時テーブルを生成する。
95
+ * Groonga::Hash.create
96
+ *
97
+ * 無名永続テーブルを生成する。
98
+ * Groonga::Hash.create(:path => "/tmp/hash.grn")
99
+ *
100
+ * 名前付き永続テーブルを生成する。ただし、ファイル名は気に
101
+ * しない。
102
+ * Groonga::Hash.create(:name => "<bookmarks>",
103
+ * :persistent => true)
104
+ *
105
+ * それぞれのレコードに512バイトの値を格納できる無名一時テー
106
+ * ブルを生成する。
107
+ * Groonga::Hash.create(:value => 512)
108
+ *
109
+ * キーとして文字列を使用する無名一時テーブルを生成する。
110
+ * Groonga::Hash.create(:key_type => Groonga::Type::TEXT)
111
+ *
112
+ * キーとして文字列を使用する無名一時テーブルを生成する。
113
+ * (キーの種類を表すオブジェクトは文字列で指定。)
114
+ * Groonga::Hash.create(:key_type => "<shorttext>")
115
+ *
116
+ * キーとして<tt><bookmarks></tt>テーブルのレコードを使用す
117
+ * る無名一時テーブルを生成する。
118
+ * bookmarks = Groonga::Hash.create(:name => "<bookmarks>")
119
+ * Groonga::Hash.create(:key_type => bookmarks)
120
+ *
121
+ * キーとして<tt><bookmarks></tt>テーブルのレコードを使用す
122
+ * る無名一時テーブルを生成する。
123
+ * (テーブルは文字列で指定。)
124
+ * Groonga::Hash.create(:name => "<bookmarks>")
125
+ * Groonga::Hash.create(:key_type => "<bookmarks>")
126
+ *
127
+ * 全文検索用のトークンをバイグラムで切り出す無名一時テーブ
128
+ * ルを生成する。
129
+ * bookmarks = Groonga::Hash.create(:name => "<bookmarks>")
130
+ * bookmarks.define_column("comment", "<text>")
131
+ * terms = Groonga::Hash.create(:name => "<terms>",
132
+ * :default_tokenizer => "<token:bigram>")
133
+ * terms.define_index_column("content", bookmarks,
134
+ * :source => "<bookmarks>.comment")
135
+ */
25
136
  static VALUE
26
137
  rb_grn_hash_s_create (int argc, VALUE *argv, VALUE self)
27
138
  {
28
- return rb_grn_table_s_create(argc, argv, self, GRN_TABLE_HASH_KEY);
139
+ grn_ctx *context;
140
+ grn_obj *key_type = NULL, *table;
141
+ const char *name = NULL, *path = NULL;
142
+ unsigned name_size = 0, value_size = 0;
143
+ grn_obj_flags flags = GRN_TABLE_HASH_KEY;
144
+ VALUE rb_table;
145
+ VALUE options, rb_context, rb_name, rb_path, rb_persistent;
146
+ VALUE rb_key_type, rb_value_size, rb_default_tokenizer;
147
+
148
+ rb_scan_args(argc, argv, "01", &options);
149
+
150
+ rb_grn_scan_options(options,
151
+ "context", &rb_context,
152
+ "name", &rb_name,
153
+ "path", &rb_path,
154
+ "persistent", &rb_persistent,
155
+ "key_type", &rb_key_type,
156
+ "value_size", &rb_value_size,
157
+ "default_tokenizer", &rb_default_tokenizer,
158
+ NULL);
159
+
160
+ context = rb_grn_context_ensure(&rb_context);
161
+
162
+ if (!NIL_P(rb_name)) {
163
+ name = StringValuePtr(rb_name);
164
+ name_size = RSTRING_LEN(rb_name);
165
+ }
166
+
167
+ if (!NIL_P(rb_path)) {
168
+ path = StringValueCStr(rb_path);
169
+ flags |= GRN_OBJ_PERSISTENT;
170
+ }
171
+
172
+ if (RVAL2CBOOL(rb_persistent))
173
+ flags |= GRN_OBJ_PERSISTENT;
174
+
175
+ if (NIL_P(rb_key_type)) {
176
+ flags |= GRN_OBJ_KEY_VAR_SIZE;
177
+ } else {
178
+ key_type = RVAL2GRNOBJECT(rb_key_type, &context);
179
+ }
180
+
181
+ if (!NIL_P(rb_value_size))
182
+ value_size = NUM2UINT(rb_value_size);
183
+
184
+ table = grn_table_create(context, name, name_size, path,
185
+ flags, key_type, value_size);
186
+ if (!table)
187
+ rb_grn_context_check(context, rb_ary_new4(argc, argv));
188
+ rb_table = rb_grn_table_key_support_alloc(self);
189
+ rb_grn_table_key_support_assign(rb_table, rb_context, context, table,
190
+ RB_GRN_TRUE);
191
+ rb_grn_context_check(context, rb_table);
192
+
193
+ if (!NIL_P(rb_default_tokenizer))
194
+ rb_funcall(rb_table, rb_intern("default_tokenizer="), 1,
195
+ rb_default_tokenizer);
196
+
197
+ if (rb_block_given_p())
198
+ return rb_ensure(rb_yield, rb_table, rb_grn_object_close, rb_table);
199
+ else
200
+ return rb_table;
201
+ }
202
+
203
+ /*
204
+ * call-seq:
205
+ * hash.search(key, options=nil) -> Groonga::Hash
206
+ *
207
+ * _key_にマッチするレコードのIDがキーに入っている
208
+ * Groonga::Hashを返す。マッチするレコードがない場合は空の
209
+ * Groonga::Hashが返。
210
+ *
211
+ * _options_で+:result+を指定することにより、そのテーブルにマッ
212
+ * チしたレコードIDがキーのレコードを追加することができる。
213
+ * +:result+にテーブルを指定した場合は、そのテーブルが返る。
214
+ *
215
+ * _options_に指定可能な値は以下の通り。
216
+ *
217
+ * [+:result+]
218
+ * 結果を格納するテーブル。
219
+ *
220
+ * 複数のキーで検索し、結果を1つのテーブルに集める。
221
+ * result = nil
222
+ * keys = ["morita", "gunyara-kun", "yu"]
223
+ * keys.each do |key|
224
+ * result = users.search(key, :result => result)
225
+ * end
226
+ * result.each do |record|
227
+ * user = record.key
228
+ * p user.key # -> "morita"または"gunyara-kun"または"yu"
229
+ * end
230
+ */
231
+ static VALUE
232
+ rb_grn_hash_search (int argc, VALUE *argv, VALUE self)
233
+ {
234
+ grn_rc rc;
235
+ grn_ctx *context;
236
+ grn_obj *table;
237
+ grn_id domain_id;
238
+ grn_obj *key, *domain, *result;
239
+ VALUE rb_key, options, rb_result;
240
+
241
+ rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
242
+ &key, &domain_id, &domain,
243
+ NULL, NULL, NULL);
244
+
245
+ rb_scan_args(argc, argv, "11", &rb_key, &options);
246
+
247
+ RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self);
248
+
249
+ rb_grn_scan_options(options,
250
+ "result", &rb_result,
251
+ NULL);
252
+
253
+ if (NIL_P(rb_result)) {
254
+ result = grn_table_create(context, NULL, 0, NULL,
255
+ GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
256
+ table, 0);
257
+ rb_grn_context_check(context, self);
258
+ rb_result = GRNOBJECT2RVAL(Qnil, context, result, RB_GRN_TRUE);
259
+ } else {
260
+ result = RVAL2GRNOBJECT(rb_result, &context);
261
+ }
262
+
263
+ rc = grn_obj_search(context, table, key,
264
+ result, GRN_SEL_OR, NULL);
265
+ rb_grn_rc_check(rc, self);
266
+
267
+ return rb_result;
29
268
  }
30
269
 
31
270
  void
32
271
  rb_grn_init_hash (VALUE mGrn)
33
272
  {
34
273
  rb_cGrnHash = rb_define_class_under(mGrn, "Hash", rb_cGrnTable);
274
+ rb_define_alloc_func(rb_cGrnHash, rb_grn_table_key_support_alloc);
35
275
 
36
276
  rb_include_module(rb_cGrnHash, rb_mGrnTableKeySupport);
37
277
 
38
278
  rb_define_singleton_method(rb_cGrnHash, "create",
39
279
  rb_grn_hash_s_create, -1);
280
+
281
+ rb_define_method(rb_cGrnHash, "search", rb_grn_hash_search, -1);
40
282
  }