rroonga 4.0.8 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d2c33b482dafe8f399af8b7470fd96e22550930d
4
- data.tar.gz: 6d52fe1e3cceffd71e9b1b93ce64549d0669d806
3
+ metadata.gz: e080d48d06e47c3504eef74495e62193e30b3ff8
4
+ data.tar.gz: bd3b0cd6fe3b2a26e550d9c7b8dfc16e786710c3
5
5
  SHA512:
6
- metadata.gz: 82734af6ca9ecc542d94d5880e2203668f8e90cf14113172d0312b71b8200a9436176054647681f708c29f89a9f175163971b053334d75c25552095166fe272d
7
- data.tar.gz: e74bfda44591c57ac21bfa6ef6b6a107cb0ab0471b3c6fde5cbf187124e6689a5bac6c9a4a3c9c12d5ade497b3cf7dff72eb00a819d7236c74e83f58b5349bf4
6
+ metadata.gz: b5c5eb1bf9999062382965a37ee20dd8dcdfffd9afd50516c8a1882165f41231602c6ed1c80efab9fbaa97272d8b2a17aa07db599d7c339621e6285cbf8e6327
7
+ data.tar.gz: 77a6604d8fd4c3831a2ee42016c1e25a8273623812d9a8582830458163f08a6ec735fe5a64af064b7a67b3150bfa429d3b0212d1decc719612390fadffd1c318
data/README.md CHANGED
@@ -40,7 +40,7 @@ contributed patches.)
40
40
  ## Dependencies
41
41
 
42
42
  * Ruby >= 1.9.3
43
- * Groonga >= 4.0.9
43
+ * Groonga >= 5.0.0
44
44
 
45
45
  ## Install
46
46
 
@@ -59,7 +59,7 @@ contributed patches.)
59
59
  ## Thanks
60
60
 
61
61
  * Daijiro MORI: sent patches to support the latest Groonga.
62
- * Tasuku SUENAGA: sent bug reports.
62
+ * Tasuku SUENAGA: sent patches and bug reports.
63
63
  * niku: sent bug reports.
64
64
  * dara:
65
65
  * wrote tests.
@@ -1,5 +1,24 @@
1
1
  h1. NEWS
2
2
 
3
+ h2(#5-0-0). 5.0.0: 2014-02-16 (planned)
4
+
5
+ h3. Improvements
6
+
7
+ * Supported Groonga 5.0.0. Groonga 4.1.1 or older aren't supported.
8
+ * Added flags for {Groonga::Normalizer.normalize}.
9
+ [GitHub#44] [Patch by Tasuku SUENAGA a.k.a. gunyarakun]
10
+ <pre>
11
+ Groonga::Normalizer.normalize("AbC Def gh") #=> "abcdefgh"
12
+ Groonga::Normalizer.normalize("AbC Def gh", :remove_blank => true) #=> "abcdefgh"
13
+ Groonga::Normalizer.normalize("AbC Def gh", :remove_blank => false) #=> "abc def gh"
14
+ </pre>
15
+ * Supported drilldown by multiple keys in {Groonga::Table#group}.
16
+ * Supported calculation for drilldown in {Groonga::Table#group}.
17
+
18
+ h3. Thanks
19
+
20
+ * Tasuku SUENAGA a.k.a. gunyarakun
21
+
3
22
  h2(#4-0-8). 4.0.8: 2014-01-08
4
23
 
5
24
  h3. Improvements
@@ -1,7 +1,7 @@
1
1
  /* -*- coding: utf-8; mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
2
  /*
3
+ Copyright (C) 2014-2015 Masafumi Yokoyama <yokoyama@clear-code.com>
3
4
  Copyright (C) 2009-2014 Kouhei Sutou <kou@clear-code.com>
4
- Copyright (C) 2014 Masafumi Yokoyama <myokoym@gmail.com>
5
5
 
6
6
  This library is free software; you can redistribute it and/or
7
7
  modify it under the terms of the GNU Lesser General Public
@@ -97,6 +97,8 @@ static VALUE eGrnCASError;
97
97
  static VALUE eGrnUnsupportedCommandVersion;
98
98
  static VALUE eGrnNormalizerError;
99
99
  static VALUE eGrnTokenFilterError;
100
+ static VALUE eGrnCommandError;
101
+ static VALUE eGrnPluginError;
100
102
 
101
103
  VALUE
102
104
  rb_grn_rc_to_exception (grn_rc rc)
@@ -329,6 +331,12 @@ rb_grn_rc_to_exception (grn_rc rc)
329
331
  case GRN_TOKEN_FILTER_ERROR:
330
332
  exception = eGrnTokenFilterError;
331
333
  break;
334
+ case GRN_COMMAND_ERROR:
335
+ exception = eGrnCommandError;
336
+ break;
337
+ case GRN_PLUGIN_ERROR:
338
+ exception = eGrnPluginError;
339
+ break;
332
340
  }
333
341
 
334
342
  if (NIL_P(exception))
@@ -568,6 +576,12 @@ rb_grn_rc_to_message (grn_rc rc)
568
576
  case GRN_TOKEN_FILTER_ERROR:
569
577
  message = "token filter error";
570
578
  break;
579
+ case GRN_COMMAND_ERROR:
580
+ message = "command error";
581
+ break;
582
+ case GRN_PLUGIN_ERROR:
583
+ message = "plugin error";
584
+ break;
571
585
  }
572
586
 
573
587
  if (!message)
@@ -1227,4 +1241,24 @@ rb_grn_init_exception (VALUE mGrn)
1227
1241
  */
1228
1242
  eGrnTokenFilterError =
1229
1243
  rb_define_class_under(mGrn, "TokenFilterError", rb_eGrnError);
1244
+
1245
+ /*
1246
+ * Document-class: Groonga::CommandError
1247
+ *
1248
+ * It is used when a command causes an error.
1249
+ *
1250
+ * @since 5.0.0
1251
+ */
1252
+ eGrnCommandError =
1253
+ rb_define_class_under(mGrn, "CommandError", rb_eGrnError);
1254
+
1255
+ /*
1256
+ * Document-class: Groonga::PluginError
1257
+ *
1258
+ * It is used when a plugin causes an error.
1259
+ *
1260
+ * @since 5.0.0
1261
+ */
1262
+ eGrnPluginError =
1263
+ rb_define_class_under(mGrn, "PluginError", rb_eGrnError);
1230
1264
  }
@@ -35,32 +35,62 @@ VALUE rb_cGrnNormalizer;
35
35
  * # Normalizes "ABC" with the default normalizer
36
36
  * Groonga::Normalizer.normalize("AbC") # => "abc"
37
37
  *
38
- * @overload normalize(string)
39
- * @return [String] The normalized string
38
+ * @overload normalize(string, options={:remove_blank => true})
40
39
  * @param [String] string The original string
40
+ *
41
+ * @param [::Hash] options The optional parameters.
42
+ * @option options :remove_blank (true)
43
+ * If it's `true`, all blank characters are removed.
44
+ * @option options :remove_tokenized_delimiter (false)
45
+ * If it's `true`, all tokenized delimiter characters are removed.
46
+ * The character is `U+FFFE`.
47
+ *
48
+ * @return [String] The normalized string
41
49
  */
42
50
  static VALUE
43
- rb_grn_normalizer_s_normalize (VALUE klass, VALUE rb_string)
51
+ rb_grn_normalizer_s_normalize (int argc, VALUE *argv, VALUE klass)
44
52
  {
45
53
  VALUE rb_context = Qnil;
54
+ VALUE rb_string;
55
+ VALUE rb_options;
56
+ VALUE rb_remove_blank_p;
57
+ VALUE rb_remove_tokenized_delimiter_p;
46
58
  VALUE rb_encoded_string;
47
59
  VALUE rb_normalized_string;
48
60
  grn_ctx *context = NULL;
49
61
  grn_obj *grn_string;
50
62
  grn_obj *normalizer = GRN_NORMALIZER_AUTO;
51
- /* TODO: make customizable */
52
- int flags = GRN_STRING_REMOVE_BLANK;
63
+ int flags = 0;
53
64
  const char *normalized_string;
54
65
  unsigned int normalized_string_length;
55
66
 
67
+ rb_scan_args(argc, argv, "11", &rb_string, &rb_options);
68
+ rb_grn_scan_options(rb_options,
69
+ "remove_blank", &rb_remove_blank_p,
70
+ "remove_tokenized_delimiter_p",
71
+ &rb_remove_tokenized_delimiter_p,
72
+ NULL);
73
+
56
74
  context = rb_grn_context_ensure(&rb_context);
57
75
  rb_encoded_string = rb_grn_context_rb_string_encode(context, rb_string);
76
+ if (NIL_P(rb_remove_blank_p)) {
77
+ rb_remove_blank_p = Qtrue;
78
+ }
79
+ if (RVAL2CBOOL(rb_remove_blank_p)) {
80
+ flags |= GRN_STRING_REMOVE_BLANK;
81
+ }
82
+ if (NIL_P(rb_remove_tokenized_delimiter_p)) {
83
+ rb_remove_tokenized_delimiter_p = Qfalse;
84
+ }
85
+ if (RVAL2CBOOL(rb_remove_tokenized_delimiter_p)) {
86
+ flags |= GRN_STRING_REMOVE_TOKENIZED_DELIMITER;
87
+ }
58
88
  grn_string = grn_string_open(context,
59
89
  RSTRING_PTR(rb_encoded_string),
60
90
  RSTRING_LEN(rb_encoded_string),
61
91
  normalizer,
62
92
  flags);
63
- rb_grn_context_check(context, rb_string);
93
+ rb_grn_context_check(context, argv[0]);
64
94
  grn_string_get_normalized(context, grn_string,
65
95
  &normalized_string, &normalized_string_length,
66
96
  NULL);
@@ -79,5 +109,5 @@ rb_grn_init_normalizer (VALUE mGrn)
79
109
  rb_cGrnNormalizer = rb_define_class_under(mGrn, "Normalizer", rb_cObject);
80
110
 
81
111
  rb_define_singleton_method(rb_cGrnNormalizer, "normalize",
82
- rb_grn_normalizer_s_normalize, 1);
112
+ rb_grn_normalizer_s_normalize, -1);
83
113
  }
@@ -1,7 +1,7 @@
1
1
  /* -*- coding: utf-8; mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
2
  /*
3
+ Copyright (C) 2014-2015 Masafumi Yokoyama <yokoyama@clear-code.com>
3
4
  Copyright (C) 2009-2014 Kouhei Sutou <kou@clear-code.com>
4
- Copyright (C) 2014 Masafumi Yokoyama <myokoym@gmail.com>
5
5
 
6
6
  This library is free software; you can redistribute it and/or
7
7
  modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,7 @@ static ID id_array_set;
35
35
  /*
36
36
  * Document-class: Groonga::Table < Groonga::Object
37
37
  *
38
- * rroongaが提供するテーブルのベースとなるクラス。このクラス
38
+ * Rroongaが提供するテーブルのベースとなるクラス。このクラス
39
39
  * から {Groonga::Array} , {Groonga::Hash} , {Groonga::PatriciaTrie}
40
40
  * が継承されている。
41
41
  */
@@ -1289,7 +1289,7 @@ rb_grn_table_sort (int argc, VALUE *argv, VALUE self)
1289
1289
  result = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_NO_KEY,
1290
1290
  NULL, table);
1291
1291
  /* use n_records that is return value from
1292
- grn_table_sort() when rroonga user become specifying
1292
+ grn_table_sort() when Rroonga user become specifying
1293
1293
  output table. */
1294
1294
  grn_table_sort(context, table, offset, limit, result, keys, n_keys);
1295
1295
  exception = rb_grn_context_to_exception(context, self);
@@ -1306,13 +1306,55 @@ rb_grn_table_sort (int argc, VALUE *argv, VALUE self)
1306
1306
  * 値でグループ化する。多くの場合、キーにはカラムを指定する。
1307
1307
  * カラムはカラム名(文字列)でも指定可能。
1308
1308
  *
1309
+ * If one key is specified, you can get the grouping key by {Groonga::Record#key}:
1310
+ *
1311
+ * <pre>
1312
+ * !!!ruby
1313
+ * grouped_records = table.group("key1").collect do |group|
1314
+ * [group.key, group.n_sub_records]
1315
+ * end
1316
+ * </pre>
1317
+ *
1318
+ * If two or more keys are specified, the default value of _:max_n_sub_records_
1319
+ * is _1_ (When one key is specified, the value is _0_.). You can get the grouping
1320
+ * keys by {Groonga::Record#sub_records}:
1321
+ *
1322
+ * <pre>
1323
+ * !!!ruby
1324
+ * grouped_records = table.group(["key1", "key2"]).collect do |group|
1325
+ * sub_record = group.sub_records.first
1326
+ * [
1327
+ * sub_record.key1,
1328
+ * sub_record.key2,
1329
+ * group.n_sub_records,
1330
+ * ]
1331
+ * end
1332
+ * </pre>
1333
+ *
1309
1334
  * @overload group([key1, key2, ...], options={})
1310
- * @return [[Groonga::Hash, ...]]
1335
+ * @return [Groonga::Hash]
1336
+ *
1337
+ * @!macro [new] table.group.options
1338
+ * @option options :max_n_sub_records
1339
+ * グループ化した後のレコードのそれぞれについて最大 _:max_n_sub_records_ 件まで
1340
+ * そのグループに含まれる _table_ のレコードをサブレコードとして格納する。
1341
+ * @option options [String or Symbol] :calc_target
1342
+ * The target column name for _:calc_types_.
1343
+ * @option options [::Array] :calc_types
1344
+ * It specifies how to calculate (aggregate) values in grouped records by
1345
+ * a drilldown. You can specify multiple calculation types.
1346
+ *
1347
+ * - +:max+ := Finding the maximum integer value from integer values in grouped records.
1348
+ * - +:min+ := Finding the minimum integer value from integer values in grouped records.
1349
+ * - +:sum+ := Summing integer values in grouped records.
1350
+ * - +:average+ := Averaging integer/float values in grouped records.
1351
+ *
1352
+ * @!macro table.group.options
1353
+ *
1311
1354
  * @overload group(key, options={})
1312
1355
  * @return [Groonga::Hash]
1313
- * @option options :max_n_sub_records
1314
- * グループ化した後のレコードのそれぞれについて最大 _:max_n_sub_records_ 件まで
1315
- * そのグループに含まれる _table_ のレコードをサブレコードとして格納する。
1356
+ *
1357
+ * @!macro table.group.options
1316
1358
  */
1317
1359
  static VALUE
1318
1360
  rb_grn_table_group (int argc, VALUE *argv, VALUE self)
@@ -1320,13 +1362,13 @@ rb_grn_table_group (int argc, VALUE *argv, VALUE self)
1320
1362
  grn_ctx *context = NULL;
1321
1363
  grn_obj *table;
1322
1364
  grn_table_sort_key *keys;
1323
- grn_table_group_result *results;
1324
- int i, n_keys, n_results;
1365
+ grn_table_group_result result;
1366
+ int i, n_keys;
1325
1367
  unsigned int max_n_sub_records = 0;
1326
1368
  grn_rc rc;
1327
1369
  VALUE rb_keys, rb_options, rb_max_n_sub_records;
1370
+ VALUE rb_calc_target, rb_calc_types;
1328
1371
  VALUE *rb_group_keys;
1329
- VALUE rb_results;
1330
1372
 
1331
1373
  rb_grn_table_deconstruct(SELF(self), &table, &context,
1332
1374
  NULL, NULL,
@@ -1345,10 +1387,19 @@ rb_grn_table_group (int argc, VALUE *argv, VALUE self)
1345
1387
 
1346
1388
  rb_grn_scan_options(rb_options,
1347
1389
  "max_n_sub_records", &rb_max_n_sub_records,
1390
+ "calc_target", &rb_calc_target,
1391
+ "calc_types", &rb_calc_types,
1348
1392
  NULL);
1349
1393
 
1350
- if (!NIL_P(rb_max_n_sub_records))
1394
+ if (NIL_P(rb_max_n_sub_records)) {
1395
+ if (n_keys > 1) {
1396
+ max_n_sub_records = 1;
1397
+ } else {
1398
+ max_n_sub_records = 0;
1399
+ }
1400
+ } else {
1351
1401
  max_n_sub_records = NUM2UINT(rb_max_n_sub_records);
1402
+ }
1352
1403
 
1353
1404
  keys = ALLOCA_N(grn_table_sort_key, n_keys);
1354
1405
  for (i = 0; i < n_keys; i++) {
@@ -1380,34 +1431,54 @@ rb_grn_table_group (int argc, VALUE *argv, VALUE self)
1380
1431
  keys[i].flags = 0;
1381
1432
  }
1382
1433
 
1383
- n_results = n_keys;
1384
- results = ALLOCA_N(grn_table_group_result, n_results);
1385
- rb_results = rb_ary_new();
1386
- for (i = 0; i < n_results; i++) {
1387
- grn_obj *result;
1388
- VALUE rb_result;
1389
-
1390
- result = grn_table_create_for_group(context, NULL, 0, NULL,
1391
- keys[i].key, table, max_n_sub_records);
1392
- results[i].table = result;
1393
- results[i].key_begin = 0;
1394
- results[i].key_end = 0;
1395
- results[i].limit = 0;
1396
- results[i].flags = 0;
1397
- results[i].op = GRN_OP_OR;
1398
-
1399
- rb_result = GRNOBJECT2RVAL(Qnil, context, result, GRN_TRUE);
1400
- rb_ary_push(rb_results, rb_result);
1434
+ result.table = NULL;
1435
+ result.key_begin = 0;
1436
+ result.key_end = n_keys - 1;
1437
+ result.limit = 1;
1438
+ result.flags = GRN_TABLE_GROUP_CALC_COUNT;
1439
+ result.op = GRN_OP_OR;
1440
+ result.max_n_subrecs = max_n_sub_records;
1441
+ result.calc_target = NULL;
1442
+
1443
+ if (!NIL_P(rb_calc_target)) {
1444
+ const char *name = NULL;
1445
+ unsigned name_size = 0;
1446
+ ruby_object_to_column_name(rb_calc_target, &name, &name_size);
1447
+ result.calc_target = grn_obj_column(context, table, name, name_size);
1448
+ }
1449
+ if (result.calc_target) {
1450
+ int i, n_calc_types;
1451
+ VALUE *raw_calc_types;
1452
+ raw_calc_types = RARRAY_PTR(rb_calc_types);
1453
+ n_calc_types = RARRAY_LEN(rb_calc_types);
1454
+ for (i = 0; i < n_calc_types; i++) {
1455
+ VALUE rb_calc_type = raw_calc_types[i];
1456
+ if (rb_grn_equal_option(rb_calc_type, "max")) {
1457
+ result.flags |= GRN_TABLE_GROUP_CALC_MAX;
1458
+ } else if (rb_grn_equal_option(rb_calc_type, "min")) {
1459
+ result.flags |= GRN_TABLE_GROUP_CALC_MIN;
1460
+ } else if (rb_grn_equal_option(rb_calc_type, "sum")) {
1461
+ result.flags |= GRN_TABLE_GROUP_CALC_SUM;
1462
+ } else if (rb_grn_equal_option(rb_calc_type, "average")) {
1463
+ result.flags |= GRN_TABLE_GROUP_CALC_AVG;
1464
+ } else {
1465
+ grn_obj_unlink(context, result.calc_target);
1466
+ rb_raise(rb_eArgError,
1467
+ "invalid calculation type: %s: "
1468
+ "available types: [:max, :min, :sum, :average]",
1469
+ rb_grn_inspect(rb_calc_type));
1470
+ }
1471
+ }
1401
1472
  }
1402
1473
 
1403
- rc = grn_table_group(context, table, keys, n_keys, results, n_results);
1474
+ rc = grn_table_group(context, table, keys, n_keys, &result, 1);
1475
+ if (result.calc_target) {
1476
+ grn_obj_unlink(context, result.calc_target);
1477
+ }
1404
1478
  rb_grn_context_check(context, self);
1405
1479
  rb_grn_rc_check(rc, self);
1406
1480
 
1407
- if (n_results == 1)
1408
- return rb_ary_pop(rb_results);
1409
- else
1410
- return rb_results;
1481
+ return GRNOBJECT2RVAL(Qnil, context, result.table, GRN_TRUE);
1411
1482
  }
1412
1483
 
1413
1484
  /*
@@ -2380,7 +2451,7 @@ rb_grn_table_support_sub_records_p (VALUE self)
2380
2451
  * records for each group, the number of records is stored to
2381
2452
  * it. Records for each group are called as "sub records".
2382
2453
  *
2383
- * Normally, you don't need to care about the space because rroonga
2454
+ * Normally, you don't need to care about the space because Rroonga
2384
2455
  * creates a table with the space automatically. Normal tables
2385
2456
  * (persistent tables) don't have the space because they don't need
2386
2457
  * it.
data/ext/groonga/rb-grn.h CHANGED
@@ -1,5 +1,6 @@
1
1
  /* -*- coding: utf-8; mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
2
  /*
3
+ Copyright (C) 2015 Masafumi Yokoyama <yokoyama@clear-code.com>
3
4
  Copyright (C) 2009-2014 Kouhei Sutou <kou@clear-code.com>
4
5
 
5
6
  This library is free software; you can redistribute it and/or
@@ -90,9 +91,9 @@ RB_GRN_BEGIN_DECLS
90
91
  # define debug(...)
91
92
  #endif
92
93
 
93
- #define RB_GRN_MAJOR_VERSION 4
94
+ #define RB_GRN_MAJOR_VERSION 5
94
95
  #define RB_GRN_MINOR_VERSION 0
95
- #define RB_GRN_MICRO_VERSION 8
96
+ #define RB_GRN_MICRO_VERSION 0
96
97
 
97
98
  #define RB_GRN_QUERY_DEFAULT_MAX_EXPRESSIONS 32
98
99
 
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2014 Masafumi Yokoyama <myokoym@gmail.com>
3
+ # Copyright (C) 2014-2015 Masafumi Yokoyama <yokoyama@clear-code.com>
4
4
  # Copyright (C) 2009-2014 Kouhei Sutou <kou@clear-code.com>
5
5
  #
6
6
  # This library is free software; you can redistribute it and/or
@@ -226,6 +226,50 @@ module Groonga
226
226
  @table.support_sub_records?
227
227
  end
228
228
 
229
+ # The maximum integer value from integer values in grouped records.
230
+ # It can be used when specifying _:calc_target_ and _:calc_types_
231
+ # to {Groonga::Table#group}.
232
+ #
233
+ # @return [Integer] The maximum integer value from integer values in grouped records.
234
+ #
235
+ # @since 5.0.0
236
+ def max
237
+ self["_max"]
238
+ end
239
+
240
+ # The minimum integer value from integer values in grouped records.
241
+ # It can be used when specifying _:calc_target_ and _:calc_types_
242
+ # to {Groonga::Table#group}.
243
+ #
244
+ # @return [Integer] The minimum integer value from integer values in grouped records.
245
+ #
246
+ # @since 5.0.0
247
+ def min
248
+ self["_min"]
249
+ end
250
+
251
+ # The sum of integer values in grouped records.
252
+ # It can be used when specifying _:calc_target_ and _:calc_types_
253
+ # to {Groonga::Table#group}.
254
+ #
255
+ # @return [Integer] The sum of integer values in grouped records.
256
+ #
257
+ # @since 5.0.0
258
+ def sum
259
+ self["_sum"]
260
+ end
261
+
262
+ # The average of integer/float values in grouped records.
263
+ # It can be used when specifying _:calc_target_ and _:calc_types_
264
+ # to {Groonga::Table#group}.
265
+ #
266
+ # @return [Float] The average of integer/float values in grouped records.
267
+ #
268
+ # @since 5.0.0
269
+ def average
270
+ self["_avg"]
271
+ end
272
+
229
273
  # レコードの値を返す。
230
274
  def value
231
275
  @table.value(@id, :id => true)