groonga 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/NEWS.ja.rdoc +11 -0
  2. data/NEWS.rdoc +11 -0
  3. data/README.ja.rdoc +4 -3
  4. data/README.rdoc +4 -3
  5. data/Rakefile +1 -1
  6. data/TUTORIAL.ja.rdoc +168 -44
  7. data/benchmark/common.rb +49 -0
  8. data/benchmark/read-write-small-many-items.rb +156 -0
  9. data/benchmark/write-small-many-items.rb +145 -0
  10. data/example/bookmark.rb +68 -20
  11. data/ext/rb-grn-array-cursor.c +8 -0
  12. data/ext/rb-grn-array.c +40 -11
  13. data/ext/rb-grn-column.c +38 -209
  14. data/ext/rb-grn-context.c +203 -56
  15. data/ext/rb-grn-database.c +119 -5
  16. data/ext/rb-grn-encoding-support.c +64 -0
  17. data/ext/rb-grn-encoding.c +58 -1
  18. data/ext/rb-grn-fix-size-column.c +220 -0
  19. data/ext/rb-grn-hash-cursor.c +8 -0
  20. data/ext/rb-grn-hash.c +244 -2
  21. data/ext/rb-grn-index-column.c +474 -0
  22. data/ext/rb-grn-object.c +143 -265
  23. data/ext/rb-grn-patricia-trie.c +148 -2
  24. data/ext/rb-grn-query.c +5 -3
  25. data/ext/rb-grn-record.c +3 -2
  26. data/ext/rb-grn-snippet.c +5 -3
  27. data/ext/rb-grn-table-cursor-key-support.c +3 -3
  28. data/ext/rb-grn-table-cursor.c +106 -112
  29. data/ext/rb-grn-table-key-support.c +220 -118
  30. data/ext/rb-grn-table.c +336 -80
  31. data/ext/rb-grn-type.c +5 -4
  32. data/ext/rb-grn-utils.c +62 -63
  33. data/ext/rb-grn.h +215 -14
  34. data/ext/rb-groonga.c +7 -16
  35. data/extconf.rb +3 -1
  36. data/html/favicon.ico +0 -0
  37. data/html/favicon.xcf +0 -0
  38. data/html/index.html +1 -7
  39. data/lib/groonga/record.rb +6 -1
  40. data/test/groonga-test-utils.rb +1 -0
  41. data/test/test-array.rb +81 -0
  42. data/test/test-column.rb +22 -12
  43. data/test/test-context.rb +1 -29
  44. data/test/test-database.rb +30 -0
  45. data/test/test-hash.rb +194 -0
  46. data/test/test-index-column.rb +57 -0
  47. data/test/test-patricia-trie.rb +82 -0
  48. data/test/test-record.rb +10 -10
  49. data/test/test-table.rb +37 -130
  50. data/test/test-type.rb +4 -3
  51. metadata +15 -4
  52. data/benchmark/small-many-items.rb +0 -175
data/ext/rb-grn-context.c CHANGED
@@ -20,8 +20,29 @@
20
20
 
21
21
  #define SELF(object) (RVAL2GRNCONTEXT(object))
22
22
 
23
+ #define OBJECTS_TABLE_NAME "<ranguba:objects>"
24
+
23
25
  static VALUE cGrnContext;
24
26
 
27
+ /*
28
+ * Document-class: Groonga::Context
29
+ *
30
+ * groonga全体に渡る情報を管理するオブジェクト。通常のアプリ
31
+ * ケーションでは1つのコンテキストを作成し、それを利用する。
32
+ * 複数のコンテキストを利用する必要はない。
33
+ *
34
+ * デフォルトで使用されるコンテキストは
35
+ * Groonga::Context#defaultでアクセスできる。コンテキストを
36
+ * 指定できる箇所でコンテキストの指定を省略したり+nil+を指定
37
+ * した場合はGroonga::Context.defaultが利用される。
38
+ *
39
+ * また、デフォルトのコンテキストは必要になると暗黙のうちに
40
+ * 作成される。そのため、コンテキストを意識することは少ない。
41
+ *
42
+ * 暗黙のうちに作成されるコンテキストにオプションを指定する
43
+ * 場合はGroonga::Context.default_options=を使用する。
44
+ */
45
+
25
46
  grn_ctx *
26
47
  rb_grn_context_from_ruby_object (VALUE object)
27
48
  {
@@ -37,13 +58,90 @@ rb_grn_context_from_ruby_object (VALUE object)
37
58
  return context;
38
59
  }
39
60
 
61
+ void
62
+ rb_grn_context_register (grn_ctx *context, RbGrnObject *object)
63
+ {
64
+ grn_obj *objects;
65
+
66
+ if (!grn_ctx_db(context))
67
+ return;
68
+
69
+ objects = grn_ctx_get(context,
70
+ OBJECTS_TABLE_NAME,
71
+ strlen(OBJECTS_TABLE_NAME));
72
+ if (!objects)
73
+ objects = grn_table_create(context,
74
+ OBJECTS_TABLE_NAME,
75
+ strlen(OBJECTS_TABLE_NAME),
76
+ NULL,
77
+ GRN_OBJ_TABLE_HASH_KEY,
78
+ grn_ctx_at(context, GRN_DB_UINT64),
79
+ 0);
80
+
81
+ grn_table_add(context, objects,
82
+ &object, sizeof(RbGrnObject *),
83
+ NULL);
84
+ }
85
+
86
+ void
87
+ rb_grn_context_unregister (grn_ctx *context, RbGrnObject *object)
88
+ {
89
+ grn_obj *objects;
90
+
91
+ if (!grn_ctx_db(context))
92
+ return;
93
+
94
+ objects = grn_ctx_get(context,
95
+ OBJECTS_TABLE_NAME,
96
+ strlen(OBJECTS_TABLE_NAME));
97
+ if (!objects)
98
+ return;
99
+
100
+ grn_table_delete(context, objects, &object, sizeof(RbGrnObject *));
101
+ }
102
+
103
+ void
104
+ rb_grn_context_unbind (grn_ctx *context)
105
+ {
106
+ grn_obj *database;
107
+ grn_obj *objects;
108
+
109
+ database = grn_ctx_db(context);
110
+ if (!database)
111
+ return;
112
+
113
+ objects = grn_ctx_get(context,
114
+ OBJECTS_TABLE_NAME,
115
+ strlen(OBJECTS_TABLE_NAME));
116
+ if (objects) {
117
+ grn_table_cursor *cursor;
118
+
119
+ cursor = grn_table_cursor_open(context, objects, NULL, 0, NULL, 0, 0);
120
+ while (grn_table_cursor_next(context, cursor) != GRN_ID_NIL) {
121
+ void *value;
122
+ RbGrnObject *object = NULL;
123
+ grn_table_cursor_get_key(context, cursor, &value);
124
+ memcpy(&object, value, sizeof(RbGrnObject *));
125
+ object->object = NULL;
126
+ object->unbind(object);
127
+ }
128
+ grn_table_cursor_close(context, cursor);
129
+ grn_obj_close(context, objects);
130
+ }
131
+
132
+ grn_obj_close(context, database);
133
+ grn_ctx_use(context, NULL);
134
+ }
135
+
40
136
  static void
41
137
  rb_grn_context_free (void *pointer)
42
138
  {
43
139
  grn_ctx *context = pointer;
44
140
 
45
- if (context->stat != GRN_CTX_FIN)
141
+ if (context->stat != GRN_CTX_FIN) {
142
+ rb_grn_context_unbind (context);
46
143
  grn_ctx_fin(context);
144
+ }
47
145
  xfree(context);
48
146
  }
49
147
 
@@ -66,21 +164,21 @@ rb_grn_context_to_exception (grn_ctx *context, VALUE related_object)
66
164
  exception_class = rb_grn_rc_to_exception(context->rc);
67
165
  message = rb_grn_rc_to_message(context->rc);
68
166
 
69
- grn_bulk_init(context, &bulk, 0);
70
- GRN_BULK_PUTS(context, &bulk, message);
71
- GRN_BULK_PUTS(context, &bulk, ": ");
72
- GRN_BULK_PUTS(context, &bulk, context->errbuf);
167
+ GRN_OBJ_INIT(&bulk, GRN_BULK, 0, GRN_ID_NIL);
168
+ GRN_TEXT_PUTS(context, &bulk, message);
169
+ GRN_TEXT_PUTS(context, &bulk, ": ");
170
+ GRN_TEXT_PUTS(context, &bulk, context->errbuf);
73
171
  if (!NIL_P(related_object)) {
74
- GRN_BULK_PUTS(context, &bulk, ": ");
75
- GRN_BULK_PUTS(context, &bulk, rb_grn_inspect(related_object));
172
+ GRN_TEXT_PUTS(context, &bulk, ": ");
173
+ GRN_TEXT_PUTS(context, &bulk, rb_grn_inspect(related_object));
76
174
  }
77
- GRN_BULK_PUTS(context, &bulk, "\n");
78
- GRN_BULK_PUTS(context, &bulk, context->errfile);
79
- GRN_BULK_PUTS(context, &bulk, ":");
80
- grn_bulk_itoa(context, &bulk, context->errline);
81
- GRN_BULK_PUTS(context, &bulk, ": ");
82
- GRN_BULK_PUTS(context, &bulk, context->errfunc);
83
- GRN_BULK_PUTS(context, &bulk, "()");
175
+ GRN_TEXT_PUTS(context, &bulk, "\n");
176
+ GRN_TEXT_PUTS(context, &bulk, context->errfile);
177
+ GRN_TEXT_PUTS(context, &bulk, ":");
178
+ grn_text_itoa(context, &bulk, context->errline);
179
+ GRN_TEXT_PUTS(context, &bulk, ": ");
180
+ GRN_TEXT_PUTS(context, &bulk, context->errfunc);
181
+ GRN_TEXT_PUTS(context, &bulk, "()");
84
182
  exception = rb_funcall(exception_class, rb_intern("new"), 1,
85
183
  rb_str_new(GRN_BULK_HEAD(&bulk),
86
184
  GRN_BULK_VSIZE(&bulk)));
@@ -102,13 +200,24 @@ rb_grn_context_check (grn_ctx *context, VALUE related_object)
102
200
  }
103
201
 
104
202
  grn_ctx *
105
- rb_grn_context_ensure (VALUE context)
203
+ rb_grn_context_ensure (VALUE *context)
106
204
  {
107
- if (NIL_P(context))
108
- context = rb_grn_context_get_default();
109
- return SELF(context);
205
+ if (NIL_P(*context))
206
+ *context = rb_grn_context_get_default();
207
+ return SELF(*context);
110
208
  }
111
209
 
210
+ /*
211
+ * call-seq:
212
+ * Groonga::Context.default -> Groonga::Context
213
+ *
214
+ * デフォルトのコンテキストを返す。デフォルトのコンテキスト
215
+ * が作成されていない場合は暗黙のうちに作成し、それを返す。
216
+ *
217
+ * 暗黙のうちにコンテキストを作成する場合は、
218
+ * Groonga::Context.default_optionsに設定されているオプショ
219
+ * ンを利用する。
220
+ */
112
221
  static VALUE
113
222
  rb_grn_context_s_get_default (VALUE self)
114
223
  {
@@ -128,6 +237,15 @@ rb_grn_context_get_default (void)
128
237
  return rb_grn_context_s_get_default(cGrnContext);
129
238
  }
130
239
 
240
+ /*
241
+ * call-seq:
242
+ * Groonga::Context.default=(context)
243
+ *
244
+ * デフォルトのコンテキストを設定する。+nil+を指定すると、デ
245
+ * フォルトのコンテキストをリセットする。リセットすると、次
246
+ * 回Groonga::Context.defaultを呼び出したときに新しくコンテ
247
+ * キストが作成される。
248
+ */
131
249
  static VALUE
132
250
  rb_grn_context_s_set_default (VALUE self, VALUE context)
133
251
  {
@@ -135,12 +253,27 @@ rb_grn_context_s_set_default (VALUE self, VALUE context)
135
253
  return Qnil;
136
254
  }
137
255
 
256
+ /*
257
+ * call-seq:
258
+ * Groonga::Context.default_options -> Hash or nil
259
+ *
260
+ * コンテキストを作成する時に利用するデフォルトのオプション
261
+ * を返す。
262
+ */
138
263
  static VALUE
139
264
  rb_grn_context_s_get_default_options (VALUE self)
140
265
  {
141
266
  return rb_cv_get(self, "@@default_options");
142
267
  }
143
268
 
269
+ /*
270
+ * call-seq:
271
+ * Groonga::Context.default_options=(options)
272
+ *
273
+ * コンテキストを作成する時に利用するデフォルトのオプション
274
+ * を設定する。利用可能なオプションは
275
+ * Groonga::Context.newを参照。
276
+ */
144
277
  static VALUE
145
278
  rb_grn_context_s_set_default_options (VALUE self, VALUE options)
146
279
  {
@@ -148,6 +281,17 @@ rb_grn_context_s_set_default_options (VALUE self, VALUE options)
148
281
  return Qnil;
149
282
  }
150
283
 
284
+ /*
285
+ * call-seq:
286
+ * Groonga::Context.new(options=nil)
287
+ *
288
+ * コンテキストを作成する。_options_に指定可能な値は以下の通
289
+ * り。
290
+ *
291
+ * [+:encoding+]
292
+ * エンコーディングを指定する。エンコーディングの指定方法
293
+ * はGroonga::Encodingを参照。
294
+ */
151
295
  static VALUE
152
296
  rb_grn_context_initialize (int argc, VALUE *argv, VALUE self)
153
297
  {
@@ -155,7 +299,7 @@ rb_grn_context_initialize (int argc, VALUE *argv, VALUE self)
155
299
  int flags = 0;
156
300
  grn_rc rc;
157
301
  VALUE options, default_options;
158
- VALUE use_ql, batch_mode, rb_encoding;
302
+ VALUE rb_encoding;
159
303
 
160
304
  rb_scan_args(argc, argv, "01", &options);
161
305
  default_options = rb_grn_context_s_get_default_options(rb_obj_class(self));
@@ -167,16 +311,9 @@ rb_grn_context_initialize (int argc, VALUE *argv, VALUE self)
167
311
  options = rb_funcall(default_options, rb_intern("merge"), 1, options);
168
312
 
169
313
  rb_grn_scan_options(options,
170
- "use_ql", &use_ql,
171
- "batch_mode", &batch_mode,
172
314
  "encoding", &rb_encoding,
173
315
  NULL);
174
316
 
175
- if (RVAL2CBOOL(use_ql))
176
- flags |= GRN_CTX_USE_QL;
177
- if (RVAL2CBOOL(batch_mode))
178
- flags |= GRN_CTX_BATCH_MODE;
179
-
180
317
  context = ALLOC(grn_ctx);
181
318
  DATA_PTR(self) = context;
182
319
  rc = grn_ctx_init(context, flags);
@@ -192,6 +329,12 @@ rb_grn_context_initialize (int argc, VALUE *argv, VALUE self)
192
329
  return Qnil;
193
330
  }
194
331
 
332
+ /*
333
+ * call-seq:
334
+ * context.inspect -> String
335
+ *
336
+ * コンテキストの中身を人に見やすい文字列で返す。
337
+ */
195
338
  static VALUE
196
339
  rb_grn_context_inspect (VALUE self)
197
340
  {
@@ -206,20 +349,6 @@ rb_grn_context_inspect (VALUE self)
206
349
  rb_str_concat(inspected, rb_inspect(rb_obj_class(self)));
207
350
  rb_str_cat2(inspected, " ");
208
351
 
209
- rb_str_cat2(inspected, "use_ql: <");
210
- if (context->flags & GRN_CTX_USE_QL)
211
- rb_str_cat2(inspected, "true");
212
- else
213
- rb_str_cat2(inspected, "false");
214
- rb_str_cat2(inspected, ">, ");
215
-
216
- rb_str_cat2(inspected, "batch_mode: <");
217
- if (context->flags & GRN_CTX_BATCH_MODE)
218
- rb_str_cat2(inspected, "true");
219
- else
220
- rb_str_cat2(inspected, "false");
221
- rb_str_cat2(inspected, ">, ");
222
-
223
352
  rb_str_cat2(inspected, "encoding: <");
224
353
  rb_str_concat(inspected, rb_inspect(GRNENCODING2RVAL(context->encoding)));
225
354
  rb_str_cat2(inspected, ">, ");
@@ -234,24 +363,25 @@ rb_grn_context_inspect (VALUE self)
234
363
  return inspected;
235
364
  }
236
365
 
237
- static VALUE
238
- rb_grn_context_use_ql_p (VALUE self)
239
- {
240
- return CBOOL2RVAL(SELF(self)->flags & GRN_CTX_USE_QL);
241
- }
242
-
243
- static VALUE
244
- rb_grn_context_batch_mode_p (VALUE self)
245
- {
246
- return CBOOL2RVAL(SELF(self)->flags & GRN_CTX_BATCH_MODE);
247
- }
248
-
366
+ /*
367
+ * call-seq:
368
+ * context.encoding -> Groonga::Encoding
369
+ *
370
+ * コンテキストが使うエンコーディングを返す。
371
+ */
249
372
  static VALUE
250
373
  rb_grn_context_get_encoding (VALUE self)
251
374
  {
252
375
  return GRNENCODING2RVAL(GRN_CTX_GET_ENCODING(SELF(self)));
253
376
  }
254
377
 
378
+ /*
379
+ * call-seq:
380
+ * context.encoding=(encoding)
381
+ *
382
+ * コンテキストが使うエンコーディングを設定する。エンコーディ
383
+ * ングの指定のしかたはGroonga::Encodingを参照。
384
+ */
255
385
  static VALUE
256
386
  rb_grn_context_set_encoding (VALUE self, VALUE rb_encoding)
257
387
  {
@@ -265,6 +395,12 @@ rb_grn_context_set_encoding (VALUE self, VALUE rb_encoding)
265
395
  return rb_encoding;
266
396
  }
267
397
 
398
+ /*
399
+ * call-seq:
400
+ * context.database -> Groonga::Database
401
+ *
402
+ * コンテキストが使うデータベースを返す。
403
+ */
268
404
  static VALUE
269
405
  rb_grn_context_get_database (VALUE self)
270
406
  {
@@ -274,6 +410,19 @@ rb_grn_context_get_database (VALUE self)
274
410
  return GRNDB2RVAL(context, grn_ctx_db(context), RB_GRN_FALSE);
275
411
  }
276
412
 
413
+ /*
414
+ * call-seq:
415
+ * context[name] -> Groonga::Object or nil
416
+ * context[id] -> Groonga::Object or nil
417
+ *
418
+ * コンテキスト管理下にあるオブジェクトを返す。
419
+ *
420
+ * _name_として文字列を指定した場合はオブジェクト名でオブジェ
421
+ * クトを検索する。
422
+ *
423
+ * _id_として数値を指定した場合はオブジェクトIDでオブジェク
424
+ * トを検索する。
425
+ */
277
426
  static VALUE
278
427
  rb_grn_context_array_reference (VALUE self, VALUE name_or_id)
279
428
  {
@@ -287,11 +436,11 @@ rb_grn_context_array_reference (VALUE self, VALUE name_or_id)
287
436
 
288
437
  name = StringValuePtr(name_or_id);
289
438
  name_size = RSTRING_LEN(name_or_id);
290
- object = grn_ctx_lookup(context, name, name_size);
439
+ object = grn_ctx_get(context, name, name_size);
291
440
  } else if (RVAL2CBOOL(rb_obj_is_kind_of(name_or_id, rb_cInteger))) {
292
441
  unsigned id;
293
442
  id = NUM2UINT(name_or_id);
294
- object = grn_ctx_get(context, id);
443
+ object = grn_ctx_at(context, id);
295
444
  } else {
296
445
  rb_raise(rb_eArgError, "should be string or unsigned integer: %s",
297
446
  rb_grn_inspect(name_or_id));
@@ -322,8 +471,6 @@ rb_grn_init_context (VALUE mGrn)
322
471
 
323
472
  rb_define_method(cGrnContext, "inspect", rb_grn_context_inspect, 0);
324
473
 
325
- rb_define_method(cGrnContext, "use_ql?", rb_grn_context_use_ql_p, 0);
326
- rb_define_method(cGrnContext, "batch_mode?", rb_grn_context_batch_mode_p, 0);
327
474
  rb_define_method(cGrnContext, "encoding", rb_grn_context_get_encoding, 0);
328
475
  rb_define_method(cGrnContext, "encoding=", rb_grn_context_set_encoding, 1);
329
476
 
@@ -18,10 +18,21 @@
18
18
 
19
19
  #include "rb-grn.h"
20
20
 
21
- #define SELF(object) (RVAL2GRNDB(object))
21
+ #define SELF(object) ((RbGrnObject *)DATA_PTR(object))
22
22
 
23
23
  VALUE rb_cGrnDatabase;
24
24
 
25
+ /*
26
+ * Document-class: Groonga::Database
27
+ *
28
+ * テーブルの集合を管理するためのオブジェクト。
29
+ *
30
+ * コンテキストに結びつけて使用する。通常、アプリケーション
31
+ * 毎に1つのコンテキストを利用するので、データベースも1つだ
32
+ * け利用する。コンテキストと違い、データベースは暗黙のうち
33
+ * に作成されないので明示的に作成する必要がある。
34
+ */
35
+
25
36
  grn_obj *
26
37
  rb_grn_database_from_ruby_object (VALUE object)
27
38
  {
@@ -39,6 +50,31 @@ rb_grn_database_to_ruby_object (grn_ctx *context, grn_obj *database,
39
50
  return GRNOBJECT2RVAL(rb_cGrnDatabase, context, database, owner);
40
51
  }
41
52
 
53
+ /*
54
+ * call-seq:
55
+ * Groonga::Database.create(options=nil) -> Groonga::Database
56
+ *
57
+ * 新しくデータベースを作成する。
58
+ *
59
+ * _options_にはハッシュでオプションを指定する。指定できるオ
60
+ * プションは以下の通り。
61
+ *
62
+ * [+:path+]
63
+ * データベースを保存するパス。省略すると一時データベース
64
+ * となる。
65
+ *
66
+ * [+:context+]
67
+ * データベースを結びつけるコンテキスト。省略すると
68
+ * Groonga::Context.defaultを利用する。
69
+ *
70
+ * 使用例は以下の通り。
71
+ *
72
+ * 一時データベースを作成:
73
+ * Groonga::Database.create
74
+ *
75
+ * 永続データベースを作成:
76
+ * Groonga::Database.create(:path => "/tmp/db.groonga")
77
+ */
42
78
  static VALUE
43
79
  rb_grn_database_s_create (int argc, VALUE *argv, VALUE klass)
44
80
  {
@@ -59,14 +95,17 @@ rb_grn_database_s_create (int argc, VALUE *argv, VALUE klass)
59
95
 
60
96
  if (!NIL_P(rb_path))
61
97
  path = StringValuePtr(rb_path);
62
- context = rb_grn_context_ensure(rb_context);
98
+ context = rb_grn_context_ensure(&rb_context);
63
99
 
64
100
  create_args.builtin_type_names = NULL;
65
101
  create_args.n_builtin_type_names = 0;
66
102
 
67
103
  database = grn_db_create(context, path, &create_args);
68
104
  rb_grn_context_check(context, rb_ary_new4(argc, argv));
69
- rb_database = GRNOBJECT2RVAL(klass, context, database, RB_GRN_FALSE);
105
+ rb_database = rb_grn_object_alloc(klass);
106
+ rb_grn_object_assign(rb_database, rb_context, context,
107
+ database, RB_GRN_TRUE);
108
+ rb_iv_set(rb_database, "context", rb_context);
70
109
  rb_grn_context_check(context, rb_ary_new4(argc, argv));
71
110
 
72
111
  if (rb_block_given_p())
@@ -76,6 +115,22 @@ rb_grn_database_s_create (int argc, VALUE *argv, VALUE klass)
76
115
  return rb_database;
77
116
  }
78
117
 
118
+ /*
119
+ * call-seq:
120
+ * Groonga::Database.new(path, options=nil) -> Groonga::Database
121
+ * Groonga::Database.new(path, options=nil) {|database| ...}
122
+ *
123
+ * 既存のデータベースを開く。ブロックを指定した場合はブロッ
124
+ * クに開いたデータベースを渡し、ブロックを抜けるときに閉じ
125
+ * る。
126
+ *
127
+ * _options_にはハッシュでオプションを指定する。指定できるオ
128
+ * プションは以下の通り。
129
+ *
130
+ * [+:context+]
131
+ * データベースを結びつけるコンテキスト。省略すると
132
+ * Groonga::Context.defaultを利用する。
133
+ */
79
134
  static VALUE
80
135
  rb_grn_database_initialize (int argc, VALUE *argv, VALUE self)
81
136
  {
@@ -91,15 +146,31 @@ rb_grn_database_initialize (int argc, VALUE *argv, VALUE self)
91
146
  "context", &rb_context,
92
147
  NULL);
93
148
 
94
- context = rb_grn_context_ensure(rb_context);
149
+ context = rb_grn_context_ensure(&rb_context);
95
150
 
96
151
  database = grn_db_open(context, path);
97
- rb_grn_object_initialize(self, context, database);
152
+ rb_grn_object_assign(self, rb_context, context, database, RB_GRN_TRUE);
98
153
  rb_grn_context_check(context, self);
99
154
 
100
155
  return Qnil;
101
156
  }
102
157
 
158
+ /*
159
+ * call-seq:
160
+ * Groonga::Database.open(path, options=nil) -> Groonga::Database
161
+ * Groonga::Database.open(path, options=nil) {|database| ...}
162
+ *
163
+ * 既存のデータベースを開く。ブロックを指定した場合はブロッ
164
+ * クに開いたデータベースを渡し、ブロックを抜けるときに閉じ
165
+ * る。
166
+ *
167
+ * _options_にはハッシュでオプションを指定する。指定できるオ
168
+ * プションは以下の通り。
169
+ *
170
+ * [+:context+]
171
+ * データベースを結びつけるコンテキスト。省略すると
172
+ * Groonga::Context.defaultを利用する。
173
+ */
103
174
  static VALUE
104
175
  rb_grn_database_s_open (int argc, VALUE *argv, VALUE klass)
105
176
  {
@@ -113,10 +184,50 @@ rb_grn_database_s_open (int argc, VALUE *argv, VALUE klass)
113
184
  return database;
114
185
  }
115
186
 
187
+ /*
188
+ * call-seq:
189
+ * database.each {|object| ...}
190
+ *
191
+ * データベース内のオブジェクトを順番にブロックに渡す。
192
+ *
193
+ * すべてのオブジェクトの名前を表示する:
194
+ * database.each do |object|
195
+ * p object.name
196
+ * end
197
+ */
198
+ static VALUE
199
+ rb_grn_database_each (VALUE self)
200
+ {
201
+ grn_ctx *context = NULL;
202
+ grn_obj *database;
203
+ grn_table_cursor *cursor;
204
+ VALUE rb_cursor;
205
+ grn_id id;
206
+
207
+ rb_grn_object_deconstruct((RbGrnObject *)SELF(self), &database, &context,
208
+ NULL, NULL, NULL, NULL);
209
+ cursor = grn_table_cursor_open(context, database, NULL, 0, NULL, 0, 0);
210
+ rb_cursor = GRNTABLECURSOR2RVAL(Qnil, context, cursor);
211
+ rb_iv_set(self, "cursor", rb_cursor);
212
+ while ((id = grn_table_cursor_next(context, cursor)) != GRN_ID_NIL) {
213
+ grn_obj *object;
214
+
215
+ object = grn_ctx_at(context, id);
216
+ if (object)
217
+ rb_yield(GRNOBJECT2RVAL(Qnil, context, object, RB_GRN_FALSE));
218
+ }
219
+ rb_grn_table_cursor_close(rb_cursor);
220
+ rb_iv_set(self, "cursor", Qnil);
221
+
222
+ return Qnil;
223
+ }
224
+
116
225
  void
117
226
  rb_grn_init_database (VALUE mGrn)
118
227
  {
119
228
  rb_cGrnDatabase = rb_define_class_under(mGrn, "Database", rb_cGrnObject);
229
+ rb_include_module(rb_cGrnDatabase, rb_mEnumerable);
230
+ rb_include_module(rb_cGrnDatabase, rb_mGrnEncodingSupport);
120
231
 
121
232
  rb_define_singleton_method(rb_cGrnDatabase, "create",
122
233
  rb_grn_database_s_create, -1);
@@ -125,4 +236,7 @@ rb_grn_init_database (VALUE mGrn)
125
236
 
126
237
  rb_define_method(rb_cGrnDatabase, "initialize",
127
238
  rb_grn_database_initialize, -1);
239
+
240
+ rb_define_method(rb_cGrnDatabase, "each",
241
+ rb_grn_database_each, 0);
128
242
  }
@@ -0,0 +1,64 @@
1
+ /* -*- c-file-style: "ruby" -*- */
2
+ /*
3
+ Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
4
+
5
+ This library is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU Lesser General Public
7
+ License version 2.1 as published by the Free Software Foundation.
8
+
9
+ This library is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ Lesser General Public License for more details.
13
+
14
+ You should have received a copy of the GNU Lesser General Public
15
+ License along with this library; if not, write to the Free Software
16
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ */
18
+
19
+ #include "rb-grn.h"
20
+
21
+ #define SELF(object) (RB_GRN_OBJECT(DATA_PTR(object)))
22
+
23
+ VALUE rb_mGrnEncodingSupport;
24
+
25
+ /*
26
+ * Document-module: Groonga::EncodingSupport
27
+ *
28
+ * オブジェクトにエンコーディング関連の機能を提供するモジュー
29
+ * ル。
30
+ */
31
+
32
+ /*
33
+ * call-seq:
34
+ * object.encoding -> エンコーディング
35
+ *
36
+ * オブジェクトのエンコーディングを返す。
37
+ */
38
+ static VALUE
39
+ rb_grn_encoding_support_get_encoding (VALUE self)
40
+ {
41
+ grn_ctx *context = NULL;
42
+ grn_obj *object = NULL;
43
+ grn_obj *encoding_value;
44
+ grn_encoding encoding;
45
+
46
+ rb_grn_object_deconstruct(SELF(self), &object, &context,
47
+ NULL, NULL, NULL, NULL);
48
+ encoding_value = grn_obj_get_info(context, object, GRN_INFO_ENCODING, NULL);
49
+ rb_grn_context_check(context, self);
50
+
51
+ memcpy(&encoding, GRN_BULK_HEAD(encoding_value), sizeof(encoding));
52
+ grn_obj_close(context, encoding_value);
53
+
54
+ return GRNENCODING2RVAL(encoding);
55
+ }
56
+
57
+ void
58
+ rb_grn_init_encoding_support (VALUE mGrn)
59
+ {
60
+ rb_mGrnEncodingSupport = rb_define_module_under(mGrn, "EncodingSupport");
61
+
62
+ rb_define_method(rb_mGrnEncodingSupport, "encoding",
63
+ rb_grn_encoding_support_get_encoding, 0);
64
+ }