groonga 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|