rroonga 2.0.8 → 2.1.0

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.
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);