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.
- data/NEWS.ja.rdoc +18 -3
- data/NEWS.rdoc +18 -3
- data/README.ja.rdoc +2 -0
- data/README.rdoc +2 -0
- data/Rakefile +14 -5
- data/TUTORIAL.ja.rdoc +82 -16
- data/benchmark/{read-write-small-many-items.rb → read-write-many-small-items.rb} +26 -23
- data/benchmark/{write-small-many-items.rb → write-many-small-items.rb} +26 -23
- data/example/bookmark.rb +49 -5
- data/ext/rb-grn-array.c +11 -1
- data/ext/rb-grn-column.c +132 -5
- data/ext/rb-grn-context.c +85 -80
- data/ext/rb-grn-database.c +182 -9
- data/ext/rb-grn-expression-builder.c +69 -0
- data/ext/rb-grn-expression.c +314 -0
- data/ext/rb-grn-fix-size-column.c +68 -89
- data/ext/rb-grn-hash.c +14 -5
- data/ext/rb-grn-index-column.c +14 -55
- data/ext/rb-grn-object.c +206 -75
- data/ext/rb-grn-operation.c +92 -0
- data/ext/rb-grn-patricia-trie.c +10 -32
- data/ext/rb-grn-query.c +9 -9
- data/ext/rb-grn-table-cursor.c +19 -80
- data/ext/rb-grn-table-key-support.c +33 -39
- data/ext/rb-grn-table.c +436 -79
- data/ext/rb-grn-type.c +10 -3
- data/ext/rb-grn-utils.c +131 -4
- data/ext/rb-grn-variable-size-column.c +36 -0
- data/ext/rb-grn-variable.c +90 -0
- data/ext/rb-grn.h +109 -56
- data/ext/rb-groonga.c +4 -0
- data/extconf.rb +39 -13
- data/html/index.html +2 -2
- data/lib/groonga.rb +22 -0
- data/lib/groonga/expression-builder.rb +141 -0
- data/lib/groonga/record.rb +25 -1
- data/lib/groonga/schema.rb +418 -0
- data/test/test-column.rb +11 -23
- data/test/test-context.rb +1 -1
- data/test/test-database.rb +60 -19
- data/test/test-expression-builder.rb +114 -0
- data/test/test-expression.rb +55 -0
- data/test/test-fix-size-column.rb +53 -0
- data/test/test-hash.rb +10 -3
- data/test/test-index-column.rb +24 -0
- data/test/test-patricia-trie.rb +9 -0
- data/test/test-procedure.rb +5 -5
- data/test/test-record.rb +71 -4
- data/test/test-schema.rb +207 -0
- data/test/test-table.rb +94 -12
- data/test/test-type.rb +18 -11
- data/test/test-variable-size-column.rb +53 -0
- data/test/test-variable.rb +28 -0
- metadata +18 -5
data/ext/rb-grn-array.c
CHANGED
@@ -65,6 +65,11 @@ VALUE rb_cGrnArray;
|
|
65
65
|
* [+:value_size+]
|
66
66
|
* 値の大きさを指定する。省略すると0になる。
|
67
67
|
*
|
68
|
+
* [+:sub_records+]
|
69
|
+
* +true+を指定すると#groupでグループ化したときに、
|
70
|
+
* <tt>record[".:nsubrecs"]</tt>でグループに含まれるレコー
|
71
|
+
* ドの件数を取得できる。
|
72
|
+
*
|
68
73
|
* 使用例:
|
69
74
|
*
|
70
75
|
* 無名一時テーブルを生成する。
|
@@ -92,7 +97,7 @@ rb_grn_array_s_create (int argc, VALUE *argv, VALUE klass)
|
|
92
97
|
grn_obj_flags flags = GRN_TABLE_NO_KEY;
|
93
98
|
VALUE rb_table;
|
94
99
|
VALUE options, rb_context, rb_name, rb_path, rb_persistent;
|
95
|
-
VALUE rb_value_size;
|
100
|
+
VALUE rb_value_size, rb_sub_records;
|
96
101
|
|
97
102
|
rb_scan_args(argc, argv, "01", &options);
|
98
103
|
|
@@ -102,6 +107,7 @@ rb_grn_array_s_create (int argc, VALUE *argv, VALUE klass)
|
|
102
107
|
"path", &rb_path,
|
103
108
|
"persistent", &rb_persistent,
|
104
109
|
"value_size", &rb_value_size,
|
110
|
+
"sub_records", &rb_sub_records,
|
105
111
|
NULL);
|
106
112
|
|
107
113
|
context = rb_grn_context_ensure(&rb_context);
|
@@ -109,6 +115,7 @@ rb_grn_array_s_create (int argc, VALUE *argv, VALUE klass)
|
|
109
115
|
if (!NIL_P(rb_name)) {
|
110
116
|
name = StringValuePtr(rb_name);
|
111
117
|
name_size = RSTRING_LEN(rb_name);
|
118
|
+
flags |= GRN_OBJ_PERSISTENT;
|
112
119
|
}
|
113
120
|
|
114
121
|
if (!NIL_P(rb_path)) {
|
@@ -122,6 +129,9 @@ rb_grn_array_s_create (int argc, VALUE *argv, VALUE klass)
|
|
122
129
|
if (!NIL_P(rb_value_size))
|
123
130
|
value_size = NUM2UINT(rb_value_size);
|
124
131
|
|
132
|
+
if (RVAL2CBOOL(rb_sub_records))
|
133
|
+
flags |= GRN_OBJ_WITH_SUBREC;
|
134
|
+
|
125
135
|
table = grn_table_create(context, name, name_size, path,
|
126
136
|
flags, NULL, value_size);
|
127
137
|
if (!table)
|
data/ext/rb-grn-column.c
CHANGED
@@ -21,7 +21,6 @@
|
|
21
21
|
#define SELF(object) ((RbGrnColumn *)DATA_PTR(object))
|
22
22
|
|
23
23
|
VALUE rb_cGrnColumn;
|
24
|
-
VALUE rb_cGrnVarSizeColumn;
|
25
24
|
|
26
25
|
/*
|
27
26
|
* Document-class: Groonga::Column < Groonga::Object
|
@@ -33,7 +32,7 @@ VALUE rb_cGrnVarSizeColumn;
|
|
33
32
|
* カラムには大きく分けて3種類ある。
|
34
33
|
* [Groonga::FixSizeColumn]
|
35
34
|
* 固定長のデータを格納するカラム。
|
36
|
-
* [Groonga::
|
35
|
+
* [Groonga::VariableSizeColumn]
|
37
36
|
* 可変長のデータを格納するカラム。
|
38
37
|
* [Groonga::IndexColumn]
|
39
38
|
* 転置インデックスを格納するカラム。全文検索や参照元レコー
|
@@ -65,6 +64,49 @@ rb_grn_column_to_ruby_object (VALUE klass, grn_ctx *context, grn_obj *column,
|
|
65
64
|
return GRNOBJECT2RVAL(klass, context, column, owner);
|
66
65
|
}
|
67
66
|
|
67
|
+
void
|
68
|
+
rb_grn_column_bind (RbGrnColumn *rb_column,
|
69
|
+
grn_ctx *context, grn_obj *column)
|
70
|
+
{
|
71
|
+
RbGrnObject *rb_grn_object;
|
72
|
+
|
73
|
+
rb_grn_object = RB_GRN_OBJECT(rb_column);
|
74
|
+
|
75
|
+
rb_column->value = grn_obj_open(context, GRN_BULK, 0,
|
76
|
+
rb_grn_object->range_id);
|
77
|
+
}
|
78
|
+
|
79
|
+
void
|
80
|
+
rb_grn_column_finalizer (grn_ctx *context, grn_obj *grn_object,
|
81
|
+
RbGrnColumn *rb_column)
|
82
|
+
{
|
83
|
+
if (context && rb_column->value)
|
84
|
+
grn_obj_close(context, rb_column->value);
|
85
|
+
rb_column->value = NULL;
|
86
|
+
}
|
87
|
+
|
88
|
+
void
|
89
|
+
rb_grn_column_deconstruct (RbGrnColumn *rb_column,
|
90
|
+
grn_obj **column,
|
91
|
+
grn_ctx **context,
|
92
|
+
grn_id *domain_id,
|
93
|
+
grn_obj **domain,
|
94
|
+
grn_obj **value,
|
95
|
+
grn_id *range_id,
|
96
|
+
grn_obj **range)
|
97
|
+
{
|
98
|
+
RbGrnObject *rb_grn_object;
|
99
|
+
|
100
|
+
rb_grn_object = RB_GRN_OBJECT(rb_column);
|
101
|
+
rb_grn_object_deconstruct(rb_grn_object, column, context,
|
102
|
+
domain_id, domain,
|
103
|
+
range_id, range);
|
104
|
+
|
105
|
+
if (value)
|
106
|
+
*value = rb_column->value;
|
107
|
+
}
|
108
|
+
|
109
|
+
|
68
110
|
/*
|
69
111
|
* call-seq:
|
70
112
|
* column.table -> Groonga::Table
|
@@ -87,16 +129,101 @@ rb_grn_column_get_table (VALUE self)
|
|
87
129
|
return GRNOBJECT2RVAL(Qnil, context, table, RB_GRN_FALSE);
|
88
130
|
}
|
89
131
|
|
132
|
+
/*
|
133
|
+
* call-seq:
|
134
|
+
* column.local_name
|
135
|
+
*
|
136
|
+
* テーブル名を除いたカラム名を返す。
|
137
|
+
*
|
138
|
+
* items = Groonga::Array.create(:name => "<items>")
|
139
|
+
* title = items.define_column("title", "<shorttext>")
|
140
|
+
* title.name # => "<items>.title"
|
141
|
+
* title.local_name # => "title"
|
142
|
+
*/
|
143
|
+
static VALUE
|
144
|
+
rb_grn_column_get_local_name (VALUE self)
|
145
|
+
{
|
146
|
+
grn_ctx *context = NULL;
|
147
|
+
grn_obj *column;
|
148
|
+
int name_size;
|
149
|
+
VALUE rb_name;
|
150
|
+
|
151
|
+
rb_grn_object_deconstruct((RbGrnObject *)(SELF(self)), &column, &context,
|
152
|
+
NULL, NULL,
|
153
|
+
NULL, NULL);
|
154
|
+
name_size = grn_column_name(context, column, NULL, 0);
|
155
|
+
if (name_size == 0)
|
156
|
+
return Qnil;
|
157
|
+
|
158
|
+
rb_name = rb_str_buf_new(name_size);
|
159
|
+
rb_str_set_len(rb_name, name_size);
|
160
|
+
grn_column_name(context, column, RSTRING_PTR(rb_name), name_size);
|
161
|
+
return rb_name;
|
162
|
+
}
|
163
|
+
|
164
|
+
static VALUE
|
165
|
+
rb_grn_column_select (int argc, VALUE *argv, VALUE self)
|
166
|
+
{
|
167
|
+
grn_ctx *context;
|
168
|
+
grn_obj *table, *column, *result, *expression;
|
169
|
+
grn_operator operator = GRN_OP_OR;
|
170
|
+
grn_rc rc;
|
171
|
+
VALUE options;
|
172
|
+
VALUE rb_query, rb_name, rb_operator, rb_result;
|
173
|
+
VALUE rb_expression, builder;
|
174
|
+
|
175
|
+
rb_scan_args(argc, argv, "11", &rb_query, &options);
|
176
|
+
|
177
|
+
rb_grn_column_deconstruct(SELF(self), &column, &context,
|
178
|
+
NULL, NULL,
|
179
|
+
NULL, NULL, NULL);
|
180
|
+
table = grn_column_table(context, column);
|
181
|
+
|
182
|
+
rb_grn_scan_options(options,
|
183
|
+
"operator", &rb_operator,
|
184
|
+
"result", &rb_result,
|
185
|
+
"name", &rb_name,
|
186
|
+
NULL);
|
187
|
+
|
188
|
+
if (!NIL_P(rb_operator))
|
189
|
+
operator = NUM2INT(rb_operator);
|
190
|
+
|
191
|
+
if (NIL_P(rb_result)) {
|
192
|
+
result = grn_table_create(context, NULL, 0, NULL,
|
193
|
+
GRN_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
|
194
|
+
table,
|
195
|
+
0);
|
196
|
+
rb_result = GRNTABLE2RVAL(context, result, RB_GRN_TRUE);
|
197
|
+
} else {
|
198
|
+
result = RVAL2GRNTABLE(rb_result, &context);
|
199
|
+
}
|
200
|
+
|
201
|
+
builder = rb_grn_column_expression_builder_new(self, rb_name, rb_query);
|
202
|
+
rb_expression = rb_grn_column_expression_builder_build(builder);
|
203
|
+
|
204
|
+
rb_grn_object_deconstruct(RB_GRN_OBJECT(DATA_PTR(rb_expression)),
|
205
|
+
&expression, NULL,
|
206
|
+
NULL, NULL, NULL, NULL);
|
207
|
+
|
208
|
+
rc = grn_table_select(context, table, expression, result, operator);
|
209
|
+
rb_grn_context_check(context, self);
|
210
|
+
rb_grn_rc_check(rc, self);
|
211
|
+
|
212
|
+
return rb_result;
|
213
|
+
}
|
214
|
+
|
90
215
|
void
|
91
216
|
rb_grn_init_column (VALUE mGrn)
|
92
217
|
{
|
93
218
|
rb_cGrnColumn = rb_define_class_under(mGrn, "Column", rb_cGrnObject);
|
94
219
|
|
95
|
-
rb_cGrnVarSizeColumn =
|
96
|
-
rb_define_class_under(mGrn, "VarSizeColumn", rb_cGrnColumn);
|
97
|
-
|
98
220
|
rb_define_method(rb_cGrnColumn, "table", rb_grn_column_get_table, 0);
|
221
|
+
rb_define_method(rb_cGrnColumn, "local_name",
|
222
|
+
rb_grn_column_get_local_name, 0);
|
223
|
+
|
224
|
+
rb_define_method(rb_cGrnColumn, "select", rb_grn_column_select, -1);
|
99
225
|
|
100
226
|
rb_grn_init_fix_size_column(mGrn);
|
227
|
+
rb_grn_init_variable_size_column(mGrn);
|
101
228
|
rb_grn_init_index_column(mGrn);
|
102
229
|
}
|
data/ext/rb-grn-context.c
CHANGED
@@ -20,8 +20,6 @@
|
|
20
20
|
|
21
21
|
#define SELF(object) (RVAL2GRNCONTEXT(object))
|
22
22
|
|
23
|
-
#define OBJECTS_TABLE_NAME "<ranguba:objects>"
|
24
|
-
|
25
23
|
static VALUE cGrnContext;
|
26
24
|
|
27
25
|
/*
|
@@ -58,90 +56,23 @@ rb_grn_context_from_ruby_object (VALUE object)
|
|
58
56
|
return context;
|
59
57
|
}
|
60
58
|
|
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
|
-
|
136
59
|
static void
|
137
60
|
rb_grn_context_free (void *pointer)
|
138
61
|
{
|
139
62
|
grn_ctx *context = pointer;
|
140
63
|
|
64
|
+
debug("context-free: %p\n", context);
|
141
65
|
if (context->stat != GRN_CTX_FIN) {
|
142
|
-
|
66
|
+
grn_obj *database;
|
67
|
+
|
68
|
+
database = grn_ctx_db(context);
|
69
|
+
debug("context:database: %p:%p\n", context, database);
|
70
|
+
if (database && database->header.type == GRN_DB) {
|
71
|
+
grn_obj_close(context, database);
|
72
|
+
}
|
143
73
|
grn_ctx_fin(context);
|
144
74
|
}
|
75
|
+
debug("context-free: %p: done\n", context);
|
145
76
|
xfree(context);
|
146
77
|
}
|
147
78
|
|
@@ -326,6 +257,8 @@ rb_grn_context_initialize (int argc, VALUE *argv, VALUE self)
|
|
326
257
|
GRN_CTX_SET_ENCODING(context, encoding);
|
327
258
|
}
|
328
259
|
|
260
|
+
debug("context new: %p\n", context);
|
261
|
+
|
329
262
|
return Qnil;
|
330
263
|
}
|
331
264
|
|
@@ -410,6 +343,77 @@ rb_grn_context_get_database (VALUE self)
|
|
410
343
|
return GRNDB2RVAL(context, grn_ctx_db(context), RB_GRN_FALSE);
|
411
344
|
}
|
412
345
|
|
346
|
+
static const char *
|
347
|
+
grn_type_name_old_to_new (const char *name, unsigned int name_size)
|
348
|
+
{
|
349
|
+
unsigned int i;
|
350
|
+
|
351
|
+
for (i = 0; i < name_size; i++) {
|
352
|
+
if (name[i] == '\0')
|
353
|
+
return NULL;
|
354
|
+
}
|
355
|
+
|
356
|
+
if (strcmp(name, "<int>") == 0) {
|
357
|
+
return "Int32";
|
358
|
+
} else if (strcmp(name, "<uint>") == 0) {
|
359
|
+
return "UInt32";
|
360
|
+
} else if (strcmp(name, "<int64>") == 0) {
|
361
|
+
return "Int64";
|
362
|
+
} else if (strcmp(name, "<uint64>") == 0) {
|
363
|
+
return "UInt64";
|
364
|
+
} else if (strcmp(name, "<float>") == 0) {
|
365
|
+
return "Float";
|
366
|
+
} else if (strcmp(name, "<time>") == 0) {
|
367
|
+
return "Time";
|
368
|
+
} else if (strcmp(name, "<shorttext>") == 0) {
|
369
|
+
return "ShortText";
|
370
|
+
} else if (strcmp(name, "<text>") == 0) {
|
371
|
+
return "Text";
|
372
|
+
} else if (strcmp(name, "<longtext>") == 0) {
|
373
|
+
return "LongText";
|
374
|
+
} else if (strcmp(name, "<token:delimit>") == 0) {
|
375
|
+
return "TokenDelimit";
|
376
|
+
} else if (strcmp(name, "<token:unigram>") == 0) {
|
377
|
+
return "TokenUnigram";
|
378
|
+
} else if (strcmp(name, "<token:bigram>") == 0) {
|
379
|
+
return "TokenBigram";
|
380
|
+
} else if (strcmp(name, "<token:trigram>") == 0) {
|
381
|
+
return "TokenTrigram";
|
382
|
+
} else if (strcmp(name, "<token:mecab>") == 0) {
|
383
|
+
return "TokenMecab";
|
384
|
+
}
|
385
|
+
|
386
|
+
return NULL;
|
387
|
+
}
|
388
|
+
|
389
|
+
grn_obj *
|
390
|
+
rb_grn_context_get_backward_compatibility (grn_ctx *context,
|
391
|
+
const char *name,
|
392
|
+
unsigned int name_size)
|
393
|
+
{
|
394
|
+
grn_obj *object;
|
395
|
+
|
396
|
+
object = grn_ctx_get(context, name, name_size);
|
397
|
+
if (!object) {
|
398
|
+
const char *new_type_name;
|
399
|
+
|
400
|
+
new_type_name = grn_type_name_old_to_new(name, name_size);
|
401
|
+
if (new_type_name) {
|
402
|
+
object = grn_ctx_get(context, new_type_name, strlen(new_type_name));
|
403
|
+
#if 0
|
404
|
+
if (object) {
|
405
|
+
rb_warn("deprecated old data type name <%s> is used. "
|
406
|
+
"Use new data type name <%s> instead.",
|
407
|
+
name, new_type_name);
|
408
|
+
}
|
409
|
+
#endif
|
410
|
+
}
|
411
|
+
}
|
412
|
+
|
413
|
+
return object;
|
414
|
+
}
|
415
|
+
|
416
|
+
|
413
417
|
/*
|
414
418
|
* call-seq:
|
415
419
|
* context[name] -> Groonga::Object or nil
|
@@ -432,11 +436,12 @@ rb_grn_context_array_reference (VALUE self, VALUE name_or_id)
|
|
432
436
|
context = SELF(self);
|
433
437
|
if (RVAL2CBOOL(rb_obj_is_kind_of(name_or_id, rb_cString))) {
|
434
438
|
const char *name;
|
435
|
-
unsigned name_size;
|
439
|
+
unsigned int name_size;
|
436
440
|
|
437
441
|
name = StringValuePtr(name_or_id);
|
438
442
|
name_size = RSTRING_LEN(name_or_id);
|
439
|
-
object =
|
443
|
+
object = rb_grn_context_get_backward_compatibility(context,
|
444
|
+
name, name_size);
|
440
445
|
} else if (RVAL2CBOOL(rb_obj_is_kind_of(name_or_id, rb_cInteger))) {
|
441
446
|
unsigned id;
|
442
447
|
id = NUM2UINT(name_or_id);
|
data/ext/rb-grn-database.c
CHANGED
@@ -50,6 +50,41 @@ rb_grn_database_to_ruby_object (grn_ctx *context, grn_obj *database,
|
|
50
50
|
return GRNOBJECT2RVAL(rb_cGrnDatabase, context, database, owner);
|
51
51
|
}
|
52
52
|
|
53
|
+
static void
|
54
|
+
rb_grn_database_deconstruct (RbGrnObject *rb_grn_database,
|
55
|
+
grn_obj **database,
|
56
|
+
grn_ctx **context,
|
57
|
+
grn_id *domain_id,
|
58
|
+
grn_obj **domain,
|
59
|
+
grn_id *range_id,
|
60
|
+
grn_obj **range)
|
61
|
+
{
|
62
|
+
rb_grn_object_deconstruct(rb_grn_database, database, context,
|
63
|
+
domain_id, domain,
|
64
|
+
range_id, range);
|
65
|
+
}
|
66
|
+
|
67
|
+
/*
|
68
|
+
* Document-method: close
|
69
|
+
*
|
70
|
+
* call-seq:
|
71
|
+
* database.close
|
72
|
+
*
|
73
|
+
* _database_が使用しているリソースを開放する。これ以降_database_を
|
74
|
+
* 使うことはできない。
|
75
|
+
*/
|
76
|
+
static VALUE
|
77
|
+
rb_grn_database_close (VALUE self)
|
78
|
+
{
|
79
|
+
VALUE rb_context;
|
80
|
+
|
81
|
+
rb_context = rb_iv_get(self, "context");
|
82
|
+
if (!NIL_P(rb_context))
|
83
|
+
rb_iv_set(rb_context, "database", Qnil);
|
84
|
+
|
85
|
+
return rb_grn_object_close(self);
|
86
|
+
}
|
87
|
+
|
53
88
|
/*
|
54
89
|
* call-seq:
|
55
90
|
* Groonga::Database.create(options=nil) -> Groonga::Database
|
@@ -79,7 +114,7 @@ static VALUE
|
|
79
114
|
rb_grn_database_s_create (int argc, VALUE *argv, VALUE klass)
|
80
115
|
{
|
81
116
|
grn_ctx *context;
|
82
|
-
grn_obj *database;
|
117
|
+
grn_obj *old_database, *database;
|
83
118
|
grn_db_create_optarg create_args;
|
84
119
|
const char *path = NULL;
|
85
120
|
VALUE rb_database;
|
@@ -100,17 +135,21 @@ rb_grn_database_s_create (int argc, VALUE *argv, VALUE klass)
|
|
100
135
|
create_args.builtin_type_names = NULL;
|
101
136
|
create_args.n_builtin_type_names = 0;
|
102
137
|
|
138
|
+
old_database = grn_ctx_db(context);
|
139
|
+
if (old_database)
|
140
|
+
grn_obj_close(context, old_database);
|
103
141
|
database = grn_db_create(context, path, &create_args);
|
104
142
|
rb_grn_context_check(context, rb_ary_new4(argc, argv));
|
105
143
|
rb_database = rb_grn_object_alloc(klass);
|
106
|
-
rb_grn_object_assign(rb_database, rb_context, context,
|
107
|
-
database, RB_GRN_TRUE);
|
144
|
+
rb_grn_object_assign(Qnil, rb_database, rb_context, context, database);
|
108
145
|
rb_iv_set(rb_database, "context", rb_context);
|
146
|
+
if (!NIL_P(rb_context))
|
147
|
+
rb_iv_set(rb_context, "database", rb_database);
|
109
148
|
rb_grn_context_check(context, rb_ary_new4(argc, argv));
|
110
149
|
|
111
150
|
if (rb_block_given_p())
|
112
151
|
return rb_ensure(rb_yield, rb_database,
|
113
|
-
|
152
|
+
rb_grn_database_close, rb_database);
|
114
153
|
else
|
115
154
|
return rb_database;
|
116
155
|
}
|
@@ -135,7 +174,7 @@ static VALUE
|
|
135
174
|
rb_grn_database_initialize (int argc, VALUE *argv, VALUE self)
|
136
175
|
{
|
137
176
|
grn_ctx *context;
|
138
|
-
grn_obj *database;
|
177
|
+
grn_obj *old_database, *database;
|
139
178
|
const char *path;
|
140
179
|
VALUE rb_path, options, rb_context;
|
141
180
|
|
@@ -148,10 +187,17 @@ rb_grn_database_initialize (int argc, VALUE *argv, VALUE self)
|
|
148
187
|
|
149
188
|
context = rb_grn_context_ensure(&rb_context);
|
150
189
|
|
190
|
+
old_database = grn_ctx_db(context);
|
191
|
+
if (old_database)
|
192
|
+
grn_obj_close(context, old_database);
|
151
193
|
database = grn_db_open(context, path);
|
152
|
-
rb_grn_object_assign(self, rb_context, context, database
|
194
|
+
rb_grn_object_assign(Qnil, self, rb_context, context, database);
|
153
195
|
rb_grn_context_check(context, self);
|
154
196
|
|
197
|
+
rb_iv_set(self, "context", rb_context);
|
198
|
+
if (!NIL_P(rb_context))
|
199
|
+
rb_iv_set(rb_context, "database", self);
|
200
|
+
|
155
201
|
return Qnil;
|
156
202
|
}
|
157
203
|
|
@@ -179,7 +225,7 @@ rb_grn_database_s_open (int argc, VALUE *argv, VALUE klass)
|
|
179
225
|
database = rb_grn_object_alloc(klass);
|
180
226
|
rb_grn_database_initialize(argc, argv, database);
|
181
227
|
if (rb_block_given_p())
|
182
|
-
return rb_ensure(rb_yield, database,
|
228
|
+
return rb_ensure(rb_yield, database, rb_grn_database_close, database);
|
183
229
|
else
|
184
230
|
return database;
|
185
231
|
}
|
@@ -204,8 +250,8 @@ rb_grn_database_each (VALUE self)
|
|
204
250
|
VALUE rb_cursor;
|
205
251
|
grn_id id;
|
206
252
|
|
207
|
-
|
208
|
-
|
253
|
+
rb_grn_database_deconstruct(SELF(self), &database, &context,
|
254
|
+
NULL, NULL, NULL, NULL);
|
209
255
|
cursor = grn_table_cursor_open(context, database, NULL, 0, NULL, 0, 0);
|
210
256
|
rb_cursor = GRNTABLECURSOR2RVAL(Qnil, context, cursor);
|
211
257
|
rb_iv_set(self, "cursor", rb_cursor);
|
@@ -222,6 +268,124 @@ rb_grn_database_each (VALUE self)
|
|
222
268
|
return Qnil;
|
223
269
|
}
|
224
270
|
|
271
|
+
/*
|
272
|
+
* Document-method: unlock
|
273
|
+
*
|
274
|
+
* call-seq:
|
275
|
+
* database.unlock
|
276
|
+
*
|
277
|
+
* _database_のロックを解除する。
|
278
|
+
*/
|
279
|
+
static VALUE
|
280
|
+
rb_grn_database_unlock (VALUE self)
|
281
|
+
{
|
282
|
+
grn_ctx *context;
|
283
|
+
grn_obj *database;
|
284
|
+
grn_rc rc;
|
285
|
+
|
286
|
+
rb_grn_database_deconstruct(SELF(self), &database, &context,
|
287
|
+
NULL, NULL, NULL, NULL);
|
288
|
+
|
289
|
+
rc = grn_obj_unlock(context, database, GRN_ID_NIL);
|
290
|
+
rb_grn_context_check(context, self);
|
291
|
+
rb_grn_rc_check(rc, self);
|
292
|
+
|
293
|
+
return Qnil;
|
294
|
+
}
|
295
|
+
|
296
|
+
/*
|
297
|
+
* Document-method: lock
|
298
|
+
*
|
299
|
+
* call-seq:
|
300
|
+
* database.lock(options={})
|
301
|
+
* database.lock(options={}) {...}
|
302
|
+
*
|
303
|
+
* _database_をロックする。ロックに失敗した場合は
|
304
|
+
* Groonga::ResourceDeadlockAvoided例外が発生する。
|
305
|
+
*
|
306
|
+
* ブロックを指定した場合はブロックを抜けたときにunlockする。
|
307
|
+
*
|
308
|
+
* 利用可能なオプションは以下の通り。
|
309
|
+
*
|
310
|
+
* [_:timeout_]
|
311
|
+
* ロックを獲得できなかった場合は_:timeout_秒間ロックの獲
|
312
|
+
* 得を試みる。_:timeout_秒以内にロックを獲得できなかった
|
313
|
+
* 場合は例外が発生する。
|
314
|
+
*/
|
315
|
+
static VALUE
|
316
|
+
rb_grn_database_lock (int argc, VALUE *argv, VALUE self)
|
317
|
+
{
|
318
|
+
grn_ctx *context;
|
319
|
+
grn_obj *database;
|
320
|
+
int timeout = 0;
|
321
|
+
grn_rc rc;
|
322
|
+
VALUE options, rb_timeout;
|
323
|
+
|
324
|
+
rb_scan_args(argc, argv, "01", &options);
|
325
|
+
|
326
|
+
rb_grn_database_deconstruct(SELF(self), &database, &context,
|
327
|
+
NULL, NULL, NULL, NULL);
|
328
|
+
|
329
|
+
rb_grn_scan_options(options,
|
330
|
+
"timeout", &rb_timeout,
|
331
|
+
NULL);
|
332
|
+
|
333
|
+
if (!NIL_P(rb_timeout))
|
334
|
+
timeout = NUM2UINT(rb_timeout);
|
335
|
+
|
336
|
+
rc = grn_obj_lock(context, database, GRN_ID_NIL, timeout);
|
337
|
+
rb_grn_context_check(context, self);
|
338
|
+
rb_grn_rc_check(rc, self);
|
339
|
+
|
340
|
+
if (rb_block_given_p()) {
|
341
|
+
return rb_ensure(rb_yield, Qnil, rb_grn_database_unlock, self);
|
342
|
+
} else {
|
343
|
+
return Qnil;
|
344
|
+
}
|
345
|
+
}
|
346
|
+
|
347
|
+
/*
|
348
|
+
* Document-method: clear_lock
|
349
|
+
*
|
350
|
+
* call-seq:
|
351
|
+
* database.clear_lock
|
352
|
+
*
|
353
|
+
* _database_のロックを強制的に解除する。
|
354
|
+
*/
|
355
|
+
static VALUE
|
356
|
+
rb_grn_database_clear_lock (VALUE self)
|
357
|
+
{
|
358
|
+
grn_ctx *context;
|
359
|
+
grn_obj *database;
|
360
|
+
|
361
|
+
rb_grn_database_deconstruct(SELF(self), &database, &context,
|
362
|
+
NULL, NULL, NULL, NULL);
|
363
|
+
|
364
|
+
grn_obj_clear_lock(context, database);
|
365
|
+
|
366
|
+
return Qnil;
|
367
|
+
}
|
368
|
+
|
369
|
+
/*
|
370
|
+
* Document-method: locked?
|
371
|
+
*
|
372
|
+
* call-seq:
|
373
|
+
* database.locked?
|
374
|
+
*
|
375
|
+
* _database_がロックされていれば+true+を返す。
|
376
|
+
*/
|
377
|
+
static VALUE
|
378
|
+
rb_grn_database_is_locked (VALUE self)
|
379
|
+
{
|
380
|
+
grn_ctx *context;
|
381
|
+
grn_obj *database;
|
382
|
+
|
383
|
+
rb_grn_database_deconstruct(SELF(self), &database, &context,
|
384
|
+
NULL, NULL, NULL, NULL);
|
385
|
+
|
386
|
+
return CBOOL2RVAL(grn_obj_is_locked(context, database));
|
387
|
+
}
|
388
|
+
|
225
389
|
void
|
226
390
|
rb_grn_init_database (VALUE mGrn)
|
227
391
|
{
|
@@ -239,4 +403,13 @@ rb_grn_init_database (VALUE mGrn)
|
|
239
403
|
|
240
404
|
rb_define_method(rb_cGrnDatabase, "each",
|
241
405
|
rb_grn_database_each, 0);
|
406
|
+
|
407
|
+
rb_define_method(rb_cGrnDatabase, "close",
|
408
|
+
rb_grn_database_close, 0);
|
409
|
+
|
410
|
+
rb_define_method(rb_cGrnDatabase, "lock", rb_grn_database_lock, -1);
|
411
|
+
rb_define_method(rb_cGrnDatabase, "unlock", rb_grn_database_unlock, 0);
|
412
|
+
rb_define_method(rb_cGrnDatabase, "clear_lock",
|
413
|
+
rb_grn_database_clear_lock, 0);
|
414
|
+
rb_define_method(rb_cGrnDatabase, "locked?", rb_grn_database_is_locked, 0);
|
242
415
|
}
|