groonga 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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-table.c CHANGED
@@ -36,67 +36,29 @@ VALUE
36
36
  rb_grn_table_to_ruby_object (grn_ctx *context, grn_obj *table,
37
37
  rb_grn_boolean owner)
38
38
  {
39
- return GRNOBJECT2RVAL(rb_cGrnTable, context, table, owner);
39
+ return GRNOBJECT2RVAL(Qnil, context, table, owner);
40
40
  }
41
41
 
42
42
  void
43
- rb_grn_table_unbind (RbGrnTable *rb_grn_table)
43
+ rb_grn_table_finalizer (grn_ctx *context, grn_obj *object,
44
+ RbGrnTable *rb_grn_table)
44
45
  {
45
- RbGrnObject *rb_grn_object;
46
- grn_ctx *context;
47
-
48
- rb_grn_object = RB_GRN_OBJECT(rb_grn_table);
49
- context = rb_grn_object->context;
50
-
51
- if (context)
46
+ if (context && rb_grn_table->value)
52
47
  grn_obj_close(context, rb_grn_table->value);
53
-
54
- rb_grn_object_unbind(rb_grn_object);
55
- }
56
-
57
- static void
58
- rb_grn_table_free (void *object)
59
- {
60
- RbGrnTable *rb_grn_table = object;
61
-
62
- rb_grn_table_unbind(rb_grn_table);
63
- xfree(rb_grn_table);
64
- }
65
-
66
- VALUE
67
- rb_grn_table_alloc (VALUE klass)
68
- {
69
- return Data_Wrap_Struct(klass, NULL, rb_grn_table_free, NULL);
48
+ rb_grn_table->value = NULL;
70
49
  }
71
50
 
72
51
  void
73
52
  rb_grn_table_bind (RbGrnTable *rb_grn_table,
74
- grn_ctx *context, grn_obj *table, rb_grn_boolean owner)
53
+ grn_ctx *context, grn_obj *table)
75
54
  {
76
55
  RbGrnObject *rb_grn_object;
77
56
 
78
57
  rb_grn_object = RB_GRN_OBJECT(rb_grn_table);
79
- rb_grn_object_bind(rb_grn_object, context, table, owner);
80
- rb_grn_object->unbind = RB_GRN_UNBIND_FUNCTION(rb_grn_table_unbind);
81
-
82
58
  rb_grn_table->value = grn_obj_open(context, GRN_BULK, 0,
83
59
  rb_grn_object->range_id);
84
60
  }
85
61
 
86
- void
87
- rb_grn_table_assign (VALUE self, VALUE rb_context,
88
- grn_ctx *context, grn_obj *table,
89
- rb_grn_boolean owner)
90
- {
91
- RbGrnTable *rb_grn_table;
92
-
93
- rb_grn_table = ALLOC(RbGrnTable);
94
- DATA_PTR(self) = rb_grn_table;
95
- rb_grn_table_bind(rb_grn_table, context, table, owner);
96
-
97
- rb_iv_set(self, "context", rb_context);
98
- }
99
-
100
62
  void
101
63
  rb_grn_table_deconstruct (RbGrnTable *rb_grn_table,
102
64
  grn_obj **table,
@@ -118,6 +80,57 @@ rb_grn_table_deconstruct (RbGrnTable *rb_grn_table,
118
80
  *value = rb_grn_table->value;
119
81
  }
120
82
 
83
+ static void
84
+ rb_grn_table_mark (void *data)
85
+ {
86
+ RbGrnObject *rb_grn_object = data;
87
+ grn_ctx *context;
88
+ grn_obj *table;
89
+ grn_obj *column_ids;
90
+ int n;
91
+ grn_table_cursor *cursor;
92
+
93
+ context = rb_grn_object->context;
94
+ table = rb_grn_object->object;
95
+ if (!context || !table)
96
+ return;
97
+
98
+ if (!grn_obj_path(context, table))
99
+ return;
100
+
101
+ column_ids = grn_table_create(context, NULL, 0, NULL,
102
+ GRN_TABLE_HASH_KEY, NULL, 0);
103
+ n = grn_table_columns(context, table, NULL, 0, column_ids);
104
+ if (n == 0) {
105
+ grn_obj_close(context, column_ids);
106
+ return;
107
+ }
108
+
109
+ cursor = grn_table_cursor_open(context, column_ids, NULL, 0, NULL, 0,
110
+ GRN_CURSOR_ASCENDING);
111
+ while (grn_table_cursor_next(context, cursor) != GRN_ID_NIL) {
112
+ void *key;
113
+ grn_id *column_id;
114
+ grn_obj *column;
115
+ RbGrnObject *rb_grn_column;
116
+
117
+ grn_table_cursor_get_key(context, cursor, &key);
118
+ column_id = key;
119
+ column = grn_ctx_at(context, *column_id);
120
+ rb_grn_column = grn_obj_user_data(context, column)->ptr;
121
+ if (rb_grn_column)
122
+ rb_gc_mark(rb_grn_column->self);
123
+ }
124
+ grn_table_cursor_close(context, cursor);
125
+ grn_obj_close(context, column_ids);
126
+ }
127
+
128
+ static VALUE
129
+ rb_grn_table_alloc (VALUE klass)
130
+ {
131
+ return Data_Wrap_Struct(klass, rb_grn_table_mark, rb_grn_object_free, NULL);
132
+ }
133
+
121
134
  VALUE
122
135
  rb_grn_table_s_create (int argc, VALUE *argv, VALUE klass,
123
136
  grn_obj_flags key_store)
@@ -150,6 +163,7 @@ rb_grn_table_s_create (int argc, VALUE *argv, VALUE klass,
150
163
  if (!NIL_P(rb_name)) {
151
164
  name = StringValuePtr(rb_name);
152
165
  name_size = RSTRING_LEN(rb_name);
166
+ flags |= GRN_OBJ_PERSISTENT;
153
167
  }
154
168
 
155
169
  if (!NIL_P(rb_path)) {
@@ -177,7 +191,7 @@ rb_grn_table_s_create (int argc, VALUE *argv, VALUE klass,
177
191
 
178
192
  table = grn_table_create(context, name, name_size, path,
179
193
  flags, key_type, value_size);
180
- rb_table = rb_grn_table_alloc(klass);
194
+ rb_table = rb_grn_object_alloc(klass);
181
195
  rb_grn_table_assign(rb_table, rb_context, context, table, RB_GRN_TRUE);
182
196
  rb_grn_context_check(context, rb_table);
183
197
 
@@ -226,13 +240,7 @@ rb_grn_table_initialize (int argc, VALUE *argv, VALUE self)
226
240
  VALUE rb_context;
227
241
 
228
242
  table = rb_grn_table_open_raw(argc, argv, &context, &rb_context);
229
- /* FIXME!!!! */
230
- if (self == rb_cGrnArray) {
231
- rb_grn_table_assign(self, rb_context, context, table, RB_GRN_TRUE);
232
- } else {
233
- rb_grn_table_key_support_assign(self, rb_context, context,
234
- table, RB_GRN_TRUE);
235
- }
243
+ rb_grn_object_assign(Qnil, self, rb_context, context, table);
236
244
  rb_grn_context_check(context, self);
237
245
 
238
246
  return Qnil;
@@ -241,7 +249,8 @@ rb_grn_table_initialize (int argc, VALUE *argv, VALUE self)
241
249
  static VALUE
242
250
  rb_grn_table_s_open (int argc, VALUE *argv, VALUE klass)
243
251
  {
244
- VALUE rb_table;
252
+ grn_user_data *user_data;
253
+ VALUE rb_table = Qnil;
245
254
  grn_obj *table;
246
255
  grn_ctx *context = NULL;
247
256
  VALUE rb_context;
@@ -255,28 +264,26 @@ rb_grn_table_s_open (int argc, VALUE *argv, VALUE klass)
255
264
  rb_grn_inspect(klass),
256
265
  rb_grn_inspect(rb_ary_new4(argc, argv)));
257
266
 
258
- if (klass == rb_cGrnTable) {
259
- klass = GRNOBJECT2RCLASS(table);
267
+ user_data = grn_obj_user_data(context, table);
268
+ if (user_data && user_data->ptr) {
269
+ rb_table = RB_GRN_OBJECT(user_data->ptr)->self;
260
270
  } else {
261
- VALUE rb_class;
262
-
263
- rb_class = GRNOBJECT2RCLASS(table);
264
- if (rb_class != klass) {
265
- rb_raise(rb_eTypeError,
266
- "unexpected existing table type: %s: expected %s",
267
- rb_grn_inspect(rb_class),
268
- rb_grn_inspect(klass));
271
+ if (klass == rb_cGrnTable) {
272
+ klass = GRNOBJECT2RCLASS(table);
273
+ } else {
274
+ VALUE rb_class;
275
+
276
+ rb_class = GRNOBJECT2RCLASS(table);
277
+ if (rb_class != klass) {
278
+ rb_raise(rb_eTypeError,
279
+ "unexpected existing table type: %s: expected %s",
280
+ rb_grn_inspect(rb_class),
281
+ rb_grn_inspect(klass));
282
+ }
269
283
  }
270
- }
271
284
 
272
- /* FIXME!!!! */
273
- if (klass == rb_cGrnArray) {
274
- rb_table = rb_grn_table_alloc(klass);
275
- rb_grn_table_assign(rb_table, rb_context, context, table, RB_GRN_TRUE);
276
- } else {
277
- rb_table = rb_grn_table_key_support_alloc(klass);
278
- rb_grn_table_key_support_assign(rb_table, rb_context, context,
279
- table, RB_GRN_TRUE);
285
+ rb_table = rb_grn_object_alloc(klass);
286
+ rb_grn_object_assign(klass, rb_table, rb_context, context, table);
280
287
  }
281
288
 
282
289
  if (rb_block_given_p())
@@ -791,20 +798,23 @@ rb_grn_table_sort (int argc, VALUE *argv, VALUE self)
791
798
  grn_obj *table;
792
799
  grn_obj *result;
793
800
  grn_table_sort_key *keys;
794
- int n_records, limit = 0;
795
801
  int i, n_keys;
802
+ int n_records, limit = 0;
796
803
  VALUE rb_keys, options;
797
804
  VALUE rb_limit;
798
805
  VALUE *rb_sort_keys;
806
+ grn_table_cursor *cursor;
807
+ VALUE rb_result;
799
808
 
800
809
  rb_grn_table_deconstruct(SELF(self), &table, &context,
801
810
  NULL, NULL,
802
811
  NULL, NULL, NULL);
803
812
 
804
813
  rb_scan_args(argc, argv, "11", &rb_keys, &options);
805
- rb_grn_scan_options(options,
806
- "limit", &rb_limit,
807
- NULL);
814
+
815
+ if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_keys, rb_cArray)))
816
+ rb_raise(rb_eArgError, "keys should be an array of key: <%s>",
817
+ rb_grn_inspect(rb_keys));
808
818
 
809
819
  n_keys = RARRAY_LEN(rb_keys);
810
820
  rb_sort_keys = RARRAY_PTR(rb_keys);
@@ -838,15 +848,113 @@ rb_grn_table_sort (int argc, VALUE *argv, VALUE self)
838
848
  }
839
849
  }
840
850
 
851
+ rb_grn_scan_options(options,
852
+ "limit", &rb_limit,
853
+ NULL);
854
+
841
855
  if (!NIL_P(rb_limit))
842
856
  limit = NUM2INT(rb_limit);
843
857
 
844
858
  result = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_NO_KEY,
845
859
  table, sizeof(grn_id));
846
- n_records = grn_table_sort(context, table, limit,
847
- result, keys, n_keys);
860
+ n_records = grn_table_sort(context, table, limit, result, keys, n_keys);
848
861
 
849
- return GRNOBJECT2RVAL(Qnil, context, result, RB_GRN_TRUE);
862
+ rb_result = rb_ary_new();
863
+ cursor = grn_table_cursor_open(context, result, NULL, 0, NULL, 0,
864
+ GRN_CURSOR_ASCENDING);
865
+ while (grn_table_cursor_next(context, cursor) != GRN_ID_NIL) {
866
+ void *value;
867
+ grn_id *id;
868
+
869
+ grn_table_cursor_get_value(context, cursor, &value);
870
+ id = value;
871
+ rb_ary_push(rb_result, rb_grn_record_new(self, *id, Qnil));
872
+ }
873
+ grn_table_cursor_close(context, cursor);
874
+ grn_obj_close(context, result);
875
+
876
+ rb_grn_context_check(context, self); /* FIXME: here is too late */
877
+
878
+ return rb_result;
879
+ }
880
+
881
+ static VALUE
882
+ rb_grn_table_group (int argc, VALUE *argv, VALUE self)
883
+ {
884
+ grn_ctx *context = NULL;
885
+ grn_obj *table;
886
+ grn_table_sort_key *keys;
887
+ grn_table_group_result *results;
888
+ int i, n_keys, n_results;
889
+ grn_rc rc;
890
+ VALUE rb_keys;
891
+ VALUE *rb_sort_keys;
892
+ VALUE rb_results;
893
+
894
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
895
+ NULL, NULL,
896
+ NULL, NULL, NULL);
897
+
898
+ rb_scan_args(argc, argv, "10", &rb_keys);
899
+
900
+ if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_keys, rb_cArray)))
901
+ rb_raise(rb_eArgError, "keys should be an array of key: <%s>",
902
+ rb_grn_inspect(rb_keys));
903
+
904
+ n_keys = RARRAY_LEN(rb_keys);
905
+ rb_sort_keys = RARRAY_PTR(rb_keys);
906
+ keys = ALLOCA_N(grn_table_sort_key, n_keys);
907
+ for (i = 0; i < n_keys; i++) {
908
+ VALUE rb_sort_options, rb_key;
909
+
910
+ if (RVAL2CBOOL(rb_obj_is_kind_of(rb_sort_keys[i], rb_cHash))) {
911
+ rb_sort_options = rb_sort_keys[i];
912
+ } else {
913
+ rb_sort_options = rb_hash_new();
914
+ rb_hash_aset(rb_sort_options,
915
+ RB_GRN_INTERN("key"),
916
+ rb_sort_keys[i]);
917
+ }
918
+ rb_grn_scan_options(rb_sort_options,
919
+ "key", &rb_key,
920
+ NULL);
921
+ if (RVAL2CBOOL(rb_obj_is_kind_of(rb_key, rb_cString)))
922
+ rb_key = rb_grn_table_get_column(self, rb_key);
923
+ keys[i].key = RVAL2GRNOBJECT(rb_key, &context);
924
+ keys[i].flags = 0;
925
+ }
926
+
927
+ n_results = n_keys;
928
+ results = ALLOCA_N(grn_table_group_result, n_results);
929
+ rb_results = rb_ary_new();
930
+ for (i = 0; i < n_results; i++) {
931
+ grn_obj *result;
932
+ grn_id range_id;
933
+ VALUE rb_result;
934
+
935
+ range_id = grn_obj_get_range(context, keys[i].key);
936
+ result = grn_table_create(context, NULL, 0, NULL,
937
+ GRN_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
938
+ grn_ctx_at(context, range_id), 0);
939
+ results[i].table = result;
940
+ results[i].key_begin = 0;
941
+ results[i].key_end = 0;
942
+ results[i].limit = 0;
943
+ results[i].flags = 0;
944
+ results[i].op = GRN_OP_OR;
945
+
946
+ rb_result = GRNOBJECT2RVAL(Qnil, context, result, RB_GRN_TRUE);
947
+ rb_ary_push(rb_results, rb_result);
948
+ }
949
+
950
+ rc = grn_table_group(context, table, keys, n_keys, results, n_results);
951
+ rb_grn_context_check(context, self);
952
+ rb_grn_rc_check(rc, self);
953
+
954
+ if (n_results == 1)
955
+ return rb_ary_pop(rb_results);
956
+ else
957
+ return rb_results;
850
958
  }
851
959
 
852
960
  /*
@@ -914,6 +1022,247 @@ rb_grn_table_array_set (VALUE self, VALUE rb_id, VALUE rb_value)
914
1022
  return Qnil;
915
1023
  }
916
1024
 
1025
+ /*
1026
+ * Document-method: unlock
1027
+ *
1028
+ * call-seq:
1029
+ * table.unlock(options={})
1030
+ *
1031
+ * _table_のロックを解除する。
1032
+ *
1033
+ * 利用可能なオプションは以下の通り。
1034
+ *
1035
+ * [_:id_]
1036
+ * _:id_で指定したレコードのロックを解除する。(注:
1037
+ * groonga側が未実装のため、現在は無視される)
1038
+ */
1039
+ static VALUE
1040
+ rb_grn_table_unlock (int argc, VALUE *argv, VALUE self)
1041
+ {
1042
+ grn_id id = GRN_ID_NIL;
1043
+ grn_ctx *context;
1044
+ grn_obj *table;
1045
+ grn_rc rc;
1046
+ VALUE options, rb_id;
1047
+
1048
+ rb_scan_args(argc, argv, "01", &options);
1049
+
1050
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1051
+ NULL, NULL,
1052
+ NULL, NULL, NULL);
1053
+
1054
+ rb_grn_scan_options(options,
1055
+ "id", &rb_id,
1056
+ NULL);
1057
+
1058
+ if (!NIL_P(rb_id))
1059
+ id = NUM2UINT(rb_id);
1060
+
1061
+ rc = grn_obj_unlock(context, table, id);
1062
+ rb_grn_context_check(context, self);
1063
+ rb_grn_rc_check(rc, self);
1064
+
1065
+ return Qnil;
1066
+ }
1067
+
1068
+ static VALUE
1069
+ rb_grn_table_unlock_ensure (VALUE self)
1070
+ {
1071
+ return rb_grn_table_unlock(0, NULL, self);
1072
+ }
1073
+
1074
+ /*
1075
+ * Document-method: lock
1076
+ *
1077
+ * call-seq:
1078
+ * table.lock(options={})
1079
+ * table.lock(options={}) {...}
1080
+ *
1081
+ * _table_をロックする。ロックに失敗した場合は
1082
+ * Groonga::ResourceDeadlockAvoided例外が発生する。
1083
+ *
1084
+ * ブロックを指定した場合はブロックを抜けたときにunlockする。
1085
+ *
1086
+ * 利用可能なオプションは以下の通り。
1087
+ *
1088
+ * [_:timeout_]
1089
+ * ロックを獲得できなかった場合は_:timeout_秒間ロックの獲
1090
+ * 得を試みる。_:timeout_秒以内にロックを獲得できなかった
1091
+ * 場合は例外が発生する。
1092
+ * [_:id_]
1093
+ * _:id_で指定したレコードをロックする。(注: groonga側が
1094
+ * 未実装のため、現在は無視される)
1095
+ */
1096
+ static VALUE
1097
+ rb_grn_table_lock (int argc, VALUE *argv, VALUE self)
1098
+ {
1099
+ grn_id id = GRN_ID_NIL;
1100
+ grn_ctx *context;
1101
+ grn_obj *table;
1102
+ int timeout = 0;
1103
+ grn_rc rc;
1104
+ VALUE options, rb_timeout, rb_id;
1105
+
1106
+ rb_scan_args(argc, argv, "01", &options);
1107
+
1108
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1109
+ NULL, NULL,
1110
+ NULL, NULL, NULL);
1111
+
1112
+ rb_grn_scan_options(options,
1113
+ "timeout", &rb_timeout,
1114
+ "id", &rb_id,
1115
+ NULL);
1116
+
1117
+ if (!NIL_P(rb_timeout))
1118
+ timeout = NUM2UINT(rb_timeout);
1119
+
1120
+ if (!NIL_P(rb_id))
1121
+ id = NUM2UINT(rb_id);
1122
+
1123
+ rc = grn_obj_lock(context, table, id, timeout);
1124
+ rb_grn_context_check(context, self);
1125
+ rb_grn_rc_check(rc, self);
1126
+
1127
+ if (rb_block_given_p()) {
1128
+ return rb_ensure(rb_yield, Qnil, rb_grn_table_unlock_ensure, self);
1129
+ } else {
1130
+ return Qnil;
1131
+ }
1132
+ }
1133
+
1134
+ /*
1135
+ * Document-method: clear_lock
1136
+ *
1137
+ * call-seq:
1138
+ * table.clear_lock(options={})
1139
+ *
1140
+ * _table_のロックを強制的に解除する。
1141
+ *
1142
+ * 利用可能なオプションは以下の通り。
1143
+ *
1144
+ * [_:id_]
1145
+ * _:id_で指定したレコードのロックを強制的に解除する。
1146
+ * (注: groonga側が未実装のため、現在は無視される。実装さ
1147
+ * れるのではないかと思っているが、実装されないかもしれな
1148
+ * い。)
1149
+ */
1150
+ static VALUE
1151
+ rb_grn_table_clear_lock (int argc, VALUE *argv, VALUE self)
1152
+ {
1153
+ grn_id id = GRN_ID_NIL;
1154
+ grn_ctx *context;
1155
+ grn_obj *table;
1156
+ VALUE options, rb_id;
1157
+
1158
+ rb_scan_args(argc, argv, "01", &options);
1159
+
1160
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1161
+ NULL, NULL,
1162
+ NULL, NULL, NULL);
1163
+
1164
+ rb_grn_scan_options(options,
1165
+ "id", &rb_id,
1166
+ NULL);
1167
+
1168
+ if (!NIL_P(rb_id))
1169
+ id = NUM2UINT(rb_id);
1170
+
1171
+ grn_obj_clear_lock(context, table);
1172
+
1173
+ return Qnil;
1174
+ }
1175
+
1176
+ /*
1177
+ * Document-method: locked?
1178
+ *
1179
+ * call-seq:
1180
+ * table.locked?(options={})
1181
+ *
1182
+ * _table_がロックされていれば+true+を返す。
1183
+ *
1184
+ * 利用可能なオプションは以下の通り。
1185
+ *
1186
+ * [_:id_]
1187
+ * _:id_で指定したレコードがロックされていれば+true+を返す。
1188
+ * (注: groonga側が未実装のため、現在は無視される。実装さ
1189
+ * れるのではないかと思っているが、実装されないかもしれな
1190
+ * い。)
1191
+ */
1192
+ static VALUE
1193
+ rb_grn_table_is_locked (int argc, VALUE *argv, VALUE self)
1194
+ {
1195
+ grn_id id = GRN_ID_NIL;
1196
+ grn_ctx *context;
1197
+ grn_obj *table;
1198
+ VALUE options, rb_id;
1199
+
1200
+ rb_scan_args(argc, argv, "01", &options);
1201
+
1202
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1203
+ NULL, NULL,
1204
+ NULL, NULL, NULL);
1205
+
1206
+ rb_grn_scan_options(options,
1207
+ "id", &rb_id,
1208
+ NULL);
1209
+
1210
+ if (!NIL_P(rb_id))
1211
+ id = NUM2UINT(rb_id);
1212
+
1213
+ return CBOOL2RVAL(grn_obj_is_locked(context, table));
1214
+ }
1215
+
1216
+ static VALUE
1217
+ rb_grn_table_select (int argc, VALUE *argv, VALUE self)
1218
+ {
1219
+ grn_ctx *context;
1220
+ grn_obj *table, *result, *expression;
1221
+ grn_operator operator = GRN_OP_OR;
1222
+ grn_rc rc;
1223
+ VALUE options;
1224
+ VALUE rb_name, rb_operator, rb_result;
1225
+ VALUE rb_expression, builder;
1226
+
1227
+ rb_scan_args(argc, argv, "01", &options);
1228
+
1229
+ rb_grn_table_deconstruct(SELF(self), &table, &context,
1230
+ NULL, NULL,
1231
+ NULL, NULL, NULL);
1232
+
1233
+ rb_grn_scan_options(options,
1234
+ "operator", &rb_operator,
1235
+ "result", &rb_result,
1236
+ "name", &rb_name,
1237
+ NULL);
1238
+
1239
+ if (!NIL_P(rb_operator))
1240
+ operator = NUM2INT(rb_operator);
1241
+
1242
+ if (NIL_P(rb_result)) {
1243
+ result = grn_table_create(context, NULL, 0, NULL,
1244
+ GRN_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
1245
+ table,
1246
+ 0);
1247
+ rb_result = GRNTABLE2RVAL(context, result, RB_GRN_TRUE);
1248
+ } else {
1249
+ result = RVAL2GRNTABLE(rb_result, &context);
1250
+ }
1251
+
1252
+ builder = rb_grn_record_expression_builder_new(self, rb_name);
1253
+ rb_expression = rb_grn_record_expression_builder_build(builder);
1254
+
1255
+ rb_grn_object_deconstruct(RB_GRN_OBJECT(DATA_PTR(rb_expression)),
1256
+ &expression, NULL,
1257
+ NULL, NULL, NULL, NULL);
1258
+
1259
+ rc = grn_table_select(context, table, expression, result, operator);
1260
+ rb_grn_context_check(context, self);
1261
+ rb_grn_rc_check(rc, self);
1262
+
1263
+ return rb_result;
1264
+ }
1265
+
917
1266
  void
918
1267
  rb_grn_init_table (VALUE mGrn)
919
1268
  {
@@ -951,10 +1300,18 @@ rb_grn_init_table (VALUE mGrn)
951
1300
  rb_define_method(rb_cGrnTable, "delete", rb_grn_table_delete, 1);
952
1301
 
953
1302
  rb_define_method(rb_cGrnTable, "sort", rb_grn_table_sort, -1);
1303
+ rb_define_method(rb_cGrnTable, "group", rb_grn_table_group, -1);
954
1304
 
955
1305
  rb_define_method(rb_cGrnTable, "[]", rb_grn_table_array_reference, 1);
956
1306
  rb_define_method(rb_cGrnTable, "[]=", rb_grn_table_array_set, 2);
957
1307
 
1308
+ rb_define_method(rb_cGrnTable, "lock", rb_grn_table_lock, -1);
1309
+ rb_define_method(rb_cGrnTable, "unlock", rb_grn_table_unlock, -1);
1310
+ rb_define_method(rb_cGrnTable, "clear_lock", rb_grn_table_clear_lock, -1);
1311
+ rb_define_method(rb_cGrnTable, "locked?", rb_grn_table_is_locked, -1);
1312
+
1313
+ rb_define_method(rb_cGrnTable, "select", rb_grn_table_select, -1);
1314
+
958
1315
  rb_grn_init_table_key_support(mGrn);
959
1316
  rb_grn_init_array(mGrn);
960
1317
  rb_grn_init_hash(mGrn);