rroonga 2.0.8 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/README.textile +2 -2
  2. data/bin/groonga-index-dump +47 -0
  3. data/doc/text/news.textile +733 -0
  4. data/doc/text/tutorial.textile +535 -0
  5. data/example/bookmark.rb +1 -1
  6. data/ext/groonga/rb-grn-database.c +21 -24
  7. data/ext/groonga/rb-grn-double-array-trie.c +50 -58
  8. data/ext/groonga/rb-grn-exception.c +18 -1
  9. data/ext/groonga/rb-grn-hash.c +18 -3
  10. data/ext/groonga/rb-grn-index-column.c +50 -2
  11. data/ext/groonga/rb-grn-normalizer.c +83 -0
  12. data/ext/groonga/rb-grn-object.c +18 -14
  13. data/ext/groonga/rb-grn-patricia-trie.c +17 -2
  14. data/ext/groonga/rb-grn-query-logger.c +263 -0
  15. data/ext/groonga/rb-grn-snippet.c +6 -0
  16. data/ext/groonga/rb-grn-table-key-support.c +204 -13
  17. data/ext/groonga/rb-grn-table.c +124 -46
  18. data/ext/groonga/rb-grn.h +14 -3
  19. data/ext/groonga/rb-groonga.c +2 -0
  20. data/lib/groonga/database.rb +7 -0
  21. data/lib/groonga/dumper.rb +21 -2
  22. data/lib/groonga/index-column.rb +170 -0
  23. data/lib/groonga/query-logger.rb +129 -0
  24. data/lib/groonga/record.rb +32 -8
  25. data/lib/groonga/schema.rb +231 -288
  26. data/lib/groonga.rb +2 -1
  27. data/rroonga-build.rb +2 -2
  28. data/rroonga.gemspec +11 -7
  29. data/test/groonga-test-utils.rb +18 -6
  30. data/test/test-hash.rb +49 -20
  31. data/test/test-index-cursor.rb +4 -4
  32. data/{Gemfile → test/test-normalizer.rb} +9 -5
  33. data/test/test-pagination.rb +1 -1
  34. data/test/test-patricia-trie.rb +8 -0
  35. data/test/test-schema.rb +16 -13
  36. data/test/test-snippet.rb +5 -0
  37. data/test/test-table.rb +24 -12
  38. data/test/test-view.rb +0 -1
  39. metadata +154 -136
  40. data/AUTHORS +0 -5
  41. data/Rakefile +0 -203
  42. data/bin/groonga-query-log-extract +0 -117
@@ -0,0 +1,263 @@
1
+ /* -*- coding: utf-8; mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
+ /*
3
+ Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
4
+
5
+ This library is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU Lesser General Public
7
+ License version 2.1 as published by the Free Software Foundation.
8
+
9
+ This library is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ Lesser General Public License for more details.
13
+
14
+ You should have received a copy of the GNU Lesser General Public
15
+ License along with this library; if not, write to the Free Software
16
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ */
18
+
19
+ #include "rb-grn.h"
20
+
21
+ /*
22
+ * Document-class: Groonga::QueryLogger
23
+ *
24
+ * A class for logging query log.
25
+ *
26
+ */
27
+
28
+ #define GRNQUERYLOGFLAGS2RVAL(flags) (rb_grn_query_log_flags_to_ruby_object(flags))
29
+
30
+ VALUE cGrnQueryLogger;
31
+ VALUE mGrnQueryLoggerFlags;
32
+ VALUE cGrnCallbackQueryLogger;
33
+
34
+ static ID id_new;
35
+ static ID id_parse;
36
+ static ID id_log;
37
+ static ID id_reopen;
38
+ static ID id_fin;
39
+
40
+ static grn_query_logger rb_grn_query_logger;
41
+
42
+ static VALUE
43
+ rb_grn_query_log_flags_to_ruby_object (unsigned int flags)
44
+ {
45
+ return UINT2NUM(flags);
46
+ }
47
+
48
+ static void
49
+ rb_grn_query_logger_log (grn_ctx *ctx, unsigned int flag,
50
+ const char *timestamp, const char *info,
51
+ const char *message, void *user_data)
52
+ {
53
+ VALUE handler = (VALUE)user_data;
54
+
55
+ if (NIL_P(handler))
56
+ return;
57
+
58
+ /* TODO: use rb_protect(). */
59
+ rb_funcall(handler, id_log, 4,
60
+ GRNQUERYLOGFLAGS2RVAL(flag),
61
+ rb_str_new2(timestamp),
62
+ rb_str_new2(info),
63
+ rb_str_new2(message));
64
+ }
65
+
66
+ static void
67
+ rb_grn_query_logger_reopen (grn_ctx *ctx, void *user_data)
68
+ {
69
+ VALUE handler = (VALUE)user_data;
70
+
71
+ if (NIL_P(handler))
72
+ return;
73
+
74
+ /* TODO: use rb_protect(). */
75
+ rb_funcall(handler, id_reopen, 0);
76
+ }
77
+
78
+ static void
79
+ rb_grn_query_logger_fin (grn_ctx *ctx, void *user_data)
80
+ {
81
+ VALUE handler = (VALUE)user_data;
82
+
83
+ if (NIL_P(handler))
84
+ return;
85
+
86
+ /* TODO: use rb_protect(). */
87
+ rb_funcall(handler, id_fin, 0);
88
+ }
89
+
90
+ /*
91
+ * Registers a query logger or a callback that is called when a
92
+ * query log event is emitted.
93
+ *
94
+ * @overload register(logger, options={})
95
+ * @param logger [#log, #reopen, #fin] The query logger. It is easy to
96
+ * inherit {QueryLogger}.
97
+ *
98
+ * @!macro query-logger.register.options
99
+ * @param options [::Hash] The options.
100
+ * @option options [Symbol, String, Integer or nil] :flags (:default)
101
+ * Flags describe what query log should be logged.
102
+ *
103
+ * @see {QueryLogger::Flags.parse}
104
+ *
105
+ * @return void
106
+ *
107
+ * @overload register(options={})
108
+ * @yield [action, flag, timestamp, info, message]
109
+ * ...
110
+ *
111
+ * @!macro query-logger.register.options
112
+ */
113
+ static VALUE
114
+ rb_grn_query_logger_s_register (int argc, VALUE *argv, VALUE klass)
115
+ {
116
+ VALUE rb_context = Qnil;
117
+ grn_ctx *context;
118
+ VALUE rb_logger, rb_callback;
119
+ VALUE rb_options, rb_command, rb_result_code, rb_destination;
120
+ VALUE rb_cache, rb_size, rb_score, rb_default, rb_all, rb_flags;
121
+ unsigned int flags = GRN_QUERY_LOG_NONE;
122
+
123
+ rb_scan_args(argc, argv, "02&", &rb_logger, &rb_options, &rb_callback);
124
+
125
+ if (rb_block_given_p()) {
126
+ rb_logger = rb_funcall(cGrnCallbackQueryLogger, id_new, 1, rb_callback);
127
+ }
128
+
129
+ rb_grn_scan_options(rb_options,
130
+ "command", &rb_command,
131
+ "result_code", &rb_result_code,
132
+ "destination", &rb_destination,
133
+ "cache", &rb_cache,
134
+ "size", &rb_size,
135
+ "score", &rb_score,
136
+ "default", &rb_default,
137
+ "all", &rb_all,
138
+ "flags", &rb_flags,
139
+ NULL);
140
+
141
+ if (RVAL2CBOOL(rb_command)) {
142
+ flags |= GRN_QUERY_LOG_COMMAND;
143
+ }
144
+ if (RVAL2CBOOL(rb_result_code)) {
145
+ flags |= GRN_QUERY_LOG_RESULT_CODE;
146
+ }
147
+ if (RVAL2CBOOL(rb_destination)) {
148
+ flags |= GRN_QUERY_LOG_DESTINATION;
149
+ }
150
+ if (RVAL2CBOOL(rb_cache)) {
151
+ flags |= GRN_QUERY_LOG_CACHE;
152
+ }
153
+ if (RVAL2CBOOL(rb_size)) {
154
+ flags |= GRN_QUERY_LOG_SIZE;
155
+ }
156
+ if (RVAL2CBOOL(rb_score)) {
157
+ flags |= GRN_QUERY_LOG_SCORE;
158
+ }
159
+ if (RVAL2CBOOL(rb_default)) {
160
+ flags |= GRN_QUERY_LOG_DEFAULT;
161
+ }
162
+ if (RVAL2CBOOL(rb_all)) {
163
+ flags |= GRN_QUERY_LOG_ALL;
164
+ }
165
+ if (!NIL_P(rb_flags)) {
166
+ flags = rb_funcall(mGrnQueryLoggerFlags, id_parse, 2,
167
+ UINT2NUM(flags), rb_flags);
168
+ }
169
+
170
+ rb_grn_query_logger.flags = flags;
171
+ rb_grn_query_logger.user_data = (void *)rb_logger;
172
+
173
+ context = rb_grn_context_ensure(&rb_context);
174
+ grn_query_logger_set(context, &rb_grn_query_logger);
175
+ rb_grn_context_check(context, rb_logger);
176
+ rb_cv_set(klass, "@@current_logger", rb_logger);
177
+
178
+ return Qnil;
179
+ }
180
+
181
+ static VALUE
182
+ rb_grn_query_logger_s_unregister (VALUE klass)
183
+ {
184
+ VALUE current_logger;
185
+ VALUE rb_context = Qnil;
186
+ grn_ctx *context;
187
+
188
+ current_logger = rb_cv_get(klass, "@@current_logger");
189
+ if (NIL_P(current_logger))
190
+ return Qnil;
191
+
192
+ rb_cv_set(klass, "@@current_logger", Qnil);
193
+
194
+ context = rb_grn_context_ensure(&rb_context);
195
+ grn_query_logger_set(context, NULL);
196
+ rb_grn_context_check(context, klass);
197
+
198
+ return Qnil;
199
+ }
200
+
201
+ /*
202
+ * Sends reopen request to the current query logger. It is useful for
203
+ * rotating log file.
204
+ *
205
+ * @overload reopen
206
+ * @return void
207
+ */
208
+ static VALUE
209
+ rb_grn_query_logger_s_reopen (VALUE klass)
210
+ {
211
+ VALUE rb_context = Qnil;
212
+ grn_ctx *context;
213
+
214
+ context = rb_grn_context_ensure(&rb_context);
215
+ grn_query_logger_reopen(context);
216
+ rb_grn_context_check(context, klass);
217
+
218
+ return Qnil;
219
+ }
220
+
221
+ void
222
+ rb_grn_init_query_logger (VALUE mGrn)
223
+ {
224
+ id_new = rb_intern("new");
225
+ id_parse = rb_intern("parse");
226
+ id_log = rb_intern("log");
227
+ id_reopen = rb_intern("reopen");
228
+ id_fin = rb_intern("fin");
229
+
230
+ rb_grn_query_logger.log = rb_grn_query_logger_log;
231
+ rb_grn_query_logger.reopen = rb_grn_query_logger_reopen;
232
+ rb_grn_query_logger.fin = rb_grn_query_logger_fin;
233
+
234
+ rb_grn_query_logger.user_data = (void *)Qnil;
235
+
236
+ cGrnQueryLogger = rb_define_class_under(mGrn, "QueryLogger", rb_cObject);
237
+
238
+ rb_cv_set(cGrnQueryLogger, "@@current_logger", Qnil);
239
+ rb_define_singleton_method(cGrnQueryLogger, "register",
240
+ rb_grn_query_logger_s_register, -1);
241
+ rb_define_singleton_method(cGrnQueryLogger, "unregister",
242
+ rb_grn_query_logger_s_unregister, 0);
243
+ rb_define_singleton_method(cGrnQueryLogger, "reopen",
244
+ rb_grn_query_logger_s_reopen, 0);
245
+
246
+ mGrnQueryLoggerFlags = rb_define_module_under(cGrnQueryLogger, "Flags");
247
+ #define DEFINE_FLAG(NAME) \
248
+ rb_define_const(mGrnQueryLoggerFlags, \
249
+ #NAME, UINT2NUM(GRN_QUERY_LOG_ ## NAME))
250
+ DEFINE_FLAG(NONE);
251
+ DEFINE_FLAG(COMMAND);
252
+ DEFINE_FLAG(RESULT_CODE);
253
+ DEFINE_FLAG(DESTINATION);
254
+ DEFINE_FLAG(CACHE);
255
+ DEFINE_FLAG(SIZE);
256
+ DEFINE_FLAG(SCORE);
257
+ DEFINE_FLAG(ALL);
258
+ DEFINE_FLAG(DEFAULT);
259
+ #undef DEFINE_FLAG
260
+
261
+ cGrnCallbackQueryLogger =
262
+ rb_define_class_under(mGrn, "CallbackQueryLogger", cGrnQueryLogger);
263
+ }
@@ -111,6 +111,12 @@ rb_grn_snippet_initialize (int argc, VALUE *argv, VALUE self)
111
111
  NULL);
112
112
 
113
113
  context = rb_grn_context_ensure(&rb_context);
114
+ if (!grn_ctx_db(context)) {
115
+ rb_raise(rb_eArgError,
116
+ "Groonga::Context should be associated with a database by "
117
+ "Groonga::Database#open or #create: %s",
118
+ rb_grn_inspect(rb_context));
119
+ }
114
120
 
115
121
  if (RVAL2CBOOL(rb_normalize))
116
122
  flags |= GRN_SNIP_NORMALIZE;
@@ -1,6 +1,6 @@
1
1
  /* -*- coding: utf-8; c-file-style: "ruby" -*- */
2
2
  /*
3
- Copyright (C) 2009-2011 Kouhei Sutou <kou@clear-code.com>
3
+ Copyright (C) 2009-2012 Kouhei Sutou <kou@clear-code.com>
4
4
 
5
5
  This library is free software; you can redistribute it and/or
6
6
  modify it under the terms of the GNU Lesser General Public
@@ -87,6 +87,101 @@ rb_grn_table_key_support_bind (RbGrnTableKeySupport *rb_grn_table_key_support,
87
87
  grn_obj_open(context, GRN_BULK, 0, rb_grn_object->domain_id);
88
88
  }
89
89
 
90
+ static VALUE
91
+ rb_grn_table_key_support_inspect_content (VALUE self, VALUE inspected)
92
+ {
93
+ RbGrnTableKeySupport *rb_grn_table;
94
+ grn_ctx *context = NULL;
95
+ grn_obj *table;
96
+
97
+ rb_grn_table = SELF(self);
98
+ if (!rb_grn_table)
99
+ return inspected;
100
+
101
+ rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
102
+ NULL, NULL, NULL,
103
+ NULL, NULL, NULL,
104
+ NULL);
105
+ if (!table)
106
+ return inspected;
107
+ if (!context)
108
+ return inspected;
109
+
110
+ {
111
+ grn_obj value;
112
+ grn_encoding encoding;
113
+
114
+ rb_str_cat2(inspected, ", ");
115
+ rb_str_cat2(inspected, "encoding: <");
116
+ GRN_OBJ_INIT(&value, GRN_BULK, 0, GRN_ID_NIL);
117
+ grn_obj_get_info(context, table, GRN_INFO_ENCODING, &value);
118
+ encoding = *((grn_encoding *)GRN_BULK_HEAD(&value));
119
+ grn_obj_unlink(context, &value);
120
+
121
+ if (context->rc == GRN_SUCCESS) {
122
+ rb_str_concat(inspected, rb_inspect(GRNENCODING2RVAL(encoding)));
123
+ } else {
124
+ rb_str_cat2(inspected, "invalid");
125
+ }
126
+
127
+ rb_str_cat2(inspected, ">");
128
+ }
129
+
130
+ {
131
+ grn_obj *default_tokenizer;
132
+
133
+ rb_str_cat2(inspected, ", ");
134
+ rb_str_cat2(inspected, "default_tokenizer: ");
135
+ default_tokenizer = grn_obj_get_info(context, table,
136
+ GRN_INFO_DEFAULT_TOKENIZER,
137
+ NULL);
138
+ if (default_tokenizer) {
139
+ rb_grn_object_inspect_object_content_name(inspected, context,
140
+ default_tokenizer);
141
+ } else {
142
+ rb_str_cat2(inspected, "(nil)");
143
+ }
144
+ }
145
+
146
+ {
147
+ grn_obj *normalizer;
148
+
149
+ rb_str_cat2(inspected, ", ");
150
+ rb_str_cat2(inspected, "normalizer: ");
151
+ normalizer = grn_obj_get_info(context, table, GRN_INFO_NORMALIZER,
152
+ NULL);
153
+ if (normalizer) {
154
+ rb_grn_object_inspect_object_content_name(inspected, context,
155
+ normalizer);
156
+ } else {
157
+ rb_str_cat2(inspected, "(nil)");
158
+ }
159
+ }
160
+
161
+ return inspected;
162
+ }
163
+
164
+ /*
165
+ * Inspects the table.
166
+ *
167
+ * @overload inspect
168
+ * @return [String] the inspected string.
169
+ */
170
+ static VALUE
171
+ rb_grn_table_key_support_inspect (VALUE self)
172
+ {
173
+ VALUE inspected;
174
+
175
+ inspected = rb_str_new2("");
176
+ rb_grn_object_inspect_header(self, inspected);
177
+ rb_grn_object_inspect_content(self, inspected);
178
+ rb_grn_table_inspect_content(self, inspected);
179
+ rb_grn_table_key_support_inspect_content(self, inspected);
180
+ rb_grn_object_inspect_footer(self, inspected);
181
+
182
+ return inspected;
183
+ }
184
+
90
185
  static grn_id
91
186
  rb_grn_table_key_support_add_raw (VALUE self, VALUE rb_key, int *added)
92
187
  {
@@ -283,16 +378,42 @@ rb_grn_table_key_support_delete_by_key (VALUE self, VALUE rb_key)
283
378
  }
284
379
 
285
380
  /*
286
- * テーブルの _id_ または _key_ に対応するレコードを削除する。
287
- *
288
381
  * @overload delete(id)
382
+ * Delete a record that has ID @id@.
383
+ *
384
+ * @param id [Integer] The ID of delete target record.
385
+ *
386
+ * @return void
387
+ *
289
388
  * @overload delete(key)
389
+ * Delete a record that has key @key@.
390
+ *
391
+ * @param key [Object] The key of delete target record.
392
+ *
393
+ * @return void
394
+ *
395
+ * @overload delete
396
+ * @yield [record]
397
+ * TODO: See #select.
398
+ * @yieldparam [Groonga::RecodExpressionBuilder] record
399
+ * TODO: See #select.
400
+ * @yieldreturn [Groonga::ExpressionBuilder]
401
+ * TODO: See #select.
402
+ *
403
+ * @return void
290
404
  */
291
405
  static VALUE
292
- rb_grn_table_key_support_delete (VALUE self, VALUE rb_id_or_key)
406
+ rb_grn_table_key_support_delete (int argc, VALUE *argv, VALUE self)
293
407
  {
408
+ VALUE rb_id_or_key;
409
+
410
+ if (rb_block_given_p()) {
411
+ return rb_grn_table_delete_by_expression(self);
412
+ }
413
+
414
+ rb_scan_args(argc, argv, "1", &rb_id_or_key);
294
415
  if (FIXNUM_P(rb_id_or_key)) {
295
- return rb_grn_table_delete(self, rb_id_or_key);
416
+ return rb_grn_table_delete_by_id(self, rb_id_or_key);
296
417
  } else {
297
418
  return rb_grn_table_key_support_delete_by_key(self, rb_id_or_key);
298
419
  }
@@ -659,21 +780,83 @@ rb_grn_table_key_support_set_default_tokenizer (VALUE self, VALUE rb_tokenizer)
659
780
  }
660
781
 
661
782
  /*
662
- * キーを正規化する場合は +true+ 、正規化しない場合は +false+ を返
663
- * す。
783
+ * Returns the normalizer that is used by {Groonga::IndexColumn}.
664
784
  *
665
- * @overload normalize_key?
785
+ * @overload normalizer
786
+ * @return [nil, Groonga::Procedure]
666
787
  */
667
788
  static VALUE
668
- rb_grn_table_key_normalize_key_p (VALUE self)
789
+ rb_grn_table_key_support_get_normalizer (VALUE self)
669
790
  {
791
+ grn_ctx *context = NULL;
670
792
  grn_obj *table;
793
+ grn_obj *normalizer = NULL;
671
794
 
672
- rb_grn_table_key_support_deconstruct(SELF(self), &table, NULL,
795
+ rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
796
+ NULL, NULL, NULL,
797
+ NULL, NULL, NULL,
798
+ NULL);
799
+
800
+ normalizer = grn_obj_get_info(context, table, GRN_INFO_NORMALIZER, NULL);
801
+ rb_grn_context_check(context, self);
802
+
803
+ return GRNOBJECT2RVAL(Qnil, context, normalizer, GRN_FALSE);
804
+ }
805
+
806
+ /*
807
+ * Specifies the normalizer used by {Groonga::IndexColumn}.
808
+ *
809
+ * @example
810
+ * # Uses NFKC normalizer.
811
+ * table.normalizer = "NormalizerNFKC51"
812
+ * # Specifies normalizer object.
813
+ * table.normalizer = Groonga::Context["NormalizerNFKC51"]
814
+ * # Uses auto normalizer that is a normalizer for backward compatibility.
815
+ * table.normalizer = "TNormalizerAuto"
816
+ *
817
+ * @overload normalizer=(name)
818
+ * @param [String] name Set a nomalizer named @name@.
819
+ *
820
+ * @overload normalizer=(normalizer)
821
+ * @param [Groonga::Procedure] normalizer Set the normalizer object.
822
+ *
823
+ * @overload normalizer=(normalizer)
824
+ * @param [nil] normalizer Unset normalizer.
825
+ */
826
+ static VALUE
827
+ rb_grn_table_key_support_set_normalizer (VALUE self, VALUE rb_normalizer)
828
+ {
829
+ grn_ctx *context;
830
+ grn_obj *table;
831
+ grn_obj *normalizer;
832
+ grn_rc rc;
833
+
834
+ rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
673
835
  NULL, NULL, NULL,
674
836
  NULL, NULL, NULL,
675
837
  NULL);
676
- return CBOOL2RVAL(table->header.flags & GRN_OBJ_KEY_NORMALIZE);
838
+
839
+ normalizer = RVAL2GRNOBJECT(rb_normalizer, &context);
840
+ rc = grn_obj_set_info(context, table, GRN_INFO_NORMALIZER, normalizer);
841
+ rb_grn_context_check(context, self);
842
+ rb_grn_rc_check(rc, self);
843
+
844
+ return Qnil;
845
+ }
846
+
847
+ /*
848
+ * キーを正規化する場合は +true+ 、正規化しない場合は +false+ を返
849
+ * す。
850
+ *
851
+ * @overload normalize_key?
852
+ */
853
+ static VALUE
854
+ rb_grn_table_key_support_normalize_key_p (VALUE self)
855
+ {
856
+ VALUE normalizer;
857
+
858
+ normalizer = rb_grn_table_key_support_get_normalizer(self);
859
+ return CBOOL2RVAL(!NIL_P(normalizer));
677
860
  }
678
861
 
679
862
  /*
@@ -700,6 +883,9 @@ rb_grn_init_table_key_support (VALUE mGrn)
700
883
  rb_mGrnTableKeySupport = rb_define_module_under(rb_cGrnTable, "KeySupport");
701
884
  rb_include_module(rb_mGrnTableKeySupport, rb_mGrnEncodingSupport);
702
885
 
886
+ rb_define_method(rb_mGrnTableKeySupport, "inspect",
887
+ rb_grn_table_key_support_inspect, 0);
888
+
703
889
  rb_define_method(rb_mGrnTableKeySupport, "add",
704
890
  rb_grn_table_key_support_add, -1);
705
891
  rb_define_method(rb_mGrnTableKeySupport, "id",
@@ -710,7 +896,7 @@ rb_grn_init_table_key_support (VALUE mGrn)
710
896
  rb_grn_table_key_support_has_key, 1);
711
897
 
712
898
  rb_define_method(rb_mGrnTableKeySupport, "delete",
713
- rb_grn_table_key_support_delete, 1);
899
+ rb_grn_table_key_support_delete, -1);
714
900
 
715
901
  rb_define_method(rb_mGrnTableKeySupport, "[]",
716
902
  rb_grn_table_key_support_array_reference, 1);
@@ -732,8 +918,13 @@ rb_grn_init_table_key_support (VALUE mGrn)
732
918
  rb_define_method(rb_mGrnTableKeySupport, "default_tokenizer=",
733
919
  rb_grn_table_key_support_set_default_tokenizer, 1);
734
920
 
921
+ rb_define_method(rb_mGrnTableKeySupport, "normalizer",
922
+ rb_grn_table_key_support_get_normalizer, 0);
923
+ rb_define_method(rb_mGrnTableKeySupport, "normalizer=",
924
+ rb_grn_table_key_support_set_normalizer, 1);
925
+
735
926
  rb_define_method(rb_mGrnTableKeySupport, "normalize_key?",
736
- rb_grn_table_key_normalize_key_p, 0);
927
+ rb_grn_table_key_support_normalize_key_p, 0);
737
928
 
738
929
  rb_define_method(rb_mGrnTableKeySupport, "support_key?",
739
930
  rb_grn_table_key_support_support_key_p, 0);