1/* -*- c-basic-offset: 2 -*- */
2/*
3 Copyright(C) 2013-2017 Brazil
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#include "../grn_ctx_impl.h"
20
21#ifdef GRN_WITH_MRUBY
22#include <mruby.h>
23#include <mruby/class.h>
24#include <mruby/variable.h>
25#include <mruby/data.h>
26#include <mruby/string.h>
27#include <mruby/array.h>
28#include <mruby/hash.h>
29
30#include "../grn_expr.h"
31#include "../grn_proc.h"
32#include "../grn_util.h"
33#include "../grn_mrb.h"
34#include "mrb_accessor.h"
35#include "mrb_ctx.h"
36#include "mrb_expr.h"
37#include "mrb_operator.h"
38#include "mrb_converter.h"
39#include "mrb_options.h"
40
41static struct mrb_data_type mrb_grn_scan_info_type = {
42 "Groonga::ScanInfo",
43 NULL
44};
45static struct mrb_data_type mrb_grn_expr_code_type = {
46 "Groonga::ExpressionCode",
47 NULL
48};
49static struct mrb_data_type mrb_grn_expression_type = {
50 "Groonga::Expression",
51 NULL
52};
53
54static mrb_value
55mrb_grn_scan_info_new(mrb_state *mrb, scan_info *scan_info)
56{
57 grn_ctx *ctx = (grn_ctx *)mrb->ud;
58 struct RClass *module = ctx->impl->mrb.module;
59 struct RClass *klass;
60 mrb_value mrb_scan_info;
61
62 mrb_scan_info = mrb_cptr_value(mrb, scan_info);
63 klass = mrb_class_get_under(mrb, module, "ScanInfo");
64 return mrb_obj_new(mrb, klass, 1, &mrb_scan_info);
65}
66
67static mrb_value
68mrb_grn_expr_code_new(mrb_state *mrb, grn_expr_code *code)
69{
70 grn_ctx *ctx = (grn_ctx *)mrb->ud;
71 struct RClass *module = ctx->impl->mrb.module;
72 struct RClass *klass;
73 mrb_value mrb_code;
74
75 mrb_code = mrb_cptr_value(mrb, code);
76 klass = mrb_class_get_under(mrb, module, "ExpressionCode");
77 return mrb_obj_new(mrb, klass, 1, &mrb_code);
78}
79
80static mrb_value
81mrb_grn_scan_info_initialize(mrb_state *mrb, mrb_value self)
82{
83 mrb_value mrb_ptr;
84
85 mrb_get_args(mrb, "o", &mrb_ptr);
86 DATA_TYPE(self) = &mrb_grn_scan_info_type;
87 DATA_PTR(self) = mrb_cptr(mrb_ptr);
88 return self;
89}
90
91static mrb_value
92mrb_grn_expr_code_initialize(mrb_state *mrb, mrb_value self)
93{
94 mrb_value mrb_code;
95
96 mrb_get_args(mrb, "o", &mrb_code);
97 DATA_TYPE(self) = &mrb_grn_expr_code_type;
98 DATA_PTR(self) = mrb_cptr(mrb_code);
99 return self;
100}
101
102static mrb_value
103mrb_grn_scan_info_put_index(mrb_state *mrb, mrb_value self)
104{
105 grn_ctx *ctx = (grn_ctx *)mrb->ud;
106 scan_info *si;
107 mrb_value mrb_index;
108 mrb_int sid;
109 mrb_int weight;
110 mrb_value mrb_scorer;
111 mrb_value mrb_scorer_args_expr;
112 mrb_int scorer_args_expr_offset;
113 grn_obj *index;
114 grn_obj *scorer = NULL;
115 grn_obj *scorer_args_expr = NULL;
116
117 mrb_get_args(mrb, "oiiooi",
118 &mrb_index, &sid, &weight,
119 &mrb_scorer,
120 &mrb_scorer_args_expr,
121 &scorer_args_expr_offset);
122 si = DATA_PTR(self);
123 index = DATA_PTR(mrb_index);
124 if (!mrb_nil_p(mrb_scorer)) {
125 scorer = DATA_PTR(mrb_scorer);
126 }
127 if (!mrb_nil_p(mrb_scorer_args_expr)) {
128 scorer_args_expr = DATA_PTR(mrb_scorer_args_expr);
129 }
130 grn_scan_info_put_index(ctx, si, index, sid, weight,
131 scorer,
132 scorer_args_expr,
133 scorer_args_expr_offset);
134 return self;
135}
136
137static mrb_value
138mrb_grn_scan_info_get_op(mrb_state *mrb, mrb_value self)
139{
140 scan_info *si;
141 grn_operator op;
142
143 si = DATA_PTR(self);
144 op = grn_scan_info_get_op(si);
145 return grn_mrb_value_from_operator(mrb, op);
146}
147
148static mrb_value
149mrb_grn_scan_info_set_op(mrb_state *mrb, mrb_value self)
150{
151 scan_info *si;
152 mrb_value mrb_op;
153 grn_operator op;
154
155 mrb_get_args(mrb, "o", &mrb_op);
156 si = DATA_PTR(self);
157 op = grn_mrb_value_to_operator(mrb, mrb_op);
158 grn_scan_info_set_op(si, op);
159 return self;
160}
161
162static mrb_value
163mrb_grn_scan_info_set_end(mrb_state *mrb, mrb_value self)
164{
165 scan_info *si;
166 mrb_int end;
167
168 mrb_get_args(mrb, "i", &end);
169 si = DATA_PTR(self);
170 grn_scan_info_set_end(si, end);
171 return self;
172}
173
174static mrb_value
175mrb_grn_scan_info_set_query(mrb_state *mrb, mrb_value self)
176{
177 scan_info *si;
178 mrb_value mrb_query;
179
180 mrb_get_args(mrb, "o", &mrb_query);
181 si = DATA_PTR(self);
182 if (mrb_nil_p(mrb_query)) {
183 grn_scan_info_set_query(si, NULL);
184 } else {
185 grn_scan_info_set_query(si, DATA_PTR(mrb_query));
186 }
187 return self;
188}
189
190static mrb_value
191mrb_grn_scan_info_set_flags(mrb_state *mrb, mrb_value self)
192{
193 scan_info *si;
194 mrb_int flags;
195
196 mrb_get_args(mrb, "i", &flags);
197 si = DATA_PTR(self);
198 grn_scan_info_set_flags(si, flags);
199 return self;
200}
201
202static mrb_value
203mrb_grn_scan_info_get_flags(mrb_state *mrb, mrb_value self)
204{
205 scan_info *si;
206 int flags;
207
208 si = DATA_PTR(self);
209 flags = grn_scan_info_get_flags(si);
210 return mrb_fixnum_value(flags);
211}
212
213static mrb_value
214mrb_grn_scan_info_set_logical_op(mrb_state *mrb, mrb_value self)
215{
216 scan_info *si;
217 mrb_value mrb_logical_op;
218 grn_operator logical_op;
219
220 mrb_get_args(mrb, "o", &mrb_logical_op);
221 si = DATA_PTR(self);
222 logical_op = grn_mrb_value_to_operator(mrb, mrb_logical_op);
223 grn_scan_info_set_logical_op(si, logical_op);
224 return self;
225}
226
227static mrb_value
228mrb_grn_scan_info_get_logical_op(mrb_state *mrb, mrb_value self)
229{
230 scan_info *si;
231 grn_operator logical_op;
232
233 si = DATA_PTR(self);
234 logical_op = grn_scan_info_get_logical_op(si);
235 return grn_mrb_value_from_operator(mrb, logical_op);
236}
237
238static mrb_value
239mrb_grn_scan_info_set_max_interval(mrb_state *mrb, mrb_value self)
240{
241 scan_info *si;
242 mrb_int max_interval;
243
244 mrb_get_args(mrb, "i", &max_interval);
245 si = DATA_PTR(self);
246 grn_scan_info_set_max_interval(si, max_interval);
247 return self;
248}
249
250static mrb_value
251mrb_grn_scan_info_get_max_interval(mrb_state *mrb, mrb_value self)
252{
253 scan_info *si;
254 int max_interval;
255
256 si = DATA_PTR(self);
257 max_interval = grn_scan_info_get_max_interval(si);
258 return mrb_fixnum_value(max_interval);
259}
260
261static mrb_value
262mrb_grn_scan_info_set_similarity_threshold(mrb_state *mrb, mrb_value self)
263{
264 scan_info *si;
265 mrb_int similarity_threshold;
266
267 mrb_get_args(mrb, "i", &similarity_threshold);
268 si = DATA_PTR(self);
269 grn_scan_info_set_similarity_threshold(si, similarity_threshold);
270 return self;
271}
272
273static mrb_value
274mrb_grn_scan_info_get_similarity_threshold(mrb_state *mrb, mrb_value self)
275{
276 scan_info *si;
277 int similarity_threshold;
278
279 si = DATA_PTR(self);
280 similarity_threshold = grn_scan_info_get_similarity_threshold(si);
281 return mrb_fixnum_value(similarity_threshold);
282}
283
284static mrb_value
285mrb_grn_scan_info_get_arg(mrb_state *mrb, mrb_value self)
286{
287 grn_ctx *ctx = (grn_ctx *)mrb->ud;
288 scan_info *si;
289 mrb_int index;
290 grn_obj *arg;
291
292 mrb_get_args(mrb, "i", &index);
293
294 si = DATA_PTR(self);
295 arg = grn_scan_info_get_arg(ctx, si, index);
296
297 return grn_mrb_value_from_grn_obj(mrb, arg);
298}
299
300static mrb_value
301mrb_grn_scan_info_push_arg(mrb_state *mrb, mrb_value self)
302{
303 scan_info *si;
304 mrb_value mrb_arg;
305 grn_bool success;
306
307 mrb_get_args(mrb, "o", &mrb_arg);
308
309 si = DATA_PTR(self);
310 success = grn_scan_info_push_arg(si, DATA_PTR(mrb_arg));
311
312 return mrb_bool_value(success);
313}
314
315static mrb_value
316mrb_grn_scan_info_get_start_position(mrb_state *mrb, mrb_value self)
317{
318 scan_info *si;
319 int start_position;
320
321 si = DATA_PTR(self);
322 start_position = grn_scan_info_get_start_position(si);
323 return mrb_fixnum_value(start_position);
324}
325
326static mrb_value
327mrb_grn_scan_info_set_start_position(mrb_state *mrb, mrb_value self)
328{
329 scan_info *si;
330 mrb_int start_position;
331
332 mrb_get_args(mrb, "i", &start_position);
333 si = DATA_PTR(self);
334 grn_scan_info_set_start_position(si, start_position);
335 return self;
336}
337
338static mrb_value
339mrb_grn_scan_info_reset_position(mrb_state *mrb, mrb_value self)
340{
341 scan_info *si;
342
343 si = DATA_PTR(self);
344 grn_scan_info_reset_position(si);
345 return self;
346}
347
348static mrb_value
349mrb_grn_expr_code_inspect(mrb_state *mrb, mrb_value self)
350{
351 grn_ctx *ctx = (grn_ctx *)mrb->ud;
352 grn_expr_code *code;
353 mrb_value inspected;
354
355 code = DATA_PTR(self);
356
357 inspected = mrb_str_buf_new(mrb, 48);
358
359 mrb_str_cat_lit(mrb, inspected, "#<");
360 mrb_str_cat_cstr(mrb, inspected, mrb_obj_classname(mrb, self));
361 mrb_str_cat_lit(mrb, inspected, ":");
362 mrb_str_concat(mrb, inspected, mrb_ptr_to_str(mrb, mrb_cptr(self)));
363
364 {
365 int32_t weight;
366 uint32_t offset;
367
368 weight = grn_expr_code_get_weight(ctx, DATA_PTR(self), &offset);
369
370 mrb_str_cat_lit(mrb, inspected, " weight=");
371 mrb_str_concat(mrb, inspected,
372 mrb_funcall(mrb,
373 mrb_fixnum_value(weight),
374 "inspect",
375 0));
376 mrb_str_cat_lit(mrb, inspected, ", offset=");
377 mrb_str_concat(mrb, inspected,
378 mrb_funcall(mrb,
379 mrb_fixnum_value(offset),
380 "inspect",
381 0));
382 }
383
384 mrb_str_cat_lit(mrb, inspected, ", n_args=");
385 mrb_str_concat(mrb, inspected,
386 mrb_funcall(mrb,
387 mrb_fixnum_value(code->nargs),
388 "inspect",
389 0));
390
391 mrb_str_cat_lit(mrb, inspected, ", modify=");
392 mrb_str_concat(mrb, inspected,
393 mrb_funcall(mrb,
394 mrb_fixnum_value(code->modify),
395 "inspect",
396 0));
397
398 mrb_str_cat_lit(mrb, inspected, ", op=");
399 mrb_str_concat(mrb, inspected,
400 mrb_funcall(mrb,
401 grn_mrb_value_from_operator(mrb, code->op),
402 "inspect",
403 0));
404
405 mrb_str_cat_lit(mrb, inspected, ", flags=");
406 mrb_str_concat(mrb, inspected,
407 mrb_funcall(mrb,
408 mrb_fixnum_value(code->flags),
409 "inspect",
410 0));
411
412 mrb_str_cat_lit(mrb, inspected, ", value=");
413 mrb_str_concat(mrb, inspected,
414 mrb_funcall(mrb,
415 grn_mrb_value_from_grn_obj(mrb, code->value),
416 "inspect",
417 0));
418
419 mrb_str_cat_lit(mrb, inspected, ">");
420
421 return inspected;
422}
423
424static mrb_value
425mrb_grn_expr_code_get_weight(mrb_state *mrb, mrb_value self)
426{
427 grn_ctx *ctx = (grn_ctx *)mrb->ud;
428 int32_t weight;
429 uint32_t offset;
430 mrb_value mrb_values[2];
431
432 weight = grn_expr_code_get_weight(ctx, DATA_PTR(self), &offset);
433 mrb_values[0] = mrb_fixnum_value(weight);
434 mrb_values[1] = mrb_fixnum_value(offset);
435 return mrb_ary_new_from_values(mrb, 2, mrb_values);
436}
437
438static mrb_value
439mrb_grn_expr_code_get_value(mrb_state *mrb, mrb_value self)
440{
441 grn_expr_code *expr_code;
442
443 expr_code = DATA_PTR(self);
444 return grn_mrb_value_from_grn_obj(mrb, expr_code->value);
445}
446
447static mrb_value
448mrb_grn_expr_code_get_n_args(mrb_state *mrb, mrb_value self)
449{
450 grn_expr_code *expr_code;
451
452 expr_code = DATA_PTR(self);
453 return mrb_fixnum_value(expr_code->nargs);
454}
455
456static mrb_value
457mrb_grn_expr_code_get_op(mrb_state *mrb, mrb_value self)
458{
459 grn_expr_code *expr_code;
460
461 expr_code = DATA_PTR(self);
462 return grn_mrb_value_from_operator(mrb, expr_code->op);
463}
464
465static mrb_value
466mrb_grn_expr_code_get_flags(mrb_state *mrb, mrb_value self)
467{
468 grn_expr_code *expr_code;
469
470 expr_code = DATA_PTR(self);
471 return mrb_fixnum_value(expr_code->flags);
472}
473
474static mrb_value
475mrb_grn_expr_code_get_modify(mrb_state *mrb, mrb_value self)
476{
477 grn_expr_code *expr_code;
478
479 expr_code = DATA_PTR(self);
480 return mrb_fixnum_value(expr_code->modify);
481}
482
483static mrb_value
484mrb_grn_expression_class_create(mrb_state *mrb, mrb_value klass)
485{
486 grn_ctx *ctx = (grn_ctx *)mrb->ud;
487 mrb_value mrb_expr;
488 mrb_value mrb_table;
489 mrb_value mrb_new_arguments[1];
490 grn_obj *expr, *variable = NULL;
491
492 mrb_get_args(mrb, "o", &mrb_table);
493 if (mrb_nil_p(mrb_table)) {
494 expr = grn_expr_create(ctx, NULL, 0);
495 } else {
496 grn_obj *table = DATA_PTR(mrb_table);
497 GRN_EXPR_CREATE_FOR_QUERY(ctx, table, expr, variable);
498 }
499
500 if (!expr) {
501 grn_mrb_ctx_check(mrb);
502 return mrb_nil_value();
503 }
504
505 mrb_new_arguments[0] = mrb_cptr_value(mrb, expr);
506 mrb_expr = mrb_obj_new(mrb, mrb_class_ptr(klass), 1, mrb_new_arguments);
507 {
508 mrb_value mrb_variable = mrb_nil_value();
509 if (variable) {
510 mrb_variable = grn_mrb_value_from_grn_obj(mrb, variable);
511 }
512 mrb_iv_set(mrb, mrb_expr, mrb_intern_lit(mrb, "@variable"), mrb_variable);
513 }
514
515 return mrb_expr;
516}
517
518static mrb_value
519mrb_grn_expression_initialize(mrb_state *mrb, mrb_value self)
520{
521 mrb_value mrb_expression_ptr;
522
523 mrb_get_args(mrb, "o", &mrb_expression_ptr);
524 DATA_TYPE(self) = &mrb_grn_expression_type;
525 DATA_PTR(self) = mrb_cptr(mrb_expression_ptr);
526 return self;
527}
528
529static mrb_value
530mrb_grn_expression_is_empty(mrb_state *mrb, mrb_value self)
531{
532 grn_expr *expr;
533
534 expr = DATA_PTR(self);
535 return mrb_bool_value(expr->codes_curr == 0);
536}
537
538static mrb_value
539mrb_grn_expression_codes(mrb_state *mrb, mrb_value self)
540{
541 grn_expr *expr;
542 mrb_value mrb_codes;
543 int i;
544
545 expr = DATA_PTR(self);
546 mrb_codes = mrb_ary_new_capa(mrb, expr->codes_curr);
547 for (i = 0; i < expr->codes_curr; i++) {
548 grn_expr_code *code = expr->codes + i;
549 mrb_ary_push(mrb, mrb_codes, mrb_grn_expr_code_new(mrb, code));
550 }
551
552 return mrb_codes;
553}
554
555static mrb_value
556mrb_grn_expression_array_reference(mrb_state *mrb, mrb_value self)
557{
558 grn_ctx *ctx = (grn_ctx *)mrb->ud;
559 grn_obj *expr;
560 mrb_value mrb_key;
561 grn_obj *var;
562
563 mrb_get_args(mrb, "o", &mrb_key);
564
565 expr = DATA_PTR(self);
566 switch (mrb_type(mrb_key)) {
567 case MRB_TT_SYMBOL :
568 {
569 const char *name;
570 mrb_int name_length;
571
572 name = mrb_sym2name_len(mrb, mrb_symbol(mrb_key), &name_length);
573 var = grn_expr_get_var(ctx, expr, name, name_length);
574 }
575 break;
576 case MRB_TT_STRING :
577 var = grn_expr_get_var(ctx, expr,
578 RSTRING_PTR(mrb_key), RSTRING_LEN(mrb_key));
579 break;
580 case MRB_TT_FIXNUM :
581 var = grn_expr_get_var_by_offset(ctx, expr, mrb_fixnum(mrb_key));
582 break;
583 default :
584 mrb_raisef(mrb, E_ARGUMENT_ERROR,
585 "key must be Symbol, String or Fixnum: %S",
586 mrb_key);
587 break;
588 }
589
590 return grn_mrb_value_from_grn_obj(mrb, var);
591}
592
593static mrb_value
594mrb_grn_expression_set_condition(mrb_state *mrb, mrb_value self)
595{
596 grn_ctx *ctx = (grn_ctx *)mrb->ud;
597 grn_obj *expr;
598 mrb_value mrb_condition;
599 grn_obj *condition_ptr;
600
601 mrb_get_args(mrb, "o", &mrb_condition);
602
603 expr = DATA_PTR(self);
604 condition_ptr = grn_expr_get_or_add_var(ctx,
605 expr,
606 GRN_SELECT_INTERNAL_VAR_CONDITION,
607 GRN_SELECT_INTERNAL_VAR_CONDITION_LEN);
608 GRN_OBJ_FIN(ctx, condition_ptr);
609 GRN_PTR_INIT(condition_ptr, 0, GRN_DB_OBJECT);
610 GRN_PTR_SET(ctx, condition_ptr, GRN_MRB_DATA_PTR(mrb_condition));
611
612 return mrb_nil_value();
613}
614
615static mrb_value
616mrb_grn_expression_take_object(mrb_state *mrb, mrb_value self)
617{
618 grn_ctx *ctx = (grn_ctx *)mrb->ud;
619 grn_obj *expr;
620 mrb_value mrb_object;
621 grn_obj *grn_object;
622
623 mrb_get_args(mrb, "o", &mrb_object);
624 expr = DATA_PTR(self);
625 grn_object = DATA_PTR(mrb_object);
626 grn_expr_take_obj(ctx, expr, grn_object);
627
628 return mrb_object;
629}
630
631static mrb_value
632mrb_grn_expression_allocate_constant(mrb_state *mrb, mrb_value self)
633{
634 grn_ctx *ctx = (grn_ctx *)mrb->ud;
635 grn_obj *expr;
636 mrb_value mrb_object;
637 grn_obj *grn_object;
638
639 mrb_get_args(mrb, "o", &mrb_object);
640 expr = DATA_PTR(self);
641
642 switch (mrb_type(mrb_object)) {
643 case MRB_TT_STRING:
644 grn_object = grn_expr_alloc_const(ctx, expr);
645 if (!grn_object) {
646 grn_mrb_ctx_check(mrb);
647 }
648 GRN_TEXT_INIT(grn_object, 0);
649 GRN_TEXT_SET(ctx, grn_object,
650 RSTRING_PTR(mrb_object), RSTRING_LEN(mrb_object));
651 break;
652 case MRB_TT_TRUE:
653 grn_object = grn_expr_alloc_const(ctx, expr);
654 if (!grn_object) {
655 grn_mrb_ctx_check(mrb);
656 }
657 GRN_BOOL_INIT(grn_object, 0);
658 GRN_BOOL_SET(ctx, grn_object, GRN_TRUE);
659 break;
660 default:
661 mrb_raisef(mrb, E_ARGUMENT_ERROR, "unsupported type: %S", mrb_object);
662 break;
663 }
664
665 return grn_mrb_value_from_grn_obj(mrb, grn_object);
666}
667
668static mrb_value
669mrb_grn_expression_parse(mrb_state *mrb, mrb_value self)
670{
671 grn_ctx *ctx = (grn_ctx *)mrb->ud;
672 grn_obj *expr;
673 char *query;
674 mrb_int query_size;
675 grn_obj *default_column = NULL;
676 grn_operator default_mode = GRN_OP_MATCH;
677 grn_operator default_operator = GRN_OP_AND;
678 grn_expr_flags flags = GRN_EXPR_SYNTAX_SCRIPT;
679 mrb_value mrb_options = mrb_nil_value();
680
681 expr = DATA_PTR(self);
682 mrb_get_args(mrb, "s|H", &query, &query_size, &mrb_options);
683
684 if (!mrb_nil_p(mrb_options)) {
685 mrb_value mrb_default_column;
686 mrb_value mrb_flags;
687
688 mrb_default_column =
689 grn_mrb_options_get_lit(mrb, mrb_options, "default_column");
690 default_column = GRN_MRB_DATA_PTR(mrb_default_column);
691
692 mrb_flags = grn_mrb_options_get_lit(mrb, mrb_options, "flags");
693 if (!mrb_nil_p(mrb_flags)) {
694 flags = mrb_fixnum(mrb_flags);
695 }
696 }
697
698 grn_expr_parse(ctx, expr, query, query_size, default_column,
699 default_mode, default_operator, flags);
700 grn_mrb_ctx_check(mrb);
701
702 return mrb_nil_value();
703}
704
705static mrb_value
706mrb_grn_expression_append_object(mrb_state *mrb, mrb_value self)
707{
708 grn_ctx *ctx = (grn_ctx *)mrb->ud;
709 grn_obj *expr;
710 mrb_value mrb_object;
711 grn_obj *object;
712 mrb_value mrb_op;
713 grn_operator op;
714 mrb_int n_args;
715
716 expr = DATA_PTR(self);
717 mrb_get_args(mrb, "ooi", &mrb_object, &mrb_op, &n_args);
718
719 object = DATA_PTR(mrb_object);
720 op = grn_mrb_value_to_operator(mrb, mrb_op);
721 grn_expr_append_obj(ctx, expr, object, op, n_args);
722 grn_mrb_ctx_check(mrb);
723
724 return mrb_nil_value();
725}
726
727static mrb_value
728mrb_grn_expression_append_constant(mrb_state *mrb, mrb_value self)
729{
730 grn_ctx *ctx = (grn_ctx *)mrb->ud;
731 grn_obj *expr;
732 mrb_value mrb_constant;
733 mrb_value mrb_op;
734 grn_operator op;
735 mrb_int n_args;
736
737 expr = DATA_PTR(self);
738 mrb_get_args(mrb, "ooi", &mrb_constant, &mrb_op, &n_args);
739
740 op = grn_mrb_value_to_operator(mrb, mrb_op);
741 switch (mrb_type(mrb_constant)) {
742 case MRB_TT_FALSE :
743 if (mrb_nil_p(mrb_constant)) {
744 grn_obj constant;
745 GRN_VOID_INIT(&constant);
746 grn_expr_append_const(ctx, expr, &constant, op, n_args);
747 GRN_OBJ_FIN(ctx, &constant);
748 } else {
749 grn_obj constant;
750 GRN_BOOL_INIT(&constant, 0);
751 GRN_BOOL_SET(ctx, &constant, GRN_FALSE);
752 grn_expr_append_const(ctx, expr, &constant, op, n_args);
753 GRN_OBJ_FIN(ctx, &constant);
754 }
755 break;
756 case MRB_TT_TRUE :
757 {
758 grn_obj constant;
759 GRN_BOOL_INIT(&constant, 0);
760 GRN_BOOL_SET(ctx, &constant, GRN_TRUE);
761 grn_expr_append_const(ctx, expr, &constant, op, n_args);
762 GRN_OBJ_FIN(ctx, &constant);
763 }
764 break;
765 case MRB_TT_FIXNUM :
766 grn_expr_append_const_int(ctx, expr, mrb_fixnum(mrb_constant), op, n_args);
767 break;
768 case MRB_TT_SYMBOL :
769 {
770 const char *value;
771 mrb_int value_length;
772
773 value = mrb_sym2name_len(mrb, mrb_symbol(mrb_constant), &value_length);
774 grn_expr_append_const_str(ctx, expr, value, value_length, op, n_args);
775 }
776 break;
777 case MRB_TT_FLOAT :
778 {
779 grn_obj constant;
780 GRN_FLOAT_INIT(&constant, 0);
781 GRN_FLOAT_SET(ctx, &constant, mrb_float(mrb_constant));
782 grn_expr_append_const(ctx, expr, &constant, op, n_args);
783 GRN_OBJ_FIN(ctx, &constant);
784 }
785 break;
786 case MRB_TT_STRING :
787 grn_expr_append_const_str(ctx, expr,
788 RSTRING_PTR(mrb_constant),
789 RSTRING_LEN(mrb_constant),
790 op, n_args);
791 break;
792 default :
793 {
794 struct RClass *klass;
795
796 klass = mrb_class(mrb, mrb_constant);
797 if (klass == ctx->impl->mrb.builtin.time_class) {
798 grn_obj constant;
799 mrb_value mrb_sec;
800 mrb_value mrb_usec;
801
802 mrb_sec = mrb_funcall(mrb, mrb_constant, "to_i", 0);
803 mrb_usec = mrb_funcall(mrb, mrb_constant, "usec", 0);
804 GRN_TIME_INIT(&constant, 0);
805 GRN_TIME_SET(ctx, &constant,
806 GRN_TIME_PACK(mrb_fixnum(mrb_sec), mrb_fixnum(mrb_usec)));
807 grn_expr_append_const(ctx, expr, &constant, op, n_args);
808 GRN_OBJ_FIN(ctx, &constant);
809 } else {
810 mrb_raisef(mrb, E_ARGUMENT_ERROR,
811 "unsupported constant to append to expression: %S",
812 mrb_constant);
813 }
814 }
815 break;
816 }
817
818 grn_mrb_ctx_check(mrb);
819
820 return mrb_nil_value();
821}
822
823static mrb_value
824mrb_grn_expression_append_operator(mrb_state *mrb, mrb_value self)
825{
826 grn_ctx *ctx = (grn_ctx *)mrb->ud;
827 grn_obj *expr;
828 mrb_value mrb_op;
829 mrb_int n_args;
830 grn_operator op;
831
832 expr = DATA_PTR(self);
833 mrb_get_args(mrb, "oi", &mrb_op, &n_args);
834
835 op = grn_mrb_value_to_operator(mrb, mrb_op);
836 grn_expr_append_op(ctx, expr, op, n_args);
837 grn_mrb_ctx_check(mrb);
838
839 return mrb_nil_value();
840}
841
842void
843grn_mrb_expr_init(grn_ctx *ctx)
844{
845 mrb_state *mrb = ctx->impl->mrb.state;
846 struct RClass *module = ctx->impl->mrb.module;
847 struct RClass *object_class = ctx->impl->mrb.object_class;
848 struct RClass *klass;
849
850 klass = mrb_define_class_under(mrb, module, "ScanInfo", mrb->object_class);
851 MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
852 mrb_define_method(mrb, klass, "initialize",
853 mrb_grn_scan_info_initialize, MRB_ARGS_REQ(1));
854 mrb_define_method(mrb, klass, "put_index",
855 mrb_grn_scan_info_put_index, MRB_ARGS_REQ(6));
856 mrb_define_method(mrb, klass, "op",
857 mrb_grn_scan_info_get_op, MRB_ARGS_NONE());
858 mrb_define_method(mrb, klass, "op=",
859 mrb_grn_scan_info_set_op, MRB_ARGS_REQ(1));
860 mrb_define_method(mrb, klass, "end=",
861 mrb_grn_scan_info_set_end, MRB_ARGS_REQ(1));
862 mrb_define_method(mrb, klass, "query=",
863 mrb_grn_scan_info_set_query, MRB_ARGS_REQ(1));
864 mrb_define_method(mrb, klass, "flags",
865 mrb_grn_scan_info_get_flags, MRB_ARGS_NONE());
866 mrb_define_method(mrb, klass, "flags=",
867 mrb_grn_scan_info_set_flags, MRB_ARGS_REQ(1));
868 mrb_define_method(mrb, klass, "logical_op",
869 mrb_grn_scan_info_get_logical_op, MRB_ARGS_NONE());
870 mrb_define_method(mrb, klass, "logical_op=",
871 mrb_grn_scan_info_set_logical_op, MRB_ARGS_REQ(1));
872 mrb_define_method(mrb, klass, "max_interval",
873 mrb_grn_scan_info_get_max_interval, MRB_ARGS_NONE());
874 mrb_define_method(mrb, klass, "max_interval=",
875 mrb_grn_scan_info_set_max_interval, MRB_ARGS_REQ(1));
876 mrb_define_method(mrb, klass, "similarity_threshold",
877 mrb_grn_scan_info_get_similarity_threshold, MRB_ARGS_NONE());
878 mrb_define_method(mrb, klass, "similarity_threshold=",
879 mrb_grn_scan_info_set_similarity_threshold, MRB_ARGS_REQ(1));
880 mrb_define_method(mrb, klass, "get_arg",
881 mrb_grn_scan_info_get_arg, MRB_ARGS_REQ(1));
882 mrb_define_method(mrb, klass, "push_arg",
883 mrb_grn_scan_info_push_arg, MRB_ARGS_REQ(1));
884 mrb_define_method(mrb, klass, "start_position",
885 mrb_grn_scan_info_get_start_position, MRB_ARGS_NONE());
886 mrb_define_method(mrb, klass, "start_position=",
887 mrb_grn_scan_info_set_start_position, MRB_ARGS_REQ(1));
888 mrb_define_method(mrb, klass, "reset_position",
889 mrb_grn_scan_info_reset_position, MRB_ARGS_NONE());
890
891 klass = mrb_define_class_under(mrb, module,
892 "ExpressionCode", mrb->object_class);
893 MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
894 mrb_define_method(mrb, klass, "initialize",
895 mrb_grn_expr_code_initialize, MRB_ARGS_REQ(1));
896 mrb_define_method(mrb, klass, "inspect",
897 mrb_grn_expr_code_inspect, MRB_ARGS_NONE());
898 mrb_define_method(mrb, klass, "weight",
899 mrb_grn_expr_code_get_weight, MRB_ARGS_NONE());
900 mrb_define_method(mrb, klass, "value",
901 mrb_grn_expr_code_get_value, MRB_ARGS_NONE());
902 mrb_define_method(mrb, klass, "n_args",
903 mrb_grn_expr_code_get_n_args, MRB_ARGS_NONE());
904 mrb_define_method(mrb, klass, "op",
905 mrb_grn_expr_code_get_op, MRB_ARGS_NONE());
906 mrb_define_method(mrb, klass, "flags",
907 mrb_grn_expr_code_get_flags, MRB_ARGS_NONE());
908 mrb_define_method(mrb, klass, "modify",
909 mrb_grn_expr_code_get_modify, MRB_ARGS_NONE());
910
911 {
912 struct RClass *expression_code_class = klass;
913 struct RClass *flags_module;
914 flags_module = mrb_define_module_under(mrb, expression_code_class, "Flags");
915 mrb_define_const(mrb, flags_module, "RELATIONAL_EXPRESSION",
916 mrb_fixnum_value(GRN_EXPR_CODE_RELATIONAL_EXPRESSION));
917 }
918
919 klass = mrb_define_class_under(mrb, module, "Expression", object_class);
920 MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
921
922#define DEFINE_FLAG(name) \
923 mrb_define_const(mrb, klass, \
924 #name, \
925 mrb_fixnum_value(GRN_EXPR_ ## name))
926
927 DEFINE_FLAG(SYNTAX_QUERY);
928 DEFINE_FLAG(SYNTAX_SCRIPT);
929 DEFINE_FLAG(SYNTAX_OUTPUT_COLUMNS);
930 DEFINE_FLAG(ALLOW_PRAGMA);
931 DEFINE_FLAG(ALLOW_COLUMN);
932 DEFINE_FLAG(ALLOW_UPDATE);
933 DEFINE_FLAG(ALLOW_LEADING_NOT);
934
935#undef DEFINE_FLAG
936
937 mrb_define_class_method(mrb, klass, "create",
938 mrb_grn_expression_class_create,
939 MRB_ARGS_REQ(1));
940
941 mrb_define_method(mrb, klass, "initialize",
942 mrb_grn_expression_initialize, MRB_ARGS_REQ(1));
943 mrb_define_method(mrb, klass, "empty?",
944 mrb_grn_expression_is_empty, MRB_ARGS_NONE());
945 mrb_define_method(mrb, klass, "codes",
946 mrb_grn_expression_codes, MRB_ARGS_NONE());
947 mrb_define_method(mrb, klass, "[]",
948 mrb_grn_expression_array_reference, MRB_ARGS_REQ(1));
949 mrb_define_method(mrb, klass, "condition=",
950 mrb_grn_expression_set_condition, MRB_ARGS_REQ(1));
951 mrb_define_method(mrb, klass, "take_object",
952 mrb_grn_expression_take_object, MRB_ARGS_REQ(1));
953 mrb_define_method(mrb, klass, "allocate_constant",
954 mrb_grn_expression_allocate_constant, MRB_ARGS_REQ(1));
955
956 mrb_define_method(mrb, klass, "parse",
957 mrb_grn_expression_parse, MRB_ARGS_ARG(1, 1));
958
959 mrb_define_method(mrb, klass, "append_object",
960 mrb_grn_expression_append_object, MRB_ARGS_REQ(2));
961 mrb_define_method(mrb, klass, "append_constant",
962 mrb_grn_expression_append_constant, MRB_ARGS_REQ(3));
963 mrb_define_method(mrb, klass, "append_operator",
964 mrb_grn_expression_append_operator, MRB_ARGS_REQ(2));
965}
966
967grn_obj *
968grn_mrb_expr_rewrite(grn_ctx *ctx, grn_obj *expr)
969{
970 grn_mrb_data *data = &(ctx->impl->mrb);
971 mrb_state *mrb = data->state;
972 mrb_value mrb_expression;
973 mrb_value mrb_rewritten_expression;
974 grn_obj *rewritten_expression = NULL;
975 int arena_index;
976
977 arena_index = mrb_gc_arena_save(mrb);
978
979 mrb_expression = grn_mrb_value_from_grn_obj(mrb, expr);
980 mrb_rewritten_expression = mrb_funcall(mrb, mrb_expression, "rewrite", 0);
981 if (mrb_nil_p(mrb_rewritten_expression)) {
982 goto exit;
983 }
984
985 if (mrb_type(mrb_rewritten_expression) == MRB_TT_EXCEPTION) {
986 mrb->exc = mrb_obj_ptr(mrb_rewritten_expression);
987 mrb_print_error(mrb);
988 goto exit;
989 }
990
991 rewritten_expression = DATA_PTR(mrb_rewritten_expression);
992
993exit:
994 mrb_gc_arena_restore(mrb, arena_index);
995
996 return rewritten_expression;
997}
998
999scan_info **
1000grn_mrb_scan_info_build(grn_ctx *ctx,
1001 grn_obj *expr,
1002 int *n,
1003 grn_operator op,
1004 grn_bool record_exist)
1005{
1006 grn_mrb_data *data = &(ctx->impl->mrb);
1007 mrb_state *mrb = data->state;
1008 mrb_value mrb_expression;
1009 mrb_value mrb_sis;
1010 scan_info **sis = NULL;
1011 int i;
1012 int arena_index;
1013
1014 arena_index = mrb_gc_arena_save(mrb);
1015
1016 mrb_expression = grn_mrb_value_from_grn_obj(mrb, expr);
1017 mrb_sis = mrb_funcall(mrb, mrb_expression, "build_scan_info", 2,
1018 grn_mrb_value_from_operator(mrb, op),
1019 mrb_bool_value(record_exist));
1020
1021 if (mrb_nil_p(mrb_sis)) {
1022 goto exit;
1023 }
1024
1025 if (mrb_type(mrb_sis) == MRB_TT_EXCEPTION) {
1026 mrb->exc = mrb_obj_ptr(mrb_sis);
1027 mrb_print_error(mrb);
1028 goto exit;
1029 }
1030
1031 *n = RARRAY_LEN(mrb_sis);
1032 sis = GRN_MALLOCN(scan_info *, *n);
1033 for (i = 0; i < *n; i++) {
1034 mrb_value mrb_si;
1035 mrb_value mrb_si_data;
1036 scan_info *si;
1037 int start;
1038
1039 mrb_si_data = RARRAY_PTR(mrb_sis)[i];
1040 start = mrb_fixnum(mrb_funcall(mrb, mrb_si_data, "start", 0));
1041 si = grn_scan_info_open(ctx, start);
1042 mrb_si = mrb_grn_scan_info_new(mrb, si);
1043 mrb_funcall(mrb, mrb_si, "apply", 1, mrb_si_data);
1044 sis[i] = si;
1045 }
1046
1047exit:
1048 mrb_gc_arena_restore(mrb, arena_index);
1049
1050 return sis;
1051}
1052
1053unsigned int
1054grn_mrb_expr_estimate_size(grn_ctx *ctx, grn_obj *expr, grn_obj *table)
1055{
1056 grn_mrb_data *data = &(ctx->impl->mrb);
1057 mrb_state *mrb = data->state;
1058 mrb_value mrb_expression;
1059 mrb_value mrb_table;
1060 mrb_value mrb_size;
1061 unsigned int size;
1062 int arena_index;
1063
1064 arena_index = mrb_gc_arena_save(mrb);
1065
1066 mrb_expression = grn_mrb_value_from_grn_obj(mrb, expr);
1067 mrb_table = grn_mrb_value_from_grn_obj(mrb, table);
1068 mrb_size = mrb_funcall(mrb, mrb_expression, "estimate_size", 1, mrb_table);
1069 if (mrb->exc) {
1070 size = grn_table_size(ctx, table);
1071 } else {
1072 size = mrb_fixnum(mrb_size);
1073 }
1074
1075 mrb_gc_arena_restore(mrb, arena_index);
1076
1077 return size;
1078}
1079#endif
1080