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-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( | 
| 39 | 
            +
                return GRNOBJECT2RVAL(Qnil, context, table, owner);
         | 
| 40 40 | 
             
            }
         | 
| 41 41 |  | 
| 42 42 | 
             
            void
         | 
| 43 | 
            -
             | 
| 43 | 
            +
            rb_grn_table_finalizer (grn_ctx *context, grn_obj *object,
         | 
| 44 | 
            +
            			RbGrnTable *rb_grn_table)
         | 
| 44 45 | 
             
            {
         | 
| 45 | 
            -
                 | 
| 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 | 
| 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 =  | 
| 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 | 
            -
                 | 
| 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 | 
            -
                 | 
| 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 | 
            -
                 | 
| 259 | 
            -
             | 
| 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 | 
            -
            	 | 
| 262 | 
            -
             | 
| 263 | 
            -
            	 | 
| 264 | 
            -
             | 
| 265 | 
            -
             | 
| 266 | 
            -
             | 
| 267 | 
            -
             | 
| 268 | 
            -
             | 
| 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 | 
            -
             | 
| 273 | 
            -
             | 
| 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 | 
            -
             | 
| 806 | 
            -
             | 
| 807 | 
            -
             | 
| 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 | 
            -
                 | 
| 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);
         |