groonga 0.0.7 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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=",