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
@@ -22,6 +22,15 @@
22
22
 
23
23
  VALUE rb_cGrnType;
24
24
 
25
+ /*
26
+ * Document-class: Groonga::Type
27
+ *
28
+ * groongaのテーブルの主キーや、カラムの値の型のためのオブジェ
29
+ * クト。型として使用可能なものはgroongaで予め定義済みの型、ユ
30
+ * ーザが定義する型、またはユーザが定義したテーブル。
31
+ */
32
+
33
+
25
34
  grn_obj *
26
35
  rb_grn_type_from_ruby_object (VALUE object)
27
36
  {
@@ -39,6 +48,30 @@ rb_grn_type_to_ruby_object (grn_ctx *context, grn_obj *type,
39
48
  return GRNOBJECT2RVAL(rb_cGrnType, context, type, owner);
40
49
  }
41
50
 
51
+ /*
52
+ * call-seq:
53
+ * Groonga::Type.new(name, options={})
54
+ *
55
+ * 名前が_name_の型を作成する。_options_に指定可能な値は以下の通
56
+ * り。
57
+ *
58
+ * [+:type+]
59
+ * :integer(符号付き整数)、:int(:integerの省略
60
+ * 形)、:unsigned_integer(符号なし整
61
+ * 数)、:uint(:unsigned_integerの省略形)、:float(浮動小
62
+ * 数点数)、:variable(可変長文字列)のいずれかを指定する。
63
+ * 省略した場合は:variableを指定したものと扱う。
64
+ *
65
+ * :variableを指定した場合は必ず+:size+を指定しなければいけない。
66
+ *
67
+ * [+:context+]
68
+ * 型の作成時に利用するGroonga::Contextを指定する。省略すると
69
+ * Groonga::Context.defaultを用いる。
70
+ *
71
+ * [+:size+]
72
+ * +:option+が:variableの場合は最大長、それ以外の場合は長さを
73
+ * 指定する(単位:byte)。
74
+ */
42
75
  static VALUE
43
76
  rb_grn_type_initialize (int argc, VALUE *argv, VALUE self)
44
77
  {
@@ -47,13 +80,13 @@ rb_grn_type_initialize (int argc, VALUE *argv, VALUE self)
47
80
  const char *name = NULL;
48
81
  unsigned name_size, size = 0;
49
82
  grn_obj_flags flags = 0;
50
- VALUE rb_name, options, rb_context, rb_option, rb_size;
83
+ VALUE rb_name, options, rb_context, rb_type, rb_size;
51
84
 
52
85
  rb_scan_args(argc, argv, "11", &rb_name, &options);
53
86
 
54
87
  rb_grn_scan_options(options,
55
88
  "context", &rb_context,
56
- "option", &rb_option,
89
+ "type", &rb_type,
57
90
  "size", &rb_size,
58
91
  NULL);
59
92
 
@@ -62,24 +95,24 @@ rb_grn_type_initialize (int argc, VALUE *argv, VALUE self)
62
95
 
63
96
  context = rb_grn_context_ensure(&rb_context);
64
97
 
65
- if (NIL_P(rb_option)) {
66
- } else if (rb_grn_equal_option(rb_option, "integer") ||
67
- rb_grn_equal_option(rb_option, "int")) {
98
+ if (NIL_P(rb_type) ||
99
+ rb_grn_equal_option(rb_type, "variable")) {
100
+ flags = GRN_OBJ_KEY_VAR_SIZE;
101
+ } else if (rb_grn_equal_option(rb_type, "integer") ||
102
+ rb_grn_equal_option(rb_type, "int")) {
68
103
  flags = GRN_OBJ_KEY_INT;
69
104
  size = sizeof(int);
70
- } else if (rb_grn_equal_option(rb_option, "unsigned_integer") ||
71
- rb_grn_equal_option(rb_option, "uint")) {
105
+ } else if (rb_grn_equal_option(rb_type, "unsigned_integer") ||
106
+ rb_grn_equal_option(rb_type, "uint")) {
72
107
  flags = GRN_OBJ_KEY_UINT;
73
108
  size = sizeof(unsigned int);
74
- } else if (rb_grn_equal_option(rb_option, "float")) {
109
+ } else if (rb_grn_equal_option(rb_type, "float")) {
75
110
  flags = GRN_OBJ_KEY_FLOAT;
76
111
  size = sizeof(double);
77
- } else if (rb_grn_equal_option(rb_option, "variable")) {
78
- flags = GRN_OBJ_KEY_VAR_SIZE;
79
112
  } else {
80
113
  rb_raise(rb_eArgError,
81
- ":option should be one of "
82
- "[:int, :integer, :uint, :unsigned_integer, "
114
+ ":type should be one of "
115
+ "[:integer, :int, :unsigned_integer, :uint, "
83
116
  ":float, :variable]: %s",
84
117
  rb_grn_inspect(options));
85
118
  }
@@ -106,21 +139,39 @@ rb_grn_init_type (VALUE mGrn)
106
139
 
107
140
  rb_define_method(rb_cGrnType, "initialize", rb_grn_type_initialize, -1);
108
141
 
142
+ /* 任意のテーブルに属する全てのレコード(Object型はv1.2で
143
+ サポートされます)。 */
109
144
  rb_define_const(rb_cGrnType, "OBJECT", INT2NUM(GRN_DB_OBJECT));
145
+ /* bool型。trueとfalse。 */
110
146
  rb_define_const(rb_cGrnType, "BOOLEAN", INT2NUM(GRN_DB_BOOL));
147
+ /* bool型。trueとfalse。 */
111
148
  rb_define_const(rb_cGrnType, "BOOL", INT2NUM(GRN_DB_BOOL));
149
+ /* 8bit符号付き整数。 */
112
150
  rb_define_const(rb_cGrnType, "INT8", INT2NUM(GRN_DB_INT8));
151
+ /* 8bit符号なし整数。 */
113
152
  rb_define_const(rb_cGrnType, "UINT8", INT2NUM(GRN_DB_UINT8));
153
+ /* 16bit符号付き整数。 */
114
154
  rb_define_const(rb_cGrnType, "INT16", INT2NUM(GRN_DB_INT16));
155
+ /* 16bit符号なし整数。 */
115
156
  rb_define_const(rb_cGrnType, "UINT16", INT2NUM(GRN_DB_UINT16));
157
+ /* 32bit符号付き整数。 */
116
158
  rb_define_const(rb_cGrnType, "INT32", INT2NUM(GRN_DB_INT32));
159
+ /* 32bit符号なし整数。 */
117
160
  rb_define_const(rb_cGrnType, "UINT32", INT2NUM(GRN_DB_UINT32));
161
+ /* 64bit符号付き整数。 */
118
162
  rb_define_const(rb_cGrnType, "INT64", INT2NUM(GRN_DB_INT64));
163
+ /* 64bit符号なし整数。 */
119
164
  rb_define_const(rb_cGrnType, "UINT64", INT2NUM(GRN_DB_UINT64));
165
+ /* ieee754形式の64bit浮動小数点数。 */
120
166
  rb_define_const(rb_cGrnType, "FLOAT", INT2NUM(GRN_DB_FLOAT));
167
+ /* 1970年1月1日0時0分0秒からの経過マイクロ秒数を64bit符
168
+ 号付き整数で表現した値。 */
121
169
  rb_define_const(rb_cGrnType, "TIME", INT2NUM(GRN_DB_TIME));
170
+ /* 4Kbyte以下の文字列。 */
122
171
  rb_define_const(rb_cGrnType, "SHORT_TEXT", INT2NUM(GRN_DB_SHORT_TEXT));
172
+ /* 64Kbyte以下の文字列。 */
123
173
  rb_define_const(rb_cGrnType, "TEXT", INT2NUM(GRN_DB_TEXT));
174
+ /* 2Gbyte以下の文字列。 */
124
175
  rb_define_const(rb_cGrnType, "LONG_TEXT", INT2NUM(GRN_DB_LONG_TEXT));
125
176
  rb_define_const(rb_cGrnType, "DELIMIT", INT2NUM(GRN_DB_DELIMIT));
126
177
  rb_define_const(rb_cGrnType, "UNIGRAM", INT2NUM(GRN_DB_UNIGRAM));
@@ -1,6 +1,7 @@
1
1
  /* -*- c-file-style: "ruby" -*- */
2
+ /* vim: set sts=4 sw=4 ts=8 noet: */
2
3
  /*
3
- Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
4
+ Copyright (C) 2009-2010 Kouhei Sutou <kou@clear-code.com>
4
5
 
5
6
  This library is free software; you can redistribute it and/or
6
7
  modify it under the terms of the GNU Lesser General Public
@@ -86,8 +87,7 @@ rb_grn_equal_option (VALUE option, const char *key)
86
87
 
87
88
  static VALUE
88
89
  rb_grn_bulk_to_ruby_object_by_range_id (grn_ctx *context, grn_obj *bulk,
89
- grn_obj *range, grn_id range_id,
90
- VALUE rb_range,
90
+ grn_id range_id,
91
91
  VALUE related_object, VALUE *rb_value)
92
92
  {
93
93
  rb_grn_boolean success = RB_GRN_TRUE;
@@ -96,6 +96,9 @@ rb_grn_bulk_to_ruby_object_by_range_id (grn_ctx *context, grn_obj *bulk,
96
96
  case GRN_DB_VOID:
97
97
  *rb_value = rb_str_new(GRN_TEXT_VALUE(bulk), GRN_TEXT_LEN(bulk));
98
98
  break;
99
+ case GRN_DB_BOOL:
100
+ *rb_value = GRN_BOOL_VALUE(bulk) ? Qtrue : Qfalse;
101
+ break;
99
102
  case GRN_DB_INT32:
100
103
  *rb_value = INT2NUM(GRN_INT32_VALUE(bulk));
101
104
  break;
@@ -139,11 +142,17 @@ rb_grn_bulk_to_ruby_object_by_range_id (grn_ctx *context, grn_obj *bulk,
139
142
  static VALUE
140
143
  rb_grn_bulk_to_ruby_object_by_range_type (grn_ctx *context, grn_obj *bulk,
141
144
  grn_obj *range, grn_id range_id,
142
- VALUE rb_range,
143
145
  VALUE related_object, VALUE *rb_value)
144
146
  {
145
147
  rb_grn_boolean success = RB_GRN_TRUE;
146
148
 
149
+ if (!range && range_id != GRN_ID_NIL) {
150
+ range = grn_ctx_at(context, range_id);
151
+ }
152
+
153
+ if (!range)
154
+ return RB_GRN_FALSE;
155
+
147
156
  switch (range->header.type) {
148
157
  case GRN_TABLE_HASH_KEY:
149
158
  case GRN_TABLE_PAT_KEY:
@@ -152,10 +161,36 @@ rb_grn_bulk_to_ruby_object_by_range_type (grn_ctx *context, grn_obj *bulk,
152
161
  grn_id id;
153
162
 
154
163
  id = *((grn_id *)GRN_BULK_HEAD(bulk));
155
- if (id == GRN_ID_NIL)
164
+ if (id == GRN_ID_NIL) {
156
165
  *rb_value = Qnil;
157
- else
166
+ } else {
167
+ VALUE rb_range;
168
+
169
+ rb_range = GRNOBJECT2RVAL(Qnil, context, range, RB_GRN_FALSE);
158
170
  *rb_value = rb_grn_record_new(rb_range, id, Qnil);
171
+ }
172
+ }
173
+ break;
174
+ case GRN_TYPE:
175
+ if (range->header.flags & GRN_OBJ_KEY_VAR_SIZE) {
176
+ *rb_value = rb_grn_context_rb_string_new(context,
177
+ GRN_BULK_HEAD(bulk),
178
+ GRN_BULK_VSIZE(bulk));
179
+ } else {
180
+ switch (range->header.flags & GRN_OBJ_KEY_MASK) {
181
+ case GRN_OBJ_KEY_UINT:
182
+ *rb_value = INT2NUM(GRN_UINT32_VALUE(bulk));
183
+ break;
184
+ case GRN_OBJ_KEY_INT:
185
+ *rb_value = INT2NUM(GRN_INT32_VALUE(bulk));
186
+ break;
187
+ case GRN_OBJ_KEY_FLOAT:
188
+ *rb_value = rb_float_new(GRN_FLOAT_VALUE(bulk));
189
+ break;
190
+ default:
191
+ success = RB_GRN_FALSE;
192
+ }
193
+ break;
159
194
  }
160
195
  break;
161
196
  default:
@@ -168,29 +203,23 @@ rb_grn_bulk_to_ruby_object_by_range_type (grn_ctx *context, grn_obj *bulk,
168
203
 
169
204
  VALUE
170
205
  rb_grn_bulk_to_ruby_object (grn_ctx *context, grn_obj *bulk,
171
- VALUE related_object)
206
+ grn_obj *range, VALUE related_object)
172
207
  {
173
208
  grn_id range_id;
174
- grn_obj *range;
175
- VALUE rb_range;
176
209
  VALUE rb_value = Qnil;
177
210
 
178
211
  if (GRN_BULK_EMPTYP(bulk))
179
212
  return Qnil;
180
213
 
181
214
  range_id = bulk->header.domain;
182
- range = grn_ctx_at(context, range_id);
183
- rb_range = GRNOBJECT2RVAL(Qnil, context, range, RB_GRN_FALSE);
184
-
185
- if (rb_grn_bulk_to_ruby_object_by_range_id(context, bulk,
186
- range, range_id, rb_range,
187
- related_object, &rb_value))
188
- return rb_value;
215
+ if (rb_grn_bulk_to_ruby_object_by_range_id(context, bulk, range_id,
216
+ related_object, &rb_value))
217
+ return rb_value;
189
218
 
190
219
  if (rb_grn_bulk_to_ruby_object_by_range_type(context, bulk,
191
- range, range_id, rb_range,
192
- related_object, &rb_value))
193
- return rb_value;
220
+ range, range_id,
221
+ related_object, &rb_value))
222
+ return rb_value;
194
223
 
195
224
  return rb_grn_context_rb_string_new(context,
196
225
  GRN_BULK_HEAD(bulk),
@@ -200,86 +229,90 @@ rb_grn_bulk_to_ruby_object (grn_ctx *context, grn_obj *bulk,
200
229
  grn_obj *
201
230
  rb_grn_bulk_from_ruby_object (VALUE object, grn_ctx *context, grn_obj *bulk)
202
231
  {
203
- const char *string;
204
- unsigned int size;
205
- int32_t int32_value;
206
- int64_t int64_value;
207
- int64_t time_value;
208
- double double_value;
209
- grn_id id_value;
210
- grn_obj_flags flags = 0;
211
-
212
232
  if (bulk && bulk->header.domain == GRN_DB_TIME)
213
233
  return rb_grn_bulk_from_ruby_object_with_type(
214
234
  object, context, bulk, bulk->header.domain,
215
235
  grn_ctx_at(context, bulk->header.domain));
216
236
 
237
+ if (!bulk) {
238
+ bulk = grn_obj_open(context, GRN_BULK, 0, GRN_ID_NIL);
239
+ rb_grn_context_check(context, object);
240
+ }
241
+
217
242
  switch (TYPE(object)) {
218
243
  case T_NIL:
219
- string = NULL;
220
- size = 0;
244
+ grn_obj_reinit(context, bulk, GRN_DB_VOID, 0);
221
245
  break;
222
246
  case T_STRING:
223
- string = RSTRING_PTR(object);
224
- size = RSTRING_LEN(object);
225
- flags |= GRN_OBJ_DO_SHALLOW_COPY;
247
+ grn_obj_reinit(context, bulk, GRN_DB_TEXT, 0);
248
+ GRN_TEXT_SET(context, bulk, RSTRING_PTR(object), RSTRING_LEN(object));
226
249
  break;
227
250
  case T_FIXNUM:
228
- int32_value = NUM2INT(object);
229
- string = (const char *)&int32_value;
230
- size = sizeof(int32_value);
251
+ grn_obj_reinit(context, bulk, GRN_DB_INT32, 0);
252
+ GRN_INT32_SET(context, bulk, NUM2INT(object));
231
253
  break;
232
254
  case T_BIGNUM:
233
- int64_value = NUM2LL(object);
234
- if (int64_value <= INT32_MAX) {
235
- int32_value = int64_value;
236
- string = (const char *)&int32_value;
237
- size = sizeof(int32_value);
238
- } else {
239
- string = (const char *)&int64_value;
240
- size = sizeof(int64_value);
241
- }
255
+ {
256
+ int64_t int64_value;
257
+ int64_value = NUM2LL(object);
258
+ if (int64_value <= INT32_MAX) {
259
+ grn_obj_reinit(context, bulk, GRN_DB_INT32, 0);
260
+ GRN_INT32_SET(context, bulk, int64_value);
261
+ } else {
262
+ grn_obj_reinit(context, bulk, GRN_DB_INT64, 0);
263
+ GRN_INT64_SET(context, bulk, int64_value);
264
+ }
265
+ }
242
266
  break;
243
267
  case T_FLOAT:
244
- double_value = NUM2DBL(object);
245
- string = (const char *)&double_value;
246
- size = sizeof(double_value);
268
+ grn_obj_reinit(context, bulk, GRN_DB_FLOAT, 0);
269
+ GRN_FLOAT_SET(context, bulk, NUM2DBL(object));
270
+ break;
271
+ case T_TRUE:
272
+ grn_obj_reinit(context, bulk, GRN_DB_BOOL, 0);
273
+ GRN_BOOL_SET(context, bulk, GRN_TRUE);
274
+ break;
275
+ case T_FALSE:
276
+ grn_obj_reinit(context, bulk, GRN_DB_BOOL, 0);
277
+ GRN_BOOL_SET(context, bulk, GRN_FALSE);
247
278
  break;
248
279
  default:
249
280
  if (RVAL2CBOOL(rb_obj_is_kind_of(object, rb_cTime))) {
250
281
  VALUE sec, usec;
282
+ int64_t time_value;
251
283
 
252
284
  sec = rb_funcall(object, rb_intern("to_i"), 0);
253
285
  usec = rb_funcall(object, rb_intern("usec"), 0);
254
286
  time_value = GRN_TIME_PACK(NUM2LL(sec), NUM2LL(usec));
255
- string = (const char *)&time_value;
256
- size = sizeof(time_value);
287
+ grn_obj_reinit(context, bulk, GRN_DB_TIME, 0);
288
+ GRN_TIME_SET(context, bulk, time_value);
257
289
  } else if (RVAL2CBOOL(rb_obj_is_kind_of(object, rb_cGrnObject))) {
258
290
  grn_obj *grn_object;
291
+ grn_id id_value;
259
292
 
260
293
  grn_object = RVAL2GRNOBJECT(object, &context);
294
+ grn_obj_reinit(context, bulk, grn_object->header.domain, 0);
261
295
  id_value = grn_obj_id(context, grn_object);
262
- string = (const char *)&id_value;
263
- size = sizeof(id_value);
296
+ GRN_RECORD_SET(context, bulk, id_value);
264
297
  } else if (RVAL2CBOOL(rb_obj_is_kind_of(object, rb_cGrnRecord))) {
298
+ grn_obj *table;
299
+ grn_id id_value;
300
+
301
+ table = RVAL2GRNOBJECT(rb_funcall(object, rb_intern("table"), 0),
302
+ &context);
265
303
  id_value = NUM2UINT(rb_funcall(object, rb_intern("id"), 0));
266
- string = (const char *)&id_value;
267
- size = sizeof(id_value);
304
+ grn_obj_reinit(context, bulk, grn_obj_id(context, table), 0);
305
+ GRN_RECORD_SET(context, bulk, id_value);
268
306
  } else {
269
307
  rb_raise(rb_eTypeError,
270
308
  "bulked object should be one of "
271
- "[nil, String, Integer, Float, Time, Groonga::Object]: %s",
309
+ "[nil, true, false, String, Integer, Float, Time, "
310
+ "Groonga::Object, Groonga::Record]: %s",
272
311
  rb_grn_inspect(object));
273
312
  }
274
313
  break;
275
314
  }
276
315
 
277
- if (!bulk) {
278
- bulk = grn_obj_open(context, GRN_BULK, flags, GRN_ID_NIL);
279
- rb_grn_context_check(context, object);
280
- }
281
- GRN_TEXT_SET(context, bulk, string, size);
282
-
283
316
  return bulk;
284
317
  }
285
318
 
@@ -346,6 +379,10 @@ rb_grn_bulk_from_ruby_object_with_type (VALUE object, grn_ctx *context,
346
379
  sec = NUM2LL(rb_sec);
347
380
  usec = (int32_t)(NUM2DBL(rb_usec) * 1000000);
348
381
  break;
382
+ case T_NIL:
383
+ sec = 0;
384
+ usec = 0;
385
+ break;
349
386
  default:
350
387
  sec = NUM2LL(rb_funcall(object, rb_intern("to_i"), 0));
351
388
  usec = NUM2INT(rb_funcall(object, rb_intern("usec"), 0));
@@ -395,30 +432,32 @@ rb_grn_bulk_from_ruby_object_with_type (VALUE object, grn_ctx *context,
395
432
  }
396
433
 
397
434
 
398
- /* FIXME: maybe not work */
399
435
  VALUE
400
436
  rb_grn_vector_to_ruby_object (grn_ctx *context, grn_obj *vector)
401
437
  {
402
438
  VALUE array;
439
+ grn_obj value;
403
440
  unsigned int i, n;
404
441
 
405
442
  if (!vector)
406
443
  return Qnil;
407
444
 
445
+ GRN_VOID_INIT(&value);
408
446
  n = grn_vector_size(context, vector);
409
447
  array = rb_ary_new2(n);
410
448
  for (i = 0; i < n; i++) {
411
- const char *value;
449
+ const char *_value;
412
450
  unsigned int weight, length;
413
451
  grn_id domain;
414
452
 
415
453
  length = grn_vector_get_element(context, vector, i,
416
- &value, &weight, &domain);
417
- rb_ary_push(array,
418
- rb_ary_new3(2,
419
- rb_str_new(value, length), /* FIXME */
420
- UINT2NUM(weight)));
454
+ &_value, &weight, &domain);
455
+ grn_obj_reinit(context, &value, domain, 0);
456
+ grn_bulk_write(context, &value, _value, length);
457
+ rb_ary_push(array, GRNOBJ2RVAL(Qnil, context, &value, Qnil));
458
+ /* UINT2NUM(weight); */ /* TODO: How handle weight? */
421
459
  }
460
+ GRN_OBJ_FIN(context, &value);
422
461
 
423
462
  return array;
424
463
  }
@@ -427,6 +466,7 @@ grn_obj *
427
466
  rb_grn_vector_from_ruby_object (VALUE object, grn_ctx *context, grn_obj *vector)
428
467
  {
429
468
  VALUE *values;
469
+ grn_obj value;
430
470
  int i, n;
431
471
 
432
472
  if (vector)
@@ -437,19 +477,19 @@ rb_grn_vector_from_ruby_object (VALUE object, grn_ctx *context, grn_obj *vector)
437
477
  if (NIL_P(object))
438
478
  return vector;
439
479
 
480
+ GRN_VOID_INIT(&value);
440
481
  n = RARRAY_LEN(object);
441
482
  values = RARRAY_PTR(object);
442
483
  for (i = 0; i < n; i++) {
443
- VALUE rb_value;
444
- grn_id id;
445
- void *grn_value;
446
-
447
- rb_value = values[i];
448
- id = NUM2UINT(rb_value);
449
- grn_value = &id;
450
- grn_vector_add_element(context, vector, grn_value, sizeof(id),
451
- 0, GRN_ID_NIL);
484
+ grn_obj *_value = &value;
485
+ RVAL2GRNOBJ(values[i], context, &_value);
486
+ grn_vector_add_element(context, vector,
487
+ GRN_BULK_HEAD(&value),
488
+ GRN_BULK_VSIZE(&value),
489
+ 0,
490
+ value.header.domain);
452
491
  }
492
+ GRN_OBJ_FIN(context, &value);
453
493
 
454
494
  return vector;
455
495
  }
@@ -476,18 +516,13 @@ rb_grn_uvector_to_ruby_object (grn_ctx *context, grn_obj *uvector)
476
516
 
477
517
  grn_obj *
478
518
  rb_grn_uvector_from_ruby_object (VALUE object, grn_ctx *context,
479
- grn_obj *uvector)
519
+ grn_obj *uvector, VALUE related_object)
480
520
  {
481
521
  VALUE *values;
482
522
  int i, n;
483
523
 
484
- if (uvector)
485
- GRN_OBJ_INIT(uvector, GRN_UVECTOR, 0, GRN_ID_NIL);
486
- else
487
- uvector = grn_obj_open(context, GRN_UVECTOR, 0, 0);
488
-
489
524
  if (NIL_P(object))
490
- return uvector;
525
+ return NULL;
491
526
 
492
527
  n = RARRAY_LEN(object);
493
528
  values = RARRAY_PTR(object);
@@ -497,9 +532,26 @@ rb_grn_uvector_from_ruby_object (VALUE object, grn_ctx *context,
497
532
  void *grn_value;
498
533
 
499
534
  value = values[i];
500
- id = NUM2UINT(value);
535
+ switch (TYPE(value)) {
536
+ case T_FIXNUM:
537
+ id = NUM2UINT(value);
538
+ break;
539
+ default:
540
+ if (RVAL2CBOOL(rb_obj_is_kind_of(value, rb_cGrnRecord))) {
541
+ id = NUM2UINT(rb_funcall(value, rb_intern("id"), 0));
542
+ } else {
543
+ grn_obj_close(context, uvector);
544
+ rb_raise(rb_eArgError,
545
+ "uvector value should be one of "
546
+ "[Fixnum, Groonga::Record]: %s (%s): %s",
547
+ rb_grn_inspect(value),
548
+ rb_grn_inspect(object),
549
+ rb_grn_inspect(related_object));
550
+ }
551
+ break;
552
+ }
501
553
  grn_value = &id;
502
- grn_bulk_write(context, uvector, grn_value, sizeof(id));
554
+ grn_bulk_write(context, uvector, grn_value, sizeof(grn_id));
503
555
  }
504
556
 
505
557
  return uvector;
@@ -523,7 +575,7 @@ rb_grn_value_to_ruby_object (grn_ctx *context,
523
575
  return Qnil;
524
576
  if (value->header.domain == GRN_ID_NIL && range)
525
577
  value->header.domain = grn_obj_id(context, range);
526
- return GRNBULK2RVAL(context, value, related_object);
578
+ return GRNBULK2RVAL(context, value, range, related_object);
527
579
  break;
528
580
  case GRN_UVECTOR:
529
581
  {
@@ -544,6 +596,9 @@ rb_grn_value_to_ruby_object (grn_ctx *context,
544
596
  return rb_value;
545
597
  }
546
598
  break;
599
+ case GRN_VECTOR:
600
+ return GRNVECTOR2RVAL(context, value);
601
+ break;
547
602
  default:
548
603
  rb_raise(rb_eGrnError,
549
604
  "unsupported value type: 0x%0x: %s",
@@ -599,11 +654,10 @@ rb_grn_key_to_ruby_object (grn_ctx *context, const void *key, int key_size,
599
654
  {
600
655
  grn_obj bulk;
601
656
 
602
- GRN_OBJ_INIT(&bulk, GRN_BULK, GRN_OBJ_DO_SHALLOW_COPY, GRN_ID_NIL);
657
+ GRN_OBJ_INIT(&bulk, GRN_BULK, GRN_OBJ_DO_SHALLOW_COPY, table->header.domain);
603
658
  GRN_TEXT_SET(context, &bulk, key, key_size);
604
- bulk.header.domain = table->header.domain;
605
659
 
606
- return GRNBULK2RVAL(context, &bulk, related_object);
660
+ return GRNBULK2RVAL(context, &bulk, NULL, related_object);
607
661
  }
608
662
 
609
663
  grn_obj *
@@ -643,75 +697,16 @@ rb_grn_key_from_ruby_object (VALUE rb_key, grn_ctx *context,
643
697
  grn_obj *
644
698
  rb_grn_obj_from_ruby_object (VALUE rb_object, grn_ctx *context, grn_obj **_obj)
645
699
  {
646
- grn_obj *obj;
647
-
648
- if (*_obj) {
649
- obj = *_obj;
650
- grn_obj_close(context, obj); /* FIXME: grn_obj_reinit() */
651
- } else {
652
- *_obj = grn_obj_open(context, GRN_VOID, 0, GRN_ID_NIL);
653
- obj = *_obj;
654
- }
655
-
656
- switch (TYPE(rb_object)) {
657
- case T_NIL:
658
- grn_obj_reinit(context, obj, GRN_DB_VOID, 0);
659
- break;
660
- case T_STRING:
661
- grn_obj_reinit(context, obj, GRN_DB_TEXT, 0);
662
- GRN_TEXT_SET(context, obj,
663
- RSTRING_PTR(rb_object), RSTRING_LEN(rb_object));
664
- break;
665
- case T_FIXNUM:
666
- grn_obj_reinit(context, obj, GRN_DB_INT32, 0);
667
- GRN_INT32_SET(context, obj, NUM2INT(rb_object));
668
- break;
669
- case T_BIGNUM:
670
- grn_obj_reinit(context, obj, GRN_DB_INT64, 0);
671
- GRN_INT64_SET(context, obj, NUM2LL(rb_object));
672
- break;
673
- case T_FLOAT:
674
- grn_obj_reinit(context, obj, GRN_DB_FLOAT, 0);
675
- GRN_FLOAT_SET(context, obj, NUM2DBL(rb_object));
676
- break;
677
- default:
678
- if (RVAL2CBOOL(rb_obj_is_kind_of(rb_object, rb_cTime))) {
679
- VALUE sec, usec;
680
- int64_t time_value;
681
-
682
- sec = rb_funcall(rb_object, rb_intern("to_i"), 0);
683
- usec = rb_funcall(rb_object, rb_intern("usec"), 0);
684
- time_value = GRN_TIME_PACK(NUM2LL(sec), NUM2LL(usec));
685
- grn_obj_reinit(context, obj, GRN_DB_TIME, 0);
686
- GRN_TIME_SET(context, obj, time_value);
687
- } else if (RVAL2CBOOL(rb_obj_is_kind_of(rb_object, rb_cGrnObject))) {
688
- grn_obj_close(context, obj); /* TODO: reduce memory allocation */
689
- *_obj = RVAL2GRNOBJECT(rb_object, &context);
690
- obj = *_obj;
691
- } else if (RVAL2CBOOL(rb_obj_is_kind_of(rb_object, rb_cGrnRecord))) {
692
- grn_id id, table_id;
693
- VALUE rb_table;
694
- grn_obj *table = NULL;
695
-
696
- id = NUM2UINT(rb_funcall(rb_object, rb_intern("id"), 0));
697
- rb_table = rb_funcall(rb_object, rb_intern("table"), 0);
698
- rb_grn_table_deconstruct(RB_GRN_TABLE(DATA_PTR(rb_table)),
699
- &table, NULL,
700
- NULL, NULL, NULL, NULL, NULL);
701
- table_id = grn_obj_id(context, table);
702
- grn_obj_reinit(context, obj, table_id, 0);
703
- GRN_RECORD_SET(context, obj, id);
704
- } else {
705
- rb_raise(rb_eTypeError,
706
- "should be one of "
707
- "[nil, String, Integer, Float, Time, Groonga::Object, "
708
- "Groonga::Record]: <%s>",
709
- rb_grn_inspect(rb_object));
700
+ if (RVAL2CBOOL(rb_obj_is_kind_of(rb_object, rb_cGrnObject))) {
701
+ if (*_obj) {
702
+ grn_obj_close(context, *_obj); /* TODO: reduce memory allocation */
710
703
  }
711
- break;
704
+ *_obj = RVAL2GRNOBJECT(rb_object, &context);
705
+ } else {
706
+ *_obj = RVAL2GRNBULK(rb_object, context, *_obj);
712
707
  }
713
708
 
714
- return obj;
709
+ return *_obj;
715
710
  }
716
711
 
717
712
  VALUE
@@ -726,10 +721,13 @@ rb_grn_obj_to_ruby_object (VALUE klass, grn_ctx *context,
726
721
 
727
722
  switch (obj->header.type) {
728
723
  case GRN_VOID:
729
- return Qnil;
724
+ if (GRN_BULK_VSIZE(obj) > 0)
725
+ return rb_str_new(GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj));
726
+ else
727
+ return Qnil;
730
728
  break;
731
729
  case GRN_BULK:
732
- return GRNBULK2RVAL(context, obj, related_object);
730
+ return GRNBULK2RVAL(context, obj, NULL, related_object);
733
731
  break;
734
732
  /* case GRN_PTR: */
735
733
  /* case GRN_UVECTOR: */