rroonga 3.0.2 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,28 @@
1
1
  h1. NEWS
2
2
 
3
+ h2(#3-0-3). 3.0.3: 2013-07-04
4
+
5
+ h3. Improvements
6
+
7
+ * Required groonga >= 3.0.5.
8
+ * Added an error check for creating a result table of {Groonga::Table#select}.
9
+ * Added {Groonga::Operator::AND_NOT}.
10
+ * Deprecated {Groonga::Operator::BUT} because groonga deprecated it.
11
+ Use {Groonga::Operator::AND_NOT} instead.
12
+ * Added {Groonga::Array#unblock}.
13
+ * Added @:max_n_sub_records@ option to {Groonga::Table#group}.
14
+ * Added {Groonga::Table#each_sub_record}.
15
+ * Supported groonga to Ruby conversion for vector value.
16
+ * Added @:reference => true@ option to {Groonga::Expression#define_variable}
17
+ that defines reference type variable.
18
+ * Added {Groonga::Record#sub_records} that returns sub records for the record.
19
+ Sub records is a {Groonga::SubRecords} instance.
20
+
21
+ h3. Fixes
22
+
23
+ * Fixed {Groonga::Expression#[]} return type. It returns {Groonga::Variable}
24
+ instead of value itself. CAUTION: It is a backward incompatible change.
25
+
3
26
  h2(#3-0-2). 3.0.2: 2013-05-29
4
27
 
5
28
  h3. Improvements
@@ -141,10 +141,20 @@ def extract_groonga_win32_binary(major, minor, micro)
141
141
  message(" done\n")
142
142
  end
143
143
 
144
+ def run_command(start_message, command)
145
+ message(start_message)
146
+ if xsystem(command)
147
+ message(" done\n")
148
+ else
149
+ message(" failed\n")
150
+ exit(false)
151
+ end
152
+ end
153
+
144
154
  def configure_command_line(prefix)
145
155
  command_line = ["./configure"]
146
156
  debug_build_p = ENV["RROONGA_DEBUG_BUILD"] == "yes"
147
- debug_flags = ["CFLAGS=-ggdb3 -O0", "CXXFLAGS=-ggdb3 -O0"]
157
+ debug_flags = ["CFLAGS=-g3 -O0", "CXXFLAGS=-g3 -O0"]
148
158
  command_line.concat(debug_flags) if debug_build_p
149
159
  command_line << "--prefix=#{prefix}"
150
160
  command_line << "--disable-static"
@@ -155,10 +165,37 @@ def configure_command_line(prefix)
155
165
  escaped_command_line.join(" ")
156
166
  end
157
167
 
158
- def build_groonga(major, minor, micro)
168
+ def install_for_gnu_build_system(install_dir)
169
+ run_command("configuring...",
170
+ configure_command_line(install_dir))
171
+ run_command("building (maybe long time)...",
172
+ "make")
173
+ run_command("installing...",
174
+ "make install")
175
+ end
176
+
177
+ def build_groonga_from_git(major, minor, micro)
178
+ message("removing old cloned repository...")
179
+ FileUtils.rm_rf("groonga")
180
+ message(" done\n")
181
+
182
+ run_command("cloning...",
183
+ "git clone --depth 1 https://github.com/groonga/groonga")
184
+
185
+ Dir.chdir("groonga") do
186
+ run_command("running autogen.sh...",
187
+ "./autogen.sh")
188
+ install_for_gnu_build_system(local_groonga_install_dir)
189
+ end
190
+
191
+ message("removing cloned repository...")
192
+ FileUtils.rm_rf("groonga")
193
+ message(" done\n")
194
+ end
195
+
196
+ def build_groonga_from_tar_gz(major, minor, micro)
159
197
  tar_gz = "groonga-#{major}.#{minor}.#{micro}.tar.gz"
160
198
  url = "http://packages.groonga.org/source/groonga/#{tar_gz}"
161
- install_dir = local_groonga_install_dir
162
199
 
163
200
  download(url)
164
201
 
@@ -172,29 +209,7 @@ def build_groonga(major, minor, micro)
172
209
 
173
210
  groonga_source_dir = "groonga-#{major}.#{minor}.#{micro}"
174
211
  Dir.chdir(groonga_source_dir) do
175
- message("configuring...")
176
- if xsystem(configure_command_line(install_dir))
177
- message(" done\n")
178
- else
179
- message(" failed\n")
180
- exit(false)
181
- end
182
-
183
- message("building (maybe long time)...")
184
- if xsystem("make")
185
- message(" done\n")
186
- else
187
- message(" failed\n")
188
- exit(false)
189
- end
190
-
191
- message("installing...")
192
- if xsystem("make install")
193
- message(" done\n")
194
- else
195
- message(" failed\n")
196
- exit(false)
197
- end
212
+ install_for_gnu_build_system(local_groonga_install_dir)
198
213
  end
199
214
 
200
215
  message("removing source...")
@@ -206,6 +221,14 @@ def build_groonga(major, minor, micro)
206
221
  message(" done\n")
207
222
  end
208
223
 
224
+ def build_groonga(major, minor, micro)
225
+ if RequiredGroongaVersion::RELEASED_DATE > Time.now
226
+ build_groonga_from_git(major, minor, micro)
227
+ else
228
+ build_groonga_from_tar_gz(major, minor, micro)
229
+ end
230
+ end
231
+
209
232
  unless PKGConfig.have_package(package_name, major, minor, micro)
210
233
  unless have_local_groonga?(package_name, major, minor, micro)
211
234
  install_groonga_locally(major, minor, micro)
@@ -326,7 +326,7 @@ rb_grn_array_push (VALUE self)
326
326
  }
327
327
 
328
328
  /*
329
- * Pulles a record from the array. The required values should be
329
+ * Pulls a record from the array. The required values should be
330
330
  * retrieved in the given block.
331
331
  *
332
332
  * If {Groonga::Array#push} failes to fill values of the pushed
@@ -353,6 +353,21 @@ rb_grn_array_push (VALUE self)
353
353
  * p pulled_record.nil? # => true
354
354
  * end
355
355
  *
356
+ * Note that your signal handlers can't be ran while a pull
357
+ * operation. You need to use {Groonga::Array#unblock} from
358
+ * another process to unblock the pull operation. If you call
359
+ * {Groonga::Array#unblock}, signal handler can be ran.
360
+ *
361
+ * @example Signal handler isn't called
362
+ * queue = Groonga::Array.open(:name => "CrawlURLQueue")
363
+ * trap(:INT) do
364
+ * p :not_called!
365
+ * end
366
+ * queue.pull do |record|
367
+ * # Send SIGINT while blocking the pull operation.
368
+ * # The signal handler isn't called.
369
+ * end
370
+ *
356
371
  * @see Groonga::Array#push Examples exist in the push documentation.
357
372
  *
358
373
  * @overload pull(options={})
@@ -406,6 +421,45 @@ rb_grn_array_pull (int argc, VALUE *argv, VALUE self)
406
421
  return data.record;
407
422
  }
408
423
 
424
+ /*
425
+ * Unblocks all {Groonga::Array#pull} operations for the array.
426
+ *
427
+ * @example Pull, unblock and signal
428
+ * # pull.rb
429
+ * queue = Groonga::Array.open(:name => "CrawlURLQueue")
430
+ * trap(:INT) do
431
+ * p :called!
432
+ * end
433
+ * queue.pull do |record|
434
+ * # 1. Send SIGINT while blocking the pull operation.
435
+ * # The signal handler isn't called.
436
+ * # 2. Run unblock.rb.
437
+ * # The signal handler is called!
438
+ * end
439
+ *
440
+ * # unblock.rb
441
+ * queue = Groonga::Array.open(:name => "CrawlURLQueue")
442
+ * queue.unblock
443
+ *
444
+ * @see Groonga::Array#pull
445
+ *
446
+ * @overload unblock
447
+ * @return [void]
448
+ *
449
+ */
450
+ static VALUE
451
+ rb_grn_array_unblock (VALUE self)
452
+ {
453
+ grn_ctx *context = NULL;
454
+ grn_obj *table;
455
+
456
+ table = SELF(self, &context);
457
+
458
+ grn_array_unblock(context, (grn_array *)table);
459
+
460
+ return Qnil;
461
+ }
462
+
409
463
  void
410
464
  rb_grn_init_array (VALUE mGrn)
411
465
  {
@@ -417,4 +471,5 @@ rb_grn_init_array (VALUE mGrn)
417
471
  rb_define_method(rb_cGrnArray, "add", rb_grn_array_add, -1);
418
472
  rb_define_method(rb_cGrnArray, "push", rb_grn_array_push, 0);
419
473
  rb_define_method(rb_cGrnArray, "pull", rb_grn_array_pull, -1);
474
+ rb_define_method(rb_cGrnArray, "unblock", rb_grn_array_unblock, 0);
420
475
  }
@@ -228,7 +228,7 @@ rb_grn_column_get_local_name (VALUE self)
228
228
  * - Groonga::Operator::AND :=
229
229
  * マッチしたレコードのスコアを増加。マッチしなかった
230
230
  * レコードを削除。 =:
231
- * - Groonga::Operator::BUT :=
231
+ * - Groonga::Operator::AND_NOT :=
232
232
  * マッチしたレコードを削除。 =:
233
233
  * - Groonga::Operator::ADJUST :=
234
234
  * マッチしたレコードのスコアを増加。 =:
@@ -286,7 +286,7 @@ rb_grn_double_array_trie_s_create (int argc, VALUE *argv, VALUE klass)
286
286
  * - Groonga::Operator::AND :=
287
287
  * マッチしたレコードのスコアを増加。マッチしなかった
288
288
  * レコードを削除。 =:
289
- * - Groonga::Operator::BUT :=
289
+ * - Groonga::Operator::AND_NOT :=
290
290
  * マッチしたレコードを削除。 =:
291
291
  * - Groonga::Operator::ADJUST :=
292
292
  * マッチしたレコードのスコアを増加。 =:
@@ -57,7 +57,7 @@ static VALUE eGrnBrokenPipe;
57
57
  static VALUE eGrnDomainError;
58
58
  static VALUE eGrnResultTooLarge;
59
59
  static VALUE eGrnResourceDeadlockAvoided;
60
- static VALUE eGrnNoMemoryAvailable;
60
+ VALUE rb_eGrnNoMemoryAvailable;
61
61
  static VALUE eGrnFilenameTooLong;
62
62
  static VALUE eGrnNoLocksAvailable;
63
63
  static VALUE eGrnFunctionNotImplemented;
@@ -211,7 +211,7 @@ rb_grn_rc_to_exception (grn_rc rc)
211
211
  exception = eGrnResourceDeadlockAvoided;
212
212
  break;
213
213
  case GRN_NO_MEMORY_AVAILABLE:
214
- exception = eGrnNoMemoryAvailable;
214
+ exception = rb_eGrnNoMemoryAvailable;
215
215
  break;
216
216
  case GRN_FILENAME_TOO_LONG:
217
217
  exception = eGrnFilenameTooLong;
@@ -910,7 +910,7 @@ rb_grn_init_exception (VALUE mGrn)
910
910
  *
911
911
  * メモリが足りないときに発生する。
912
912
  */
913
- eGrnNoMemoryAvailable =
913
+ rb_eGrnNoMemoryAvailable =
914
914
  rb_define_class_under(mGrn, "NoMemoryAvailable", rb_eGrnError);
915
915
 
916
916
  /*
@@ -112,10 +112,14 @@ rb_grn_expression_initialize (int argc, VALUE *argv, VALUE self)
112
112
  * @overload define_variable(options={})
113
113
  * @param [::Hash] options The name and value
114
114
  * pairs. Omitted names are initialized as the default value.
115
- * @option options :name (false)
115
+ * @option options :name [String] (nil)
116
116
  * 変数の名前。省略した場合は名前を付けない。
117
- * @option options :domain
117
+ * @option options :domain [Groonga::Table] (nil)
118
118
  * テーブルを指定すると、そのテーブル用のレコードとして初期化する。
119
+ * @option options :reference [Bool] (nil)
120
+ * Initializes this variable as reference hold variable if
121
+ * @:reference@ is true. Reference hold variable is GRN_PTR type
122
+ * in groonga. You can't use @:reference@ with @:domain@.
119
123
  * @return [Groonga::Variable]
120
124
  *
121
125
  */
@@ -126,7 +130,7 @@ rb_grn_expression_define_variable (int argc, VALUE *argv, VALUE self)
126
130
  grn_obj *expression, *variable;
127
131
  char *name = NULL;
128
132
  unsigned name_size = 0;
129
- VALUE options, rb_name, rb_domain, rb_variable;
133
+ VALUE options, rb_name, rb_domain, rb_variable, rb_reference;
130
134
 
131
135
  rb_scan_args(argc, argv, "01", &options);
132
136
 
@@ -137,6 +141,7 @@ rb_grn_expression_define_variable (int argc, VALUE *argv, VALUE self)
137
141
  rb_grn_scan_options(options,
138
142
  "name", &rb_name,
139
143
  "domain", &rb_domain,
144
+ "reference", &rb_reference,
140
145
  NULL);
141
146
 
142
147
  if (!NIL_P(rb_name)) {
@@ -151,6 +156,8 @@ rb_grn_expression_define_variable (int argc, VALUE *argv, VALUE self)
151
156
  grn_id domain_id;
152
157
  domain_id = NUM2UINT(rb_funcall(rb_domain, rb_intern("id"), 0));
153
158
  GRN_RECORD_INIT(variable, 0, domain_id);
159
+ } else if (!NIL_P(rb_reference) && RVAL2CBOOL(rb_reference)) {
160
+ GRN_PTR_INIT(variable, 0, GRN_DB_OBJECT);
154
161
  }
155
162
 
156
163
  return rb_variable;
@@ -277,7 +284,7 @@ rb_grn_expression_append_operation (VALUE self, VALUE rb_operation,
277
284
  * レコードはいずれかの条件にマッチすればいい。 =:
278
285
  * - Groonga::Operator::AND :=
279
286
  * レコードは全ての条件にマッチしなければならない。 =:
280
- * - Groonga::Operator::BUT :=
287
+ * - Groonga::Operator::AND_NOT :=
281
288
  * 最初の条件にレコードはマッチし、残りの条件にレコードは
282
289
  * マッチしてはならない。 =:
283
290
  *
@@ -500,7 +507,7 @@ static VALUE
500
507
  rb_grn_expression_array_reference (VALUE self, VALUE rb_name_or_offset)
501
508
  {
502
509
  grn_ctx *context = NULL;
503
- grn_obj *expression, *variable, *value;
510
+ grn_obj *expression, *variable;
504
511
  char *name = NULL;
505
512
  unsigned name_size = 0;
506
513
  int offset;
@@ -514,19 +521,17 @@ rb_grn_expression_array_reference (VALUE self, VALUE rb_name_or_offset)
514
521
  name = RSTRING_PTR(rb_name_or_offset);
515
522
  name_size = RSTRING_LEN(rb_name_or_offset);
516
523
  variable = grn_expr_get_var(context, expression, name, name_size);
517
- return GRNBULK2RVAL(context, variable, NULL, self);
518
524
  break;
519
525
  case T_FIXNUM:
520
526
  offset = NUM2INT(rb_name_or_offset);
521
- value = grn_expr_get_var_by_offset(context, expression, offset);
522
- return GRNBULK2RVAL(context, value, NULL, self);
527
+ variable = grn_expr_get_var_by_offset(context, expression, offset);
523
528
  break;
524
529
  default:
525
530
  rb_raise(rb_eArgError, "xxx");
526
531
  break;
527
532
  }
528
533
 
529
- return Qnil;
534
+ return GRNVARIABLE2RVAL(context, variable);
530
535
  }
531
536
 
532
537
  /* REMOVE ME */
@@ -451,7 +451,7 @@ rb_grn_index_column_delete (int argc, VALUE *argv, VALUE self)
451
451
  * updated automatically by using @:source@ option of
452
452
  * {Groonga::Table#define_index_column}.
453
453
  *
454
- * @example Updates sentences of an article to index
454
+ * @example Updates sentences of an article in index
455
455
  * articles = Groonga::Array.create(:name => "Articles")
456
456
  * articles.define_column("title", "ShortText")
457
457
  * articles.define_column("content", "Text")
@@ -35,15 +35,19 @@ rb_grn_operator_from_ruby_object (VALUE rb_operator)
35
35
  operator = GRN_OP_AND;
36
36
  } else if (rb_grn_equal_option(rb_operator, "but") ||
37
37
  rb_grn_equal_option(rb_operator, "not") ||
38
- rb_grn_equal_option(rb_operator, "-")) {
39
- operator = GRN_OP_BUT;
38
+ rb_grn_equal_option(rb_operator, "and-not") ||
39
+ rb_grn_equal_option(rb_operator, "and_not") ||
40
+ rb_grn_equal_option(rb_operator, "-") ||
41
+ rb_grn_equal_option(rb_operator, "&!")) {
42
+ operator = GRN_OP_AND_NOT;
40
43
  } else if (rb_grn_equal_option(rb_operator, "adjust") ||
41
44
  rb_grn_equal_option(rb_operator, ">")) {
42
45
  operator = GRN_OP_ADJUST;
43
46
  } else {
44
47
  rb_raise(rb_eArgError,
45
48
  "operator should be one of "
46
- "[:or, :||, :and, :+, :&&, :but, :not, :-, :adjust, :>]: <%s>",
49
+ "[:or, :||, :and, :+, :&&, :but, :not, :and_not, :-, :&!, "
50
+ ":adjust, :>]: <%s>",
47
51
  rb_grn_inspect(rb_operator));
48
52
  }
49
53
 
@@ -73,6 +77,9 @@ rb_grn_init_operator (VALUE mGrn)
73
77
  UINT2NUM(GRN_OP_GET_VALUE));
74
78
  rb_define_const(rb_mGrnOperator, "AND",
75
79
  UINT2NUM(GRN_OP_AND));
80
+ rb_define_const(rb_mGrnOperator, "AND_NOT",
81
+ UINT2NUM(GRN_OP_AND_NOT));
82
+ /* Just for backward compatiblity. TODO: REMOVE ME! */
76
83
  rb_define_const(rb_mGrnOperator, "BUT",
77
84
  UINT2NUM(GRN_OP_BUT));
78
85
  rb_define_const(rb_mGrnOperator, "OR",
@@ -274,7 +274,7 @@ rb_grn_patricia_trie_s_create (int argc, VALUE *argv, VALUE klass)
274
274
  * - Groonga::Operator::AND :=
275
275
  * マッチしたレコードのスコアを増加。マッチしなかった
276
276
  * レコードを削除。 =:
277
- * - Groonga::Operator::BUT :=
277
+ * - Groonga::Operator::AND_NOT :=
278
278
  * マッチしたレコードを削除。 =:
279
279
  * - Groonga::Operator::ADJUST :=
280
280
  * マッチしたレコードのスコアを増加。 =:
@@ -18,16 +18,6 @@
18
18
 
19
19
  #include "rb-grn.h"
20
20
 
21
- /* GRN_TABLE_* should be defined in groonga.h. If they are defined in
22
- * groonga.h, the following defines are removed. */
23
- #ifndef GRN_TABLE_GROUPED
24
- # define GRN_TABLE_GROUPED (0x01<<0)
25
- #endif
26
- #ifndef GRN_TABLE_IS_GROUPED
27
- # define GRN_TABLE_IS_GROUPED(table) \
28
- ((table)->header.impl_flags & GRN_TABLE_GROUPED)
29
- #endif
30
-
31
21
  grn_obj *grn_table_open(grn_ctx *ctx,
32
22
  const char *name, unsigned name_size, const char *path);
33
23
  grn_obj *grn_column_open(grn_ctx *ctx, grn_obj *table,
@@ -70,10 +60,10 @@ rb_grn_table_to_ruby_object (grn_ctx *context, grn_obj *table,
70
60
 
71
61
  void
72
62
  rb_grn_table_finalizer (grn_ctx *context, grn_obj *object,
73
- RbGrnTable *rb_grn_table)
63
+ RbGrnTable *rb_grn_table)
74
64
  {
75
65
  if (context && rb_grn_table->value)
76
- grn_obj_unlink(context, rb_grn_table->value);
66
+ grn_obj_unlink(context, rb_grn_table->value);
77
67
  rb_grn_table->value = NULL;
78
68
  rb_grn_table->columns = Qnil;
79
69
  }
@@ -1267,6 +1257,9 @@ rb_grn_table_sort (int argc, VALUE *argv, VALUE self)
1267
1257
  * @return [[Groonga::Hash, ...]]
1268
1258
  * @overload group(key, options={})
1269
1259
  * @return [Groonga::Hash]
1260
+ * @option options :max_n_sub_records
1261
+ * グループ化した後のレコードのそれぞれについて最大 _:max_n_sub_records_ 件まで
1262
+ * そのグループに含まれる _table_ のレコードをサブレコードとして格納する。
1270
1263
  */
1271
1264
  static VALUE
1272
1265
  rb_grn_table_group (int argc, VALUE *argv, VALUE self)
@@ -1275,9 +1268,9 @@ rb_grn_table_group (int argc, VALUE *argv, VALUE self)
1275
1268
  grn_obj *table;
1276
1269
  grn_table_sort_key *keys;
1277
1270
  grn_table_group_result *results;
1278
- int i, n_keys, n_results;
1271
+ int i, n_keys, n_results, max_n_sub_records = 0;
1279
1272
  grn_rc rc;
1280
- VALUE rb_keys, rb_options;
1273
+ VALUE rb_keys, rb_options, rb_max_n_sub_records;
1281
1274
  VALUE *rb_group_keys;
1282
1275
  VALUE rb_results;
1283
1276
 
@@ -1296,6 +1289,13 @@ rb_grn_table_group (int argc, VALUE *argv, VALUE self)
1296
1289
  rb_group_keys = &rb_keys;
1297
1290
  }
1298
1291
 
1292
+ rb_grn_scan_options(rb_options,
1293
+ "max_n_sub_records", &rb_max_n_sub_records,
1294
+ NULL);
1295
+
1296
+ if (!NIL_P(rb_max_n_sub_records))
1297
+ max_n_sub_records = NUM2INT(rb_max_n_sub_records);
1298
+
1299
1299
  keys = ALLOCA_N(grn_table_sort_key, n_keys);
1300
1300
  for (i = 0; i < n_keys; i++) {
1301
1301
  VALUE rb_sort_options, rb_key;
@@ -1331,13 +1331,10 @@ rb_grn_table_group (int argc, VALUE *argv, VALUE self)
1331
1331
  rb_results = rb_ary_new();
1332
1332
  for (i = 0; i < n_results; i++) {
1333
1333
  grn_obj *result;
1334
- grn_id range_id;
1335
1334
  VALUE rb_result;
1336
1335
 
1337
- range_id = grn_obj_get_range(context, keys[i].key);
1338
- result = grn_table_create(context, NULL, 0, NULL,
1339
- GRN_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
1340
- grn_ctx_at(context, range_id), 0);
1336
+ result = grn_table_create_for_group(context, NULL, 0, NULL,
1337
+ keys[i].key, table, max_n_sub_records);
1341
1338
  results[i].table = result;
1342
1339
  results[i].key_begin = 0;
1343
1340
  results[i].key_end = 0;
@@ -1359,6 +1356,45 @@ rb_grn_table_group (int argc, VALUE *argv, VALUE self)
1359
1356
  return rb_results;
1360
1357
  }
1361
1358
 
1359
+ /*
1360
+ * Iterates each sub records for the record _id_.
1361
+ *
1362
+ * @overload each_sub_record(id)
1363
+ * @yield [sub_record] Gives a sub record for the record _id_ to the block.
1364
+ * @yieldparam sub_record [Record] A sub record for the record _id_.
1365
+ * @return [void]
1366
+ *
1367
+ * @since 3.0.3
1368
+ */
1369
+ static VALUE
1370
+ rb_grn_table_each_sub_record (VALUE self, VALUE rb_id)
1371
+ {
1372
+ VALUE rb_range;
1373
+ grn_obj *table, *range;
1374
+ grn_ctx *context = NULL;
1375
+ grn_id *sub_records_buffer;
1376
+ unsigned int i, n_sub_records, max_n_sub_records;
1377
+
1378
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1379
+ NULL, NULL,
1380
+ NULL, NULL, &range,
1381
+ NULL);
1382
+ max_n_sub_records = grn_table_max_n_subrecs(context, table);
1383
+ if (max_n_sub_records == 0) {
1384
+ return Qnil;
1385
+ }
1386
+ RETURN_ENUMERATOR(self, 0, NULL);
1387
+ sub_records_buffer = ALLOCA_N(grn_id, max_n_sub_records);
1388
+ n_sub_records = grn_table_get_subrecs(context, table, NUM2UINT(rb_id),
1389
+ sub_records_buffer, NULL,
1390
+ (int)max_n_sub_records);
1391
+ rb_range = GRNOBJECT2RVAL(Qnil, context, range, GRN_FALSE);
1392
+ for (i = 0; i < n_sub_records; i++) {
1393
+ rb_yield(rb_grn_record_new(rb_range, sub_records_buffer[i], Qnil));
1394
+ }
1395
+ return Qnil;
1396
+ }
1397
+
1362
1398
  /*
1363
1399
  * _table_ の _id_ に対応する {Groonga::Record} を返す。
1364
1400
  *
@@ -2005,7 +2041,7 @@ rb_grn_table_is_locked (int argc, VALUE *argv, VALUE self)
2005
2041
  * は何もしない。 =:
2006
2042
  * - Groonga::Operator::AND :=
2007
2043
  * マッチしたレコードのスコアを増加。マッチしなかったレコードを削除。 =:
2008
- * - Groonga::Operator::BUT :=
2044
+ * - Groonga::Operator::AND_NOT :=
2009
2045
  * マッチしたレコードを削除。 =:
2010
2046
  * - Groonga::Operator::ADJUST :=
2011
2047
  * マッチしたレコードのスコアを増加。 =:
@@ -2120,6 +2156,12 @@ rb_grn_table_select (int argc, VALUE *argv, VALUE self)
2120
2156
  GRN_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
2121
2157
  table,
2122
2158
  NULL);
2159
+ rb_grn_context_check(context, self);
2160
+ if (!result) {
2161
+ rb_raise(rb_eGrnNoMemoryAvailable,
2162
+ "failed to create result table: %s",
2163
+ rb_grn_inspect(rb_ary_new4(argc, argv)));
2164
+ }
2123
2165
  rb_result = GRNTABLE2RVAL(context, result, GRN_TRUE);
2124
2166
  } else {
2125
2167
  result = RVAL2GRNTABLE(rb_result, &context);
@@ -2212,7 +2254,7 @@ rb_grn_table_intersection_bang (VALUE self, VALUE rb_other)
2212
2254
  static VALUE
2213
2255
  rb_grn_table_difference_bang (VALUE self, VALUE rb_other)
2214
2256
  {
2215
- return rb_grn_table_set_operation_bang(self, rb_other, GRN_OP_BUT);
2257
+ return rb_grn_table_set_operation_bang(self, rb_other, GRN_OP_AND_NOT);
2216
2258
  }
2217
2259
 
2218
2260
  /*
@@ -2251,12 +2293,13 @@ static VALUE
2251
2293
  rb_grn_table_support_sub_records_p (VALUE self)
2252
2294
  {
2253
2295
  grn_obj *table;
2296
+ grn_ctx *context;
2254
2297
 
2255
- rb_grn_table_deconstruct(SELF(self), &table, NULL,
2298
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
2256
2299
  NULL, NULL,
2257
2300
  NULL, NULL, NULL,
2258
2301
  NULL);
2259
- return CBOOL2RVAL(GRN_TABLE_IS_GROUPED(table));
2302
+ return CBOOL2RVAL(grn_table_is_grouped(context, table));
2260
2303
  }
2261
2304
 
2262
2305
  /*
@@ -2423,6 +2466,9 @@ rb_grn_init_table (VALUE mGrn)
2423
2466
 
2424
2467
  rb_define_method(rb_cGrnTable, "each", rb_grn_table_each, -1);
2425
2468
 
2469
+ rb_define_method(rb_cGrnTable, "each_sub_record",
2470
+ rb_grn_table_each_sub_record, 1);
2471
+
2426
2472
  rb_define_method(rb_cGrnTable, "delete", rb_grn_table_delete, -1);
2427
2473
 
2428
2474
  rb_define_method(rb_cGrnTable, "sort", rb_grn_table_sort, -1);