rroonga 0.9.2-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. data/AUTHORS +5 -0
  2. data/NEWS.ja.rdoc +114 -0
  3. data/NEWS.rdoc +116 -0
  4. data/README.ja.rdoc +65 -0
  5. data/README.rdoc +66 -0
  6. data/Rakefile +217 -0
  7. data/benchmark/common.rb +49 -0
  8. data/benchmark/read-write-many-small-items.rb +144 -0
  9. data/benchmark/write-many-small-items.rb +135 -0
  10. data/example/bookmark.rb +161 -0
  11. data/example/index-html.rb +89 -0
  12. data/example/search/config.ru +211 -0
  13. data/example/search/public/css/groonga.css +122 -0
  14. data/ext/.gitignore +2 -0
  15. data/ext/libruby-groonga.a +0 -0
  16. data/ext/rb-grn-accessor.c +52 -0
  17. data/ext/rb-grn-array-cursor.c +36 -0
  18. data/ext/rb-grn-array.c +210 -0
  19. data/ext/rb-grn-column.c +573 -0
  20. data/ext/rb-grn-context.c +655 -0
  21. data/ext/rb-grn-database.c +472 -0
  22. data/ext/rb-grn-encoding-support.c +64 -0
  23. data/ext/rb-grn-encoding.c +257 -0
  24. data/ext/rb-grn-exception.c +1110 -0
  25. data/ext/rb-grn-expression-builder.c +75 -0
  26. data/ext/rb-grn-expression.c +735 -0
  27. data/ext/rb-grn-fix-size-column.c +166 -0
  28. data/ext/rb-grn-hash-cursor.c +38 -0
  29. data/ext/rb-grn-hash.c +294 -0
  30. data/ext/rb-grn-index-column.c +488 -0
  31. data/ext/rb-grn-logger.c +504 -0
  32. data/ext/rb-grn-object.c +1369 -0
  33. data/ext/rb-grn-operation.c +198 -0
  34. data/ext/rb-grn-patricia-trie-cursor.c +39 -0
  35. data/ext/rb-grn-patricia-trie.c +488 -0
  36. data/ext/rb-grn-procedure.c +52 -0
  37. data/ext/rb-grn-query.c +260 -0
  38. data/ext/rb-grn-record.c +40 -0
  39. data/ext/rb-grn-snippet.c +334 -0
  40. data/ext/rb-grn-table-cursor-key-support.c +69 -0
  41. data/ext/rb-grn-table-cursor.c +247 -0
  42. data/ext/rb-grn-table-key-support.c +731 -0
  43. data/ext/rb-grn-table.c +2141 -0
  44. data/ext/rb-grn-type.c +181 -0
  45. data/ext/rb-grn-utils.c +769 -0
  46. data/ext/rb-grn-variable-size-column.c +36 -0
  47. data/ext/rb-grn-variable.c +108 -0
  48. data/ext/rb-grn-view-accessor.c +53 -0
  49. data/ext/rb-grn-view-cursor.c +35 -0
  50. data/ext/rb-grn-view-record.c +41 -0
  51. data/ext/rb-grn-view.c +421 -0
  52. data/ext/rb-grn.h +700 -0
  53. data/ext/rb-groonga.c +117 -0
  54. data/extconf.rb +266 -0
  55. data/html/bar.svg +153 -0
  56. data/html/developer.html +117 -0
  57. data/html/developer.svg +469 -0
  58. data/html/download.svg +253 -0
  59. data/html/favicon.ico +0 -0
  60. data/html/favicon.xcf +0 -0
  61. data/html/footer.html.erb +28 -0
  62. data/html/head.html.erb +4 -0
  63. data/html/header.html.erb +17 -0
  64. data/html/index.html +147 -0
  65. data/html/install.svg +636 -0
  66. data/html/logo.xcf +0 -0
  67. data/html/ranguba.css +250 -0
  68. data/html/tutorial.svg +559 -0
  69. data/lib/groonga.rb +90 -0
  70. data/lib/groonga/context.rb +184 -0
  71. data/lib/groonga/expression-builder.rb +285 -0
  72. data/lib/groonga/patricia-trie.rb +53 -0
  73. data/lib/groonga/record.rb +311 -0
  74. data/lib/groonga/schema.rb +1191 -0
  75. data/lib/groonga/view-record.rb +56 -0
  76. data/license/GPL +340 -0
  77. data/license/LGPL +504 -0
  78. data/license/RUBY +59 -0
  79. data/misc/grnop2ruby.rb +49 -0
  80. data/pkg-config.rb +333 -0
  81. data/test-unit/Rakefile +40 -0
  82. data/test-unit/TODO +5 -0
  83. data/test-unit/bin/testrb +5 -0
  84. data/test-unit/html/classic.html +15 -0
  85. data/test-unit/html/index.html +25 -0
  86. data/test-unit/html/index.html.ja +27 -0
  87. data/test-unit/lib/test/unit.rb +323 -0
  88. data/test-unit/lib/test/unit/assertionfailederror.rb +25 -0
  89. data/test-unit/lib/test/unit/assertions.rb +1230 -0
  90. data/test-unit/lib/test/unit/attribute.rb +125 -0
  91. data/test-unit/lib/test/unit/autorunner.rb +360 -0
  92. data/test-unit/lib/test/unit/collector.rb +36 -0
  93. data/test-unit/lib/test/unit/collector/descendant.rb +23 -0
  94. data/test-unit/lib/test/unit/collector/dir.rb +108 -0
  95. data/test-unit/lib/test/unit/collector/load.rb +136 -0
  96. data/test-unit/lib/test/unit/collector/objectspace.rb +34 -0
  97. data/test-unit/lib/test/unit/color-scheme.rb +102 -0
  98. data/test-unit/lib/test/unit/color.rb +96 -0
  99. data/test-unit/lib/test/unit/diff.rb +724 -0
  100. data/test-unit/lib/test/unit/error.rb +130 -0
  101. data/test-unit/lib/test/unit/exceptionhandler.rb +39 -0
  102. data/test-unit/lib/test/unit/failure.rb +136 -0
  103. data/test-unit/lib/test/unit/fixture.rb +176 -0
  104. data/test-unit/lib/test/unit/notification.rb +129 -0
  105. data/test-unit/lib/test/unit/omission.rb +191 -0
  106. data/test-unit/lib/test/unit/pending.rb +150 -0
  107. data/test-unit/lib/test/unit/priority.rb +180 -0
  108. data/test-unit/lib/test/unit/runner/console.rb +52 -0
  109. data/test-unit/lib/test/unit/runner/emacs.rb +8 -0
  110. data/test-unit/lib/test/unit/runner/tap.rb +8 -0
  111. data/test-unit/lib/test/unit/testcase.rb +476 -0
  112. data/test-unit/lib/test/unit/testresult.rb +89 -0
  113. data/test-unit/lib/test/unit/testsuite.rb +110 -0
  114. data/test-unit/lib/test/unit/ui/console/outputlevel.rb +14 -0
  115. data/test-unit/lib/test/unit/ui/console/testrunner.rb +466 -0
  116. data/test-unit/lib/test/unit/ui/emacs/testrunner.rb +63 -0
  117. data/test-unit/lib/test/unit/ui/tap/testrunner.rb +92 -0
  118. data/test-unit/lib/test/unit/ui/testrunner.rb +28 -0
  119. data/test-unit/lib/test/unit/ui/testrunnermediator.rb +77 -0
  120. data/test-unit/lib/test/unit/ui/testrunnerutilities.rb +41 -0
  121. data/test-unit/lib/test/unit/util/backtracefilter.rb +41 -0
  122. data/test-unit/lib/test/unit/util/method-owner-finder.rb +28 -0
  123. data/test-unit/lib/test/unit/util/observable.rb +90 -0
  124. data/test-unit/lib/test/unit/util/procwrapper.rb +48 -0
  125. data/test-unit/lib/test/unit/version.rb +7 -0
  126. data/test-unit/sample/adder.rb +13 -0
  127. data/test-unit/sample/subtracter.rb +12 -0
  128. data/test-unit/sample/test_adder.rb +20 -0
  129. data/test-unit/sample/test_subtracter.rb +20 -0
  130. data/test-unit/sample/test_user.rb +23 -0
  131. data/test-unit/test/collector/test-descendant.rb +133 -0
  132. data/test-unit/test/collector/test-load.rb +348 -0
  133. data/test-unit/test/collector/test_dir.rb +406 -0
  134. data/test-unit/test/collector/test_objectspace.rb +100 -0
  135. data/test-unit/test/run-test.rb +15 -0
  136. data/test-unit/test/test-attribute.rb +86 -0
  137. data/test-unit/test/test-color-scheme.rb +67 -0
  138. data/test-unit/test/test-color.rb +47 -0
  139. data/test-unit/test/test-diff.rb +518 -0
  140. data/test-unit/test/test-emacs-runner.rb +60 -0
  141. data/test-unit/test/test-fixture.rb +287 -0
  142. data/test-unit/test/test-notification.rb +33 -0
  143. data/test-unit/test/test-omission.rb +81 -0
  144. data/test-unit/test/test-pending.rb +70 -0
  145. data/test-unit/test/test-priority.rb +119 -0
  146. data/test-unit/test/test-testcase.rb +544 -0
  147. data/test-unit/test/test_assertions.rb +1151 -0
  148. data/test-unit/test/test_error.rb +26 -0
  149. data/test-unit/test/test_failure.rb +33 -0
  150. data/test-unit/test/test_testresult.rb +113 -0
  151. data/test-unit/test/test_testsuite.rb +129 -0
  152. data/test-unit/test/testunit-test-util.rb +14 -0
  153. data/test-unit/test/ui/test_testrunmediator.rb +20 -0
  154. data/test-unit/test/util/test-method-owner-finder.rb +38 -0
  155. data/test-unit/test/util/test_backtracefilter.rb +41 -0
  156. data/test-unit/test/util/test_observable.rb +102 -0
  157. data/test-unit/test/util/test_procwrapper.rb +36 -0
  158. data/test/.gitignore +1 -0
  159. data/test/groonga-test-utils.rb +133 -0
  160. data/test/run-test.rb +58 -0
  161. data/test/test-array.rb +97 -0
  162. data/test/test-column.rb +316 -0
  163. data/test/test-context-select.rb +93 -0
  164. data/test/test-context.rb +73 -0
  165. data/test/test-database.rb +113 -0
  166. data/test/test-encoding.rb +33 -0
  167. data/test/test-exception.rb +93 -0
  168. data/test/test-expression-builder.rb +156 -0
  169. data/test/test-expression.rb +134 -0
  170. data/test/test-fix-size-column.rb +65 -0
  171. data/test/test-gqtp.rb +72 -0
  172. data/test/test-hash.rb +312 -0
  173. data/test/test-index-column.rb +81 -0
  174. data/test/test-logger.rb +37 -0
  175. data/test/test-patricia-trie.rb +189 -0
  176. data/test/test-procedure.rb +37 -0
  177. data/test/test-query.rb +22 -0
  178. data/test/test-record.rb +279 -0
  179. data/test/test-remote.rb +54 -0
  180. data/test/test-schema-view.rb +90 -0
  181. data/test/test-schema.rb +459 -0
  182. data/test/test-snippet.rb +130 -0
  183. data/test/test-table-cursor.rb +153 -0
  184. data/test/test-table-offset-and-limit.rb +102 -0
  185. data/test/test-table-select-normalize.rb +53 -0
  186. data/test/test-table-select.rb +150 -0
  187. data/test/test-table.rb +690 -0
  188. data/test/test-type.rb +71 -0
  189. data/test/test-variable-size-column.rb +98 -0
  190. data/test/test-variable.rb +28 -0
  191. data/test/test-vector-column.rb +76 -0
  192. data/test/test-version.rb +31 -0
  193. data/test/test-view.rb +72 -0
  194. data/text/TUTORIAL.ja.rdoc +392 -0
  195. data/text/expression.rdoc +284 -0
  196. data/vendor/local/bin/grntest.exe +0 -0
  197. data/vendor/local/bin/groonga.exe +0 -0
  198. data/vendor/local/bin/libgroonga.dll +0 -0
  199. data/vendor/local/bin/libmecab.dll +0 -0
  200. data/vendor/local/include/groonga.h +2285 -0
  201. data/vendor/local/lib/libgroonga.lib +0 -0
  202. metadata +280 -0
@@ -0,0 +1,2141 @@
1
+ /* -*- c-file-style: "ruby" -*- */
2
+ /*
3
+ Copyright (C) 2009-2010 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
+ grn_obj *grn_table_open(grn_ctx *ctx,
22
+ const char *name, unsigned name_size, const char *path);
23
+ grn_obj *grn_column_open(grn_ctx *ctx, grn_obj *table,
24
+ const char *name, unsigned name_size,
25
+ const char *path, grn_obj *type);
26
+
27
+ #define SELF(object) ((RbGrnTable *)DATA_PTR(object))
28
+
29
+ VALUE rb_cGrnTable;
30
+
31
+ static ID id_array_reference;
32
+ static ID id_array_set;
33
+
34
+ /*
35
+ * Document-class: Groonga::Table < Groonga::Object
36
+ *
37
+ * Ruby/groongaが提供するテーブルのベースとなるクラス。このクラス
38
+ * からGroonga::Array, Groonga::Hash, Groonga::PatriciaTrie
39
+ * が継承されている。
40
+ */
41
+
42
+ grn_obj *
43
+ rb_grn_table_from_ruby_object (VALUE object, grn_ctx **context)
44
+ {
45
+ if (!RVAL2CBOOL(rb_obj_is_kind_of(object, rb_cGrnTable))) {
46
+ rb_raise(rb_eTypeError, "not a groonga table");
47
+ }
48
+
49
+ return RVAL2GRNOBJECT(object, context);
50
+ }
51
+
52
+ VALUE
53
+ rb_grn_table_to_ruby_object (grn_ctx *context, grn_obj *table,
54
+ rb_grn_boolean owner)
55
+ {
56
+ return GRNOBJECT2RVAL(Qnil, context, table, owner);
57
+ }
58
+
59
+ void
60
+ rb_grn_table_finalizer (grn_ctx *context, grn_obj *object,
61
+ RbGrnTable *rb_grn_table)
62
+ {
63
+ if (context && rb_grn_table->value)
64
+ grn_obj_unlink(context, rb_grn_table->value);
65
+ rb_grn_table->value = NULL;
66
+ rb_grn_table->columns = Qnil;
67
+ }
68
+
69
+ void
70
+ rb_grn_table_bind (RbGrnTable *rb_grn_table,
71
+ grn_ctx *context, grn_obj *table)
72
+ {
73
+ RbGrnObject *rb_grn_object;
74
+
75
+ rb_grn_object = RB_GRN_OBJECT(rb_grn_table);
76
+ rb_grn_table->value = grn_obj_open(context, GRN_BULK, 0,
77
+ rb_grn_object->range_id);
78
+ rb_grn_table->columns = rb_ary_new();
79
+ }
80
+
81
+ void
82
+ rb_grn_table_deconstruct (RbGrnTable *rb_grn_table,
83
+ grn_obj **table,
84
+ grn_ctx **context,
85
+ grn_id *domain_id,
86
+ grn_obj **domain,
87
+ grn_obj **value,
88
+ grn_id *range_id,
89
+ grn_obj **range,
90
+ VALUE *columns)
91
+ {
92
+ RbGrnObject *rb_grn_object;
93
+
94
+ rb_grn_object = RB_GRN_OBJECT(rb_grn_table);
95
+ rb_grn_object_deconstruct(rb_grn_object, table, context,
96
+ domain_id, domain,
97
+ range_id, range);
98
+
99
+ if (value)
100
+ *value = rb_grn_table->value;
101
+ if (columns)
102
+ *columns = rb_grn_table->columns;
103
+ }
104
+
105
+ static void
106
+ rb_grn_table_mark (void *data)
107
+ {
108
+ RbGrnObject *rb_grn_object = data;
109
+ RbGrnTable *rb_grn_table = data;
110
+ grn_ctx *context;
111
+ grn_obj *table;
112
+
113
+ if (!rb_grn_object)
114
+ return;
115
+
116
+ rb_gc_mark(rb_grn_table->columns);
117
+
118
+ context = rb_grn_object->context;
119
+ table = rb_grn_object->object;
120
+ if (!context || !table)
121
+ return;
122
+
123
+ if (!grn_obj_path(context, table))
124
+ return;
125
+
126
+ if (grn_obj_name(context, table, NULL, 0) == 0)
127
+ return;
128
+ }
129
+
130
+ static VALUE
131
+ rb_grn_table_alloc (VALUE klass)
132
+ {
133
+ return Data_Wrap_Struct(klass, rb_grn_table_mark, rb_grn_object_free, NULL);
134
+ }
135
+
136
+ grn_obj *
137
+ rb_grn_table_open_raw (int argc, VALUE *argv,
138
+ grn_ctx **context, VALUE *rb_context)
139
+ {
140
+ grn_obj *table = NULL;
141
+
142
+ #ifdef WIN32
143
+ rb_raise(rb_eNotImpError, "grn_table_open() isn't available on Windows.");
144
+ #else
145
+ char *name = NULL, *path = NULL;
146
+ unsigned name_size = 0;
147
+ VALUE rb_path, options, rb_name;
148
+
149
+ rb_scan_args(argc, argv, "01", &options);
150
+
151
+ rb_grn_scan_options(options,
152
+ "context", rb_context,
153
+ "name", &rb_name,
154
+ "path", &rb_path,
155
+ NULL);
156
+
157
+ *context = rb_grn_context_ensure(rb_context);
158
+
159
+ if (!NIL_P(rb_name)) {
160
+ name = StringValuePtr(rb_name);
161
+ name_size = RSTRING_LEN(rb_name);
162
+ }
163
+
164
+ if (!NIL_P(rb_path))
165
+ path = StringValueCStr(rb_path);
166
+
167
+ table = grn_table_open(*context, name, name_size, path);
168
+ #endif
169
+
170
+ return table;
171
+ }
172
+
173
+ static VALUE
174
+ rb_grn_table_initialize (int argc, VALUE *argv, VALUE self)
175
+ {
176
+ grn_ctx *context = NULL;
177
+ grn_obj *table;
178
+ VALUE rb_context;
179
+
180
+ table = rb_grn_table_open_raw(argc, argv, &context, &rb_context);
181
+ rb_grn_object_assign(Qnil, self, rb_context, context, table);
182
+ rb_grn_context_check(context, self);
183
+
184
+ return Qnil;
185
+ }
186
+
187
+ /*
188
+ * call-seq:
189
+ * Groonga::Table.open(options={}) -> Groonga::Table
190
+ * Groonga::Table.open(options={}) {|table| ... }
191
+ *
192
+ * 既存のテーブルを開く。ブロックを指定すると、そのブロック
193
+ * に開かれたテーブルが渡され、ブロックを抜けると自動的にテ
194
+ * ーブルが破棄される。
195
+ *
196
+ * _options_に指定可能な値は以下の通り。
197
+ *
198
+ * [+:context+]
199
+ * テーブルが利用するGroonga::Context。省略すると
200
+ * Groonga::Context.defaultを用いる。
201
+ *
202
+ * [+:name+]
203
+ * 開こうとするテーブルの名前。
204
+ *
205
+ * [+:path+]
206
+ * 開こうとするテーブルのパス。
207
+ */
208
+ static VALUE
209
+ rb_grn_table_s_open (int argc, VALUE *argv, VALUE klass)
210
+ {
211
+ grn_user_data *user_data;
212
+ VALUE rb_table = Qnil;
213
+ grn_obj *table;
214
+ grn_ctx *context = NULL;
215
+ VALUE rb_context;
216
+
217
+ table = rb_grn_table_open_raw(argc, argv, &context, &rb_context);
218
+ rb_grn_context_check(context, rb_ary_new4(argc, argv));
219
+
220
+ if (!table)
221
+ rb_raise(rb_eGrnError,
222
+ "unable to open table: %s: %s",
223
+ rb_grn_inspect(klass),
224
+ rb_grn_inspect(rb_ary_new4(argc, argv)));
225
+
226
+ user_data = grn_obj_user_data(context, table);
227
+ if (user_data && user_data->ptr) {
228
+ rb_table = RB_GRN_OBJECT(user_data->ptr)->self;
229
+ } else {
230
+ if (klass == rb_cGrnTable) {
231
+ klass = GRNOBJECT2RCLASS(table);
232
+ } else {
233
+ VALUE rb_class;
234
+
235
+ rb_class = GRNOBJECT2RCLASS(table);
236
+ if (rb_class != klass) {
237
+ rb_raise(rb_eTypeError,
238
+ "unexpected existing table type: %s: expected %s",
239
+ rb_grn_inspect(rb_class),
240
+ rb_grn_inspect(klass));
241
+ }
242
+ }
243
+
244
+ rb_table = GRNOBJECT2RVAL(klass, context, table, RB_GRN_TRUE);
245
+ }
246
+
247
+ if (rb_block_given_p())
248
+ return rb_ensure(rb_yield, rb_table, rb_grn_object_close, rb_table);
249
+ else
250
+ return rb_table;
251
+ }
252
+
253
+ static VALUE
254
+ rb_grn_table_inspect_content (VALUE self, VALUE inspected)
255
+ {
256
+ RbGrnTable *rb_grn_table;
257
+ grn_ctx *context = NULL;
258
+ grn_obj *table;
259
+ VALUE columns;
260
+
261
+ rb_grn_table = SELF(self);
262
+ if (!rb_grn_table)
263
+ return inspected;
264
+
265
+ rb_grn_table_deconstruct(rb_grn_table, &table, &context,
266
+ NULL, NULL,
267
+ NULL, NULL, NULL,
268
+ &columns);
269
+
270
+ if (!table)
271
+ return inspected;
272
+ if (!context)
273
+ return inspected;
274
+
275
+ if (table->header.type != GRN_TABLE_NO_KEY) {
276
+ grn_obj value;
277
+ grn_encoding encoding;
278
+
279
+ rb_str_cat2(inspected, ", ");
280
+ rb_str_cat2(inspected, "encoding: <");
281
+ GRN_OBJ_INIT(&value, GRN_BULK, 0, GRN_ID_NIL);
282
+ grn_obj_get_info(context, table, GRN_INFO_ENCODING, &value);
283
+ encoding = *((grn_encoding *)GRN_BULK_HEAD(&value));
284
+ grn_obj_unlink(context, &value);
285
+
286
+ if (context->rc == GRN_SUCCESS)
287
+ rb_str_concat(inspected, rb_inspect(GRNENCODING2RVAL(encoding)));
288
+ else
289
+ rb_str_cat2(inspected, "invalid");
290
+
291
+ rb_str_cat2(inspected, ">");
292
+ }
293
+
294
+ rb_str_cat2(inspected, ", ");
295
+ rb_str_cat2(inspected, "size: <");
296
+ {
297
+ char buf[21]; /* ceil(log10(2 ** 64)) + 1('\0') == 21 */
298
+ snprintf(buf, sizeof(buf), "%u", grn_table_size(context, table));
299
+ rb_str_cat2(inspected, buf);
300
+ }
301
+ rb_str_cat2(inspected, ">");
302
+
303
+ /*
304
+ rb_str_cat2(inspected, ", ");
305
+ rb_str_cat2(inspected, "columns: <");
306
+ rb_str_concat(inspected, rb_inspect(columns));
307
+ rb_str_cat2(inspected, ">");
308
+ */
309
+
310
+ return inspected;
311
+ }
312
+
313
+ /*
314
+ * call-seq:
315
+ * _table_.inspect -> String
316
+ *
317
+ * テーブルの中身を人に見やすい文字列で返す。
318
+ */
319
+ static VALUE
320
+ rb_grn_table_inspect (VALUE self)
321
+ {
322
+ VALUE inspected;
323
+
324
+ inspected = rb_str_new2("");
325
+ rb_grn_object_inspect_header(self, inspected);
326
+ rb_grn_object_inspect_content(self, inspected);
327
+ rb_grn_table_inspect_content(self, inspected);
328
+ rb_grn_object_inspect_footer(self, inspected);
329
+
330
+ return inspected;
331
+ }
332
+
333
+ /*
334
+ * call-seq:
335
+ * table.define_column(name, value_type, options={}) ->
336
+ * Groonga::FixSizeColumnかGroonga::VariableSizeColumn
337
+ *
338
+ * テーブルに名前が_name_で型が_value_type_のカラムを定義
339
+ * し、新しく定義されたカラムを返す。
340
+ *
341
+ * _options_に指定可能な値は以下の通り。
342
+ *
343
+ * [+:path+]
344
+ * カラムを保存するパス。
345
+ *
346
+ * [+:persistent+]
347
+ * +true+を指定すると永続カラムとなる。省略した場合は永
348
+ * 続カラムとなる。+:path+を省略した場合は自動的にパスが
349
+ * 付加される。
350
+ *
351
+ * [+:type+]
352
+ * カラムの値の格納方法について指定する。省略した場合は、
353
+ * +:scalar+になる。
354
+ *
355
+ * [+:scalar+]
356
+ * スカラ値(単独の値)を格納する。
357
+ *
358
+ * [+:vector+]
359
+ * 値の配列を格納する。
360
+ *
361
+ * [+:compress+]
362
+ * 値の圧縮方法を指定する。省略した場合は、圧縮しない。
363
+ *
364
+ * [+:zlib+]
365
+ * 値をzlib圧縮して格納する。
366
+ *
367
+ * [+:lzo+]
368
+ * 値をlzo圧縮して格納する。
369
+ */
370
+ static VALUE
371
+ rb_grn_table_define_column (int argc, VALUE *argv, VALUE self)
372
+ {
373
+ grn_ctx *context = NULL;
374
+ grn_obj *table;
375
+ grn_obj *value_type, *column;
376
+ char *name = NULL, *path = NULL;
377
+ unsigned name_size = 0;
378
+ grn_obj_flags flags = 0;
379
+ VALUE rb_name, rb_value_type;
380
+ VALUE options, rb_path, rb_persistent, rb_compress, rb_type;
381
+ VALUE columns;
382
+ VALUE rb_column;
383
+
384
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
385
+ NULL, NULL,
386
+ NULL, NULL, NULL,
387
+ &columns);
388
+
389
+ rb_scan_args(argc, argv, "21", &rb_name, &rb_value_type, &options);
390
+
391
+ name = StringValuePtr(rb_name);
392
+ name_size = RSTRING_LEN(rb_name);
393
+
394
+ rb_grn_scan_options(options,
395
+ "path", &rb_path,
396
+ "persistent", &rb_persistent,
397
+ "type", &rb_type,
398
+ "compress", &rb_compress,
399
+ NULL);
400
+
401
+ value_type = RVAL2GRNOBJECT(rb_value_type, &context);
402
+
403
+ if ((NIL_P(rb_persistent) && grn_obj_path(context, table)) ||
404
+ RVAL2CBOOL(rb_persistent)) {
405
+ flags |= GRN_OBJ_PERSISTENT;
406
+ }
407
+
408
+ if (!NIL_P(rb_path)) {
409
+ path = StringValueCStr(rb_path);
410
+ if ((flags & GRN_OBJ_PERSISTENT) != GRN_OBJ_PERSISTENT) {
411
+ rb_raise(rb_eArgError,
412
+ "should not pass :path if :persistent is false: <%s>",
413
+ path);
414
+ }
415
+ flags |= GRN_OBJ_PERSISTENT;
416
+ }
417
+
418
+ if (NIL_P(rb_type) ||
419
+ (rb_grn_equal_option(rb_type, "scalar"))) {
420
+ flags |= GRN_OBJ_COLUMN_SCALAR;
421
+ } else if (rb_grn_equal_option(rb_type, "vector")) {
422
+ flags |= GRN_OBJ_COLUMN_VECTOR;
423
+ } else {
424
+ rb_raise(rb_eArgError,
425
+ "invalid column type: %s: "
426
+ "available types: [:scalar, :vector, nil]",
427
+ rb_grn_inspect(rb_type));
428
+ }
429
+
430
+ if (NIL_P(rb_compress)) {
431
+ } else if (rb_grn_equal_option(rb_compress, "zlib")) {
432
+ flags |= GRN_OBJ_COMPRESS_ZLIB;
433
+ } else if (rb_grn_equal_option(rb_compress, "lzo")) {
434
+ flags |= GRN_OBJ_COMPRESS_LZO;
435
+ } else {
436
+ rb_raise(rb_eArgError,
437
+ "invalid compress type: %s: "
438
+ "available types: [:zlib, :lzo, nil]",
439
+ rb_grn_inspect(rb_compress));
440
+ }
441
+
442
+ column = grn_column_create(context, table, name, name_size,
443
+ path, flags, value_type);
444
+ if (context->rc) {
445
+ rb_grn_context_check(context,
446
+ rb_ary_new3(2, self, rb_ary_new4(argc, argv)));
447
+ }
448
+
449
+ rb_column = GRNCOLUMN2RVAL(Qnil, context, column, RB_GRN_TRUE);
450
+ rb_ary_push(columns, rb_column);
451
+ rb_grn_named_object_set_name(RB_GRN_NAMED_OBJECT(DATA_PTR(rb_column)),
452
+ name, name_size);
453
+
454
+ return rb_column;
455
+ }
456
+
457
+ /*
458
+ * call-seq:
459
+ * table.define_index_column(name, value_type, options={}) -> Groonga::IndexColumn
460
+ *
461
+ * テーブルに名前が_name_で型が_value_type_のインデックスカ
462
+ * ラムを定義し、新しく定義されたカラムを返す。
463
+ *
464
+ * _options_に指定可能な値は以下の通り。
465
+ *
466
+ * [+:path+]
467
+ * カラムを保存するパス。
468
+ *
469
+ * [+:persistent+]
470
+ * +true+を指定すると永続カラムとなる。省略した場合は永
471
+ * 続カラムとなる。+:path+を省略した場合は自動的にパスが
472
+ * 付加される。
473
+ *
474
+ * [+:with_section+]
475
+ * 転置索引にsection(段落情報)を合わせて格納する。
476
+ *
477
+ * [+:with_weight+]
478
+ * 転置索引にweight情報を合わせて格納する。
479
+ *
480
+ * [+:with_position+]
481
+ * 転置索引に出現位置情報を合わせて格納する。
482
+ *
483
+ * [+:source+]
484
+ * インデックス対象となるカラムを指定する。+:sources+との併用はできない。
485
+ *
486
+ * [+:sources+]
487
+ * インデックス対象となる複数のカラムを指定する。+:source+との併用はできない。
488
+ */
489
+ static VALUE
490
+ rb_grn_table_define_index_column (int argc, VALUE *argv, VALUE self)
491
+ {
492
+ grn_ctx *context = NULL;
493
+ grn_obj *table;
494
+ grn_obj *value_type, *column;
495
+ char *name = NULL, *path = NULL;
496
+ unsigned name_size = 0;
497
+ grn_obj_flags flags = GRN_OBJ_COLUMN_INDEX;
498
+ VALUE rb_name, rb_value_type;
499
+ VALUE options, rb_path, rb_persistent;
500
+ VALUE rb_with_section, rb_with_weight, rb_with_position;
501
+ VALUE rb_column, rb_source, rb_sources;
502
+ VALUE columns;
503
+
504
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
505
+ NULL, NULL,
506
+ NULL, NULL, NULL,
507
+ &columns);
508
+
509
+ rb_scan_args(argc, argv, "21", &rb_name, &rb_value_type, &options);
510
+
511
+ name = StringValuePtr(rb_name);
512
+ name_size = RSTRING_LEN(rb_name);
513
+
514
+ rb_grn_scan_options(options,
515
+ "path", &rb_path,
516
+ "persistent", &rb_persistent,
517
+ "with_section", &rb_with_section,
518
+ "with_weight", &rb_with_weight,
519
+ "with_position", &rb_with_position,
520
+ "source", &rb_source,
521
+ "sources", &rb_sources,
522
+ NULL);
523
+
524
+ value_type = RVAL2GRNOBJECT(rb_value_type, &context);
525
+
526
+ if ((NIL_P(rb_persistent) && grn_obj_path(context, table)) ||
527
+ RVAL2CBOOL(rb_persistent)) {
528
+ flags |= GRN_OBJ_PERSISTENT;
529
+ }
530
+
531
+ if (!NIL_P(rb_path)) {
532
+ path = StringValueCStr(rb_path);
533
+ if ((flags & GRN_OBJ_PERSISTENT) != GRN_OBJ_PERSISTENT) {
534
+ rb_raise(rb_eArgError,
535
+ "should not pass :path if :persistent is false: <%s>",
536
+ path);
537
+ }
538
+ flags |= GRN_OBJ_PERSISTENT;
539
+ }
540
+
541
+ if (RVAL2CBOOL(rb_with_section))
542
+ flags |= GRN_OBJ_WITH_SECTION;
543
+
544
+ if (RVAL2CBOOL(rb_with_weight))
545
+ flags |= GRN_OBJ_WITH_WEIGHT;
546
+
547
+ if (NIL_P(rb_with_position) &&
548
+ (table->header.type == GRN_TABLE_HASH_KEY ||
549
+ table->header.type == GRN_TABLE_PAT_KEY)) {
550
+ grn_id tokenizer_id;
551
+ grn_obj *tokenizer;
552
+
553
+ tokenizer = grn_obj_get_info(context, table,
554
+ GRN_INFO_DEFAULT_TOKENIZER,
555
+ NULL);
556
+ tokenizer_id = grn_obj_id(context, tokenizer);
557
+ if ((tokenizer_id == GRN_DB_UNIGRAM) ||
558
+ (tokenizer_id == GRN_DB_BIGRAM) ||
559
+ (tokenizer_id == GRN_DB_TRIGRAM)) {
560
+ rb_with_position = Qtrue;
561
+ }
562
+ }
563
+ if (RVAL2CBOOL(rb_with_position))
564
+ flags |= GRN_OBJ_WITH_POSITION;
565
+
566
+ if (!NIL_P(rb_source) && !NIL_P(rb_sources))
567
+ rb_raise(rb_eArgError, "should not pass both of :source and :sources.");
568
+
569
+ column = grn_column_create(context, table, name, name_size,
570
+ path, flags, value_type);
571
+ if (context->rc) {
572
+ rb_grn_context_check(context,
573
+ rb_ary_new3(2, self, rb_ary_new4(argc, argv)));
574
+ }
575
+
576
+ rb_column = GRNCOLUMN2RVAL(Qnil, context, column, RB_GRN_TRUE);
577
+ if (!NIL_P(rb_source))
578
+ rb_funcall(rb_column, rb_intern("source="), 1, rb_source);
579
+ if (!NIL_P(rb_sources))
580
+ rb_funcall(rb_column, rb_intern("sources="), 1, rb_sources);
581
+
582
+ rb_ary_push(columns, rb_column);
583
+ rb_grn_named_object_set_name(RB_GRN_NAMED_OBJECT(DATA_PTR(rb_column)),
584
+ name, name_size);
585
+
586
+ return rb_column;
587
+ }
588
+
589
+ /*
590
+ * call-seq:
591
+ * table.add_column(name, value_type, path)
592
+ *
593
+ * _value_type_を値の型として、_path_に保存されている永続的
594
+ * なカラムを、テーブルの_name_に対応するカラムとして開く。
595
+ */
596
+ static VALUE
597
+ rb_grn_table_add_column (VALUE self, VALUE rb_name, VALUE rb_value_type,
598
+ VALUE rb_path)
599
+ {
600
+ VALUE rb_column = Qnil;
601
+
602
+ #ifdef WIN32
603
+ rb_raise(rb_eNotImpError, "grn_column_open() isn't available on Windows.");
604
+ #else
605
+ grn_ctx *context = NULL;
606
+ grn_obj *table;
607
+ grn_obj *value_type, *column;
608
+ char *name = NULL, *path = NULL;
609
+ unsigned name_size = 0;
610
+ VALUE columns;
611
+
612
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
613
+ NULL, NULL,
614
+ NULL, NULL, NULL,
615
+ &columns);
616
+
617
+ name = StringValuePtr(rb_name);
618
+ name_size = RSTRING_LEN(rb_name);
619
+
620
+ value_type = RVAL2GRNOBJECT(rb_value_type, &context);
621
+
622
+ path = StringValueCStr(rb_path);
623
+
624
+ column = grn_column_open(context, table, name, name_size,
625
+ path, value_type);
626
+ rb_grn_context_check(context, self);
627
+
628
+ rb_column = GRNCOLUMN2RVAL(Qnil, context, column, RB_GRN_TRUE);
629
+ rb_iv_set(rb_column, "table", self);
630
+ rb_ary_push(columns, rb_column);
631
+ rb_grn_named_object_set_name(RB_GRN_NAMED_OBJECT(DATA_PTR(rb_column)),
632
+ name, name_size);
633
+ #endif
634
+
635
+ return rb_column;
636
+ }
637
+
638
+ static void
639
+ ruby_object_to_column_name (VALUE rb_name,
640
+ const char **name, unsigned *name_size)
641
+ {
642
+ switch (TYPE(rb_name)) {
643
+ case T_SYMBOL:
644
+ *name = rb_id2name(SYM2ID(rb_name));
645
+ *name_size = strlen(*name);
646
+ break;
647
+ case T_STRING:
648
+ *name = StringValuePtr(rb_name);
649
+ *name_size = RSTRING_LEN(rb_name);
650
+ break;
651
+ default:
652
+ rb_raise(rb_eArgError,
653
+ "column name should be String or Symbol: %s",
654
+ rb_grn_inspect(rb_name));
655
+ break;
656
+ }
657
+ }
658
+
659
+ /*
660
+ * call-seq:
661
+ * table.column(name) -> Groonga::Column or nil
662
+ *
663
+ * テーブルの_name_に対応するカラムを返す。カラムが存在しな
664
+ * い場合は+nil+を返す。
665
+ */
666
+ VALUE
667
+ rb_grn_table_get_column (VALUE self, VALUE rb_name)
668
+ {
669
+ grn_user_data *user_data;
670
+ grn_ctx *context = NULL;
671
+ grn_obj *table;
672
+ grn_obj *column;
673
+ const char *name = NULL;
674
+ unsigned name_size = 0;
675
+ rb_grn_boolean owner;
676
+ VALUE rb_column;
677
+ VALUE columns;
678
+ VALUE *raw_columns;
679
+ long i, n;
680
+
681
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
682
+ NULL, NULL,
683
+ NULL, NULL, NULL,
684
+ &columns);
685
+
686
+ ruby_object_to_column_name(rb_name, &name, &name_size);
687
+ raw_columns = RARRAY_PTR(columns);
688
+ n = RARRAY_LEN(columns);
689
+ for (i = 0; i < n; i++) {
690
+ VALUE rb_column = raw_columns[i];
691
+ RbGrnNamedObject *rb_grn_named_object;
692
+
693
+ rb_grn_named_object = RB_GRN_NAMED_OBJECT(DATA_PTR(rb_column));
694
+ if (name_size == rb_grn_named_object->name_size &&
695
+ memcmp(name, rb_grn_named_object->name, name_size) == 0) {
696
+ return rb_column;
697
+ }
698
+ }
699
+
700
+ column = grn_obj_column(context, table, name, name_size);
701
+ rb_grn_context_check(context, self);
702
+ if (!column)
703
+ return Qnil;
704
+
705
+ user_data = grn_obj_user_data(context, column);
706
+ if (user_data) {
707
+ RbGrnObject *rb_grn_object;
708
+ rb_grn_object = user_data->ptr;
709
+ if (rb_grn_object) {
710
+ rb_ary_push(columns, rb_grn_object->self);
711
+ return rb_grn_object->self;
712
+ }
713
+ }
714
+
715
+ owner = column->header.type == GRN_ACCESSOR;
716
+ rb_column = GRNCOLUMN2RVAL(Qnil, context, column, owner);
717
+ if (owner) {
718
+ rb_iv_set(rb_column, "table", self);
719
+ }
720
+ rb_grn_named_object_set_name(RB_GRN_NAMED_OBJECT(DATA_PTR(rb_column)),
721
+ name, name_size);
722
+
723
+ return rb_column;
724
+ }
725
+
726
+ VALUE
727
+ rb_grn_table_get_column_surely (VALUE self, VALUE rb_name)
728
+ {
729
+ VALUE rb_column;
730
+
731
+ rb_column = rb_grn_table_get_column(self, rb_name);
732
+ if (NIL_P(rb_column)) {
733
+ rb_raise(rb_eGrnNoSuchColumn,
734
+ "no such column: <%s>: <%s>",
735
+ rb_grn_inspect(rb_name), rb_grn_inspect(self));
736
+ }
737
+ return rb_column;
738
+ }
739
+
740
+ /*
741
+ * call-seq:
742
+ * table.columns(name=nil) -> Groonga::Columnの配列
743
+ *
744
+ * テーブルの全てのカラムを返す。_name_が指定された場合はカ
745
+ * ラム名の先頭が_name_で始まるカラムを返す。
746
+ */
747
+ static VALUE
748
+ rb_grn_table_get_columns (int argc, VALUE *argv, VALUE self)
749
+ {
750
+ grn_ctx *context = NULL;
751
+ grn_obj *table;
752
+ grn_obj *columns;
753
+ grn_rc rc;
754
+ int n;
755
+ grn_table_cursor *cursor;
756
+ VALUE rb_name, rb_columns;
757
+ char *name = NULL;
758
+ unsigned name_size = 0;
759
+
760
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
761
+ NULL, NULL,
762
+ NULL, NULL, NULL,
763
+ NULL);
764
+
765
+ rb_scan_args(argc, argv, "01", &rb_name);
766
+
767
+ if (!NIL_P(rb_name)) {
768
+ name = StringValuePtr(rb_name);
769
+ name_size = RSTRING_LEN(rb_name);
770
+ }
771
+
772
+ columns = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_HASH_KEY,
773
+ NULL, 0);
774
+ n = grn_table_columns(context, table, name, name_size, columns);
775
+ rb_grn_context_check(context, self);
776
+
777
+ rb_columns = rb_ary_new2(n);
778
+ if (n == 0)
779
+ return rb_columns;
780
+
781
+ cursor = grn_table_cursor_open(context, columns, NULL, 0, NULL, 0,
782
+ 0, -1, GRN_CURSOR_ASCENDING);
783
+ rb_grn_context_check(context, self);
784
+ while (grn_table_cursor_next(context, cursor) != GRN_ID_NIL) {
785
+ void *key;
786
+ grn_id *column_id;
787
+ grn_obj *column;
788
+ VALUE rb_column;
789
+
790
+ grn_table_cursor_get_key(context, cursor, &key);
791
+ column_id = key;
792
+ column = grn_ctx_at(context, *column_id);
793
+ rb_column = GRNOBJECT2RVAL(Qnil, context, column, RB_GRN_FALSE);
794
+ rb_ary_push(rb_columns, rb_column);
795
+ }
796
+ rc = grn_table_cursor_close(context, cursor);
797
+ if (rc != GRN_SUCCESS) {
798
+ rb_grn_context_check(context, self);
799
+ rb_grn_rc_check(rc, self);
800
+ }
801
+
802
+ return rb_columns;
803
+ }
804
+
805
+ /*
806
+ * call-seq:
807
+ * table.have_column?(name) -> true/false
808
+ *
809
+ * テーブルが_name_カラムを持っている場合は+true+を返す。
810
+ */
811
+ static VALUE
812
+ rb_grn_table_have_column (VALUE self, VALUE rb_name)
813
+ {
814
+ grn_ctx *context = NULL;
815
+ grn_obj *table;
816
+ grn_obj *column;
817
+ const char *name = NULL;
818
+ unsigned name_size = 0;
819
+ VALUE result = Qfalse;
820
+
821
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
822
+ NULL, NULL,
823
+ NULL, NULL, NULL,
824
+ NULL);
825
+
826
+ ruby_object_to_column_name(rb_name, &name, &name_size);
827
+ column = grn_obj_column(context, table, name, name_size);
828
+ if (!column)
829
+ return Qfalse;
830
+
831
+ if (column->header.type != GRN_ACCESSOR)
832
+ result = Qtrue;
833
+ grn_obj_unlink(context, column);
834
+
835
+ return result;
836
+ }
837
+
838
+ static grn_table_cursor *
839
+ rb_grn_table_open_grn_cursor (int argc, VALUE *argv, VALUE self,
840
+ grn_ctx **context)
841
+ {
842
+ grn_obj *table;
843
+ grn_table_cursor *cursor;
844
+ void *min_key = NULL, *max_key = NULL;
845
+ unsigned min_key_size = 0, max_key_size = 0;
846
+ int offset = 0, limit = -1;
847
+ int flags = 0;
848
+ VALUE options, rb_min, rb_max, rb_order, rb_greater_than, rb_less_than;
849
+ VALUE rb_offset, rb_limit;
850
+
851
+ rb_grn_table_deconstruct(SELF(self), &table, context,
852
+ NULL, NULL,
853
+ NULL, NULL, NULL,
854
+ NULL);
855
+
856
+ rb_scan_args(argc, argv, "01", &options);
857
+
858
+ rb_grn_scan_options(options,
859
+ "min", &rb_min,
860
+ "max", &rb_max,
861
+ "offset", &rb_offset,
862
+ "limit", &rb_limit,
863
+ "order", &rb_order,
864
+ "greater_than", &rb_greater_than,
865
+ "less_than", &rb_less_than,
866
+ NULL);
867
+
868
+ if (!NIL_P(rb_min)) {
869
+ min_key = StringValuePtr(rb_min);
870
+ min_key_size = RSTRING_LEN(rb_min);
871
+ }
872
+ if (!NIL_P(rb_max)) {
873
+ max_key = StringValuePtr(rb_max);
874
+ max_key_size = RSTRING_LEN(rb_max);
875
+ }
876
+ if (!NIL_P(rb_offset))
877
+ offset = NUM2INT(rb_offset);
878
+ if (!NIL_P(rb_limit))
879
+ limit = NUM2INT(rb_limit);
880
+
881
+ if (NIL_P(rb_order)) {
882
+ } else if (rb_grn_equal_option(rb_order, "asc") ||
883
+ rb_grn_equal_option(rb_order, "ascending")) {
884
+ flags |= GRN_CURSOR_ASCENDING;
885
+ } else if (rb_grn_equal_option(rb_order, "desc") ||
886
+ rb_grn_equal_option(rb_order, "descending")) {
887
+ flags |= GRN_CURSOR_DESCENDING;
888
+ } else {
889
+ rb_raise(rb_eArgError,
890
+ "order should be one of "
891
+ "[:asc, :ascending, :desc, :descending]: %s",
892
+ rb_grn_inspect(rb_order));
893
+ }
894
+
895
+ if (RVAL2CBOOL(rb_greater_than))
896
+ flags |= GRN_CURSOR_GT;
897
+ if (RVAL2CBOOL(rb_less_than))
898
+ flags |= GRN_CURSOR_LT;
899
+
900
+ cursor = grn_table_cursor_open(*context, table,
901
+ min_key, min_key_size,
902
+ max_key, max_key_size,
903
+ offset, limit, flags);
904
+ rb_grn_context_check(*context, self);
905
+
906
+ return cursor;
907
+ }
908
+
909
+ /*
910
+ * call-seq:
911
+ * table.open_cursor(options={}) -> Groonga::TableCursor
912
+ * table.open_cursor(options={}) {|cursor| ... }
913
+ *
914
+ * カーソルを生成して返す。ブロックを指定すると、そのブロッ
915
+ * クに生成したカーソルが渡され、ブロックを抜けると自動的に
916
+ * カーソルが破棄される。
917
+ *
918
+ * _options_に指定可能な値は以下の通り。
919
+ *
920
+ * [+:min+]
921
+ * キーの下限
922
+ *
923
+ * [+:max+]
924
+ * キーの上限
925
+ *
926
+ * [+:offset+]
927
+ * 該当する範囲のレコードのうち、(0ベースで)_:offset_番目
928
+ * からレコードを取り出す。
929
+ *
930
+ * [+:limit+]
931
+ * 該当する範囲のレコードのうち、_:limit_件のみを取り出す。
932
+ * 省略された場合または-1が指定された場合は、全件が指定され
933
+ * たものとみなす。
934
+ *
935
+ * [+:order+]
936
+ * +:asc+または+:ascending+を指定すると昇順にレコードを取
937
+ * り出す。
938
+ * +:desc+または+:descending+を指定すると降順にレコードを
939
+ * 取り出す。
940
+ *
941
+ * [+:greater_than+]
942
+ * +true+を指定すると+:min+で指定した値に一致した[+key+]を
943
+ * 範囲に含まない。
944
+ *
945
+ * [+:less_than+]
946
+ * +true+を指定すると+:max+で指定した値に一致した[+key+]を
947
+ * 範囲に含まない。
948
+ */
949
+ static VALUE
950
+ rb_grn_table_open_cursor (int argc, VALUE *argv, VALUE self)
951
+ {
952
+ grn_ctx *context = NULL;
953
+ grn_table_cursor *cursor;
954
+ VALUE rb_cursor;
955
+
956
+ cursor = rb_grn_table_open_grn_cursor(argc, argv, self, &context);
957
+ rb_cursor = GRNTABLECURSOR2RVAL(Qnil, context, cursor);
958
+ rb_iv_set(rb_cursor, "@table", self); /* FIXME: cursor should mark table */
959
+ if (rb_block_given_p())
960
+ return rb_ensure(rb_yield, rb_cursor, rb_grn_object_close, rb_cursor);
961
+ else
962
+ return rb_cursor;
963
+ }
964
+
965
+ /*
966
+ * call-seq:
967
+ * table.records -> Groonga::Recordの配列
968
+ *
969
+ * テーブルに登録されている全てのレコードが入っている配列を
970
+ * 返す。
971
+ */
972
+ static VALUE
973
+ rb_grn_table_get_records (int argc, VALUE *argv, VALUE self)
974
+ {
975
+ grn_ctx *context = NULL;
976
+ grn_table_cursor *cursor;
977
+ grn_id record_id;
978
+ VALUE records;
979
+
980
+ cursor = rb_grn_table_open_grn_cursor(argc, argv, self, &context);
981
+ records = rb_ary_new();
982
+ while ((record_id = grn_table_cursor_next(context, cursor))) {
983
+ rb_ary_push(records, rb_grn_record_new(self, record_id, Qnil));
984
+ }
985
+ grn_table_cursor_close(context, cursor);
986
+
987
+ return records;
988
+ }
989
+
990
+ /*
991
+ * call-seq:
992
+ * table.size -> レコード数
993
+ *
994
+ * テーブルに登録されているレコード数を返す。
995
+ */
996
+ static VALUE
997
+ rb_grn_table_get_size (VALUE self)
998
+ {
999
+ grn_ctx *context = NULL;
1000
+ grn_obj *table;
1001
+ unsigned int size;
1002
+
1003
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1004
+ NULL, NULL,
1005
+ NULL, NULL, NULL,
1006
+ NULL);
1007
+ size = grn_table_size(context, table);
1008
+ return UINT2NUM(size);
1009
+ }
1010
+
1011
+ /*
1012
+ * call-seq:
1013
+ * table.empty? -> true/false
1014
+ *
1015
+ * テーブルにレコードが登録されていなければ+true+を返す。
1016
+ */
1017
+ static VALUE
1018
+ rb_grn_table_empty_p (VALUE self)
1019
+ {
1020
+ grn_ctx *context = NULL;
1021
+ grn_obj *table;
1022
+ unsigned int size;
1023
+
1024
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1025
+ NULL, NULL,
1026
+ NULL, NULL, NULL,
1027
+ NULL);
1028
+ size = grn_table_size(context, table);
1029
+ return size == 0;
1030
+ }
1031
+
1032
+ /*
1033
+ * call-seq:
1034
+ * table.truncate
1035
+ *
1036
+ * テーブルの全レコードを一括して削除する。
1037
+ */
1038
+ static VALUE
1039
+ rb_grn_table_truncate (VALUE self)
1040
+ {
1041
+ grn_ctx *context = NULL;
1042
+ grn_obj *table;
1043
+ grn_rc rc;
1044
+
1045
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1046
+ NULL, NULL,
1047
+ NULL, NULL, NULL,
1048
+ NULL);
1049
+ rc = grn_table_truncate(context, table);
1050
+ rb_grn_rc_check(rc, self);
1051
+
1052
+ return Qnil;
1053
+ }
1054
+
1055
+ /*
1056
+ * call-seq:
1057
+ * table.each {|record| ...}
1058
+ *
1059
+ * テーブルに登録されているレコードを順番にブロックに渡す。
1060
+ */
1061
+ static VALUE
1062
+ rb_grn_table_each (VALUE self)
1063
+ {
1064
+ RbGrnTable *rb_table;
1065
+ RbGrnObject *rb_grn_object;
1066
+ grn_ctx *context = NULL;
1067
+ grn_obj *table;
1068
+ grn_table_cursor *cursor;
1069
+ VALUE rb_cursor;
1070
+ grn_id id;
1071
+
1072
+ rb_table = SELF(self);
1073
+ rb_grn_table_deconstruct(rb_table, &table, &context,
1074
+ NULL, NULL,
1075
+ NULL, NULL, NULL,
1076
+ NULL);
1077
+ cursor = grn_table_cursor_open(context, table, NULL, 0, NULL, 0,
1078
+ 0, -1, GRN_CURSOR_ASCENDING);
1079
+ rb_cursor = GRNTABLECURSOR2RVAL(Qnil, context, cursor);
1080
+ rb_grn_object = RB_GRN_OBJECT(rb_table);
1081
+ while (rb_grn_object->object &&
1082
+ (id = grn_table_cursor_next(context, cursor)) != GRN_ID_NIL) {
1083
+ rb_yield(rb_grn_record_new(self, id, Qnil));
1084
+ }
1085
+ rb_grn_object_close(rb_cursor);
1086
+
1087
+ return Qnil;
1088
+ }
1089
+
1090
+ /*
1091
+ * call-seq:
1092
+ * table.delete(id)
1093
+ *
1094
+ * テーブルの_id_に対応するレコードを削除する。
1095
+ */
1096
+ VALUE
1097
+ rb_grn_table_delete (VALUE self, VALUE rb_id)
1098
+ {
1099
+ grn_ctx *context = NULL;
1100
+ grn_obj *table;
1101
+ grn_id id;
1102
+ grn_rc rc;
1103
+
1104
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1105
+ NULL, NULL,
1106
+ NULL, NULL, NULL,
1107
+ NULL);
1108
+
1109
+ id = NUM2UINT(rb_id);
1110
+ rc = grn_table_delete_by_id(context, table, id);
1111
+ rb_grn_rc_check(rc, self);
1112
+
1113
+ return Qnil;
1114
+ }
1115
+
1116
+ /*
1117
+ * call-seq:
1118
+ * table.sort(keys, options={}) -> Groonga::Recordの配列
1119
+ *
1120
+ * テーブルに登録されているレコードを_keys_で指定されたルー
1121
+ * ルに従ってソートしたレコードの配列を返す。
1122
+ *
1123
+ * [
1124
+ * {:key => "カラム名", :order => :asc, :ascending,
1125
+ * :desc, :descendingのいずれか},
1126
+ * {:key => "カラム名", :order => :asc, :ascending,
1127
+ * :desc, :descendingのいずれか},
1128
+ * ...,
1129
+ * ]
1130
+ *
1131
+ * _options_に指定可能な値は以下の通り。
1132
+ *
1133
+ * [+:offset+]
1134
+ * ソートされたレコードのうち、(0ベースで)_:offset_番目
1135
+ * からレコードを取り出す。
1136
+ *
1137
+ * [+:limit+]
1138
+ * ソートされたレコードのうち、_:limit_件のみを取り出す。
1139
+ * 省略された場合または-1が指定された場合は、全件が指定され
1140
+ * たものとみなす。
1141
+ */
1142
+ static VALUE
1143
+ rb_grn_table_sort (int argc, VALUE *argv, VALUE self)
1144
+ {
1145
+ grn_ctx *context = NULL;
1146
+ grn_obj *table;
1147
+ grn_obj *result;
1148
+ grn_table_sort_key *keys;
1149
+ int i, n_keys;
1150
+ int n_records, offset = 0, limit = -1;
1151
+ VALUE rb_keys, options;
1152
+ VALUE rb_offset, rb_limit;
1153
+ VALUE *rb_sort_keys;
1154
+ grn_table_cursor *cursor;
1155
+ VALUE rb_result;
1156
+ VALUE exception;
1157
+
1158
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1159
+ NULL, NULL,
1160
+ NULL, NULL, NULL,
1161
+ NULL);
1162
+
1163
+ rb_scan_args(argc, argv, "11", &rb_keys, &options);
1164
+
1165
+ if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_keys, rb_cArray)))
1166
+ rb_raise(rb_eArgError, "keys should be an array of key: <%s>",
1167
+ rb_grn_inspect(rb_keys));
1168
+
1169
+ n_keys = RARRAY_LEN(rb_keys);
1170
+ rb_sort_keys = RARRAY_PTR(rb_keys);
1171
+ keys = ALLOCA_N(grn_table_sort_key, n_keys);
1172
+ for (i = 0; i < n_keys; i++) {
1173
+ VALUE rb_sort_options, rb_key, rb_resolved_key, rb_order;
1174
+
1175
+ if (RVAL2CBOOL(rb_obj_is_kind_of(rb_sort_keys[i], rb_cHash))) {
1176
+ rb_sort_options = rb_sort_keys[i];
1177
+ } else if (RVAL2CBOOL(rb_obj_is_kind_of(rb_sort_keys[i], rb_cArray))) {
1178
+ rb_sort_options = rb_hash_new();
1179
+ rb_hash_aset(rb_sort_options,
1180
+ RB_GRN_INTERN("key"),
1181
+ rb_ary_entry(rb_sort_keys[i], 0));
1182
+ rb_hash_aset(rb_sort_options,
1183
+ RB_GRN_INTERN("order"),
1184
+ rb_ary_entry(rb_sort_keys[i], 1));
1185
+ } else {
1186
+ rb_sort_options = rb_hash_new();
1187
+ rb_hash_aset(rb_sort_options,
1188
+ RB_GRN_INTERN("key"),
1189
+ rb_sort_keys[i]);
1190
+ }
1191
+ rb_grn_scan_options(rb_sort_options,
1192
+ "key", &rb_key,
1193
+ "order", &rb_order,
1194
+ NULL);
1195
+ if (RVAL2CBOOL(rb_obj_is_kind_of(rb_key, rb_cString))) {
1196
+ rb_resolved_key = rb_grn_table_get_column(self, rb_key);
1197
+ } else {
1198
+ rb_resolved_key = rb_key;
1199
+ }
1200
+ keys[i].key = RVAL2GRNOBJECT(rb_resolved_key, &context);
1201
+ if (!keys[i].key) {
1202
+ rb_raise(rb_eGrnNoSuchColumn,
1203
+ "no such column: <%s>: <%s>",
1204
+ rb_grn_inspect(rb_key), rb_grn_inspect(self));
1205
+ }
1206
+ if (NIL_P(rb_order)) {
1207
+ keys[i].flags = 0;
1208
+ } else if (rb_grn_equal_option(rb_order, "desc") ||
1209
+ rb_grn_equal_option(rb_order, "descending")) {
1210
+ keys[i].flags = GRN_TABLE_SORT_DESC;
1211
+ } else if (rb_grn_equal_option(rb_order, "asc") ||
1212
+ rb_grn_equal_option(rb_order, "ascending")) {
1213
+ keys[i].flags = GRN_TABLE_SORT_ASC;
1214
+ } else {
1215
+ rb_raise(rb_eArgError,
1216
+ "order should be one of "
1217
+ "[nil, :desc, :descending, :asc, :ascending]: %s",
1218
+ rb_grn_inspect(rb_order));
1219
+ }
1220
+ }
1221
+
1222
+ rb_grn_scan_options(options,
1223
+ "offset", &rb_offset,
1224
+ "limit", &rb_limit,
1225
+ NULL);
1226
+
1227
+ if (!NIL_P(rb_offset))
1228
+ offset = NUM2INT(rb_offset);
1229
+ if (!NIL_P(rb_limit))
1230
+ limit = NUM2INT(rb_limit);
1231
+
1232
+ result = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_NO_KEY,
1233
+ NULL, table);
1234
+ n_records = grn_table_sort(context, table, offset, limit,
1235
+ result, keys, n_keys);
1236
+ exception = rb_grn_context_to_exception(context, self);
1237
+ if (!NIL_P(exception)) {
1238
+ grn_obj_unlink(context, result);
1239
+ rb_exc_raise(exception);
1240
+ }
1241
+
1242
+ rb_result = rb_ary_new();
1243
+ cursor = grn_table_cursor_open(context, result, NULL, 0, NULL, 0,
1244
+ 0, -1, GRN_CURSOR_ASCENDING);
1245
+ while (grn_table_cursor_next(context, cursor) != GRN_ID_NIL) {
1246
+ void *value;
1247
+ grn_id *id;
1248
+
1249
+ grn_table_cursor_get_value(context, cursor, &value);
1250
+ id = value;
1251
+ rb_ary_push(rb_result, rb_grn_record_new(self, *id, Qnil));
1252
+ }
1253
+ grn_table_cursor_close(context, cursor);
1254
+ grn_obj_unlink(context, result);
1255
+
1256
+ return rb_result;
1257
+ }
1258
+
1259
+ /*
1260
+ * call-seq:
1261
+ * table.group(column, options={}) -> Groonga::Hash
1262
+ * table.group(column1, column2, ..., options={}) -> [Groonga::Hash, ...]
1263
+ *
1264
+ * _table_のレコードを_column1_, _column2_, _..._で指定したカ
1265
+ * ラムの値でグループ化する。カラムはカラム名(文字列)でも
1266
+ * 指定可能。
1267
+ *
1268
+ * このAPIは将来変更されます。
1269
+ */
1270
+ static VALUE
1271
+ rb_grn_table_group (int argc, VALUE *argv, VALUE self)
1272
+ {
1273
+ grn_ctx *context = NULL;
1274
+ grn_obj *table;
1275
+ grn_table_sort_key *keys;
1276
+ grn_table_group_result *results;
1277
+ int i, n_keys, n_results;
1278
+ grn_rc rc;
1279
+ VALUE rb_keys;
1280
+ VALUE *rb_sort_keys;
1281
+ VALUE rb_results;
1282
+
1283
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1284
+ NULL, NULL,
1285
+ NULL, NULL, NULL,
1286
+ NULL);
1287
+
1288
+ rb_scan_args(argc, argv, "00*", &rb_keys);
1289
+
1290
+ n_keys = RARRAY_LEN(rb_keys);
1291
+ rb_sort_keys = RARRAY_PTR(rb_keys);
1292
+ if (n_keys == 1 && TYPE(rb_sort_keys[0]) == T_ARRAY) {
1293
+ n_keys = RARRAY_LEN(rb_sort_keys[0]);
1294
+ rb_sort_keys = RARRAY_PTR(rb_sort_keys[0]);
1295
+ }
1296
+ keys = ALLOCA_N(grn_table_sort_key, n_keys);
1297
+ for (i = 0; i < n_keys; i++) {
1298
+ VALUE rb_sort_options, rb_key;
1299
+
1300
+ if (RVAL2CBOOL(rb_obj_is_kind_of(rb_sort_keys[i], rb_cHash))) {
1301
+ rb_sort_options = rb_sort_keys[i];
1302
+ } else {
1303
+ rb_sort_options = rb_hash_new();
1304
+ rb_hash_aset(rb_sort_options,
1305
+ RB_GRN_INTERN("key"),
1306
+ rb_sort_keys[i]);
1307
+ }
1308
+ rb_grn_scan_options(rb_sort_options,
1309
+ "key", &rb_key,
1310
+ NULL);
1311
+ if (RVAL2CBOOL(rb_obj_is_kind_of(rb_key, rb_cString)))
1312
+ rb_key = rb_grn_table_get_column(self, rb_key);
1313
+ keys[i].key = RVAL2GRNOBJECT(rb_key, &context);
1314
+ keys[i].flags = 0;
1315
+ }
1316
+
1317
+ n_results = n_keys;
1318
+ results = ALLOCA_N(grn_table_group_result, n_results);
1319
+ rb_results = rb_ary_new();
1320
+ for (i = 0; i < n_results; i++) {
1321
+ grn_obj *result;
1322
+ grn_id range_id;
1323
+ VALUE rb_result;
1324
+
1325
+ range_id = grn_obj_get_range(context, keys[i].key);
1326
+ result = grn_table_create(context, NULL, 0, NULL,
1327
+ GRN_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
1328
+ grn_ctx_at(context, range_id), 0);
1329
+ results[i].table = result;
1330
+ results[i].key_begin = 0;
1331
+ results[i].key_end = 0;
1332
+ results[i].limit = 0;
1333
+ results[i].flags = 0;
1334
+ results[i].op = GRN_OP_OR;
1335
+
1336
+ rb_result = GRNOBJECT2RVAL(Qnil, context, result, RB_GRN_TRUE);
1337
+ rb_ary_push(rb_results, rb_result);
1338
+ }
1339
+
1340
+ rc = grn_table_group(context, table, keys, n_keys, results, n_results);
1341
+ rb_grn_context_check(context, self);
1342
+ rb_grn_rc_check(rc, self);
1343
+
1344
+ if (n_results == 1)
1345
+ return rb_ary_pop(rb_results);
1346
+ else
1347
+ return rb_results;
1348
+ }
1349
+
1350
+ /*
1351
+ * Document-method: []
1352
+ *
1353
+ * call-seq:
1354
+ * table[id] -> Groonga::Record
1355
+ *
1356
+ * _table_の_id_に対応するGroonga::Recordを返す。
1357
+ *
1358
+ * 0.9.0から値ではなくGroonga::Recordを返すようになった。
1359
+ */
1360
+ VALUE
1361
+ rb_grn_table_array_reference (VALUE self, VALUE rb_id)
1362
+ {
1363
+ return rb_grn_record_new_raw(self, rb_id, Qnil);
1364
+ }
1365
+
1366
+ VALUE
1367
+ rb_grn_table_get_value (VALUE self, VALUE rb_id)
1368
+ {
1369
+ grn_id id;
1370
+ grn_ctx *context;
1371
+ grn_obj *table;
1372
+ grn_obj *range;
1373
+ grn_obj *value;
1374
+
1375
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1376
+ NULL, NULL,
1377
+ &value, NULL, &range,
1378
+ NULL);
1379
+
1380
+ id = NUM2UINT(rb_id);
1381
+ GRN_BULK_REWIND(value);
1382
+ grn_obj_get_value(context, table, id, value);
1383
+ rb_grn_context_check(context, self);
1384
+
1385
+ return GRNBULK2RVAL(context, value, range, self);
1386
+ }
1387
+
1388
+ /*
1389
+ * Document-method: value
1390
+ *
1391
+ * call-seq:
1392
+ * table.value(id) -> 値
1393
+ * table.value(id, :id => true) -> 値
1394
+ *
1395
+ * _table_の_id_に対応する値を返す。
1396
+ *
1397
+ * <tt>:id => true</tt>が指定できるのは利便性のため。
1398
+ * Groonga::ArrayでもGroonga::HashやGroonga::PatriciaTrieと
1399
+ * 同じ引数で動くようになる。
1400
+ */
1401
+ static VALUE
1402
+ rb_grn_table_get_value_convenience (int argc, VALUE *argv, VALUE self)
1403
+ {
1404
+ VALUE rb_id, rb_options;
1405
+
1406
+ rb_scan_args(argc, argv, "11", &rb_id, &rb_options);
1407
+ if (!NIL_P(rb_options)) {
1408
+ VALUE rb_option_id;
1409
+ rb_grn_scan_options(rb_options,
1410
+ "id", &rb_option_id,
1411
+ NULL);
1412
+ if (!(NIL_P(rb_option_id) || RVAL2CBOOL(rb_option_id))) {
1413
+ rb_raise(rb_eArgError, ":id options must be true or nil: %s: %s",
1414
+ rb_grn_inspect(rb_option_id),
1415
+ rb_grn_inspect(rb_ary_new3(2,
1416
+ self, rb_ary_new4(argc, argv))));
1417
+ }
1418
+ }
1419
+
1420
+ return rb_grn_table_get_value(self, rb_id);
1421
+ }
1422
+
1423
+ VALUE
1424
+ rb_grn_table_set_value (VALUE self, VALUE rb_id, VALUE rb_value)
1425
+ {
1426
+ grn_id id;
1427
+ grn_ctx *context;
1428
+ grn_obj *table;
1429
+ grn_obj *range;
1430
+ grn_obj *value;
1431
+ grn_rc rc;
1432
+
1433
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1434
+ NULL, NULL,
1435
+ &value, NULL, &range,
1436
+ NULL);
1437
+
1438
+ id = NUM2UINT(rb_id);
1439
+ GRN_BULK_REWIND(value);
1440
+ RVAL2GRNBULK(rb_value, context, value);
1441
+ rc = grn_obj_set_value(context, table, id, value, GRN_OBJ_SET);
1442
+ rb_grn_context_check(context, self);
1443
+ rb_grn_rc_check(rc, self);
1444
+
1445
+ return Qnil;
1446
+ }
1447
+
1448
+ /*
1449
+ * Document-method: set_value
1450
+ *
1451
+ * call-seq:
1452
+ * table.set_value(id, value)
1453
+ * table.set_value(id, value, :id => true)
1454
+ *
1455
+ * _table_の_id_に対応する値として_value_設定する。既存の値は
1456
+ * 上書きされる。
1457
+ *
1458
+ * <tt>:id => true</tt>が指定できるのは利便性のため。
1459
+ * Groonga::ArrayでもGroonga::HashやGroonga::PatriciaTrieと
1460
+ * 同じ引数で動くようになる。
1461
+ */
1462
+ static VALUE
1463
+ rb_grn_table_set_value_convenience (int argc, VALUE *argv, VALUE self)
1464
+ {
1465
+ VALUE rb_id, rb_value, rb_options;
1466
+
1467
+ rb_scan_args(argc, argv, "21", &rb_id, &rb_value, &rb_options);
1468
+ if (!NIL_P(rb_options)) {
1469
+ VALUE rb_option_id;
1470
+ rb_grn_scan_options(rb_options,
1471
+ "id", &rb_option_id,
1472
+ NULL);
1473
+ if (!(NIL_P(rb_option_id) || RVAL2CBOOL(rb_option_id))) {
1474
+ rb_raise(rb_eArgError, ":id options must be true or nil: %s: %s",
1475
+ rb_grn_inspect(rb_option_id),
1476
+ rb_grn_inspect(rb_ary_new3(2,
1477
+ self, rb_ary_new4(argc, argv))));
1478
+ }
1479
+ }
1480
+
1481
+ return rb_grn_table_set_value(self, rb_id, rb_value);
1482
+ }
1483
+
1484
+ VALUE
1485
+ rb_grn_table_get_column_value_raw (VALUE self, grn_id id, VALUE rb_name)
1486
+ {
1487
+ VALUE rb_column;
1488
+
1489
+ rb_column = rb_grn_table_get_column_surely(self, rb_name);
1490
+
1491
+ /* TODO: improve speed. */
1492
+ return rb_funcall(rb_column, id_array_reference, 1, INT2NUM(id));
1493
+ }
1494
+
1495
+ VALUE
1496
+ rb_grn_table_get_column_value (VALUE self, VALUE rb_id, VALUE rb_name)
1497
+ {
1498
+ return rb_grn_table_get_column_value_raw(self, NUM2INT(rb_id), rb_name);
1499
+ }
1500
+
1501
+ /*
1502
+ * Document-method: column_value
1503
+ *
1504
+ * call-seq:
1505
+ * table.column_value(id, name) -> 値
1506
+ * table.column_value(id, name, :id => true) -> 値
1507
+ *
1508
+ * _table_の_id_に対応するカラム_name_の値を返す。
1509
+ *
1510
+ * <tt>:id => true</tt>が指定できるのは利便性のため。
1511
+ * Groonga::ArrayでもGroonga::HashやGroonga::PatriciaTrieと
1512
+ * 同じ引数で動くようになる。
1513
+ */
1514
+ static VALUE
1515
+ rb_grn_table_get_column_value_convenience (int argc, VALUE *argv, VALUE self)
1516
+ {
1517
+ VALUE rb_id, rb_name, rb_options;
1518
+
1519
+ rb_scan_args(argc, argv, "21", &rb_id, &rb_name, &rb_options);
1520
+ if (!NIL_P(rb_options)) {
1521
+ VALUE rb_option_id;
1522
+ rb_grn_scan_options(rb_options,
1523
+ "id", &rb_option_id,
1524
+ NULL);
1525
+ if (!(NIL_P(rb_option_id) || RVAL2CBOOL(rb_option_id))) {
1526
+ rb_raise(rb_eArgError, ":id options must be true or nil: %s: %s",
1527
+ rb_grn_inspect(rb_option_id),
1528
+ rb_grn_inspect(rb_ary_new3(2,
1529
+ self,
1530
+ rb_ary_new4(argc, argv))));
1531
+ }
1532
+ }
1533
+
1534
+ return rb_grn_table_get_column_value(self, rb_id, rb_name);
1535
+ }
1536
+
1537
+ VALUE
1538
+ rb_grn_table_set_column_value_raw (VALUE self, grn_id id,
1539
+ VALUE rb_name, VALUE rb_value)
1540
+ {
1541
+ VALUE rb_column;
1542
+
1543
+ rb_column = rb_grn_table_get_column_surely(self, rb_name);
1544
+
1545
+ /* TODO: improve speed. */
1546
+ return rb_funcall(rb_column, id_array_set, 2, INT2NUM(id), rb_value);
1547
+ }
1548
+
1549
+ VALUE
1550
+ rb_grn_table_set_column_value (VALUE self, VALUE rb_id,
1551
+ VALUE rb_name, VALUE rb_value)
1552
+ {
1553
+ return rb_grn_table_set_column_value_raw(self, NUM2INT(rb_id),
1554
+ rb_name, rb_value);
1555
+ }
1556
+
1557
+ /*
1558
+ * Document-method: set_column_value
1559
+ *
1560
+ * call-seq:
1561
+ * table.set_column_value(id, name, value)
1562
+ * table.set_column_value(id, name, value, :id => true)
1563
+ *
1564
+ * _table_の_id_に対応するカラム_name_の値として_value_設定す
1565
+ * る。既存の値は上書きされる。
1566
+ *
1567
+ * <tt>:id => true</tt>が指定できるのは利便性のため。
1568
+ * Groonga::ArrayでもGroonga::HashやGroonga::PatriciaTrieと
1569
+ * 同じ引数で動くようになる。
1570
+ */
1571
+ static VALUE
1572
+ rb_grn_table_set_column_value_convenience (int argc, VALUE *argv, VALUE self)
1573
+ {
1574
+ VALUE rb_id, rb_name, rb_value, rb_options;
1575
+
1576
+ rb_scan_args(argc, argv, "31", &rb_id, &rb_name, &rb_value, &rb_options);
1577
+ if (!NIL_P(rb_options)) {
1578
+ VALUE rb_option_id;
1579
+ rb_grn_scan_options(rb_options,
1580
+ "id", &rb_option_id,
1581
+ NULL);
1582
+ if (!(NIL_P(rb_option_id) || RVAL2CBOOL(rb_option_id))) {
1583
+ rb_raise(rb_eArgError, ":id options must be true or nil: %s: %s",
1584
+ rb_grn_inspect(rb_option_id),
1585
+ rb_grn_inspect(rb_ary_new3(2,
1586
+ self,
1587
+ rb_ary_new4(argc, argv))));
1588
+ }
1589
+ }
1590
+
1591
+ return rb_grn_table_set_column_value(self, rb_id, rb_name, rb_value);
1592
+ }
1593
+
1594
+ /*
1595
+ * Document-method: unlock
1596
+ *
1597
+ * call-seq:
1598
+ * table.unlock(options={})
1599
+ *
1600
+ * _table_のロックを解除する。
1601
+ *
1602
+ * 利用可能なオプションは以下の通り。
1603
+ *
1604
+ * [_:id_]
1605
+ * _:id_で指定したレコードのロックを解除する。(注:
1606
+ * groonga側が未実装のため、現在は無視される)
1607
+ */
1608
+ static VALUE
1609
+ rb_grn_table_unlock (int argc, VALUE *argv, VALUE self)
1610
+ {
1611
+ grn_id id = GRN_ID_NIL;
1612
+ grn_ctx *context;
1613
+ grn_obj *table;
1614
+ grn_rc rc;
1615
+ VALUE options, rb_id;
1616
+
1617
+ rb_scan_args(argc, argv, "01", &options);
1618
+
1619
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1620
+ NULL, NULL,
1621
+ NULL, NULL, NULL,
1622
+ NULL);
1623
+
1624
+ rb_grn_scan_options(options,
1625
+ "id", &rb_id,
1626
+ NULL);
1627
+
1628
+ if (!NIL_P(rb_id))
1629
+ id = NUM2UINT(rb_id);
1630
+
1631
+ rc = grn_obj_unlock(context, table, id);
1632
+ rb_grn_context_check(context, self);
1633
+ rb_grn_rc_check(rc, self);
1634
+
1635
+ return Qnil;
1636
+ }
1637
+
1638
+ static VALUE
1639
+ rb_grn_table_unlock_ensure (VALUE self)
1640
+ {
1641
+ return rb_grn_table_unlock(0, NULL, self);
1642
+ }
1643
+
1644
+ /*
1645
+ * Document-method: lock
1646
+ *
1647
+ * call-seq:
1648
+ * table.lock(options={})
1649
+ * table.lock(options={}) {...}
1650
+ *
1651
+ * _table_をロックする。ロックに失敗した場合は
1652
+ * Groonga::ResourceDeadlockAvoided例外が発生する。
1653
+ *
1654
+ * ブロックを指定した場合はブロックを抜けたときにunlockする。
1655
+ *
1656
+ * 利用可能なオプションは以下の通り。
1657
+ *
1658
+ * [_:timeout_]
1659
+ * ロックを獲得できなかった場合は_:timeout_秒間ロックの獲
1660
+ * 得を試みる。_:timeout_秒以内にロックを獲得できなかった
1661
+ * 場合は例外が発生する。
1662
+ * [_:id_]
1663
+ * _:id_で指定したレコードをロックする。(注: groonga側が
1664
+ * 未実装のため、現在は無視される)
1665
+ */
1666
+ static VALUE
1667
+ rb_grn_table_lock (int argc, VALUE *argv, VALUE self)
1668
+ {
1669
+ grn_id id = GRN_ID_NIL;
1670
+ grn_ctx *context;
1671
+ grn_obj *table;
1672
+ int timeout = 0;
1673
+ grn_rc rc;
1674
+ VALUE options, rb_timeout, rb_id;
1675
+
1676
+ rb_scan_args(argc, argv, "01", &options);
1677
+
1678
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1679
+ NULL, NULL,
1680
+ NULL, NULL, NULL,
1681
+ NULL);
1682
+
1683
+ rb_grn_scan_options(options,
1684
+ "timeout", &rb_timeout,
1685
+ "id", &rb_id,
1686
+ NULL);
1687
+
1688
+ if (!NIL_P(rb_timeout))
1689
+ timeout = NUM2UINT(rb_timeout);
1690
+
1691
+ if (!NIL_P(rb_id))
1692
+ id = NUM2UINT(rb_id);
1693
+
1694
+ rc = grn_obj_lock(context, table, id, timeout);
1695
+ rb_grn_context_check(context, self);
1696
+ rb_grn_rc_check(rc, self);
1697
+
1698
+ if (rb_block_given_p()) {
1699
+ return rb_ensure(rb_yield, Qnil, rb_grn_table_unlock_ensure, self);
1700
+ } else {
1701
+ return Qnil;
1702
+ }
1703
+ }
1704
+
1705
+ /*
1706
+ * Document-method: clear_lock
1707
+ *
1708
+ * call-seq:
1709
+ * table.clear_lock(options={})
1710
+ *
1711
+ * _table_のロックを強制的に解除する。
1712
+ *
1713
+ * 利用可能なオプションは以下の通り。
1714
+ *
1715
+ * [_:id_]
1716
+ * _:id_で指定したレコードのロックを強制的に解除する。
1717
+ * (注: groonga側が未実装のため、現在は無視される。実装さ
1718
+ * れるのではないかと思っているが、実装されないかもしれな
1719
+ * い。)
1720
+ */
1721
+ static VALUE
1722
+ rb_grn_table_clear_lock (int argc, VALUE *argv, VALUE self)
1723
+ {
1724
+ grn_id id = GRN_ID_NIL;
1725
+ grn_ctx *context;
1726
+ grn_obj *table;
1727
+ VALUE options, rb_id;
1728
+
1729
+ rb_scan_args(argc, argv, "01", &options);
1730
+
1731
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1732
+ NULL, NULL,
1733
+ NULL, NULL, NULL,
1734
+ NULL);
1735
+
1736
+ rb_grn_scan_options(options,
1737
+ "id", &rb_id,
1738
+ NULL);
1739
+
1740
+ if (!NIL_P(rb_id))
1741
+ id = NUM2UINT(rb_id);
1742
+
1743
+ grn_obj_clear_lock(context, table);
1744
+
1745
+ return Qnil;
1746
+ }
1747
+
1748
+ /*
1749
+ * Document-method: locked?
1750
+ *
1751
+ * call-seq:
1752
+ * table.locked?(options={})
1753
+ *
1754
+ * _table_がロックされていれば+true+を返す。
1755
+ *
1756
+ * 利用可能なオプションは以下の通り。
1757
+ *
1758
+ * [_:id_]
1759
+ * _:id_で指定したレコードがロックされていれば+true+を返す。
1760
+ * (注: groonga側が未実装のため、現在は無視される。実装さ
1761
+ * れるのではないかと思っているが、実装されないかもしれな
1762
+ * い。)
1763
+ */
1764
+ static VALUE
1765
+ rb_grn_table_is_locked (int argc, VALUE *argv, VALUE self)
1766
+ {
1767
+ grn_id id = GRN_ID_NIL;
1768
+ grn_ctx *context;
1769
+ grn_obj *table;
1770
+ VALUE options, rb_id;
1771
+
1772
+ rb_scan_args(argc, argv, "01", &options);
1773
+
1774
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1775
+ NULL, NULL,
1776
+ NULL, NULL, NULL,
1777
+ NULL);
1778
+
1779
+ rb_grn_scan_options(options,
1780
+ "id", &rb_id,
1781
+ NULL);
1782
+
1783
+ if (!NIL_P(rb_id))
1784
+ id = NUM2UINT(rb_id);
1785
+
1786
+ return CBOOL2RVAL(grn_obj_is_locked(context, table));
1787
+ }
1788
+
1789
+ /*
1790
+ * call-seq:
1791
+ * table.select(options) {|record| ...} -> Groonga::Hash
1792
+ * table.select(query, options) -> Groonga::Hash
1793
+ * table.select(expression, options) -> Groonga::Hash
1794
+ *
1795
+ * _table_からブロックまたは文字列で指定した条件にマッチする
1796
+ * レコードを返す。返されたテーブルには+expression+という特
1797
+ * 異メソッドがあり、指定した条件を表している
1798
+ * Groonga::Expressionを取得できる。
1799
+ * Groonga::Expression#snippetを使うことにより、指定した条件
1800
+ * 用のスニペットを簡単に生成できる。
1801
+ *
1802
+ * results = table.select do |record|
1803
+ * record["description"] =~ "groonga"
1804
+ * end
1805
+ * snippet = results.expression.snippet([["<em>", "</em>"]])
1806
+ * results.each do |record|
1807
+ * puts "#{record['name']}の説明文の中で「groonga」が含まれる部分"
1808
+ * snippet.execute(record["description"].each do |snippet|
1809
+ * puts "---"
1810
+ * puts "#{snippet}..."
1811
+ * puts "---"
1812
+ * end
1813
+ * end
1814
+ *
1815
+ * 出力例
1816
+ * Ruby/groongaの説明文の中で「groonga」が含まれる部分
1817
+ * ---
1818
+ * Ruby/<em>groonga</em>は<em>groonga</em>のいわゆるDB-APIの層の...
1819
+ * ---
1820
+ *
1821
+ * _query_には「[カラム名]:[演算子][値]」という書式で条件を
1822
+ * 指定する。演算子は以下の通り。
1823
+ *
1824
+ * [なし]
1825
+ * [カラム値] == [値]
1826
+ * [<tt>!</tt>]
1827
+ * [カラム値] != [値]
1828
+ * [<tt><</tt>]
1829
+ * [カラム値] < [値]
1830
+ * [<tt>></tt>]
1831
+ * [カラム値] > [値]
1832
+ * [<tt><=</tt>]
1833
+ * [カラム値] <= [値]
1834
+ * [<tt>>=</tt>]
1835
+ * [カラム値] >= [値]
1836
+ * [<tt>@</tt>]
1837
+ * [カラム値]が[値]を含んでいるかどうか
1838
+ *
1839
+ * 例:
1840
+ * "name:daijiro" # "name"カラムの値が"daijiro"のレコードにマッチ
1841
+ * "description:@groonga" # "description"カラムが
1842
+ * # "groonga"を含んでいるレコードにマッチ
1843
+ *
1844
+ * _expression_には既に作成済みのGroonga::Expressionを渡す
1845
+ *
1846
+ * ブロックで条件を指定する場合は
1847
+ * Groonga::RecordExpressionBuilderを参照。
1848
+ *
1849
+ * _options_に指定可能な値は以下の通り。
1850
+ *
1851
+ * [+:default_column+]
1852
+ * "column_name:hoge"ではなく"hoge"のようにcolumn_nameが指
1853
+ * 定されない条件の検索対象となるカラムを指定する。
1854
+ *
1855
+ * [+:operator+]
1856
+ * マッチしたレコードをどのように扱うか。指定可能な値は以
1857
+ * 下の通り。省略した場合はGroonga::Operation::OR。
1858
+ *
1859
+ * [Groonga::Operation::OR]
1860
+ * マッチしたレコードを追加。すでにレコードが追加され
1861
+ * ている場合は何もしない。
1862
+ * [Groonga::Operation::AND]
1863
+ * マッチしたレコードのスコアを増加。マッチしなかった
1864
+ * レコードを削除。
1865
+ * [Groonga::Operation::BUT]
1866
+ * マッチしたレコードを削除。
1867
+ * [Groonga::Operation::ADJUST]
1868
+ * マッチしたレコードのスコアを増加。
1869
+ *
1870
+ * [+:result+]
1871
+ * 検索結果を格納するテーブル。マッチしたレコードが追加さ
1872
+ * れていく。省略した場合は新しくテーブルを作成して返す。
1873
+ *
1874
+ * [+:name+]
1875
+ * 条件の名前。省略した場合は名前を付けない。
1876
+ *
1877
+ * [+:syntax+]
1878
+ * _query_の構文。省略した場合は+:query+。
1879
+ *
1880
+ * 参考: Groonga::Expression#parse.
1881
+ *
1882
+ * [+:allow_pragma+]
1883
+ * query構文時にプラグマを利用するかどうか。省略した場合は
1884
+ * 利用する。
1885
+ *
1886
+ * 参考: Groonga::Expression#parse.
1887
+ *
1888
+ * [+:allow_column+]
1889
+ * query構文時にカラム指定を利用するかどうか。省略した場合
1890
+ * は利用する。
1891
+ *
1892
+ * 参考: Groonga::Expression#parse.
1893
+ *
1894
+ * [+:allow_update+]
1895
+ * script構文時に更新操作を利用するかどうか。省略した場合
1896
+ * は利用する。
1897
+ *
1898
+ * 参考: Groonga::Expression#parse.
1899
+ */
1900
+ static VALUE
1901
+ rb_grn_table_select (int argc, VALUE *argv, VALUE self)
1902
+ {
1903
+ grn_ctx *context;
1904
+ grn_obj *table, *result, *expression;
1905
+ grn_operator operator = GRN_OP_OR;
1906
+ VALUE rb_query = Qnil, condition_or_options, options;
1907
+ VALUE rb_name, rb_operator, rb_result, rb_syntax;
1908
+ VALUE rb_allow_pragma, rb_allow_column, rb_allow_update;
1909
+ VALUE rb_default_column;
1910
+ VALUE rb_expression = Qnil, builder;
1911
+
1912
+ rb_scan_args(argc, argv, "02", &condition_or_options, &options);
1913
+
1914
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1915
+ NULL, NULL,
1916
+ NULL, NULL, NULL,
1917
+ NULL);
1918
+
1919
+ if (RVAL2CBOOL(rb_obj_is_kind_of(condition_or_options, rb_cString))) {
1920
+ rb_query = condition_or_options;
1921
+ } else if (RVAL2CBOOL(rb_obj_is_kind_of(condition_or_options,
1922
+ rb_cGrnExpression))) {
1923
+ rb_expression = condition_or_options;
1924
+ } else {
1925
+ if (!NIL_P(options))
1926
+ rb_raise(rb_eArgError,
1927
+ "should be [query_string, option_hash], "
1928
+ "[expression, opion_hash] "
1929
+ "or [option_hash]: %s",
1930
+ rb_grn_inspect(rb_ary_new4(argc, argv)));
1931
+ options = condition_or_options;
1932
+ }
1933
+
1934
+ rb_grn_scan_options(options,
1935
+ "operator", &rb_operator,
1936
+ "result", &rb_result,
1937
+ "name", &rb_name,
1938
+ "syntax", &rb_syntax,
1939
+ "allow_pragma", &rb_allow_pragma,
1940
+ "allow_column", &rb_allow_column,
1941
+ "allow_update", &rb_allow_update,
1942
+ "default_column", &rb_default_column,
1943
+ NULL);
1944
+
1945
+ if (!NIL_P(rb_operator))
1946
+ operator = NUM2INT(rb_operator);
1947
+
1948
+ if (NIL_P(rb_result)) {
1949
+ result = grn_table_create(context, NULL, 0, NULL,
1950
+ GRN_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
1951
+ table,
1952
+ 0);
1953
+ rb_result = GRNTABLE2RVAL(context, result, RB_GRN_TRUE);
1954
+ } else {
1955
+ result = RVAL2GRNTABLE(rb_result, &context);
1956
+ }
1957
+
1958
+ if (NIL_P(rb_expression)) {
1959
+ builder = rb_grn_record_expression_builder_new(self, rb_name);
1960
+ rb_funcall(builder, rb_intern("query="), 1, rb_query);
1961
+ rb_funcall(builder, rb_intern("syntax="), 1, rb_syntax);
1962
+ rb_funcall(builder, rb_intern("allow_pragma="), 1, rb_allow_pragma);
1963
+ rb_funcall(builder, rb_intern("allow_column="), 1, rb_allow_column);
1964
+ rb_funcall(builder, rb_intern("allow_update="), 1, rb_allow_update);
1965
+ rb_funcall(builder, rb_intern("default_column="), 1, rb_default_column);
1966
+ rb_expression = rb_grn_record_expression_builder_build(builder);
1967
+ }
1968
+ rb_grn_object_deconstruct(RB_GRN_OBJECT(DATA_PTR(rb_expression)),
1969
+ &expression, NULL,
1970
+ NULL, NULL, NULL, NULL);
1971
+
1972
+ grn_table_select(context, table, expression, result, operator);
1973
+ rb_grn_context_check(context, self);
1974
+
1975
+ rb_attr(rb_singleton_class(rb_result),
1976
+ rb_intern("expression"),
1977
+ RB_GRN_TRUE, RB_GRN_FALSE, RB_GRN_FALSE);
1978
+ rb_iv_set(rb_result, "@expression", rb_expression);
1979
+
1980
+ return rb_result;
1981
+ }
1982
+
1983
+ static VALUE
1984
+ rb_grn_table_set_operation_bang (VALUE self, VALUE rb_other,
1985
+ grn_operator operator)
1986
+ {
1987
+ grn_ctx *context;
1988
+ grn_obj *table, *other;
1989
+ grn_rc rc;
1990
+
1991
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1992
+ NULL, NULL,
1993
+ NULL, NULL, NULL,
1994
+ NULL);
1995
+ rb_grn_table_deconstruct(SELF(rb_other), &other, NULL,
1996
+ NULL, NULL,
1997
+ NULL, NULL, NULL,
1998
+ NULL);
1999
+
2000
+ rc = grn_table_setoperation(context, table, other, table, operator);
2001
+ rb_grn_context_check(context, self);
2002
+ rb_grn_rc_check(rc, self);
2003
+
2004
+ return self;
2005
+ }
2006
+
2007
+ /*
2008
+ * call-seq:
2009
+ * table.union!(other) -> Groonga::Table
2010
+ *
2011
+ * キーを比較し、_table_には登録されていない_other_のレコー
2012
+ * ドを_table_に作成する。
2013
+ *
2014
+ */
2015
+ static VALUE
2016
+ rb_grn_table_union_bang (VALUE self, VALUE rb_other)
2017
+ {
2018
+ return rb_grn_table_set_operation_bang(self, rb_other, GRN_OP_OR);
2019
+ }
2020
+
2021
+
2022
+ /*
2023
+ * call-seq:
2024
+ * table.intersection!(other) -> Groonga::Table
2025
+ *
2026
+ * キーを比較し、_other_には登録されていないレコードを
2027
+ * _table_から削除する。
2028
+ *
2029
+ */
2030
+ static VALUE
2031
+ rb_grn_table_intersection_bang (VALUE self, VALUE rb_other)
2032
+ {
2033
+ return rb_grn_table_set_operation_bang(self, rb_other, GRN_OP_AND);
2034
+ }
2035
+
2036
+ /*
2037
+ * call-seq:
2038
+ * table.difference!(other) -> Groonga::Table
2039
+ *
2040
+ * キーを比較し、_other_にも登録されているレコードを_table_
2041
+ * から削除する。
2042
+ *
2043
+ */
2044
+ static VALUE
2045
+ rb_grn_table_difference_bang (VALUE self, VALUE rb_other)
2046
+ {
2047
+ return rb_grn_table_set_operation_bang(self, rb_other, GRN_OP_BUT);
2048
+ }
2049
+
2050
+ /*
2051
+ * call-seq:
2052
+ * table.merge!(other) -> Groonga::Table
2053
+ *
2054
+ * キーを比較し、_other_にも登録されている_table_のレコード
2055
+ * のスコアを_other_のスコアと同値にする。
2056
+ *
2057
+ */
2058
+ static VALUE
2059
+ rb_grn_table_merge_bang (VALUE self, VALUE rb_other)
2060
+ {
2061
+ return rb_grn_table_set_operation_bang(self, rb_other, GRN_OP_ADJUST);
2062
+ }
2063
+
2064
+ void
2065
+ rb_grn_init_table (VALUE mGrn)
2066
+ {
2067
+ id_array_reference = rb_intern("[]");
2068
+ id_array_set = rb_intern("[]=");
2069
+
2070
+ rb_cGrnTable = rb_define_class_under(mGrn, "Table", rb_cGrnObject);
2071
+ rb_define_alloc_func(rb_cGrnTable, rb_grn_table_alloc);
2072
+
2073
+ rb_include_module(rb_cGrnTable, rb_mEnumerable);
2074
+
2075
+ rb_define_singleton_method(rb_cGrnTable, "open",
2076
+ rb_grn_table_s_open, -1);
2077
+
2078
+ rb_define_method(rb_cGrnTable, "initialize", rb_grn_table_initialize, -1);
2079
+
2080
+ rb_define_method(rb_cGrnTable, "inspect", rb_grn_table_inspect, 0);
2081
+
2082
+ rb_define_method(rb_cGrnTable, "define_column",
2083
+ rb_grn_table_define_column, -1);
2084
+ rb_define_method(rb_cGrnTable, "define_index_column",
2085
+ rb_grn_table_define_index_column, -1);
2086
+ rb_define_method(rb_cGrnTable, "add_column",
2087
+ rb_grn_table_add_column, 3);
2088
+ rb_define_method(rb_cGrnTable, "column",
2089
+ rb_grn_table_get_column, 1);
2090
+ rb_define_method(rb_cGrnTable, "columns",
2091
+ rb_grn_table_get_columns, -1);
2092
+ rb_define_method(rb_cGrnTable, "have_column?",
2093
+ rb_grn_table_have_column, 1);
2094
+
2095
+ rb_define_method(rb_cGrnTable, "open_cursor", rb_grn_table_open_cursor, -1);
2096
+ rb_define_method(rb_cGrnTable, "records", rb_grn_table_get_records, -1);
2097
+
2098
+ rb_define_method(rb_cGrnTable, "size", rb_grn_table_get_size, 0);
2099
+ rb_define_method(rb_cGrnTable, "empty?", rb_grn_table_empty_p, 0);
2100
+ rb_define_method(rb_cGrnTable, "truncate", rb_grn_table_truncate, 0);
2101
+
2102
+ rb_define_method(rb_cGrnTable, "each", rb_grn_table_each, 0);
2103
+
2104
+ rb_define_method(rb_cGrnTable, "delete", rb_grn_table_delete, 1);
2105
+
2106
+ rb_define_method(rb_cGrnTable, "sort", rb_grn_table_sort, -1);
2107
+ rb_define_method(rb_cGrnTable, "group", rb_grn_table_group, -1);
2108
+
2109
+ rb_define_method(rb_cGrnTable, "[]", rb_grn_table_array_reference, 1);
2110
+ rb_undef_method(rb_cGrnTable, "[]=");
2111
+
2112
+ rb_define_method(rb_cGrnTable, "value",
2113
+ rb_grn_table_get_value_convenience, -1);
2114
+ rb_define_method(rb_cGrnTable, "set_value",
2115
+ rb_grn_table_set_value_convenience, -1);
2116
+ rb_define_method(rb_cGrnTable, "column_value",
2117
+ rb_grn_table_get_column_value_convenience, -1);
2118
+ rb_define_method(rb_cGrnTable, "set_column_value",
2119
+ rb_grn_table_set_column_value_convenience, -1);
2120
+
2121
+ rb_define_method(rb_cGrnTable, "lock", rb_grn_table_lock, -1);
2122
+ rb_define_method(rb_cGrnTable, "unlock", rb_grn_table_unlock, -1);
2123
+ rb_define_method(rb_cGrnTable, "clear_lock", rb_grn_table_clear_lock, -1);
2124
+ rb_define_method(rb_cGrnTable, "locked?", rb_grn_table_is_locked, -1);
2125
+
2126
+ rb_define_method(rb_cGrnTable, "select", rb_grn_table_select, -1);
2127
+
2128
+ rb_define_method(rb_cGrnTable, "union!", rb_grn_table_union_bang, 1);
2129
+ rb_define_method(rb_cGrnTable, "intersection!",
2130
+ rb_grn_table_intersection_bang, 1);
2131
+ rb_define_method(rb_cGrnTable, "difference!",
2132
+ rb_grn_table_difference_bang, 1);
2133
+ rb_define_method(rb_cGrnTable, "merge!",
2134
+ rb_grn_table_merge_bang, 1);
2135
+
2136
+ rb_grn_init_table_key_support(mGrn);
2137
+ rb_grn_init_array(mGrn);
2138
+ rb_grn_init_hash(mGrn);
2139
+ rb_grn_init_patricia_trie(mGrn);
2140
+ rb_grn_init_view(mGrn);
2141
+ }