groonga 0.0.2 → 0.0.3

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 (54) hide show
  1. data/NEWS.ja.rdoc +18 -3
  2. data/NEWS.rdoc +18 -3
  3. data/README.ja.rdoc +2 -0
  4. data/README.rdoc +2 -0
  5. data/Rakefile +14 -5
  6. data/TUTORIAL.ja.rdoc +82 -16
  7. data/benchmark/{read-write-small-many-items.rb → read-write-many-small-items.rb} +26 -23
  8. data/benchmark/{write-small-many-items.rb → write-many-small-items.rb} +26 -23
  9. data/example/bookmark.rb +49 -5
  10. data/ext/rb-grn-array.c +11 -1
  11. data/ext/rb-grn-column.c +132 -5
  12. data/ext/rb-grn-context.c +85 -80
  13. data/ext/rb-grn-database.c +182 -9
  14. data/ext/rb-grn-expression-builder.c +69 -0
  15. data/ext/rb-grn-expression.c +314 -0
  16. data/ext/rb-grn-fix-size-column.c +68 -89
  17. data/ext/rb-grn-hash.c +14 -5
  18. data/ext/rb-grn-index-column.c +14 -55
  19. data/ext/rb-grn-object.c +206 -75
  20. data/ext/rb-grn-operation.c +92 -0
  21. data/ext/rb-grn-patricia-trie.c +10 -32
  22. data/ext/rb-grn-query.c +9 -9
  23. data/ext/rb-grn-table-cursor.c +19 -80
  24. data/ext/rb-grn-table-key-support.c +33 -39
  25. data/ext/rb-grn-table.c +436 -79
  26. data/ext/rb-grn-type.c +10 -3
  27. data/ext/rb-grn-utils.c +131 -4
  28. data/ext/rb-grn-variable-size-column.c +36 -0
  29. data/ext/rb-grn-variable.c +90 -0
  30. data/ext/rb-grn.h +109 -56
  31. data/ext/rb-groonga.c +4 -0
  32. data/extconf.rb +39 -13
  33. data/html/index.html +2 -2
  34. data/lib/groonga.rb +22 -0
  35. data/lib/groonga/expression-builder.rb +141 -0
  36. data/lib/groonga/record.rb +25 -1
  37. data/lib/groonga/schema.rb +418 -0
  38. data/test/test-column.rb +11 -23
  39. data/test/test-context.rb +1 -1
  40. data/test/test-database.rb +60 -19
  41. data/test/test-expression-builder.rb +114 -0
  42. data/test/test-expression.rb +55 -0
  43. data/test/test-fix-size-column.rb +53 -0
  44. data/test/test-hash.rb +10 -3
  45. data/test/test-index-column.rb +24 -0
  46. data/test/test-patricia-trie.rb +9 -0
  47. data/test/test-procedure.rb +5 -5
  48. data/test/test-record.rb +71 -4
  49. data/test/test-schema.rb +207 -0
  50. data/test/test-table.rb +94 -12
  51. data/test/test-type.rb +18 -11
  52. data/test/test-variable-size-column.rb +53 -0
  53. data/test/test-variable.rb +28 -0
  54. metadata +18 -5
data/ext/rb-grn-hash.c CHANGED
@@ -89,6 +89,11 @@ VALUE rb_cGrnHash;
89
89
  * Groonga::IndexColumnを定義する場合は
90
90
  * <tt>"<token:bigram>"</tt>などを指定する必要がある。
91
91
  *
92
+ * [+:sub_records+]
93
+ * +true+を指定すると#groupでグループ化したときに、
94
+ * <tt>record[".:nsubrecs"]</tt>でグループに含まれるレコー
95
+ * ドの件数を取得できる。
96
+ *
92
97
  * 使用例:
93
98
  *
94
99
  * 無名一時テーブルを生成する。
@@ -144,6 +149,7 @@ rb_grn_hash_s_create (int argc, VALUE *argv, VALUE self)
144
149
  VALUE rb_table;
145
150
  VALUE options, rb_context, rb_name, rb_path, rb_persistent;
146
151
  VALUE rb_key_type, rb_value_size, rb_default_tokenizer;
152
+ VALUE rb_sub_records;
147
153
 
148
154
  rb_scan_args(argc, argv, "01", &options);
149
155
 
@@ -155,6 +161,7 @@ rb_grn_hash_s_create (int argc, VALUE *argv, VALUE self)
155
161
  "key_type", &rb_key_type,
156
162
  "value_size", &rb_value_size,
157
163
  "default_tokenizer", &rb_default_tokenizer,
164
+ "sub_records", &rb_sub_records,
158
165
  NULL);
159
166
 
160
167
  context = rb_grn_context_ensure(&rb_context);
@@ -162,6 +169,7 @@ rb_grn_hash_s_create (int argc, VALUE *argv, VALUE self)
162
169
  if (!NIL_P(rb_name)) {
163
170
  name = StringValuePtr(rb_name);
164
171
  name_size = RSTRING_LEN(rb_name);
172
+ flags |= GRN_OBJ_PERSISTENT;
165
173
  }
166
174
 
167
175
  if (!NIL_P(rb_path)) {
@@ -181,13 +189,15 @@ rb_grn_hash_s_create (int argc, VALUE *argv, VALUE self)
181
189
  if (!NIL_P(rb_value_size))
182
190
  value_size = NUM2UINT(rb_value_size);
183
191
 
192
+ if (RVAL2CBOOL(rb_sub_records))
193
+ flags |= GRN_OBJ_WITH_SUBREC;
194
+
184
195
  table = grn_table_create(context, name, name_size, path,
185
196
  flags, key_type, value_size);
186
197
  if (!table)
187
198
  rb_grn_context_check(context, rb_ary_new4(argc, argv));
188
- rb_table = rb_grn_table_key_support_alloc(self);
189
- rb_grn_table_key_support_assign(rb_table, rb_context, context, table,
190
- RB_GRN_TRUE);
199
+ rb_table = rb_grn_object_alloc(self);
200
+ rb_grn_object_assign(Qnil, rb_table, rb_context, context, table);
191
201
  rb_grn_context_check(context, rb_table);
192
202
 
193
203
  if (!NIL_P(rb_default_tokenizer))
@@ -261,7 +271,7 @@ rb_grn_hash_search (int argc, VALUE *argv, VALUE self)
261
271
  }
262
272
 
263
273
  rc = grn_obj_search(context, table, key,
264
- result, GRN_SEL_OR, NULL);
274
+ result, GRN_OP_OR, NULL);
265
275
  rb_grn_rc_check(rc, self);
266
276
 
267
277
  return rb_result;
@@ -271,7 +281,6 @@ void
271
281
  rb_grn_init_hash (VALUE mGrn)
272
282
  {
273
283
  rb_cGrnHash = rb_define_class_under(mGrn, "Hash", rb_cGrnTable);
274
- rb_define_alloc_func(rb_cGrnHash, rb_grn_table_key_support_alloc);
275
284
 
276
285
  rb_include_module(rb_cGrnHash, rb_mGrnTableKeySupport);
277
286
 
@@ -33,52 +33,28 @@ VALUE rb_cGrnIndexColumn;
33
33
  */
34
34
 
35
35
  void
36
- rb_grn_index_column_unbind (RbGrnIndexColumn *rb_grn_index_column)
36
+ rb_grn_index_column_finalizer (grn_ctx *context, grn_obj *object,
37
+ RbGrnIndexColumn *rb_grn_index_column)
37
38
  {
38
- RbGrnObject *rb_grn_object;
39
- grn_ctx *context;
40
-
41
- rb_grn_object = RB_GRN_OBJECT(rb_grn_index_column);
42
- context = rb_grn_object->context;
43
-
44
- if (context) {
45
- grn_obj_close(context, rb_grn_index_column->id_query);
46
- grn_obj_close(context, rb_grn_index_column->string_query);
47
- grn_obj_close(context, rb_grn_index_column->value);
48
- grn_obj_close(context, rb_grn_index_column->old_value);
49
- }
50
-
51
- rb_grn_object_unbind(rb_grn_object);
52
- }
53
-
54
- static void
55
- rb_grn_index_column_free (void *object)
56
- {
57
- RbGrnIndexColumn *rb_grn_index_column = object;
39
+ if (!context)
40
+ return;
58
41
 
59
- rb_grn_index_column_unbind(rb_grn_index_column);
60
- xfree(rb_grn_index_column);
61
- }
42
+ grn_obj_close(context, rb_grn_index_column->id_query);
43
+ grn_obj_close(context, rb_grn_index_column->string_query);
44
+ grn_obj_close(context, rb_grn_index_column->old_value);
62
45
 
63
- VALUE
64
- rb_grn_index_column_alloc (VALUE klass)
65
- {
66
- return Data_Wrap_Struct(klass, NULL, rb_grn_index_column_free, NULL);
46
+ rb_grn_column_finalizer(context, object, RB_GRN_COLUMN(rb_grn_index_column));
67
47
  }
68
48
 
69
49
  void
70
50
  rb_grn_index_column_bind (RbGrnIndexColumn *rb_grn_index_column,
71
- grn_ctx *context, grn_obj *column,
72
- rb_grn_boolean owner)
51
+ grn_ctx *context, grn_obj *column)
73
52
  {
74
53
  RbGrnObject *rb_grn_object;
75
54
 
55
+ rb_grn_column_bind(RB_GRN_COLUMN(rb_grn_index_column), context, column);
76
56
  rb_grn_object = RB_GRN_OBJECT(rb_grn_index_column);
77
- rb_grn_object_bind(rb_grn_object, context, column, owner);
78
- rb_grn_object->unbind = RB_GRN_UNBIND_FUNCTION(rb_grn_index_column_unbind);
79
57
 
80
- rb_grn_index_column->value = grn_obj_open(context, GRN_BULK, 0,
81
- rb_grn_object->range_id);
82
58
  rb_grn_index_column->old_value = grn_obj_open(context, GRN_BULK, 0,
83
59
  rb_grn_object->range_id);
84
60
 
@@ -89,20 +65,6 @@ rb_grn_index_column_bind (RbGrnIndexColumn *rb_grn_index_column,
89
65
  GRN_ID_NIL);
90
66
  }
91
67
 
92
- void
93
- rb_grn_index_column_assign (VALUE self, VALUE rb_context,
94
- grn_ctx *context, grn_obj *column,
95
- rb_grn_boolean owner)
96
- {
97
- RbGrnIndexColumn *rb_grn_index_column;
98
-
99
- rb_grn_index_column = ALLOC(RbGrnIndexColumn);
100
- DATA_PTR(self) = rb_grn_index_column;
101
- rb_grn_index_column_bind(rb_grn_index_column, context, column, owner);
102
-
103
- rb_iv_set(self, "context", rb_context);
104
- }
105
-
106
68
  void
107
69
  rb_grn_index_column_deconstruct (RbGrnIndexColumn *rb_grn_index_column,
108
70
  grn_obj **column,
@@ -119,12 +81,10 @@ rb_grn_index_column_deconstruct (RbGrnIndexColumn *rb_grn_index_column,
119
81
  RbGrnObject *rb_grn_object;
120
82
 
121
83
  rb_grn_object = RB_GRN_OBJECT(rb_grn_index_column);
122
- rb_grn_object_deconstruct(rb_grn_object, column, context,
123
- domain_id, domain,
84
+ rb_grn_column_deconstruct(RB_GRN_COLUMN(rb_grn_object), column, context,
85
+ domain_id, domain, value,
124
86
  range_id, range);
125
87
 
126
- if (value)
127
- *value = rb_grn_index_column->value;
128
88
  if (old_value)
129
89
  *old_value = rb_grn_index_column->old_value;
130
90
  if (id_query)
@@ -402,7 +362,7 @@ rb_grn_index_column_search (int argc, VALUE *argv, VALUE self)
402
362
  grn_obj *range;
403
363
  grn_obj *query = NULL, *id_query = NULL, *string_query = NULL;
404
364
  grn_obj *result;
405
- grn_sel_operator operator;
365
+ grn_operator operator;
406
366
  grn_rc rc;
407
367
  VALUE rb_query, options, rb_result, rb_operator;
408
368
 
@@ -444,7 +404,7 @@ rb_grn_index_column_search (int argc, VALUE *argv, VALUE self)
444
404
  result = RVAL2GRNOBJECT(rb_result, &context);
445
405
  }
446
406
 
447
- operator = RVAL2GRNSELECTOPERATOR(rb_operator);
407
+ operator = RVAL2GRNOPERATOR(rb_operator);
448
408
 
449
409
  rc = grn_obj_search(context, column, query, result, operator, NULL);
450
410
  rb_grn_rc_check(rc, self);
@@ -457,7 +417,6 @@ rb_grn_init_index_column (VALUE mGrn)
457
417
  {
458
418
  rb_cGrnIndexColumn =
459
419
  rb_define_class_under(mGrn, "IndexColumn", rb_cGrnColumn);
460
- rb_define_alloc_func(rb_cGrnIndexColumn, rb_grn_index_column_alloc);
461
420
 
462
421
  rb_define_method(rb_cGrnIndexColumn, "[]=",
463
422
  rb_grn_index_column_array_set, 2);
data/ext/rb-grn-object.c CHANGED
@@ -41,9 +41,14 @@ rb_grn_object_from_ruby_object (VALUE object, grn_ctx **context)
41
41
  if (context && *context) {
42
42
  grn_obj *grn_object;
43
43
  if (RVAL2CBOOL(rb_obj_is_kind_of(object, rb_cString))) {
44
- grn_object = grn_ctx_get(*context,
45
- StringValuePtr(object),
46
- RSTRING_LEN(object));
44
+ const char *name;
45
+ unsigned int name_size;
46
+
47
+ name = StringValuePtr(object);
48
+ name_size = RSTRING_LEN(object);
49
+ grn_object = rb_grn_context_get_backward_compatibility(*context,
50
+ name,
51
+ name_size);
47
52
  if (!grn_object)
48
53
  rb_raise(rb_eArgError,
49
54
  "unregistered groonga object: name: <%s>",
@@ -73,44 +78,92 @@ rb_grn_object_from_ruby_object (VALUE object, grn_ctx **context)
73
78
  return rb_grn_object->object;
74
79
  }
75
80
 
76
- void
77
- rb_grn_object_unbind (RbGrnObject *rb_grn_object)
81
+ grn_rc
82
+ rb_grn_object_finalizer (grn_ctx *context, grn_obj *grn_object,
83
+ grn_user_data *user_data)
78
84
  {
79
- grn_ctx *context;
80
- grn_obj *grn_object;
85
+ RbGrnObject *rb_grn_object;
86
+ rb_grn_boolean need_finalize = RB_GRN_TRUE;
81
87
 
82
- context = rb_grn_object->context;
83
- grn_object = rb_grn_object->object;
88
+ rb_grn_object = user_data->ptr;
84
89
 
85
- if (context)
86
- rb_grn_context_unregister(context, rb_grn_object);
90
+ grn_obj_user_data(context, grn_object)->ptr = NULL;
91
+ grn_obj_set_finalizer(context, grn_object, NULL);
87
92
 
88
- if (rb_grn_object->owner && context && grn_object) {
89
- const char *path;
90
- grn_obj *db = NULL;
93
+ debug("finalize %p:%p:%p:%p:%p %x\n",
94
+ context, grn_object, rb_grn_object,
95
+ rb_grn_object->context, rb_grn_object->object,
96
+ grn_object->header.type);
91
97
 
92
- path = grn_obj_path(context, grn_object);
93
- db = grn_ctx_db(context);
94
- if (path == NULL || (path && db)) {
95
- if (grn_object == db) {
96
- rb_grn_context_unbind(context);
97
- } else {
98
- grn_obj_close(context, grn_object);
99
- }
100
- }
98
+ if (rb_grn_object->context != context ||
99
+ rb_grn_object->object != grn_object) {
100
+ if (grn_object->header.type == GRN_DB)
101
+ grn_ctx_use(context, NULL);
102
+ need_finalize = RB_GRN_FALSE;
101
103
  }
102
104
 
103
105
  rb_grn_object->context = NULL;
104
106
  rb_grn_object->object = NULL;
105
- rb_grn_object->owner = RB_GRN_FALSE;
107
+
108
+ if (!need_finalize)
109
+ return GRN_SUCCESS;
110
+
111
+ switch (grn_object->header.type) {
112
+ case GRN_DB:
113
+ grn_ctx_use(context, NULL);
114
+ break;
115
+ case GRN_TYPE:
116
+ case GRN_ACCESSOR:
117
+ case GRN_PROC:
118
+ break;
119
+ case GRN_TABLE_HASH_KEY:
120
+ case GRN_TABLE_PAT_KEY:
121
+ rb_grn_table_key_support_finalizer(context, grn_object,
122
+ RB_GRN_TABLE_KEY_SUPPORT(rb_grn_object));
123
+ break;
124
+ case GRN_TABLE_NO_KEY:
125
+ rb_grn_table_finalizer(context, grn_object,
126
+ RB_GRN_TABLE(rb_grn_object));
127
+ break;
128
+ case GRN_COLUMN_FIX_SIZE:
129
+ case GRN_COLUMN_VAR_SIZE:
130
+ rb_grn_column_finalizer(context, grn_object,
131
+ RB_GRN_COLUMN(rb_grn_object));
132
+ break;
133
+ case GRN_COLUMN_INDEX:
134
+ rb_grn_index_column_finalizer(context, grn_object,
135
+ RB_GRN_INDEX_COLUMN(rb_grn_object));
136
+ break;
137
+ case GRN_EXPR:
138
+ rb_grn_expression_finalizer(context, grn_object,
139
+ RB_GRN_EXPRESSION(rb_grn_object));
140
+ break;
141
+ default:
142
+ rb_raise(rb_eTypeError,
143
+ "unsupported groonga object type: 0x%x",
144
+ grn_object->header.type);
145
+ break;
146
+ }
147
+
148
+ return GRN_SUCCESS;
106
149
  }
107
150
 
108
- static void
109
- rb_grn_object_free (void *object)
151
+ void
152
+ rb_grn_object_free (RbGrnObject *rb_grn_object)
110
153
  {
111
- RbGrnObject *rb_grn_object = object;
154
+ grn_ctx *context;
155
+ grn_obj *grn_object;
112
156
 
113
- rb_grn_object->unbind(rb_grn_object);
157
+ context = rb_grn_object->context;
158
+ grn_object = rb_grn_object->object;
159
+ debug("rb-free: %p:%p:%p\n", context, grn_object, rb_grn_object);
160
+ if (context && grn_object) {
161
+ rb_grn_object->context = NULL;
162
+ rb_grn_object->object = NULL;
163
+ debug("type: %x\n", grn_object->header.type);
164
+ if (rb_grn_object->need_close)
165
+ grn_obj_close(context, grn_object);
166
+ }
114
167
  xfree(rb_grn_object);
115
168
  }
116
169
 
@@ -145,14 +198,26 @@ rb_grn_object_to_ruby_class (grn_obj *object)
145
198
  klass = rb_cGrnFixSizeColumn;
146
199
  break;
147
200
  case GRN_COLUMN_VAR_SIZE:
148
- klass = rb_cGrnVarSizeColumn;
201
+ klass = rb_cGrnVariableSizeColumn;
149
202
  break;
150
203
  case GRN_COLUMN_INDEX:
151
204
  klass = rb_cGrnIndexColumn;
152
205
  break;
206
+ case GRN_EXPR:
207
+ klass = rb_cGrnExpression;
208
+ break;
209
+ case GRN_CURSOR_TABLE_HASH_KEY:
210
+ klass = rb_cGrnHashCursor;
211
+ break;
212
+ case GRN_CURSOR_TABLE_PAT_KEY:
213
+ klass = rb_cGrnPatriciaTrieCursor;
214
+ break;
215
+ case GRN_CURSOR_TABLE_NO_KEY:
216
+ klass = rb_cGrnArrayCursor;
217
+ break;
153
218
  default:
154
219
  rb_raise(rb_eTypeError,
155
- "unsupported groonga object type: %d",
220
+ "unsupported groonga object type: 0x%x",
156
221
  object->header.type);
157
222
  break;
158
223
  }
@@ -165,30 +230,20 @@ rb_grn_object_to_ruby_object (VALUE klass, grn_ctx *context, grn_obj *object,
165
230
  rb_grn_boolean owner)
166
231
  {
167
232
  VALUE rb_object;
233
+ grn_user_data *user_data;
168
234
 
169
235
  if (!object)
170
236
  return Qnil;
171
237
 
238
+ user_data = grn_obj_user_data(context, object);
239
+ if (user_data && user_data->ptr)
240
+ return RB_GRN_OBJECT(user_data->ptr)->self;
241
+
172
242
  if (NIL_P(klass))
173
243
  klass = GRNOBJECT2RCLASS(object);
174
244
 
175
- if (klass == rb_cGrnHash ||
176
- klass == rb_cGrnPatriciaTrie) {
177
- rb_object = rb_grn_table_key_support_alloc(klass);
178
- rb_grn_table_key_support_assign(rb_object, Qnil, context, object, owner);
179
- } else if (klass == rb_cGrnArray) {
180
- rb_object = rb_grn_table_alloc(klass);
181
- rb_grn_table_assign(rb_object, Qnil, context, object, owner);
182
- } else if (klass == rb_cGrnFixSizeColumn) {
183
- rb_object = rb_grn_fix_size_column_alloc(klass);
184
- rb_grn_fix_size_column_assign(rb_object, Qnil, context, object, owner);
185
- } else if (klass == rb_cGrnIndexColumn) {
186
- rb_object = rb_grn_index_column_alloc(klass);
187
- rb_grn_index_column_assign(rb_object, Qnil, context, object, owner);
188
- } else {
189
- rb_object = rb_grn_object_alloc(klass);
190
- rb_grn_object_assign(rb_object, Qnil, context, object, owner);
191
- }
245
+ rb_object = rb_obj_alloc(klass);
246
+ rb_grn_object_assign(klass, rb_object, Qnil, context, object);
192
247
 
193
248
  return rb_object;
194
249
  }
@@ -199,10 +254,38 @@ rb_grn_object_alloc (VALUE klass)
199
254
  return Data_Wrap_Struct(klass, NULL, rb_grn_object_free, NULL);
200
255
  }
201
256
 
202
- void
203
- rb_grn_object_bind (RbGrnObject *rb_grn_object,
204
- grn_ctx *context, grn_obj *object, rb_grn_boolean owner)
257
+ static void
258
+ rb_grn_object_bind_common (VALUE klass, VALUE self, VALUE rb_context,
259
+ RbGrnObject *rb_grn_object,
260
+ grn_ctx *context, grn_obj *object)
205
261
  {
262
+ DATA_PTR(self) = rb_grn_object;
263
+ rb_iv_set(self, "context", rb_context);
264
+
265
+ rb_grn_object->self = self;
266
+ rb_grn_object->need_close = RB_GRN_TRUE;
267
+ switch (object->header.type) {
268
+ case GRN_DB:
269
+ case GRN_TABLE_HASH_KEY:
270
+ case GRN_TABLE_PAT_KEY:
271
+ case GRN_TABLE_NO_KEY:
272
+ case GRN_COLUMN_FIX_SIZE:
273
+ case GRN_COLUMN_VAR_SIZE:
274
+ case GRN_COLUMN_INDEX:
275
+ grn_obj_user_data(context, object)->ptr = rb_grn_object;
276
+ grn_obj_set_finalizer(context, object, rb_grn_object_finalizer);
277
+ break;
278
+ case GRN_PROC:
279
+ case GRN_EXPR:
280
+ case GRN_TYPE:
281
+ rb_grn_object->need_close = RB_GRN_FALSE;
282
+ break;
283
+ default:
284
+ if (klass == rb_cGrnVariable)
285
+ rb_grn_object->need_close = RB_GRN_FALSE;
286
+ break;
287
+ }
288
+
206
289
  rb_grn_object->context = context;
207
290
  rb_grn_object->object = object;
208
291
 
@@ -221,27 +304,67 @@ rb_grn_object_bind (RbGrnObject *rb_grn_object,
221
304
  rb_grn_object->range = NULL;
222
305
  else
223
306
  rb_grn_object->range = grn_ctx_at(context, rb_grn_object->range_id);
224
-
225
- rb_grn_object->owner = owner;
226
-
227
- rb_grn_object->unbind = RB_GRN_UNBIND_FUNCTION(rb_grn_object_unbind);
228
-
229
- if (context)
230
- rb_grn_context_register(context, rb_grn_object);
231
307
  }
232
308
 
233
309
  void
234
- rb_grn_object_assign (VALUE self, VALUE rb_context,
235
- grn_ctx *context, grn_obj *object,
236
- rb_grn_boolean owner)
310
+ rb_grn_object_assign (VALUE klass, VALUE self, VALUE rb_context,
311
+ grn_ctx *context, grn_obj *object)
237
312
  {
238
- RbGrnObject *rb_grn_object;
313
+ void *rb_grn_object;
239
314
 
240
- rb_grn_object = ALLOC(RbGrnObject);
241
- DATA_PTR(self) = rb_grn_object;
242
- rb_grn_object_bind(rb_grn_object, context, object, owner);
315
+ if (!object)
316
+ return;
243
317
 
244
- rb_iv_set(self, "context", rb_context);
318
+ if (NIL_P(klass))
319
+ klass = rb_obj_class(self);
320
+
321
+ if (klass == rb_cGrnDatabase ||
322
+ (RVAL2CBOOL(rb_obj_is_kind_of(self, rb_cGrnType))) ||
323
+ klass == rb_cGrnAccessor ||
324
+ klass == rb_cGrnHashCursor ||
325
+ klass == rb_cGrnPatriciaTrieCursor ||
326
+ klass == rb_cGrnArrayCursor ||
327
+ klass == rb_cGrnProcedure ||
328
+ klass == rb_cGrnVariable) {
329
+ rb_grn_object = ALLOC(RbGrnObject);
330
+ rb_grn_object_bind_common(klass, self, rb_context, rb_grn_object,
331
+ context, object);
332
+ } else if (RVAL2CBOOL(rb_obj_is_kind_of(self, rb_mGrnTableKeySupport))) {
333
+ rb_grn_object = ALLOC(RbGrnTableKeySupport);
334
+ rb_grn_object_bind_common(klass, self, rb_context, rb_grn_object,
335
+ context, object);
336
+ rb_grn_table_key_support_bind(RB_GRN_TABLE_KEY_SUPPORT(rb_grn_object),
337
+ context, object);
338
+ } else if (RVAL2CBOOL(rb_obj_is_kind_of(self, rb_cGrnTable))) {
339
+ rb_grn_object = ALLOC(RbGrnTable);
340
+ rb_grn_object_bind_common(klass, self, rb_context, rb_grn_object,
341
+ context, object);
342
+ rb_grn_table_bind(RB_GRN_TABLE(rb_grn_object), context, object);
343
+ } else if (RVAL2CBOOL(rb_obj_is_kind_of(self, rb_cGrnIndexColumn))) {
344
+ rb_grn_object = ALLOC(RbGrnIndexColumn);
345
+ rb_grn_object_bind_common(klass, self, rb_context, rb_grn_object,
346
+ context, object);
347
+ rb_grn_index_column_bind(RB_GRN_INDEX_COLUMN(rb_grn_object),
348
+ context, object);
349
+ } else if (RVAL2CBOOL(rb_obj_is_kind_of(self, rb_cGrnColumn))) {
350
+ rb_grn_object = ALLOC(RbGrnColumn);
351
+ rb_grn_object_bind_common(klass, self, rb_context, rb_grn_object,
352
+ context, object);
353
+ rb_grn_column_bind(RB_GRN_COLUMN(rb_grn_object), context, object);
354
+ } else if (klass == rb_cGrnExpression) {
355
+ rb_grn_object = ALLOC(RbGrnExpression);
356
+ rb_grn_object_bind_common(klass, self, rb_context, rb_grn_object,
357
+ context, object);
358
+ rb_grn_expression_bind(RB_GRN_EXPRESSION(rb_grn_object),
359
+ context, object);
360
+ } else {
361
+ rb_raise(rb_eTypeError,
362
+ "unsupported groonga object type: 0x%x",
363
+ object->header.type);
364
+ }
365
+
366
+ debug("assign: %p:%p:%p 0x%x\n", context, object, rb_grn_object,
367
+ object->header.type);
245
368
  }
246
369
 
247
370
  void
@@ -282,7 +405,13 @@ rb_grn_object_deconstruct (RbGrnObject *rb_grn_object,
282
405
  VALUE
283
406
  rb_grn_object_close (VALUE self)
284
407
  {
285
- rb_grn_object_unbind(SELF(self));
408
+ grn_obj *object;
409
+ grn_ctx *context;
410
+
411
+ rb_grn_object_deconstruct(SELF(self), &object, &context,
412
+ NULL, NULL, NULL, NULL);
413
+ if (object && context)
414
+ grn_obj_close(context, object);
286
415
  return Qnil;
287
416
  }
288
417
 
@@ -298,10 +427,12 @@ rb_grn_object_close (VALUE self)
298
427
  static VALUE
299
428
  rb_grn_object_closed_p (VALUE self)
300
429
  {
301
- RbGrnObject *rb_grn_object;
430
+ grn_obj *object;
431
+ grn_ctx *context;
302
432
 
303
- rb_grn_object = SELF(self);
304
- if (rb_grn_object->context && rb_grn_object->object)
433
+ rb_grn_object_deconstruct(SELF(self), &object, &context,
434
+ NULL, NULL, NULL, NULL);
435
+ if (context && object)
305
436
  return Qfalse;
306
437
  else
307
438
  return Qtrue;
@@ -323,7 +454,6 @@ rb_grn_object_inspect_header (VALUE self, VALUE inspected)
323
454
  {
324
455
  rb_str_cat2(inspected, "#<");
325
456
  rb_str_concat(inspected, rb_inspect(rb_obj_class(self)));
326
- rb_str_cat2(inspected, " ");
327
457
 
328
458
  return inspected;
329
459
  }
@@ -480,10 +610,12 @@ rb_grn_object_inspect_content (VALUE self, VALUE inspected)
480
610
  context = rb_grn_object->context;
481
611
  object = rb_grn_object->object;
482
612
 
483
- if (!object)
484
- return inspected;
485
-
486
- rb_grn_object_inspect_object_content(inspected, context, object);
613
+ rb_str_cat2(inspected, " ");
614
+ if (object) {
615
+ rb_grn_object_inspect_object_content(inspected, context, object);
616
+ } else {
617
+ rb_str_cat2(inspected, "(closed)");
618
+ }
487
619
 
488
620
  return inspected;
489
621
  }
@@ -831,7 +963,6 @@ rb_grn_object_remove (VALUE self)
831
963
  rc = grn_obj_remove(context, rb_grn_object->object);
832
964
  rb_grn_rc_check(rc, self);
833
965
 
834
- rb_grn_object->unbind(rb_grn_object);
835
966
  rb_iv_set(self, "context", Qnil);
836
967
 
837
968
  return Qnil;