groonga 0.0.7 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/NEWS.ja.rdoc +56 -0
  2. data/NEWS.rdoc +58 -0
  3. data/Rakefile +2 -3
  4. data/benchmark/read-write-many-small-items.rb +16 -32
  5. data/benchmark/write-many-small-items.rb +14 -28
  6. data/example/bookmark.rb +19 -17
  7. data/example/index-html.rb +11 -1
  8. data/example/search/config.ru +14 -9
  9. data/ext/rb-grn-array.c +6 -6
  10. data/ext/rb-grn-column.c +348 -18
  11. data/ext/rb-grn-context.c +8 -4
  12. data/ext/rb-grn-database.c +6 -7
  13. data/ext/rb-grn-exception.c +101 -5
  14. data/ext/rb-grn-expression.c +206 -23
  15. data/ext/rb-grn-fix-size-column.c +6 -39
  16. data/ext/rb-grn-hash.c +24 -24
  17. data/ext/rb-grn-index-column.c +74 -19
  18. data/ext/rb-grn-logger.c +48 -0
  19. data/ext/rb-grn-object.c +281 -67
  20. data/ext/rb-grn-operation.c +1 -1
  21. data/ext/rb-grn-patricia-trie-cursor.c +10 -1
  22. data/ext/rb-grn-patricia-trie.c +268 -7
  23. data/ext/rb-grn-query.c +52 -1
  24. data/ext/rb-grn-record.c +8 -2
  25. data/ext/rb-grn-snippet.c +63 -1
  26. data/ext/rb-grn-table-cursor-key-support.c +15 -1
  27. data/ext/rb-grn-table-cursor.c +57 -0
  28. data/ext/rb-grn-table-key-support.c +382 -46
  29. data/ext/rb-grn-table.c +729 -192
  30. data/ext/rb-grn-type.c +63 -12
  31. data/ext/rb-grn-utils.c +156 -158
  32. data/ext/rb-grn-variable.c +18 -0
  33. data/ext/rb-grn.h +85 -21
  34. data/ext/rb-groonga.c +13 -3
  35. data/extconf.rb +19 -4
  36. data/html/developer.html +1 -1
  37. data/html/header.html.erb +1 -1
  38. data/html/index.html +4 -4
  39. data/lib/groonga.rb +10 -0
  40. data/lib/groonga/expression-builder.rb +81 -42
  41. data/lib/groonga/patricia-trie.rb +13 -0
  42. data/lib/groonga/record.rb +158 -13
  43. data/lib/groonga/schema.rb +339 -33
  44. data/pkg-config.rb +6 -1
  45. data/test-unit/lib/test/unit.rb +23 -42
  46. data/test-unit/lib/test/unit/assertionfailederror.rb +11 -0
  47. data/test-unit/lib/test/unit/assertions.rb +87 -9
  48. data/test-unit/lib/test/unit/autorunner.rb +20 -11
  49. data/test-unit/lib/test/unit/collector.rb +1 -8
  50. data/test-unit/lib/test/unit/collector/load.rb +2 -3
  51. data/test-unit/lib/test/unit/color-scheme.rb +13 -1
  52. data/test-unit/lib/test/unit/diff.rb +223 -37
  53. data/test-unit/lib/test/unit/error.rb +4 -0
  54. data/test-unit/lib/test/unit/failure.rb +31 -5
  55. data/test-unit/lib/test/unit/notification.rb +8 -4
  56. data/test-unit/lib/test/unit/omission.rb +51 -3
  57. data/test-unit/lib/test/unit/pending.rb +4 -0
  58. data/test-unit/lib/test/unit/testcase.rb +55 -4
  59. data/test-unit/lib/test/unit/ui/console/testrunner.rb +190 -4
  60. data/test-unit/lib/test/unit/ui/emacs/testrunner.rb +14 -0
  61. data/test-unit/lib/test/unit/ui/testrunner.rb +8 -0
  62. data/test-unit/lib/test/unit/version.rb +1 -1
  63. data/test-unit/sample/{tc_adder.rb → test_adder.rb} +3 -1
  64. data/test-unit/sample/{tc_subtracter.rb → test_subtracter.rb} +3 -1
  65. data/test-unit/sample/test_user.rb +1 -0
  66. data/test-unit/test/collector/test-descendant.rb +2 -4
  67. data/test-unit/test/collector/test_objectspace.rb +7 -5
  68. data/test-unit/test/run-test.rb +2 -0
  69. data/test-unit/test/test-color-scheme.rb +7 -0
  70. data/test-unit/test/test-diff.rb +48 -7
  71. data/test-unit/test/test-omission.rb +1 -1
  72. data/test-unit/test/test-testcase.rb +47 -0
  73. data/test-unit/test/test_assertions.rb +79 -10
  74. data/test/groonga-test-utils.rb +6 -1
  75. data/test/test-array.rb +29 -14
  76. data/test/test-column.rb +107 -55
  77. data/test/test-context.rb +5 -0
  78. data/test/test-database.rb +2 -37
  79. data/test/test-exception.rb +9 -1
  80. data/test/test-expression-builder.rb +23 -5
  81. data/test/test-expression.rb +44 -8
  82. data/test/test-fix-size-column.rb +16 -5
  83. data/test/test-gqtp.rb +70 -0
  84. data/test/test-hash.rb +142 -43
  85. data/test/test-index-column.rb +9 -9
  86. data/test/test-patricia-trie.rb +79 -20
  87. data/test/test-procedure.rb +4 -2
  88. data/test/test-record.rb +32 -20
  89. data/test/test-remote.rb +3 -2
  90. data/test/test-schema.rb +226 -92
  91. data/test/test-table-cursor.rb +103 -1
  92. data/test/test-table-offset-and-limit.rb +102 -0
  93. data/test/test-table-select-normalize.rb +4 -4
  94. data/test/test-table-select.rb +52 -8
  95. data/test/test-table.rb +235 -116
  96. data/test/test-type.rb +2 -2
  97. data/test/test-variable-size-column.rb +21 -5
  98. data/test/test-vector-column.rb +76 -0
  99. data/{TUTORIAL.ja.rdoc → text/TUTORIAL.ja.rdoc} +52 -52
  100. data/text/expression.rdoc +284 -0
  101. metadata +11 -7
  102. data/test-unit/sample/ts_examples.rb +0 -7
@@ -285,6 +285,7 @@ rb_grn_context_initialize (int argc, VALUE *argv, VALUE self)
285
285
 
286
286
  rb_grn_context = ALLOC(RbGrnContext);
287
287
  DATA_PTR(self) = rb_grn_context;
288
+ rb_grn_context->self = self;
288
289
  context = rb_grn_context->context = grn_ctx_open(flags);
289
290
  rb_grn_context_check(context, self);
290
291
 
@@ -440,8 +441,6 @@ rb_grn_context_connect (int argc, VALUE *argv, VALUE self)
440
441
  * context.send(string) -> ID
441
442
  *
442
443
  * groongaサーバにクエリ文字列を送信する。
443
- *
444
- * 実験的: APIが変わる可能性があります。
445
444
  */
446
445
  static VALUE
447
446
  rb_grn_context_send (VALUE self, VALUE rb_string)
@@ -466,8 +465,6 @@ rb_grn_context_send (VALUE self, VALUE rb_string)
466
465
  * context.receive -> [ID, String]
467
466
  *
468
467
  * groongaサーバからクエリ実行結果文字列を受信する。
469
- *
470
- * 実験的: APIが変わる可能性があります。
471
468
  */
472
469
  static VALUE
473
470
  rb_grn_context_receive (VALUE self)
@@ -606,6 +603,13 @@ rb_grn_context_array_reference (VALUE self, VALUE name_or_id)
606
603
  return GRNOBJECT2RVAL(Qnil, context, object, RB_GRN_FALSE);
607
604
  }
608
605
 
606
+ /*
607
+ * call-seq:
608
+ * context.pop -> 値
609
+ *
610
+ * コンテキスト内にあるスタックから値を取り出す。このスタッ
611
+ * クにはGroonga::Expression#executeの実行結果が格納される。
612
+ */
609
613
  static VALUE
610
614
  rb_grn_context_pop (VALUE self)
611
615
  {
@@ -78,7 +78,7 @@ rb_grn_database_close (VALUE self)
78
78
  {
79
79
  VALUE rb_context;
80
80
 
81
- rb_context = rb_iv_get(self, "context");
81
+ rb_context = rb_iv_get(self, "@context");
82
82
  if (!NIL_P(rb_context))
83
83
  rb_iv_set(rb_context, "database", Qnil);
84
84
 
@@ -140,9 +140,8 @@ rb_grn_database_s_create (int argc, VALUE *argv, VALUE klass)
140
140
  grn_obj_close(context, old_database);
141
141
  database = grn_db_create(context, path, &create_args);
142
142
  rb_grn_context_check(context, rb_ary_new4(argc, argv));
143
- rb_database = rb_grn_object_alloc(klass);
144
- rb_grn_object_assign(Qnil, rb_database, rb_context, context, database);
145
- rb_iv_set(rb_database, "context", rb_context);
143
+ rb_database = GRNOBJECT2RVAL(klass, context, database, RB_GRN_TRUE);
144
+ rb_iv_set(rb_database, "@context", rb_context);
146
145
  if (!NIL_P(rb_context))
147
146
  rb_iv_set(rb_context, "database", rb_database);
148
147
  rb_grn_context_check(context, rb_ary_new4(argc, argv));
@@ -194,7 +193,7 @@ rb_grn_database_initialize (int argc, VALUE *argv, VALUE self)
194
193
  rb_grn_object_assign(Qnil, self, rb_context, context, database);
195
194
  rb_grn_context_check(context, self);
196
195
 
197
- rb_iv_set(self, "context", rb_context);
196
+ rb_iv_set(self, "@context", rb_context);
198
197
  if (!NIL_P(rb_context))
199
198
  rb_iv_set(rb_context, "database", self);
200
199
 
@@ -222,7 +221,7 @@ rb_grn_database_s_open (int argc, VALUE *argv, VALUE klass)
222
221
  {
223
222
  VALUE database;
224
223
 
225
- database = rb_grn_object_alloc(klass);
224
+ database = rb_obj_alloc(klass);
226
225
  rb_grn_database_initialize(argc, argv, database);
227
226
  if (rb_block_given_p())
228
227
  return rb_ensure(rb_yield, database, rb_grn_database_close, database);
@@ -253,7 +252,7 @@ rb_grn_database_each (VALUE self)
253
252
  rb_grn_database_deconstruct(SELF(self), &database, &context,
254
253
  NULL, NULL, NULL, NULL);
255
254
  cursor = grn_table_cursor_open(context, database, NULL, 0, NULL, 0,
256
- 0, 0, GRN_CURSOR_ASCENDING);
255
+ 0, -1, GRN_CURSOR_ASCENDING);
257
256
  rb_cursor = GRNTABLECURSOR2RVAL(Qnil, context, cursor);
258
257
  rb_iv_set(self, "cursor", rb_cursor);
259
258
  while ((id = grn_table_cursor_next(context, cursor)) != GRN_ID_NIL) {
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby" -*- */
2
2
  /*
3
- Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
3
+ Copyright (C) 2009-2010 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
@@ -19,6 +19,8 @@
19
19
  #include "rb-grn.h"
20
20
 
21
21
  VALUE rb_eGrnError;
22
+ VALUE rb_eGrnObjectClosed;
23
+ VALUE rb_eGrnNoSuchColumn;
22
24
 
23
25
  static VALUE eGrnEndOfData;
24
26
  static VALUE eGrnUnknownError;
@@ -82,6 +84,11 @@ static VALUE eGrnOperationNotSupported;
82
84
  static VALUE eGrnAddressIsInUse;
83
85
  static VALUE eGrnZLibError;
84
86
  static VALUE eGrnLZOError;
87
+ static VALUE eGrnStackOverFlow;
88
+ static VALUE eGrnSyntaxError;
89
+ static VALUE eGrnRetryMax;
90
+ static VALUE eGrnIncompatibleFileFormat;
91
+ static VALUE eGrnUpdateNotAllowed;
85
92
 
86
93
  VALUE
87
94
  rb_grn_rc_to_exception (grn_rc rc)
@@ -90,6 +97,7 @@ rb_grn_rc_to_exception (grn_rc rc)
90
97
 
91
98
  switch (rc) {
92
99
  case GRN_SUCCESS:
100
+ return Qnil;
93
101
  break;
94
102
  case GRN_END_OF_DATA:
95
103
  exception = eGrnEndOfData;
@@ -277,11 +285,26 @@ rb_grn_rc_to_exception (grn_rc rc)
277
285
  case GRN_LZO_ERROR:
278
286
  exception = eGrnLZOError;
279
287
  break;
280
- default:
281
- rb_raise(rb_eGrnError, "invalid return code: %d", rc);
288
+ case GRN_STACK_OVER_FLOW:
289
+ exception = eGrnStackOverFlow;
290
+ break;
291
+ case GRN_SYNTAX_ERROR:
292
+ exception = eGrnSyntaxError;
293
+ break;
294
+ case GRN_RETRY_MAX:
295
+ exception = eGrnRetryMax;
296
+ break;
297
+ case GRN_INCOMPATIBLE_FILE_FORMAT:
298
+ exception = eGrnIncompatibleFileFormat;
299
+ break;
300
+ case GRN_UPDATE_NOT_ALLOWED:
301
+ exception = eGrnUpdateNotAllowed;
282
302
  break;
283
303
  }
284
304
 
305
+ if (NIL_P(exception))
306
+ rb_raise(rb_eGrnError, "invalid return code: %d", rc);
307
+
285
308
  return exception;
286
309
  }
287
310
 
@@ -292,6 +315,7 @@ rb_grn_rc_to_message (grn_rc rc)
292
315
 
293
316
  switch (rc) {
294
317
  case GRN_SUCCESS:
318
+ return NULL;
295
319
  break;
296
320
  case GRN_END_OF_DATA:
297
321
  message = "end of data";
@@ -479,11 +503,26 @@ rb_grn_rc_to_message (grn_rc rc)
479
503
  case GRN_LZO_ERROR:
480
504
  message = "LZO error";
481
505
  break;
482
- default:
483
- rb_raise(rb_eGrnError, "invalid return code: %d", rc);
506
+ case GRN_STACK_OVER_FLOW:
507
+ message = "stack over flow";
508
+ break;
509
+ case GRN_SYNTAX_ERROR:
510
+ message = "syntax error";
511
+ break;
512
+ case GRN_RETRY_MAX:
513
+ message = "retry max";
514
+ break;
515
+ case GRN_INCOMPATIBLE_FILE_FORMAT:
516
+ message = "incompatible file format";
517
+ break;
518
+ case GRN_UPDATE_NOT_ALLOWED:
519
+ message = "update isn't allowed";
484
520
  break;
485
521
  }
486
522
 
523
+ if (!message)
524
+ rb_raise(rb_eGrnError, "invalid return code: %d", rc);
525
+
487
526
  return message;
488
527
  }
489
528
 
@@ -515,6 +554,23 @@ rb_grn_init_exception (VALUE mGrn)
515
554
  rb_eGrnError =
516
555
  rb_define_class_under(mGrn, "Error", rb_eStandardError);
517
556
 
557
+ /*
558
+ * Document-class: Groonga::ObjectClosed
559
+ *
560
+ * groongaレベルでは破棄されているが、Rubyレベルでは生き
561
+ * ているオブジェクトにアクセスすると発生する。
562
+ */
563
+ rb_eGrnObjectClosed =
564
+ rb_define_class_under(mGrn, "ObjectClosed", rb_eGrnError);
565
+
566
+ /*
567
+ * Document-class: Groonga::NoSuchColumn
568
+ *
569
+ * 存在しないカラムにアクセスすると発生する。
570
+ */
571
+ rb_eGrnNoSuchColumn =
572
+ rb_define_class_under(mGrn, "NoSuchColumn", rb_eGrnError);
573
+
518
574
  /*
519
575
  * Document-class: Groonga::EndOfData
520
576
  *
@@ -1011,4 +1067,44 @@ rb_grn_init_exception (VALUE mGrn)
1011
1067
  */
1012
1068
  eGrnLZOError =
1013
1069
  rb_define_class_under(mGrn, "LZOError", rb_eGrnError);
1070
+
1071
+ /*
1072
+ * Document-class: Groonga::StackOverFlow
1073
+ *
1074
+ * スタックオーバーフロー時に発生する。
1075
+ */
1076
+ eGrnStackOverFlow =
1077
+ rb_define_class_under(mGrn, "StackOverFlow", rb_eGrnError);
1078
+
1079
+ /*
1080
+ * Document-class: Groonga::SyntaxError
1081
+ *
1082
+ * 構文に問題があるときに発生する。
1083
+ */
1084
+ eGrnSyntaxError =
1085
+ rb_define_class_under(mGrn, "SyntaxError", rb_eGrnError);
1086
+
1087
+ /*
1088
+ * Document-class: Groonga::RetryMax
1089
+ *
1090
+ * 再試行回数が最大数に達したときに発生する。
1091
+ */
1092
+ eGrnRetryMax =
1093
+ rb_define_class_under(mGrn, "RetryMax", rb_eGrnError);
1094
+
1095
+ /*
1096
+ * Document-class: Groonga::IncompatibleFileFormat
1097
+ *
1098
+ * 互換性のないファイルフォーマットを読み込んだときに発生する。
1099
+ */
1100
+ eGrnIncompatibleFileFormat =
1101
+ rb_define_class_under(mGrn, "IncompatibleFileFormat", rb_eGrnError);
1102
+
1103
+ /*
1104
+ * Document-class: Groonga::UpdateNotAllowed
1105
+ *
1106
+ * 更新操作が許可されていないのに更新操作を行ったときに発生する。
1107
+ */
1108
+ eGrnUpdateNotAllowed =
1109
+ rb_define_class_under(mGrn, "UpdateNotAllowed", rb_eGrnError);
1014
1110
  }
@@ -22,6 +22,13 @@
22
22
 
23
23
  VALUE rb_cGrnExpression;
24
24
 
25
+ /*
26
+ * Document-class: Groonga::Expression < Groonga::Object
27
+ *
28
+ * 検索条件やデータベースへの操作を表現するオブジェクト。
29
+ *
30
+ */
31
+
25
32
  void
26
33
  rb_grn_expression_finalizer (grn_ctx *context, grn_obj *object,
27
34
  RbGrnExpression *rb_grn_expression)
@@ -94,6 +101,20 @@ rb_grn_expression_initialize (int argc, VALUE *argv, VALUE self)
94
101
  return Qnil;
95
102
  }
96
103
 
104
+ /*
105
+ * call-seq:
106
+ * expression.define_variable(options={}) -> Groonga::Variable
107
+ *
108
+ * _expression_で使用可能な変数を作成する。
109
+ *
110
+ * _options_に指定可能な値は以下の通り。
111
+ *
112
+ * [+:name+]
113
+ * 変数の名前。省略した場合は名前を付けない。
114
+ *
115
+ * [+:domain+]
116
+ * テーブルを指定すると、そのテーブル用のレコードとして初期化する。
117
+ */
97
118
  static VALUE
98
119
  rb_grn_expression_define_variable (int argc, VALUE *argv, VALUE self)
99
120
  {
@@ -131,6 +152,14 @@ rb_grn_expression_define_variable (int argc, VALUE *argv, VALUE self)
131
152
  return rb_variable;
132
153
  }
133
154
 
155
+ /*
156
+ * call-seq:
157
+ * expression.append_object(object,
158
+ * operation=Groonga::Operation::PUSH,
159
+ * n_arguments=1) -> self
160
+ *
161
+ * _object_を追加し、_n_arguments_個の引数を取る_operation_を追加する。
162
+ */
134
163
  static VALUE
135
164
  rb_grn_expression_append_object (int argc, VALUE *argv, VALUE self)
136
165
  {
@@ -157,10 +186,19 @@ rb_grn_expression_append_object (int argc, VALUE *argv, VALUE self)
157
186
  return self;
158
187
  }
159
188
 
189
+ /*
190
+ * call-seq:
191
+ * expression.append_constant(constant,
192
+ * operation=Groonga::Operation::PUSH,
193
+ * n_arguments=1) -> self
194
+ *
195
+ * _constant_を追加し、_n_arguments_個の引数を取る_operation_を追加する。
196
+ */
160
197
  static VALUE
161
198
  rb_grn_expression_append_constant (int argc, VALUE *argv, VALUE self)
162
199
  {
163
200
  VALUE rb_constant, rb_operator, rb_n_arguments;
201
+ VALUE exception;
164
202
  grn_ctx *context = NULL;
165
203
  grn_obj *expression, *constant = NULL;
166
204
  grn_operator operator = GRN_OP_PUSH;
@@ -178,11 +216,21 @@ rb_grn_expression_append_constant (int argc, VALUE *argv, VALUE self)
178
216
 
179
217
  RVAL2GRNOBJ(rb_constant, context, &constant);
180
218
  grn_expr_append_const(context, expression, constant, operator, n_arguments);
219
+
220
+ exception = rb_grn_context_to_exception(context, self);
181
221
  grn_obj_close(context, constant);
182
- rb_grn_context_check(context, self);
222
+ if (!NIL_P(exception))
223
+ rb_exc_raise(exception);
224
+
183
225
  return self;
184
226
  }
185
227
 
228
+ /*
229
+ * call-seq:
230
+ * expression.append_operation(operation, n_arguments)
231
+ *
232
+ * _n_arguments_個の引数を取る_operation_を追加する。
233
+ */
186
234
  static VALUE
187
235
  rb_grn_expression_append_operation (VALUE self, VALUE rb_operation,
188
236
  VALUE rb_n_arguments)
@@ -203,6 +251,84 @@ rb_grn_expression_append_operation (VALUE self, VALUE rb_operation,
203
251
  return Qnil;
204
252
  }
205
253
 
254
+ /*
255
+ * call-seq:
256
+ * expression.parse(query, options={})
257
+ *
258
+ * 文字列_query_をパースする。
259
+ *
260
+ * _options_に指定可能な値は以下の通り。
261
+ *
262
+ * [+:default_column+]
263
+ * "column_name:hoge"ではなく"hoge"のようにcolumn_nameが指
264
+ * 定されない条件の検索対象となるカラムを指定する。
265
+ *
266
+ * [+:default_operator+]
267
+ * "+"や"OR"で繋がれず、ただ列挙された複数の条件があった時、
268
+ * _expression_全体として各レコードをヒットとみなすかの論理
269
+ * 条件を指定する。省略した場合はGroonga::Operation::AND。
270
+ *
271
+ * [Groonga::Operation::OR]
272
+ * レコードはいずれかの条件にマッチすればいい。
273
+ * [Groonga::Operation::AND]
274
+ * レコードは全ての条件にマッチしなければならない。
275
+ * [Groonga::Operation::BUT]
276
+ * 最初の条件にレコードはマッチし、残りの条件にレコードは
277
+ * マッチしてはならない。
278
+ *
279
+ * [+:default_mode+]
280
+ * 検索時のモードを指定する。省略した場合は
281
+ * Groonga::Operation::MATCH。(FIXME: モードによってどう
282
+ * いう動作になるかを書く。)
283
+ *
284
+ * [+:syntax+]
285
+ * _query_の構文を指定する。指定可能な値は以下の通り。省略
286
+ * した場合は+:query+。
287
+ *
288
+ * [+nil+]
289
+ * +:query+と同様。
290
+ * [+:query+]
291
+ * 「文字列1 OR 文字列2」で「"文字列1"あるいは"文字列2"
292
+ * にマッチという検索エンジンで利用できるような構文を使
293
+ * う。
294
+ *
295
+ * 参考: grn式のquery形式(link:text/expression_rdoc.html)
296
+ * [+:script+]
297
+ * 「[カラム名] == [値]」というようにECMAScript風の構文
298
+ * を使う。
299
+ *
300
+ * 参考: grn式のscript形式(link:text/expression_rdoc.html)
301
+ *
302
+ * [+:allow_pragma+]
303
+ * _query_の構文にqueryを用いているとき(+:syntax+オプショ
304
+ * ン参照)、「*E-1」というようにクエリの先頭でpragmaを利
305
+ * 用できるようにする。script構文を用いているときはこのオ
306
+ * プションを利用できない。
307
+ *
308
+ * デフォルトではプラグマを利用できる。
309
+ *
310
+ * 参考: grn式のquery形式(link:text/expression_rdoc.html)
311
+ *
312
+ * [+:allow_column+]
313
+ * _query_の構文にqueryを用いているとき(+:syntax+オプショ
314
+ * ン参照)、「カラム名:値」というようにカラム名を指定した
315
+ * 条件式を利用できるようにする。script構文を用いていると
316
+ * きはこのオプションを利用できない。
317
+ *
318
+ * デフォルトではカラム名を指定した条件式を利用できる。
319
+ *
320
+ * 参考: grn式のquery形式(link:text/expression_rdoc.html)
321
+ *
322
+ * [+:allow_update+]
323
+ * _query_の構文にscriptを用いているとき(+:syntax+オプショ
324
+ * ン参照)、「カラム名 = 値」というように更新操作を利用で
325
+ * きるようにする。query構文を用いているときはこのオプショ
326
+ * ンを利用できない。
327
+ *
328
+ * デフォルトでは更新操作を利用できる。
329
+ *
330
+ * 参考: grn式のscript形式(link:text/expression_rdoc.html)
331
+ */
206
332
  static VALUE
207
333
  rb_grn_expression_parse (int argc, VALUE *argv, VALUE self)
208
334
  {
@@ -213,9 +339,10 @@ rb_grn_expression_parse (int argc, VALUE *argv, VALUE self)
213
339
  grn_rc rc;
214
340
  char *query = NULL;
215
341
  unsigned query_size = 0;
216
- int parse_level = 0;
342
+ grn_expr_flags flags = 0;
217
343
  VALUE options, rb_query, rb_default_column, rb_default_operator;
218
- VALUE rb_default_mode, rb_parser;
344
+ VALUE rb_default_mode, rb_syntax;
345
+ VALUE rb_allow_pragma, rb_allow_column, rb_allow_update;
219
346
  VALUE exception = Qnil;
220
347
 
221
348
  rb_scan_args(argc, argv, "11", &rb_query, &options);
@@ -223,7 +350,10 @@ rb_grn_expression_parse (int argc, VALUE *argv, VALUE self)
223
350
  "default_column", &rb_default_column,
224
351
  "default_operator", &rb_default_operator,
225
352
  "default_mode", &rb_default_mode,
226
- "parser", &rb_parser,
353
+ "syntax", &rb_syntax,
354
+ "allow_pragma", &rb_allow_pragma,
355
+ "allow_column", &rb_allow_column,
356
+ "allow_update", &rb_allow_update,
227
357
  NULL);
228
358
 
229
359
  query = StringValuePtr(rb_query);
@@ -238,29 +368,55 @@ rb_grn_expression_parse (int argc, VALUE *argv, VALUE self)
238
368
  default_mode = RVAL2GRNOPERATOR(rb_default_mode);
239
369
  if (!NIL_P(rb_default_operator))
240
370
  default_operator = RVAL2GRNOPERATOR(rb_default_operator);
241
- if (NIL_P(rb_parser) ||
242
- rb_grn_equal_option(rb_parser, "column") ||
243
- rb_grn_equal_option(rb_parser, "column-query") ||
244
- rb_grn_equal_option(rb_parser, "column_query")) {
245
- parse_level = 0;
246
- } else if (rb_grn_equal_option(rb_parser, "table") ||
247
- rb_grn_equal_option(rb_parser, "table-query") ||
248
- rb_grn_equal_option(rb_parser, "table_query")) {
249
- parse_level = 2;
250
- } else if (rb_grn_equal_option(rb_parser, "expression") ||
251
- rb_grn_equal_option(rb_parser, "language")) {
252
- parse_level = 4;
371
+
372
+ if (NIL_P(rb_syntax) ||
373
+ rb_grn_equal_option(rb_syntax, "query")) {
374
+ flags = GRN_EXPR_SYNTAX_QUERY;
375
+ } else if (rb_grn_equal_option(rb_syntax, "script")) {
376
+ flags = GRN_EXPR_SYNTAX_SCRIPT;
253
377
  } else {
254
378
  rb_raise(rb_eArgError,
255
- "parser should be one of "
256
- "[nil, :column, :column_query, :table, :table_query, "
257
- ":expression, :language]: %s",
258
- rb_grn_inspect(rb_parser));
379
+ "syntax should be one of "
380
+ "[nil, :query, :script]: %s",
381
+ rb_grn_inspect(rb_syntax));
382
+ }
383
+
384
+ if (NIL_P(rb_allow_pragma)) {
385
+ if ((flags & GRN_EXPR_SYNTAX_QUERY) == GRN_EXPR_SYNTAX_QUERY)
386
+ flags |= GRN_EXPR_ALLOW_PRAGMA;
387
+ } else {
388
+ if ((flags & GRN_EXPR_SYNTAX_SCRIPT) == GRN_EXPR_SYNTAX_SCRIPT)
389
+ rb_raise(rb_eArgError,
390
+ ":allow_pragma isn't allowed in script syntax");
391
+ if (RVAL2CBOOL(rb_allow_pragma))
392
+ flags |= GRN_EXPR_ALLOW_PRAGMA;
393
+ }
394
+
395
+ if (NIL_P(rb_allow_column)) {
396
+ if ((flags & GRN_EXPR_SYNTAX_QUERY) == GRN_EXPR_SYNTAX_QUERY)
397
+ flags |= GRN_EXPR_ALLOW_COLUMN;
398
+ } else {
399
+ if ((flags & GRN_EXPR_SYNTAX_SCRIPT) == GRN_EXPR_SYNTAX_SCRIPT)
400
+ rb_raise(rb_eArgError,
401
+ ":allow_column isn't allowed in script syntax");
402
+ if (RVAL2CBOOL(rb_allow_column))
403
+ flags |= GRN_EXPR_ALLOW_COLUMN;
404
+ }
405
+
406
+ if (NIL_P(rb_allow_update)) {
407
+ if ((flags & GRN_EXPR_SYNTAX_SCRIPT) == GRN_EXPR_SYNTAX_SCRIPT)
408
+ flags |= GRN_EXPR_ALLOW_UPDATE;
409
+ } else {
410
+ if ((flags & GRN_EXPR_SYNTAX_QUERY) == GRN_EXPR_SYNTAX_QUERY)
411
+ rb_raise(rb_eArgError,
412
+ ":allow_update isn't allowed in query syntax");
413
+ if (RVAL2CBOOL(rb_allow_update))
414
+ flags |= GRN_EXPR_ALLOW_UPDATE;
259
415
  }
260
416
 
261
417
  rc = grn_expr_parse(context, expression, query, query_size,
262
418
  default_column, default_mode, default_operator,
263
- parse_level);
419
+ flags);
264
420
  if (rc != GRN_SUCCESS) {
265
421
  VALUE related_object;
266
422
 
@@ -275,6 +431,12 @@ rb_grn_expression_parse (int argc, VALUE *argv, VALUE self)
275
431
  return Qnil;
276
432
  }
277
433
 
434
+ /*
435
+ * call-seq:
436
+ * expression.execute
437
+ *
438
+ * _expression_を実行する。
439
+ */
278
440
  static VALUE
279
441
  rb_grn_expression_execute (VALUE self)
280
442
  {
@@ -293,6 +455,12 @@ rb_grn_expression_execute (VALUE self)
293
455
  return Qnil;
294
456
  }
295
457
 
458
+ /*
459
+ * call-seq:
460
+ * expression.compile
461
+ *
462
+ * _expression_をコンパイルする。
463
+ */
296
464
  static VALUE
297
465
  rb_grn_expression_compile (VALUE self)
298
466
  {
@@ -311,6 +479,15 @@ rb_grn_expression_compile (VALUE self)
311
479
  return Qnil;
312
480
  }
313
481
 
482
+ /*
483
+ * call-seq:
484
+ * expression[name] -> 変数の値
485
+ * expression[offset] -> 変数の値
486
+ *
487
+ * _expression_で使用可能な変数のうち、名前が_name_または
488
+ * _offset_番目にExpression#append_objectされた変数の値を返
489
+ * す。
490
+ */
314
491
  static VALUE
315
492
  rb_grn_expression_array_reference (VALUE self, VALUE rb_name_or_offset)
316
493
  {
@@ -329,12 +506,12 @@ rb_grn_expression_array_reference (VALUE self, VALUE rb_name_or_offset)
329
506
  name = RSTRING_PTR(rb_name_or_offset);
330
507
  name_size = RSTRING_LEN(rb_name_or_offset);
331
508
  variable = grn_expr_get_var(context, expression, name, name_size);
332
- return GRNBULK2RVAL(context, variable, self);
509
+ return GRNBULK2RVAL(context, variable, NULL, self);
333
510
  break;
334
511
  case T_FIXNUM:
335
512
  offset = NUM2INT(rb_name_or_offset);
336
513
  value = grn_expr_get_var_by_offset(context, expression, offset);
337
- return GRNBULK2RVAL(context, value, self);
514
+ return GRNBULK2RVAL(context, value, NULL, self);
338
515
  break;
339
516
  default:
340
517
  rb_raise(rb_eArgError, "xxx");
@@ -347,6 +524,12 @@ rb_grn_expression_array_reference (VALUE self, VALUE rb_name_or_offset)
347
524
  /* REMOVE ME */
348
525
  grn_rc grn_expr_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *expr);
349
526
 
527
+ /*
528
+ * call-seq:
529
+ * _expression_.inspect -> String
530
+ *
531
+ * _expression_の中身を人に見やすい文字列で返す。
532
+ */
350
533
  static VALUE
351
534
  rb_grn_expression_inspect (VALUE self)
352
535
  {