groonga 0.0.7 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/NEWS.ja.rdoc +56 -0
  2. data/NEWS.rdoc +58 -0
  3. data/Rakefile +2 -3
  4. data/benchmark/read-write-many-small-items.rb +16 -32
  5. data/benchmark/write-many-small-items.rb +14 -28
  6. data/example/bookmark.rb +19 -17
  7. data/example/index-html.rb +11 -1
  8. data/example/search/config.ru +14 -9
  9. data/ext/rb-grn-array.c +6 -6
  10. data/ext/rb-grn-column.c +348 -18
  11. data/ext/rb-grn-context.c +8 -4
  12. data/ext/rb-grn-database.c +6 -7
  13. data/ext/rb-grn-exception.c +101 -5
  14. data/ext/rb-grn-expression.c +206 -23
  15. data/ext/rb-grn-fix-size-column.c +6 -39
  16. data/ext/rb-grn-hash.c +24 -24
  17. data/ext/rb-grn-index-column.c +74 -19
  18. data/ext/rb-grn-logger.c +48 -0
  19. data/ext/rb-grn-object.c +281 -67
  20. data/ext/rb-grn-operation.c +1 -1
  21. data/ext/rb-grn-patricia-trie-cursor.c +10 -1
  22. data/ext/rb-grn-patricia-trie.c +268 -7
  23. data/ext/rb-grn-query.c +52 -1
  24. data/ext/rb-grn-record.c +8 -2
  25. data/ext/rb-grn-snippet.c +63 -1
  26. data/ext/rb-grn-table-cursor-key-support.c +15 -1
  27. data/ext/rb-grn-table-cursor.c +57 -0
  28. data/ext/rb-grn-table-key-support.c +382 -46
  29. data/ext/rb-grn-table.c +729 -192
  30. data/ext/rb-grn-type.c +63 -12
  31. data/ext/rb-grn-utils.c +156 -158
  32. data/ext/rb-grn-variable.c +18 -0
  33. data/ext/rb-grn.h +85 -21
  34. data/ext/rb-groonga.c +13 -3
  35. data/extconf.rb +19 -4
  36. data/html/developer.html +1 -1
  37. data/html/header.html.erb +1 -1
  38. data/html/index.html +4 -4
  39. data/lib/groonga.rb +10 -0
  40. data/lib/groonga/expression-builder.rb +81 -42
  41. data/lib/groonga/patricia-trie.rb +13 -0
  42. data/lib/groonga/record.rb +158 -13
  43. data/lib/groonga/schema.rb +339 -33
  44. data/pkg-config.rb +6 -1
  45. data/test-unit/lib/test/unit.rb +23 -42
  46. data/test-unit/lib/test/unit/assertionfailederror.rb +11 -0
  47. data/test-unit/lib/test/unit/assertions.rb +87 -9
  48. data/test-unit/lib/test/unit/autorunner.rb +20 -11
  49. data/test-unit/lib/test/unit/collector.rb +1 -8
  50. data/test-unit/lib/test/unit/collector/load.rb +2 -3
  51. data/test-unit/lib/test/unit/color-scheme.rb +13 -1
  52. data/test-unit/lib/test/unit/diff.rb +223 -37
  53. data/test-unit/lib/test/unit/error.rb +4 -0
  54. data/test-unit/lib/test/unit/failure.rb +31 -5
  55. data/test-unit/lib/test/unit/notification.rb +8 -4
  56. data/test-unit/lib/test/unit/omission.rb +51 -3
  57. data/test-unit/lib/test/unit/pending.rb +4 -0
  58. data/test-unit/lib/test/unit/testcase.rb +55 -4
  59. data/test-unit/lib/test/unit/ui/console/testrunner.rb +190 -4
  60. data/test-unit/lib/test/unit/ui/emacs/testrunner.rb +14 -0
  61. data/test-unit/lib/test/unit/ui/testrunner.rb +8 -0
  62. data/test-unit/lib/test/unit/version.rb +1 -1
  63. data/test-unit/sample/{tc_adder.rb → test_adder.rb} +3 -1
  64. data/test-unit/sample/{tc_subtracter.rb → test_subtracter.rb} +3 -1
  65. data/test-unit/sample/test_user.rb +1 -0
  66. data/test-unit/test/collector/test-descendant.rb +2 -4
  67. data/test-unit/test/collector/test_objectspace.rb +7 -5
  68. data/test-unit/test/run-test.rb +2 -0
  69. data/test-unit/test/test-color-scheme.rb +7 -0
  70. data/test-unit/test/test-diff.rb +48 -7
  71. data/test-unit/test/test-omission.rb +1 -1
  72. data/test-unit/test/test-testcase.rb +47 -0
  73. data/test-unit/test/test_assertions.rb +79 -10
  74. data/test/groonga-test-utils.rb +6 -1
  75. data/test/test-array.rb +29 -14
  76. data/test/test-column.rb +107 -55
  77. data/test/test-context.rb +5 -0
  78. data/test/test-database.rb +2 -37
  79. data/test/test-exception.rb +9 -1
  80. data/test/test-expression-builder.rb +23 -5
  81. data/test/test-expression.rb +44 -8
  82. data/test/test-fix-size-column.rb +16 -5
  83. data/test/test-gqtp.rb +70 -0
  84. data/test/test-hash.rb +142 -43
  85. data/test/test-index-column.rb +9 -9
  86. data/test/test-patricia-trie.rb +79 -20
  87. data/test/test-procedure.rb +4 -2
  88. data/test/test-record.rb +32 -20
  89. data/test/test-remote.rb +3 -2
  90. data/test/test-schema.rb +226 -92
  91. data/test/test-table-cursor.rb +103 -1
  92. data/test/test-table-offset-and-limit.rb +102 -0
  93. data/test/test-table-select-normalize.rb +4 -4
  94. data/test/test-table-select.rb +52 -8
  95. data/test/test-table.rb +235 -116
  96. data/test/test-type.rb +2 -2
  97. data/test/test-variable-size-column.rb +21 -5
  98. data/test/test-vector-column.rb +76 -0
  99. data/{TUTORIAL.ja.rdoc → text/TUTORIAL.ja.rdoc} +52 -52
  100. data/text/expression.rdoc +284 -0
  101. metadata +11 -7
  102. data/test-unit/sample/ts_examples.rb +0 -7
@@ -30,6 +30,12 @@ struct _RbGrnSnippet
30
30
 
31
31
  VALUE rb_cGrnSnippet;
32
32
 
33
+ /*
34
+ * Document-class: Groonga::Snippet
35
+ *
36
+ * スニペット(検索語周辺のテキスト)を生成するためのオブジェクト。
37
+ */
38
+
33
39
  static RbGrnSnippet *
34
40
  rb_rb_grn_snippet_from_ruby_object (VALUE object)
35
41
  {
@@ -92,6 +98,41 @@ rb_grn_snippet_alloc (VALUE klass)
92
98
  return Data_Wrap_Struct(klass, NULL, rb_rb_grn_snippet_free, NULL);
93
99
  }
94
100
 
101
+ /*
102
+ * call-seq:
103
+ * Groonga::Snippet.new(options={})
104
+ *
105
+ * スニペットを作成する。_options_に指定可能な値は以下の通
106
+ * り。
107
+ *
108
+ * [+:context+]
109
+ * スキーマ作成時に使用するGroonga::Contextを指定する。
110
+ * 省略した場合はGroonga::Context.defaultを使用する。
111
+ *
112
+ * [+:normalize+]
113
+ * キーワード文字列・スニペット元の文字列を正規化するかど
114
+ * うか。省略した場合は+false+で正規化しない。
115
+ *
116
+ * [+:skip_leading_spaces+]
117
+ * 先頭の空白を無視するかどうか。省略した場合は+false+で無
118
+ * 視しない。
119
+ *
120
+ * [+:width+]
121
+ * スニペット文字列の長さ。省略した場合は100文字。
122
+ *
123
+ * [+:max_results+]
124
+ * 生成するスニペットの最大数。省略した場合は3。
125
+ *
126
+ * [+:html_escape+]
127
+ * スニペット内の+<+, +>+, +&+, +"+をHTMLエスケープするか
128
+ * どうか。省略した場合は+false+で、HTMLエスケープしない。
129
+ *
130
+ * [+:default_open_tag+]
131
+ * デフォルトの開始タグ。省略した場合は""(空文字列)
132
+ *
133
+ * [+:default_close_tag+]
134
+ * デフォルトの終了タグ。省略した場合は""(空文字列)
135
+ */
95
136
  static VALUE
96
137
  rb_grn_snippet_initialize (int argc, VALUE *argv, VALUE self)
97
138
  {
@@ -162,11 +203,26 @@ rb_grn_snippet_initialize (int argc, VALUE *argv, VALUE self)
162
203
  rb_grn_snippet->snippet = snippet;
163
204
  rb_grn_snippet->owner = RB_GRN_TRUE;
164
205
 
165
- rb_iv_set(self, "context", rb_context);
206
+ rb_iv_set(self, "@context", rb_context);
166
207
 
167
208
  return Qnil;
168
209
  }
169
210
 
211
+ /*
212
+ * call-seq:
213
+ * snippet.add_keyword(keyword, options={})
214
+ *
215
+ * _keyword_を追加する。_options_に指定可能な値は以下の通
216
+ * り。
217
+ *
218
+ * [+:open_tag+]
219
+ * 開始タグ。省略した場合はGroonga::Snippet.newで指定し
220
+ * た+:default_open_tag+。
221
+ *
222
+ * [+:close_tag+]
223
+ * 終了タグ。省略した場合はGroonga::Snippet.newで指定し
224
+ * た+:default_close_tag+。
225
+ */
170
226
  static VALUE
171
227
  rb_grn_snippet_add_keyword (int argc, VALUE *argv, VALUE self)
172
228
  {
@@ -209,6 +265,12 @@ rb_grn_snippet_add_keyword (int argc, VALUE *argv, VALUE self)
209
265
  return Qnil;
210
266
  }
211
267
 
268
+ /*
269
+ * call-seq:
270
+ * snippet.execute(string) -> スニペットの配列
271
+ *
272
+ * _string_を走査し、スニペットを作成する。
273
+ */
212
274
  static VALUE
213
275
  rb_grn_snippet_execute (VALUE self, VALUE rb_string)
214
276
  {
@@ -22,6 +22,20 @@
22
22
 
23
23
  VALUE rb_mGrnTableCursorKeySupport;
24
24
 
25
+ /*
26
+ * Document-module: Groonga::TableCursor::KeySupport
27
+ *
28
+ * 主キーを持つテーブル用のカーソルであるGroonga::HashCursor
29
+ * とGroonga::PatriciaTrieCursorに主キーの機能を提供するモジ
30
+ * ュール。
31
+ */
32
+
33
+ /*
34
+ * call-seq:
35
+ * cursor.key -> 主キー
36
+ *
37
+ * カレントレコードの主キーを返す。
38
+ */
25
39
  static VALUE
26
40
  rb_grn_table_cursor_get_key (VALUE self)
27
41
  {
@@ -50,6 +64,6 @@ rb_grn_init_table_cursor_key_support (VALUE mGrn)
50
64
  rb_mGrnTableCursorKeySupport =
51
65
  rb_define_module_under(rb_cGrnTableCursor, "KeySupport");
52
66
 
53
- rb_define_method(rb_cGrnTableCursor, "key",
67
+ rb_define_method(rb_mGrnTableCursorKeySupport, "key",
54
68
  rb_grn_table_cursor_get_key, 0);
55
69
  }
@@ -22,6 +22,13 @@
22
22
 
23
23
  VALUE rb_cGrnTableCursor;
24
24
 
25
+ /*
26
+ * Document-class: Groonga::TableCursor
27
+ *
28
+ * テーブルに登録されているレコードを順番に取り出すための
29
+ * オブジェクト。Groonga::Table#open_cursorで生成できる。
30
+ */
31
+
25
32
  grn_table_cursor *
26
33
  rb_grn_table_cursor_from_ruby_object (VALUE object, grn_ctx **context)
27
34
  {
@@ -57,6 +64,12 @@ rb_grn_table_cursor_deconstruct (RbGrnTableCursor *rb_grn_table_cursor,
57
64
  range_id, range);
58
65
  }
59
66
 
67
+ /*
68
+ * call-seq:
69
+ * cursor.value -> 値
70
+ *
71
+ * カレントレコードの値を返す。
72
+ */
60
73
  static VALUE
61
74
  rb_grn_table_cursor_get_value (VALUE self)
62
75
  {
@@ -77,6 +90,12 @@ rb_grn_table_cursor_get_value (VALUE self)
77
90
  return rb_value;
78
91
  }
79
92
 
93
+ /*
94
+ * call-seq:
95
+ * cursor.value = 値
96
+ *
97
+ * カレントレコードの値を設定する。既存の値は上書きされる。
98
+ */
80
99
  static VALUE
81
100
  rb_grn_table_cursor_set_value (VALUE self, VALUE value)
82
101
  {
@@ -98,6 +117,12 @@ rb_grn_table_cursor_set_value (VALUE self, VALUE value)
98
117
  return Qnil;
99
118
  }
100
119
 
120
+ /*
121
+ * call-seq:
122
+ * table_cursor.delete
123
+ *
124
+ * カレントレコードを削除する。
125
+ */
101
126
  static VALUE
102
127
  rb_grn_table_cursor_delete (VALUE self)
103
128
  {
@@ -116,6 +141,12 @@ rb_grn_table_cursor_delete (VALUE self)
116
141
  return Qnil;
117
142
  }
118
143
 
144
+ /*
145
+ * call-seq:
146
+ * table_cursor.next -> Groonga::Record
147
+ *
148
+ * カレントレコードを一件進めてそのレコードを返す。
149
+ */
119
150
  static VALUE
120
151
  rb_grn_table_cursor_next (VALUE self)
121
152
  {
@@ -137,6 +168,12 @@ rb_grn_table_cursor_next (VALUE self)
137
168
  return rb_record;
138
169
  }
139
170
 
171
+ /*
172
+ * call-seq:
173
+ * table_cursor.each {|record| ...}
174
+ *
175
+ * カーソルの範囲内にあるレコードを順番にブロックに渡す。
176
+ */
140
177
  static VALUE
141
178
  rb_grn_table_cursor_each (VALUE self)
142
179
  {
@@ -157,6 +194,26 @@ rb_grn_table_cursor_each (VALUE self)
157
194
  return Qnil;
158
195
  }
159
196
 
197
+ /*
198
+ * Document-method: close
199
+ *
200
+ * call-seq:
201
+ * cursor.close
202
+ *
203
+ * カーソルが使用しているリソースを開放する。これ以降カーソルを
204
+ * 使うことはできない。
205
+ */
206
+
207
+ /*
208
+ * Document-method: closed?
209
+ *
210
+ * call-seq:
211
+ * cursor.closed? -> true/false
212
+ *
213
+ * カーソルが開放済みの場合は+true+を返し、そうでない場合は
214
+ * +false+を返す。
215
+ */
216
+
160
217
  void
161
218
  rb_grn_init_table_cursor (VALUE mGrn)
162
219
  {
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby" -*- */
2
2
  /*
3
- Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
3
+ Copyright (C) 2009-2010 Kouhei Sutou <kou@clear-code.com>
4
4
 
5
5
  This library is free software; you can redistribute it and/or
6
6
  modify it under the terms of the GNU Lesser General Public
@@ -22,6 +22,13 @@
22
22
 
23
23
  VALUE rb_mGrnTableKeySupport;
24
24
 
25
+ /*
26
+ * Document-module: Groonga::Table::KeySupport
27
+ *
28
+ * 主キーを持つテーブルであるGroonga::Hashと
29
+ * Groonga::PatriciaTrieに主キーの機能を提供するモジュール。
30
+ */
31
+
25
32
  void
26
33
  rb_grn_table_key_support_deconstruct (RbGrnTableKeySupport *rb_grn_table_key_support,
27
34
  grn_obj **table_key_support,
@@ -31,7 +38,8 @@ rb_grn_table_key_support_deconstruct (RbGrnTableKeySupport *rb_grn_table_key_sup
31
38
  grn_obj **domain,
32
39
  grn_obj **value,
33
40
  grn_id *range_id,
34
- grn_obj **range)
41
+ grn_obj **range,
42
+ VALUE *columns)
35
43
  {
36
44
  RbGrnTable *rb_grn_table;
37
45
 
@@ -39,7 +47,8 @@ rb_grn_table_key_support_deconstruct (RbGrnTableKeySupport *rb_grn_table_key_sup
39
47
 
40
48
  rb_grn_table_deconstruct(rb_grn_table, table_key_support, context,
41
49
  domain_id, domain,
42
- value, range_id, range);
50
+ value, range_id, range,
51
+ columns);
43
52
 
44
53
  if (key)
45
54
  *key = rb_grn_table_key_support->key;
@@ -102,7 +111,8 @@ rb_grn_table_key_support_add_raw (VALUE self, VALUE rb_key)
102
111
 
103
112
  rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
104
113
  &key, &domain_id, &domain,
105
- NULL, NULL, NULL);
114
+ NULL, NULL, NULL,
115
+ NULL);
106
116
 
107
117
  GRN_BULK_REWIND(key);
108
118
  RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self);
@@ -113,6 +123,18 @@ rb_grn_table_key_support_add_raw (VALUE self, VALUE rb_key)
113
123
  return id;
114
124
  }
115
125
 
126
+ /*
127
+ * call-seq:
128
+ * table.add(key, values=nil) -> Groonga::Recordまたはnil
129
+ *
130
+ * 主キーが_key_のレコード追加し、追加したレコードを返す。レ
131
+ * コードの追加に失敗した場合は+nil+を返す。
132
+ *
133
+ * _values_にはレコードのカラムに設定する値を指定する。省略
134
+ * した場合または+nil+を指定した場合はカラムは設定しない。カ
135
+ * ラムの値は<tt>{:カラム名1 => 値1, :カラム名2 => 値2,
136
+ * ...}</tt>と指定する。
137
+ */
116
138
  static VALUE
117
139
  rb_grn_table_key_support_add (int argc, VALUE *argv, VALUE self)
118
140
  {
@@ -127,6 +149,63 @@ rb_grn_table_key_support_add (int argc, VALUE *argv, VALUE self)
127
149
  return rb_grn_record_new(self, id, values);
128
150
  }
129
151
 
152
+ grn_id
153
+ rb_grn_table_key_support_get (VALUE self, VALUE rb_key)
154
+ {
155
+ grn_ctx *context;
156
+ grn_obj *table, *key, *domain;
157
+ grn_id id, domain_id;
158
+
159
+ rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
160
+ &key, &domain_id, &domain,
161
+ NULL, NULL, NULL,
162
+ NULL);
163
+
164
+ GRN_BULK_REWIND(key);
165
+ RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self);
166
+ id = grn_table_get(context, table,
167
+ GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key));
168
+ rb_grn_context_check(context, self);
169
+
170
+ return id;
171
+ }
172
+
173
+ /*
174
+ * call-seq:
175
+ * table.id -> テーブルID
176
+ * table.id(key) -> レコードID
177
+ *
178
+ * _key_を指定しない場合はテーブルのIDを返す。
179
+ *
180
+ * _key_を指定した場合はテーブルの_key_に対応するレコードの
181
+ * IDを返す。
182
+ */
183
+ static VALUE
184
+ rb_grn_table_key_support_get_id (int argc, VALUE *argv, VALUE self)
185
+ {
186
+ VALUE rb_key;
187
+
188
+ rb_scan_args(argc, argv, "01", &rb_key);
189
+ if (NIL_P(rb_key)) {
190
+ return rb_grn_object_get_id(self);
191
+ } else {
192
+ grn_id id;
193
+
194
+ id = rb_grn_table_key_support_get(self, rb_key);
195
+ if (id == GRN_ID_NIL) {
196
+ return Qnil;
197
+ } else {
198
+ return UINT2NUM(id);
199
+ }
200
+ }
201
+ }
202
+
203
+ /*
204
+ * call-seq:
205
+ * table.key(id) -> 主キー
206
+ *
207
+ * テーブルの_id_に対応する主キーを返す。
208
+ */
130
209
  static VALUE
131
210
  rb_grn_table_key_support_get_key (VALUE self, VALUE rb_id)
132
211
  {
@@ -138,7 +217,8 @@ rb_grn_table_key_support_get_key (VALUE self, VALUE rb_id)
138
217
 
139
218
  rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
140
219
  &key, NULL, NULL,
141
- NULL, NULL, NULL);
220
+ NULL, NULL, NULL,
221
+ NULL);
142
222
 
143
223
  id = NUM2UINT(rb_id);
144
224
  GRN_BULK_REWIND(key);
@@ -156,6 +236,12 @@ rb_grn_table_key_support_get_key (VALUE self, VALUE rb_id)
156
236
  return rb_key;
157
237
  }
158
238
 
239
+ /*
240
+ * call-seq:
241
+ * table.has_key?(key) -> true/false
242
+ *
243
+ * テーブルに主キーが_key_のレコードがあるならtrueを返す。
244
+ */
159
245
  static VALUE
160
246
  rb_grn_table_key_support_has_key (VALUE self, VALUE rb_key)
161
247
  {
@@ -165,7 +251,8 @@ rb_grn_table_key_support_has_key (VALUE self, VALUE rb_key)
165
251
 
166
252
  rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
167
253
  &key, &domain_id, &domain,
168
- NULL, NULL, NULL);
254
+ NULL, NULL, NULL,
255
+ NULL);
169
256
 
170
257
  GRN_BULK_REWIND(key);
171
258
  RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self);
@@ -185,7 +272,8 @@ rb_grn_table_key_support_delete_by_key (VALUE self, VALUE rb_key)
185
272
 
186
273
  rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
187
274
  &key, &domain_id, &domain,
188
- NULL, NULL, NULL);
275
+ NULL, NULL, NULL,
276
+ NULL);
189
277
 
190
278
  GRN_BULK_REWIND(key);
191
279
  RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self);
@@ -197,6 +285,13 @@ rb_grn_table_key_support_delete_by_key (VALUE self, VALUE rb_key)
197
285
  return Qnil;
198
286
  }
199
287
 
288
+ /*
289
+ * call-seq:
290
+ * table.delete(id)
291
+ * table.delete(key)
292
+ *
293
+ * テーブルの_id_または_key_に対応するレコードを削除する。
294
+ */
200
295
  static VALUE
201
296
  rb_grn_table_key_support_delete (VALUE self, VALUE rb_id_or_key)
202
297
  {
@@ -207,41 +302,194 @@ rb_grn_table_key_support_delete (VALUE self, VALUE rb_id_or_key)
207
302
  }
208
303
  }
209
304
 
210
- grn_id
211
- rb_grn_table_key_support_get (VALUE self, VALUE rb_key)
305
+ /*
306
+ * Document-method: []
307
+ *
308
+ * call-seq:
309
+ * table[key] -> Groonga::Record
310
+ *
311
+ * _table_の_key_に対応するGroonga::Recordを返す。
312
+ *
313
+ * 0.9.0から値ではなくGroonga::Recordを返すようになった。
314
+ */
315
+ static VALUE
316
+ rb_grn_table_key_support_array_reference (VALUE self, VALUE rb_key)
317
+ {
318
+ grn_id id;
319
+
320
+ id = rb_grn_table_key_support_get(self, rb_key);
321
+ if (id == GRN_ID_NIL) {
322
+ return Qnil;
323
+ } else {
324
+ return rb_grn_record_new(self, id, Qnil);
325
+ }
326
+ }
327
+
328
+ typedef struct _SetValueData
212
329
  {
330
+ VALUE self;
331
+ grn_id id;
332
+ grn_obj *table;
333
+ RbGrnObject rb_grn_object;
334
+ } SetValueData;
335
+
336
+ static VALUE
337
+ set_value (VALUE args, SetValueData *data)
338
+ {
339
+ VALUE rb_name, rb_value, rb_column;
340
+ RbGrnObject *rb_grn_object;
341
+
342
+ rb_name = rb_ary_entry(args, 0);
343
+ rb_value = rb_ary_entry(args, 1);
344
+
345
+ rb_column = rb_grn_table_get_column(data->self, rb_name);
346
+ if (NIL_P(rb_column)) {
347
+ rb_raise(rb_eGrnNoSuchColumn,
348
+ "no such column: <%s>: <%s>",
349
+ rb_grn_inspect(rb_name), rb_grn_inspect(data->self));
350
+ }
351
+
352
+ rb_grn_object = RB_GRN_OBJECT(DATA_PTR(rb_column));
353
+ return rb_grn_object_set_raw(rb_grn_object,
354
+ data->id, rb_value, GRN_OBJ_SET, data->self);
355
+ }
356
+
357
+ /*
358
+ * Document-method: []=
359
+ *
360
+ * call-seq:
361
+ * table[key] = {:column_name => value, ...}
362
+ *
363
+ * _table_の_key_に対応するカラム_column_name_の値を設定する。
364
+ * _key_に対応するレコードがない場合は新しく作成される。
365
+ *
366
+ * 0.9.0から値ではなくカラムの値を設定するようになった。
367
+ */
368
+ static VALUE
369
+ rb_grn_table_key_support_array_set (VALUE self, VALUE rb_key, VALUE rb_values)
370
+ {
371
+ grn_id id;
372
+ SetValueData data;
213
373
  grn_ctx *context;
214
- grn_obj *table, *key, *domain;
215
- grn_id id, domain_id;
374
+ grn_obj *table;
216
375
 
217
376
  rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
218
- &key, &domain_id, &domain,
219
- NULL, NULL, NULL);
377
+ NULL, NULL, NULL,
378
+ NULL, NULL, NULL,
379
+ NULL);
220
380
 
221
- GRN_BULK_REWIND(key);
222
- RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self);
223
- id = grn_table_get(context, table,
224
- GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key));
225
- rb_grn_context_check(context, self);
381
+ id = rb_grn_table_key_support_add_raw(self, rb_key);
226
382
 
227
- return id;
383
+ if (id == GRN_ID_NIL) {
384
+ rb_raise(rb_eGrnError,
385
+ "failed to add record: %s",
386
+ rb_grn_inspect(rb_ary_new3(3, self, rb_key, rb_values)));
387
+ }
388
+
389
+ data.self = self;
390
+ data.id = id;
391
+ data.table = table;
392
+ data.rb_grn_object.context = context;
393
+ rb_iterate(rb_each, rb_values, set_value, (VALUE)&data);
394
+
395
+ return Qnil;
228
396
  }
229
397
 
398
+ /*
399
+ * call-seq:
400
+ * table.set_column_value(key, name, value)
401
+ * table.set_column_value(id, name, value, :id => true)
402
+ *
403
+ * _table_の_key_に対応するカラム_name_の値を設定する。
404
+ * _key_に対応するレコードがない場合は新しく作成される。
405
+ */
230
406
  static VALUE
231
- rb_grn_table_key_support_find (VALUE self, VALUE rb_key)
407
+ rb_grn_table_key_support_set_column_value (int argc, VALUE *argv, VALUE self)
232
408
  {
233
409
  grn_id id;
410
+ VALUE rb_key, rb_id_or_key, rb_name, rb_value, rb_options;
411
+
412
+ rb_scan_args(argc, argv, "31",
413
+ &rb_id_or_key, &rb_name, &rb_value, &rb_options);
414
+ if (!NIL_P(rb_options)) {
415
+ VALUE rb_option_id;
416
+ rb_grn_scan_options(rb_options,
417
+ "id", &rb_option_id,
418
+ NULL);
419
+ if (RVAL2CBOOL(rb_option_id)) {
420
+ VALUE rb_id = rb_id_or_key;
421
+ return rb_grn_table_set_column_value(self, rb_id, rb_name, rb_value);
422
+ }
423
+ }
234
424
 
235
- id = rb_grn_table_key_support_get(self, rb_key);
425
+ rb_key = rb_id_or_key;
426
+ id = rb_grn_table_key_support_add_raw(self, rb_key);
427
+ if (id == GRN_ID_NIL) {
428
+ rb_raise(rb_eGrnError,
429
+ "failed to add record: %s",
430
+ rb_grn_inspect(rb_ary_new3(4,
431
+ self, rb_key,
432
+ rb_name, rb_value)));
433
+ }
236
434
 
237
- if (id == GRN_ID_NIL)
435
+ return rb_grn_table_set_column_value_raw(self, id, rb_name, rb_value);
436
+ }
437
+
438
+ /*
439
+ * call-seq:
440
+ * table.column_value(key, name)
441
+ * table.column_value(id, name, :id => true)
442
+ *
443
+ * _table_の_key_に対応するカラム_name_の値を設定する。
444
+ *
445
+ * TODO: _key_に対応するレコードがない場合は例外?
446
+ */
447
+ static VALUE
448
+ rb_grn_table_key_support_get_column_value (int argc, VALUE *argv, VALUE self)
449
+ {
450
+ grn_id id;
451
+ VALUE rb_key, rb_id_or_key, rb_name, rb_options;
452
+
453
+ rb_scan_args(argc, argv, "21", &rb_id_or_key, &rb_name, &rb_options);
454
+ if (!NIL_P(rb_options)) {
455
+ VALUE rb_option_id;
456
+ rb_grn_scan_options(rb_options,
457
+ "id", &rb_option_id,
458
+ NULL);
459
+ if (RVAL2CBOOL(rb_option_id)) {
460
+ VALUE rb_id = rb_id_or_key;
461
+ return rb_grn_table_get_column_value(self, rb_id, rb_name);
462
+ }
463
+ }
464
+
465
+ rb_key = rb_id_or_key;
466
+ id = rb_grn_table_key_support_get(self, rb_key);
467
+ if (id == GRN_ID_NIL) {
238
468
  return Qnil;
239
- else
240
- return rb_grn_record_new(self, id, Qnil);
469
+ }
470
+
471
+ return rb_grn_table_get_column_value_raw(self, id, rb_name);
241
472
  }
242
473
 
474
+ /*
475
+ * call-seq:
476
+ * table.find(key) -> Groonga::Record
477
+ *
478
+ * テーブルの_key_に対応するレコードを返す。
479
+ *
480
+ * 0.9.0から非推奨。代わりにtable[key]を使うこと。
481
+ */
243
482
  static VALUE
244
- rb_grn_table_key_support_array_reference_by_key (VALUE self, VALUE rb_key)
483
+ rb_grn_table_key_support_find (VALUE self, VALUE rb_key)
484
+ {
485
+ rb_warn("#find is deprecated. Use #[] instead: %s",
486
+ rb_grn_inspect(self));
487
+
488
+ return rb_grn_table_key_support_array_reference(self, rb_key);
489
+ }
490
+
491
+ static VALUE
492
+ rb_grn_table_key_support_get_value_by_key (VALUE self, VALUE rb_key)
245
493
  {
246
494
  grn_ctx *context;
247
495
  grn_obj *table, *value, *range;
@@ -254,30 +502,50 @@ rb_grn_table_key_support_array_reference_by_key (VALUE self, VALUE rb_key)
254
502
 
255
503
  rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
256
504
  NULL, NULL, NULL,
257
- &value, NULL, &range);
505
+ &value, NULL, &range,
506
+ NULL);
258
507
  GRN_BULK_REWIND(value);
259
508
  grn_obj_get_value(context, table, id, value);
260
509
  rb_grn_context_check(context, self);
261
510
 
262
- if (GRN_BULK_EMPTYP(value))
263
- return Qnil;
264
- else
265
- return rb_str_new(GRN_BULK_HEAD(value), GRN_BULK_VSIZE(value));
511
+ return GRNBULK2RVAL(context, value, range, self);
266
512
  }
267
513
 
514
+ /*
515
+ * call-seq:
516
+ * table.value(id, :id => true) -> 値
517
+ * table.value(key) -> 値
518
+ *
519
+ * _table_の_id_または_key_に対応する値を返す。
520
+ */
268
521
  static VALUE
269
- rb_grn_table_key_support_array_reference (VALUE self, VALUE rb_id_or_key)
522
+ rb_grn_table_key_support_get_value (int argc, VALUE *argv, VALUE self)
270
523
  {
271
- if (FIXNUM_P(rb_id_or_key)) {
272
- return rb_grn_table_array_reference(self, rb_id_or_key);
524
+ VALUE rb_id_or_key, rb_options;
525
+ rb_grn_boolean use_key;
526
+
527
+ rb_scan_args(argc, argv, "11", &rb_id_or_key, &rb_options);
528
+
529
+ if (NIL_P(rb_options)) {
530
+ use_key = RB_GRN_TRUE;
531
+ } else {
532
+ VALUE rb_option_id;
533
+
534
+ rb_grn_scan_options(rb_options,
535
+ "id", &rb_option_id,
536
+ NULL);
537
+ use_key = !RVAL2CBOOL(rb_option_id);
538
+ }
539
+
540
+ if (use_key) {
541
+ return rb_grn_table_key_support_get_value_by_key(self, rb_id_or_key);
273
542
  } else {
274
- return rb_grn_table_key_support_array_reference_by_key(self,
275
- rb_id_or_key);
543
+ return rb_grn_table_get_value(self, rb_id_or_key);
276
544
  }
277
545
  }
278
546
 
279
547
  static VALUE
280
- rb_grn_table_key_support_array_set_by_key (VALUE self,
548
+ rb_grn_table_key_support_set_value_by_key (VALUE self,
281
549
  VALUE rb_key, VALUE rb_value)
282
550
  {
283
551
  grn_ctx *context;
@@ -286,20 +554,23 @@ rb_grn_table_key_support_array_set_by_key (VALUE self,
286
554
  grn_obj *value;
287
555
  grn_rc rc;
288
556
 
289
- if (NIL_P(rb_key))
557
+ if (NIL_P(rb_key)) {
290
558
  rb_raise(rb_eArgError, "key should not be nil: <%s>",
291
559
  rb_grn_inspect(self));
560
+ }
292
561
 
293
562
  rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
294
563
  NULL, NULL, NULL,
295
- &value, NULL, NULL);
564
+ &value, NULL, NULL,
565
+ NULL);
296
566
 
297
567
  id = rb_grn_table_key_support_add_raw(self, rb_key);
298
- if (GRN_ID_NIL == id)
568
+ if (GRN_ID_NIL == id) {
299
569
  rb_raise(rb_eGrnError,
300
570
  "failed to add new record with key: <%s>: <%s>",
301
571
  rb_grn_inspect(rb_key),
302
572
  rb_grn_inspect(self));
573
+ }
303
574
 
304
575
  GRN_BULK_REWIND(value);
305
576
  RVAL2GRNBULK(rb_value, context, value);
@@ -310,19 +581,48 @@ rb_grn_table_key_support_array_set_by_key (VALUE self,
310
581
  return rb_value;
311
582
  }
312
583
 
584
+ /*
585
+ * call-seq:
586
+ * table.set_value(id, value, :id => true)
587
+ * table.set_value(key, value)
588
+ *
589
+ * _table_の_id_または_key_に対応する値を_value_に設定する。
590
+ * 既存の値は上書きされる。
591
+ */
313
592
  static VALUE
314
- rb_grn_table_key_support_array_set (VALUE self,
315
- VALUE rb_id_or_key, VALUE rb_value)
593
+ rb_grn_table_key_support_set_value (int argc, VALUE *argv, VALUE self)
316
594
  {
317
- if (FIXNUM_P(rb_id_or_key)) {
318
- return rb_grn_table_array_set(self, rb_id_or_key, rb_value);
595
+ VALUE rb_id_or_key, rb_value, rb_options;
596
+ rb_grn_boolean use_key;
597
+
598
+ rb_scan_args(argc, argv, "21", &rb_id_or_key, &rb_value, &rb_options);
599
+
600
+ if (NIL_P(rb_options)) {
601
+ use_key = RB_GRN_TRUE;
319
602
  } else {
320
- return rb_grn_table_key_support_array_set_by_key(self,
603
+ VALUE rb_option_id;
604
+
605
+ rb_grn_scan_options(rb_options,
606
+ "id", &rb_option_id,
607
+ NULL);
608
+ use_key = !RVAL2CBOOL(rb_option_id);
609
+ }
610
+
611
+ if (use_key) {
612
+ return rb_grn_table_key_support_set_value_by_key(self,
321
613
  rb_id_or_key,
322
614
  rb_value);
615
+ } else {
616
+ return rb_grn_table_set_value(self, rb_id_or_key, rb_value);
323
617
  }
324
618
  }
325
619
 
620
+ /*
621
+ * call-seq:
622
+ * table.default_tokenizer -> nilまたはGroonga::Procedure
623
+ *
624
+ * Groonga::IndexColumnで使用するトークナイザを返す。
625
+ */
326
626
  static VALUE
327
627
  rb_grn_table_key_support_get_default_tokenizer (VALUE self)
328
628
  {
@@ -332,7 +632,8 @@ rb_grn_table_key_support_get_default_tokenizer (VALUE self)
332
632
 
333
633
  rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
334
634
  NULL, NULL, NULL,
335
- NULL, NULL, NULL);
635
+ NULL, NULL, NULL,
636
+ NULL);
336
637
 
337
638
  tokenizer = grn_obj_get_info(context, table, GRN_INFO_DEFAULT_TOKENIZER,
338
639
  NULL);
@@ -341,6 +642,28 @@ rb_grn_table_key_support_get_default_tokenizer (VALUE self)
341
642
  return GRNOBJECT2RVAL(Qnil, context, tokenizer, RB_GRN_FALSE);
342
643
  }
343
644
 
645
+ /*
646
+ * call-seq:
647
+ * table.default_tokenizer = トークナイザ
648
+ *
649
+ * Groonga::IndexColumnで使用するトークナイザを設定する。
650
+ *
651
+ * 例:
652
+ * # 2-gramを使用。
653
+ * table.default_tokenizer = "TokenBigram"
654
+ * # オブジェクトで指定
655
+ * table.default_tokenizer = Groonga::Context.default["TokenBigram"]
656
+ * # オブジェクトIDで指定
657
+ * table.default_tokenizer = Groonga::Type::BIGRAM
658
+ * # N-gram用のトークナイザを使うときはGroonga::IndexColumn
659
+ * # には自動的に:with_section => trueが指定される。
660
+ * index = table.define_index_column("blog_content", "Blogs",
661
+ * :source => "content")
662
+ * p index # -> #<Groonga::IndexColumn ... flags: <WITH_POSITION|...>>
663
+ *
664
+ * # MeCabを使用
665
+ * table.default_tokenizer = "TokenMecab"
666
+ */
344
667
  static VALUE
345
668
  rb_grn_table_key_support_set_default_tokenizer (VALUE self, VALUE rb_tokenizer)
346
669
  {
@@ -351,7 +674,8 @@ rb_grn_table_key_support_set_default_tokenizer (VALUE self, VALUE rb_tokenizer)
351
674
 
352
675
  rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
353
676
  NULL, NULL, NULL,
354
- NULL, NULL, NULL);
677
+ NULL, NULL, NULL,
678
+ NULL);
355
679
 
356
680
  tokenizer = RVAL2GRNOBJECT(rb_tokenizer, &context);
357
681
  rc = grn_obj_set_info(context, table,
@@ -373,6 +697,8 @@ rb_grn_init_table_key_support (VALUE mGrn)
373
697
 
374
698
  rb_define_method(rb_mGrnTableKeySupport, "add",
375
699
  rb_grn_table_key_support_add, -1);
700
+ rb_define_method(rb_mGrnTableKeySupport, "id",
701
+ rb_grn_table_key_support_get_id, -1);
376
702
  rb_define_method(rb_mGrnTableKeySupport, "key",
377
703
  rb_grn_table_key_support_get_key, 1);
378
704
  rb_define_method(rb_mGrnTableKeySupport, "has_key?",
@@ -388,6 +714,16 @@ rb_grn_init_table_key_support (VALUE mGrn)
388
714
  rb_define_method(rb_mGrnTableKeySupport, "[]=",
389
715
  rb_grn_table_key_support_array_set, 2);
390
716
 
717
+ rb_define_method(rb_mGrnTableKeySupport, "column_value",
718
+ rb_grn_table_key_support_get_column_value, -1);
719
+ rb_define_method(rb_mGrnTableKeySupport, "set_column_value",
720
+ rb_grn_table_key_support_set_column_value, -1);
721
+
722
+ rb_define_method(rb_mGrnTableKeySupport, "value",
723
+ rb_grn_table_key_support_get_value, -1);
724
+ rb_define_method(rb_mGrnTableKeySupport, "set_value",
725
+ rb_grn_table_key_support_set_value, -1);
726
+
391
727
  rb_define_method(rb_mGrnTableKeySupport, "default_tokenizer",
392
728
  rb_grn_table_key_support_get_default_tokenizer, 0);
393
729
  rb_define_method(rb_mGrnTableKeySupport, "default_tokenizer=",