groonga 0.0.7 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/NEWS.ja.rdoc +56 -0
  2. data/NEWS.rdoc +58 -0
  3. data/Rakefile +2 -3
  4. data/benchmark/read-write-many-small-items.rb +16 -32
  5. data/benchmark/write-many-small-items.rb +14 -28
  6. data/example/bookmark.rb +19 -17
  7. data/example/index-html.rb +11 -1
  8. data/example/search/config.ru +14 -9
  9. data/ext/rb-grn-array.c +6 -6
  10. data/ext/rb-grn-column.c +348 -18
  11. data/ext/rb-grn-context.c +8 -4
  12. data/ext/rb-grn-database.c +6 -7
  13. data/ext/rb-grn-exception.c +101 -5
  14. data/ext/rb-grn-expression.c +206 -23
  15. data/ext/rb-grn-fix-size-column.c +6 -39
  16. data/ext/rb-grn-hash.c +24 -24
  17. data/ext/rb-grn-index-column.c +74 -19
  18. data/ext/rb-grn-logger.c +48 -0
  19. data/ext/rb-grn-object.c +281 -67
  20. data/ext/rb-grn-operation.c +1 -1
  21. data/ext/rb-grn-patricia-trie-cursor.c +10 -1
  22. data/ext/rb-grn-patricia-trie.c +268 -7
  23. data/ext/rb-grn-query.c +52 -1
  24. data/ext/rb-grn-record.c +8 -2
  25. data/ext/rb-grn-snippet.c +63 -1
  26. data/ext/rb-grn-table-cursor-key-support.c +15 -1
  27. data/ext/rb-grn-table-cursor.c +57 -0
  28. data/ext/rb-grn-table-key-support.c +382 -46
  29. data/ext/rb-grn-table.c +729 -192
  30. data/ext/rb-grn-type.c +63 -12
  31. data/ext/rb-grn-utils.c +156 -158
  32. data/ext/rb-grn-variable.c +18 -0
  33. data/ext/rb-grn.h +85 -21
  34. data/ext/rb-groonga.c +13 -3
  35. data/extconf.rb +19 -4
  36. data/html/developer.html +1 -1
  37. data/html/header.html.erb +1 -1
  38. data/html/index.html +4 -4
  39. data/lib/groonga.rb +10 -0
  40. data/lib/groonga/expression-builder.rb +81 -42
  41. data/lib/groonga/patricia-trie.rb +13 -0
  42. data/lib/groonga/record.rb +158 -13
  43. data/lib/groonga/schema.rb +339 -33
  44. data/pkg-config.rb +6 -1
  45. data/test-unit/lib/test/unit.rb +23 -42
  46. data/test-unit/lib/test/unit/assertionfailederror.rb +11 -0
  47. data/test-unit/lib/test/unit/assertions.rb +87 -9
  48. data/test-unit/lib/test/unit/autorunner.rb +20 -11
  49. data/test-unit/lib/test/unit/collector.rb +1 -8
  50. data/test-unit/lib/test/unit/collector/load.rb +2 -3
  51. data/test-unit/lib/test/unit/color-scheme.rb +13 -1
  52. data/test-unit/lib/test/unit/diff.rb +223 -37
  53. data/test-unit/lib/test/unit/error.rb +4 -0
  54. data/test-unit/lib/test/unit/failure.rb +31 -5
  55. data/test-unit/lib/test/unit/notification.rb +8 -4
  56. data/test-unit/lib/test/unit/omission.rb +51 -3
  57. data/test-unit/lib/test/unit/pending.rb +4 -0
  58. data/test-unit/lib/test/unit/testcase.rb +55 -4
  59. data/test-unit/lib/test/unit/ui/console/testrunner.rb +190 -4
  60. data/test-unit/lib/test/unit/ui/emacs/testrunner.rb +14 -0
  61. data/test-unit/lib/test/unit/ui/testrunner.rb +8 -0
  62. data/test-unit/lib/test/unit/version.rb +1 -1
  63. data/test-unit/sample/{tc_adder.rb → test_adder.rb} +3 -1
  64. data/test-unit/sample/{tc_subtracter.rb → test_subtracter.rb} +3 -1
  65. data/test-unit/sample/test_user.rb +1 -0
  66. data/test-unit/test/collector/test-descendant.rb +2 -4
  67. data/test-unit/test/collector/test_objectspace.rb +7 -5
  68. data/test-unit/test/run-test.rb +2 -0
  69. data/test-unit/test/test-color-scheme.rb +7 -0
  70. data/test-unit/test/test-diff.rb +48 -7
  71. data/test-unit/test/test-omission.rb +1 -1
  72. data/test-unit/test/test-testcase.rb +47 -0
  73. data/test-unit/test/test_assertions.rb +79 -10
  74. data/test/groonga-test-utils.rb +6 -1
  75. data/test/test-array.rb +29 -14
  76. data/test/test-column.rb +107 -55
  77. data/test/test-context.rb +5 -0
  78. data/test/test-database.rb +2 -37
  79. data/test/test-exception.rb +9 -1
  80. data/test/test-expression-builder.rb +23 -5
  81. data/test/test-expression.rb +44 -8
  82. data/test/test-fix-size-column.rb +16 -5
  83. data/test/test-gqtp.rb +70 -0
  84. data/test/test-hash.rb +142 -43
  85. data/test/test-index-column.rb +9 -9
  86. data/test/test-patricia-trie.rb +79 -20
  87. data/test/test-procedure.rb +4 -2
  88. data/test/test-record.rb +32 -20
  89. data/test/test-remote.rb +3 -2
  90. data/test/test-schema.rb +226 -92
  91. data/test/test-table-cursor.rb +103 -1
  92. data/test/test-table-offset-and-limit.rb +102 -0
  93. data/test/test-table-select-normalize.rb +4 -4
  94. data/test/test-table-select.rb +52 -8
  95. data/test/test-table.rb +235 -116
  96. data/test/test-type.rb +2 -2
  97. data/test/test-variable-size-column.rb +21 -5
  98. data/test/test-vector-column.rb +76 -0
  99. data/{TUTORIAL.ja.rdoc → text/TUTORIAL.ja.rdoc} +52 -52
  100. data/text/expression.rdoc +284 -0
  101. metadata +11 -7
  102. data/test-unit/sample/ts_examples.rb +0 -7
@@ -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: */