1/* -*- c-basic-offset: 2 -*- */
2/*
3 Copyright(C) 2010-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.h"
20#include "grn_ctx_impl.h"
21#include "grn_expr_executor.h"
22
23#ifdef GRN_WITH_ONIGMO
24# define GRN_SUPPORT_REGEXP
25#endif
26
27#ifdef GRN_SUPPORT_REGEXP
28# include "grn_normalizer.h"
29# include <onigmo.h>
30#endif
31
32typedef union {
33 struct {
34 grn_obj result_buffer;
35 } constant;
36 struct {
37 grn_obj *column;
38 grn_obj value_buffer;
39 } value;
40#ifdef GRN_SUPPORT_REGEXP
41 struct {
42 grn_obj result_buffer;
43 OnigRegex regex;
44 grn_obj value_buffer;
45 grn_obj *normalizer;
46 } simple_regexp;
47#endif /* GRN_SUPPORT_REGEXP */
48 struct {
49 grn_proc_ctx proc_ctx;
50 int n_args;
51 } proc;
52 struct {
53 grn_obj result_buffer;
54 grn_ra *ra;
55 grn_ra_cache ra_cache;
56 unsigned int ra_element_size;
57 grn_obj value_buffer;
58 grn_obj constant_buffer;
59 grn_operator_exec_func *exec;
60 } simple_condition_ra;
61 struct {
62 grn_bool need_exec;
63 grn_obj result_buffer;
64 grn_obj value_buffer;
65 grn_obj constant_buffer;
66 grn_operator_exec_func *exec;
67 } simple_condition;
68} grn_expr_executor_data;
69
70typedef grn_obj *(*grn_expr_executor_exec_func)(grn_ctx *ctx,
71 grn_expr_executor *executor,
72 grn_id id);
73typedef void (*grn_expr_executor_fin_func)(grn_ctx *ctx,
74 grn_expr_executor *executor);
75
76struct _grn_expr_executor {
77 grn_obj *expr;
78 grn_obj *variable;
79 grn_expr_executor_exec_func exec;
80 grn_expr_executor_fin_func fin;
81 grn_expr_executor_data data;
82};
83
84static void
85grn_expr_executor_init_general(grn_ctx *ctx,
86 grn_expr_executor *executor)
87{
88}
89
90static grn_obj *
91grn_expr_executor_exec_general(grn_ctx *ctx,
92 grn_expr_executor *executor,
93 grn_id id)
94{
95 GRN_RECORD_SET(ctx, executor->variable, id);
96 return grn_expr_exec(ctx, executor->expr, 0);
97}
98
99static void
100grn_expr_executor_fin_general(grn_ctx *ctx,
101 grn_expr_executor *executor)
102{
103}
104
105static grn_bool
106grn_expr_executor_is_constant(grn_ctx *ctx, grn_obj *expr)
107{
108 grn_expr *e = (grn_expr *)expr;
109 grn_expr_code *target;
110
111 if (e->codes_curr != 1) {
112 return GRN_FALSE;
113 }
114
115 target = &(e->codes[0]);
116
117 if (target->op != GRN_OP_PUSH) {
118 return GRN_FALSE;
119 }
120 if (!target->value) {
121 return GRN_FALSE;
122 }
123
124 return GRN_TRUE;
125}
126
127static void
128grn_expr_executor_init_constant(grn_ctx *ctx,
129 grn_expr_executor *executor)
130{
131 grn_obj *result_buffer = &(executor->data.constant.result_buffer);
132 grn_obj *result;
133
134 GRN_VOID_INIT(result_buffer);
135 result = grn_expr_exec(ctx, executor->expr, 0);
136 if (ctx->rc == GRN_SUCCESS) {
137 grn_obj_reinit(ctx,
138 result_buffer,
139 result->header.domain,
140 result->header.flags);
141 /* TODO: Support vector */
142 grn_bulk_write(ctx,
143 result_buffer,
144 GRN_BULK_HEAD(result),
145 GRN_BULK_VSIZE(result));
146 }
147}
148
149static grn_obj *
150grn_expr_executor_exec_constant(grn_ctx *ctx,
151 grn_expr_executor *executor,
152 grn_id id)
153{
154 return &(executor->data.constant.result_buffer);
155}
156
157static void
158grn_expr_executor_fin_constant(grn_ctx *ctx,
159 grn_expr_executor *executor)
160{
161 GRN_OBJ_FIN(ctx, &(executor->data.constant.result_buffer));
162}
163
164static grn_bool
165grn_expr_executor_is_value(grn_ctx *ctx, grn_obj *expr)
166{
167 grn_expr *e = (grn_expr *)expr;
168 grn_expr_code *target;
169
170 if (e->codes_curr != 1) {
171 return GRN_FALSE;
172 }
173
174 target = &(e->codes[0]);
175
176 if (target->op != GRN_OP_GET_VALUE) {
177 return GRN_FALSE;
178 }
179 if (!target->value) {
180 return GRN_FALSE;
181 }
182
183 return GRN_TRUE;
184}
185
186static void
187grn_expr_executor_init_value(grn_ctx *ctx,
188 grn_expr_executor *executor)
189{
190 grn_expr *e = (grn_expr *)(executor->expr);
191
192 executor->data.value.column = e->codes[0].value;
193 GRN_VOID_INIT(&(executor->data.value.value_buffer));
194}
195
196static grn_obj *
197grn_expr_executor_exec_value(grn_ctx *ctx,
198 grn_expr_executor *executor,
199 grn_id id)
200{
201 grn_obj *value_buffer = &(executor->data.value.value_buffer);
202
203 GRN_BULK_REWIND(value_buffer);
204 grn_obj_get_value(ctx, executor->data.value.column, id, value_buffer);
205
206 return value_buffer;
207}
208
209static void
210grn_expr_executor_fin_value(grn_ctx *ctx,
211 grn_expr_executor *executor)
212{
213 GRN_OBJ_FIN(ctx, &(executor->data.value.value_buffer));
214}
215
216#ifdef GRN_SUPPORT_REGEXP
217static grn_bool
218grn_expr_executor_is_simple_regexp(grn_ctx *ctx, grn_obj *expr)
219{
220 grn_expr *e = (grn_expr *)expr;
221 grn_expr_code *target;
222 grn_expr_code *pattern;
223 grn_expr_code *operator;
224
225 if (e->codes_curr != 3) {
226 return GRN_FALSE;
227 }
228
229 target = &(e->codes[0]);
230 pattern = &(e->codes[1]);
231 operator = &(e->codes[2]);
232
233 if (operator->op != GRN_OP_REGEXP) {
234 return GRN_FALSE;
235 }
236 if (operator->nargs != 2) {
237 return GRN_FALSE;
238 }
239
240 if (target->op != GRN_OP_GET_VALUE) {
241 return GRN_FALSE;
242 }
243 if (target->nargs != 1) {
244 return GRN_FALSE;
245 }
246 if (!target->value) {
247 return GRN_FALSE;
248 }
249 if (target->value->header.type != GRN_COLUMN_VAR_SIZE) {
250 return GRN_FALSE;
251 }
252 if ((target->value->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) !=
253 GRN_OBJ_COLUMN_SCALAR) {
254 return GRN_FALSE;
255 }
256 switch (grn_obj_get_range(ctx, target->value)) {
257 case GRN_DB_SHORT_TEXT :
258 case GRN_DB_TEXT :
259 case GRN_DB_LONG_TEXT :
260 break;
261 default :
262 return GRN_FALSE;
263 }
264
265 if (pattern->op != GRN_OP_PUSH) {
266 return GRN_FALSE;
267 }
268 if (pattern->nargs != 1) {
269 return GRN_FALSE;
270 }
271 if (!pattern->value) {
272 return GRN_FALSE;
273 }
274 if (pattern->value->header.type != GRN_BULK) {
275 return GRN_FALSE;
276 }
277 switch (pattern->value->header.domain) {
278 case GRN_DB_SHORT_TEXT :
279 case GRN_DB_TEXT :
280 case GRN_DB_LONG_TEXT :
281 break;
282 default :
283 return GRN_FALSE;
284 }
285
286 return GRN_TRUE;
287}
288
289static void
290grn_expr_executor_init_simple_regexp(grn_ctx *ctx,
291 grn_expr_executor *executor)
292{
293 grn_expr *e = (grn_expr *)(executor->expr);
294 grn_obj *result_buffer = &(executor->data.simple_regexp.result_buffer);
295 OnigEncoding onig_encoding;
296 int onig_result;
297 OnigErrorInfo onig_error_info;
298 grn_obj *pattern;
299
300 GRN_BOOL_INIT(result_buffer, 0);
301 GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE);
302
303 if (ctx->encoding == GRN_ENC_NONE) {
304 executor->data.simple_regexp.regex = NULL;
305 return;
306 }
307
308 switch (ctx->encoding) {
309 case GRN_ENC_EUC_JP :
310 onig_encoding = ONIG_ENCODING_EUC_JP;
311 break;
312 case GRN_ENC_UTF8 :
313 onig_encoding = ONIG_ENCODING_UTF8;
314 break;
315 case GRN_ENC_SJIS :
316 onig_encoding = ONIG_ENCODING_CP932;
317 break;
318 case GRN_ENC_LATIN1 :
319 onig_encoding = ONIG_ENCODING_ISO_8859_1;
320 break;
321 case GRN_ENC_KOI8R :
322 onig_encoding = ONIG_ENCODING_KOI8_R;
323 break;
324 default :
325 executor->data.simple_regexp.regex = NULL;
326 return;
327 }
328
329 pattern = e->codes[1].value;
330 onig_result = onig_new(&(executor->data.simple_regexp.regex),
331 GRN_TEXT_VALUE(pattern),
332 GRN_TEXT_VALUE(pattern) + GRN_TEXT_LEN(pattern),
333 ONIG_OPTION_ASCII_RANGE |
334 ONIG_OPTION_MULTILINE,
335 onig_encoding,
336 ONIG_SYNTAX_RUBY,
337 &onig_error_info);
338 if (onig_result != ONIG_NORMAL) {
339 char message[ONIG_MAX_ERROR_MESSAGE_LEN];
340 onig_error_code_to_str(message, onig_result, onig_error_info);
341 ERR(GRN_INVALID_ARGUMENT,
342 "[expr-executor][regexp] "
343 "failed to create regular expression object: <%.*s>: %s",
344 (int)GRN_TEXT_LEN(pattern), GRN_TEXT_VALUE(pattern),
345 message);
346 return;
347 }
348
349 GRN_VOID_INIT(&(executor->data.simple_regexp.value_buffer));
350
351 executor->data.simple_regexp.normalizer =
352 grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1);
353}
354
355static grn_obj *
356grn_expr_executor_exec_simple_regexp(grn_ctx *ctx,
357 grn_expr_executor *executor,
358 grn_id id)
359{
360 grn_expr *e = (grn_expr *)(executor->expr);
361 OnigRegex regex = executor->data.simple_regexp.regex;
362 grn_obj *value_buffer = &(executor->data.simple_regexp.value_buffer);
363 grn_obj *result_buffer = &(executor->data.simple_regexp.result_buffer);
364
365 if (ctx->rc) {
366 GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE);
367 return result_buffer;
368 }
369
370 if (!regex) {
371 return result_buffer;
372 }
373
374 grn_obj_reinit_for(ctx, value_buffer, e->codes[0].value);
375 grn_obj_get_value(ctx, e->codes[0].value, id, value_buffer);
376 {
377 grn_obj *norm_target;
378 const char *norm_target_raw;
379 unsigned int norm_target_raw_length_in_bytes;
380
381 norm_target = grn_string_open(ctx,
382 GRN_TEXT_VALUE(value_buffer),
383 GRN_TEXT_LEN(value_buffer),
384 executor->data.simple_regexp.normalizer,
385 0);
386 grn_string_get_normalized(ctx, norm_target,
387 &norm_target_raw,
388 &norm_target_raw_length_in_bytes,
389 NULL);
390
391 {
392 OnigPosition position;
393 position = onig_search(regex,
394 norm_target_raw,
395 norm_target_raw + norm_target_raw_length_in_bytes,
396 norm_target_raw,
397 norm_target_raw + norm_target_raw_length_in_bytes,
398 NULL,
399 ONIG_OPTION_NONE);
400 grn_obj_close(ctx, norm_target);
401 GRN_BOOL_SET(ctx, result_buffer, (position != ONIG_MISMATCH));
402 return result_buffer;
403 }
404 }
405}
406
407static void
408grn_expr_executor_fin_simple_regexp(grn_ctx *ctx,
409 grn_expr_executor *executor)
410{
411 GRN_OBJ_FIN(ctx, &(executor->data.simple_regexp.result_buffer));
412
413 if (!executor->data.simple_regexp.regex) {
414 return;
415 }
416
417 onig_free(executor->data.simple_regexp.regex);
418 GRN_OBJ_FIN(ctx, &(executor->data.simple_regexp.value_buffer));
419}
420#endif /* GRN_SUPPORT_REGEXP */
421
422static grn_bool
423grn_expr_executor_is_proc(grn_ctx *ctx, grn_obj *expr)
424{
425 grn_expr *e = (grn_expr *)expr;
426 grn_obj *first;
427 grn_proc *proc;
428
429 if (e->codes_curr < 2) {
430 return GRN_FALSE;
431 }
432
433 first = e->codes[0].value;
434 if (!grn_obj_is_function_proc(ctx, first)) {
435 return GRN_FALSE;
436 }
437
438 proc = (grn_proc *)first;
439 if (!(proc->funcs[PROC_INIT] &&
440 proc->funcs[PROC_NEXT])) {
441 return GRN_FALSE;
442 }
443
444 if (e->codes[e->codes_curr - 1].op != GRN_OP_CALL) {
445 return GRN_FALSE;
446 }
447
448 return GRN_TRUE;
449}
450
451static void
452grn_expr_executor_init_proc(grn_ctx *ctx,
453 grn_expr_executor *executor)
454{
455 grn_proc_ctx *proc_ctx = &(executor->data.proc.proc_ctx);
456 grn_expr *expr;
457 grn_proc *proc;
458
459 expr = (grn_expr *)(executor->expr);
460 proc = (grn_proc *)(expr->codes[0].value);
461 proc_ctx->proc = proc;
462 proc_ctx->caller = executor->expr;
463 proc_ctx->phase = PROC_INIT;
464
465 executor->data.proc.n_args = expr->codes[expr->codes_curr - 1].nargs - 1;
466
467 proc->funcs[PROC_INIT](ctx, 0, NULL, &(proc_ctx->user_data));
468}
469
470static grn_obj *
471grn_expr_executor_exec_proc(grn_ctx *ctx,
472 grn_expr_executor *executor,
473 grn_id id)
474{
475 grn_proc_ctx *proc_ctx = &(executor->data.proc.proc_ctx);
476 int n_args = executor->data.proc.n_args;
477 grn_proc *proc;
478 grn_expr *expr;
479 grn_obj **args;
480 uint32_t values_curr;
481 uint32_t values_tail;
482 grn_obj *result;
483
484 proc = proc_ctx->proc;
485 proc_ctx->phase = PROC_NEXT;
486 GRN_RECORD_SET(ctx, executor->variable, id);
487
488 expr = (grn_expr *)(executor->expr);
489 values_curr = expr->values_curr;
490 values_tail = expr->values_tail;
491
492 expr->codes += 1;
493 expr->codes_curr -= 2;
494 grn_expr_exec(ctx, executor->expr, 0);
495 expr->codes_curr += 2;
496 expr->codes -= 1;
497
498 args = ctx->impl->stack + ctx->impl->stack_curr;
499 ctx->impl->stack_curr += n_args;
500 expr->values_curr = expr->values_tail;
501 result = proc->funcs[PROC_NEXT](ctx,
502 n_args,
503 args,
504 &(proc_ctx->user_data));
505 ctx->impl->stack_curr -= n_args;
506
507 expr->values_tail = values_tail;
508 expr->values_curr = values_curr;
509
510 return result;
511}
512
513static void
514grn_expr_executor_fin_proc(grn_ctx *ctx,
515 grn_expr_executor *executor)
516{
517 grn_proc_ctx *proc_ctx = &(executor->data.proc.proc_ctx);
518 grn_proc *proc;
519
520 proc = proc_ctx->proc;
521 proc_ctx->phase = PROC_FIN;
522 if (proc->funcs[PROC_FIN]) {
523 proc->funcs[PROC_FIN](ctx, 0, NULL, &(proc_ctx->user_data));
524 }
525}
526
527static grn_bool
528grn_expr_executor_is_simple_condition_ra(grn_ctx *ctx, grn_obj *expr)
529{
530 grn_expr *e = (grn_expr *)expr;
531 grn_expr_code *target;
532 grn_expr_code *constant;
533 grn_expr_code *operator;
534
535 if (e->codes_curr != 3) {
536 return GRN_FALSE;
537 }
538
539 target = &(e->codes[0]);
540 constant = &(e->codes[1]);
541 operator = &(e->codes[2]);
542
543 switch (operator->op) {
544 case GRN_OP_EQUAL :
545 case GRN_OP_NOT_EQUAL :
546 case GRN_OP_LESS :
547 case GRN_OP_GREATER :
548 case GRN_OP_LESS_EQUAL :
549 case GRN_OP_GREATER_EQUAL :
550 break;
551 default :
552 return GRN_FALSE;
553 }
554 if (operator->nargs != 2) {
555 return GRN_FALSE;
556 }
557
558 if (target->op != GRN_OP_GET_VALUE) {
559 return GRN_FALSE;
560 }
561 if (target->nargs != 1) {
562 return GRN_FALSE;
563 }
564 if (target->value->header.type != GRN_COLUMN_FIX_SIZE) {
565 return GRN_FALSE;
566 }
567
568 if (constant->op != GRN_OP_PUSH) {
569 return GRN_FALSE;
570 }
571 if (constant->nargs != 1) {
572 return GRN_FALSE;
573 }
574 if (!constant->value) {
575 return GRN_FALSE;
576 }
577 if (constant->value->header.type != GRN_BULK) {
578 return GRN_FALSE;
579 }
580
581 {
582 grn_obj constant_buffer;
583 grn_rc rc;
584 GRN_VOID_INIT(&constant_buffer);
585 grn_obj_reinit_for(ctx, &constant_buffer, target->value);
586 rc = grn_obj_cast(ctx, constant->value, &constant_buffer, GRN_FALSE);
587 GRN_OBJ_FIN(ctx, &constant_buffer);
588 if (rc != GRN_SUCCESS) {
589 return GRN_FALSE;
590 }
591 }
592
593 return GRN_TRUE;
594}
595
596static void
597grn_expr_executor_init_simple_condition_ra(grn_ctx *ctx,
598 grn_expr_executor *executor)
599{
600 grn_expr *e = (grn_expr *)(executor->expr);
601 grn_obj *target;
602 grn_obj *constant;
603 grn_operator op;
604 grn_obj *result_buffer;
605 grn_obj *value_buffer;
606 grn_obj *constant_buffer;
607
608 target = e->codes[0].value;
609 constant = e->codes[1].value;
610 op = e->codes[2].op;
611
612 result_buffer = &(executor->data.simple_condition_ra.result_buffer);
613 GRN_BOOL_INIT(result_buffer, 0);
614 GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE);
615
616 value_buffer = &(executor->data.simple_condition_ra.value_buffer);
617 GRN_VOID_INIT(value_buffer);
618 grn_obj_reinit_for(ctx, value_buffer, target);
619
620 executor->data.simple_condition_ra.ra = (grn_ra *)target;
621 GRN_RA_CACHE_INIT(executor->data.simple_condition_ra.ra,
622 &(executor->data.simple_condition_ra.ra_cache));
623 grn_ra_info(ctx,
624 executor->data.simple_condition_ra.ra,
625 &(executor->data.simple_condition_ra.ra_element_size));
626
627 executor->data.simple_condition_ra.exec = grn_operator_to_exec_func(op);
628
629 constant_buffer = &(executor->data.simple_condition_ra.constant_buffer);
630 GRN_VOID_INIT(constant_buffer);
631 grn_obj_reinit_for(ctx, constant_buffer, target);
632 grn_obj_cast(ctx, constant, constant_buffer, GRN_FALSE);
633}
634
635static grn_obj *
636grn_expr_executor_exec_simple_condition_ra(grn_ctx *ctx,
637 grn_expr_executor *executor,
638 grn_id id)
639{
640 grn_obj *result_buffer = &(executor->data.simple_condition_ra.result_buffer);
641 grn_obj *value_buffer = &(executor->data.simple_condition_ra.value_buffer);
642 grn_obj *constant_buffer =
643 &(executor->data.simple_condition_ra.constant_buffer);
644
645 if (ctx->rc) {
646 GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE);
647 return result_buffer;
648 }
649
650 {
651 grn_ra *ra = executor->data.simple_condition_ra.ra;
652 grn_ra_cache *ra_cache = &(executor->data.simple_condition_ra.ra_cache);
653 unsigned int ra_element_size =
654 executor->data.simple_condition_ra.ra_element_size;
655 void *raw_value;
656 raw_value = grn_ra_ref_cache(ctx, ra, id, ra_cache);
657 GRN_BULK_REWIND(value_buffer);
658 grn_bulk_write(ctx, value_buffer, raw_value, ra_element_size);
659 }
660
661 if (executor->data.simple_condition_ra.exec(ctx,
662 value_buffer,
663 constant_buffer)) {
664 GRN_BOOL_SET(ctx, result_buffer, GRN_TRUE);
665 } else {
666 GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE);
667 }
668 return result_buffer;
669}
670
671static void
672grn_expr_executor_fin_simple_condition_ra(grn_ctx *ctx,
673 grn_expr_executor *executor)
674{
675 GRN_OBJ_FIN(ctx, &(executor->data.simple_condition_ra.result_buffer));
676 GRN_RA_CACHE_FIN(executor->data.simple_condition_ra.ra,
677 &(executor->data.simple_condition_ra.ra_cache));
678 GRN_OBJ_FIN(ctx, &(executor->data.simple_condition_ra.value_buffer));
679 GRN_OBJ_FIN(ctx, &(executor->data.simple_condition_ra.constant_buffer));
680}
681
682static grn_bool
683grn_expr_executor_is_simple_condition(grn_ctx *ctx, grn_obj *expr)
684{
685 grn_expr *e = (grn_expr *)expr;
686 grn_expr_code *target;
687 grn_expr_code *constant;
688 grn_expr_code *operator;
689
690 if (e->codes_curr != 3) {
691 return GRN_FALSE;
692 }
693
694 target = &(e->codes[0]);
695 constant = &(e->codes[1]);
696 operator = &(e->codes[2]);
697
698 switch (operator->op) {
699 case GRN_OP_EQUAL :
700 case GRN_OP_NOT_EQUAL :
701 case GRN_OP_LESS :
702 case GRN_OP_GREATER :
703 case GRN_OP_LESS_EQUAL :
704 case GRN_OP_GREATER_EQUAL :
705 break;
706 default :
707 return GRN_FALSE;
708 }
709 if (operator->nargs != 2) {
710 return GRN_FALSE;
711 }
712
713 if (target->op != GRN_OP_GET_VALUE) {
714 return GRN_FALSE;
715 }
716 if (target->nargs != 1) {
717 return GRN_FALSE;
718 }
719 if (!grn_obj_is_scalar_column(ctx, target->value)) {
720 return GRN_FALSE;
721 }
722
723 if (constant->op != GRN_OP_PUSH) {
724 return GRN_FALSE;
725 }
726 if (constant->nargs != 1) {
727 return GRN_FALSE;
728 }
729 if (!constant->value) {
730 return GRN_FALSE;
731 }
732 if (constant->value->header.type != GRN_BULK) {
733 return GRN_FALSE;
734 }
735
736 return GRN_TRUE;
737}
738
739static void
740grn_expr_executor_init_simple_condition(grn_ctx *ctx,
741 grn_expr_executor *executor)
742{
743 grn_expr *e = (grn_expr *)(executor->expr);
744 grn_obj *target;
745 grn_obj *constant;
746 grn_operator op;
747 grn_obj *result_buffer;
748 grn_obj *value_buffer;
749 grn_obj *constant_buffer;
750 grn_rc rc;
751
752 target = e->codes[0].value;
753 constant = e->codes[1].value;
754 op = e->codes[2].op;
755
756 executor->data.simple_condition.need_exec = GRN_TRUE;
757
758 result_buffer = &(executor->data.simple_condition.result_buffer);
759 GRN_BOOL_INIT(result_buffer, 0);
760 GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE);
761
762 value_buffer = &(executor->data.simple_condition.value_buffer);
763 GRN_VOID_INIT(value_buffer);
764 grn_obj_reinit_for(ctx, value_buffer, target);
765
766 executor->data.simple_condition.exec = grn_operator_to_exec_func(op);
767
768 constant_buffer = &(executor->data.simple_condition.constant_buffer);
769 GRN_VOID_INIT(constant_buffer);
770 grn_obj_reinit_for(ctx, constant_buffer, target);
771 rc = grn_obj_cast(ctx, constant, constant_buffer, GRN_FALSE);
772 if (rc != GRN_SUCCESS) {
773 grn_obj *type;
774
775 type = grn_ctx_at(ctx, constant_buffer->header.domain);
776 if (grn_obj_is_table(ctx, type)) {
777 GRN_BOOL_SET(ctx, result_buffer, (op == GRN_OP_NOT_EQUAL));
778 executor->data.simple_condition.need_exec = GRN_FALSE;
779 } else {
780 int type_name_size;
781 char type_name[GRN_TABLE_MAX_KEY_SIZE];
782 grn_obj inspected;
783
784 type_name_size = grn_obj_name(ctx, type, type_name,
785 GRN_TABLE_MAX_KEY_SIZE);
786 GRN_TEXT_INIT(&inspected, 0);
787 grn_inspect(ctx, &inspected, constant);
788 ERR(rc,
789 "[expr-executor][condition] "
790 "failed to cast to <%.*s>: <%.*s>",
791 type_name_size, type_name,
792 (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected));
793 }
794 }
795}
796
797static grn_obj *
798grn_expr_executor_exec_simple_condition(grn_ctx *ctx,
799 grn_expr_executor *executor,
800 grn_id id)
801{
802 grn_expr *e = (grn_expr *)(executor->expr);
803 grn_obj *target;
804 grn_obj *result_buffer = &(executor->data.simple_condition.result_buffer);
805 grn_obj *value_buffer = &(executor->data.simple_condition.value_buffer);
806 grn_obj *constant_buffer = &(executor->data.simple_condition.constant_buffer);
807
808 if (ctx->rc) {
809 GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE);
810 return result_buffer;
811 }
812
813 if (!executor->data.simple_condition.need_exec) {
814 return result_buffer;
815 }
816
817 target = e->codes[0].value;
818 GRN_BULK_REWIND(value_buffer);
819 grn_obj_get_value(ctx, target, id, value_buffer);
820
821 if (executor->data.simple_condition.exec(ctx, value_buffer, constant_buffer)) {
822 GRN_BOOL_SET(ctx, result_buffer, GRN_TRUE);
823 } else {
824 GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE);
825 }
826 return result_buffer;
827}
828
829static void
830grn_expr_executor_fin_simple_condition(grn_ctx *ctx,
831 grn_expr_executor *executor)
832{
833 GRN_OBJ_FIN(ctx, &(executor->data.simple_condition.result_buffer));
834 GRN_OBJ_FIN(ctx, &(executor->data.simple_condition.value_buffer));
835 GRN_OBJ_FIN(ctx, &(executor->data.simple_condition.constant_buffer));
836}
837
838grn_expr_executor *
839grn_expr_executor_open(grn_ctx *ctx, grn_obj *expr)
840{
841 grn_obj *variable;
842 grn_expr_executor *executor;
843
844 GRN_API_ENTER;
845
846 if (!grn_obj_is_expr(ctx, expr)) {
847 grn_obj inspected;
848 GRN_TEXT_INIT(&inspected, 0);
849 grn_inspect(ctx, &inspected, expr);
850 ERR(ctx->rc,
851 "[expr-executor][open] invalid expression: %.*s",
852 (int)GRN_TEXT_LEN(&inspected),
853 GRN_TEXT_VALUE(&inspected));
854 GRN_OBJ_FIN(ctx, &inspected);
855 GRN_API_RETURN(NULL);
856 }
857
858 variable = grn_expr_get_var_by_offset(ctx, expr, 0);
859 if (!variable) {
860 grn_obj inspected;
861 GRN_TEXT_INIT(&inspected, 0);
862 grn_inspect(ctx, &inspected, expr);
863 ERR(ctx->rc,
864 "[expr-executor][open] expression has no variable: %.*s",
865 (int)GRN_TEXT_LEN(&inspected),
866 GRN_TEXT_VALUE(&inspected));
867 GRN_OBJ_FIN(ctx, &inspected);
868 GRN_API_RETURN(NULL);
869 }
870
871 executor = GRN_CALLOC(sizeof(grn_expr_executor));
872 if (!executor) {
873 ERR(ctx->rc,
874 "[expr-executor][open] failed to allocate: %s",
875 ctx->errbuf);
876 GRN_API_RETURN(NULL);
877 }
878
879 executor->expr = expr;
880 executor->variable = variable;
881 if (grn_expr_executor_is_constant(ctx, expr)) {
882 grn_expr_executor_init_constant(ctx, executor);
883 executor->exec = grn_expr_executor_exec_constant;
884 executor->fin = grn_expr_executor_fin_constant;
885 } else if (grn_expr_executor_is_value(ctx, expr)) {
886 grn_expr_executor_init_value(ctx, executor);
887 executor->exec = grn_expr_executor_exec_value;
888 executor->fin = grn_expr_executor_fin_value;
889#ifdef GRN_SUPPORT_REGEXP
890 } else if (grn_expr_executor_is_simple_regexp(ctx, expr)) {
891 grn_expr_executor_init_simple_regexp(ctx, executor);
892 executor->exec = grn_expr_executor_exec_simple_regexp;
893 executor->fin = grn_expr_executor_fin_simple_regexp;
894#endif /* GRN_SUPPORT_REGEXP */
895 } else if (grn_expr_executor_is_proc(ctx, expr)) {
896 grn_expr_executor_init_proc(ctx, executor);
897 executor->exec = grn_expr_executor_exec_proc;
898 executor->fin = grn_expr_executor_fin_proc;
899 } else if (grn_expr_executor_is_simple_condition_ra(ctx, expr)) {
900 grn_expr_executor_init_simple_condition_ra(ctx, executor);
901 executor->exec = grn_expr_executor_exec_simple_condition_ra;
902 executor->fin = grn_expr_executor_fin_simple_condition_ra;
903 } else if (grn_expr_executor_is_simple_condition(ctx, expr)) {
904 grn_expr_executor_init_simple_condition(ctx, executor);
905 executor->exec = grn_expr_executor_exec_simple_condition;
906 executor->fin = grn_expr_executor_fin_simple_condition;
907 } else {
908 grn_expr_executor_init_general(ctx, executor);
909 executor->exec = grn_expr_executor_exec_general;
910 executor->fin = grn_expr_executor_fin_general;
911 }
912
913 GRN_API_RETURN(executor);
914}
915
916grn_obj *
917grn_expr_executor_exec(grn_ctx *ctx, grn_expr_executor *executor, grn_id id)
918{
919 grn_obj *value;
920
921 GRN_API_ENTER;
922
923 if (!executor) {
924 GRN_API_RETURN(NULL);
925 }
926
927 value = executor->exec(ctx, executor, id);
928
929 GRN_API_RETURN(value);
930}
931
932grn_rc
933grn_expr_executor_close(grn_ctx *ctx, grn_expr_executor *executor)
934{
935 GRN_API_ENTER;
936
937 if (!executor) {
938 GRN_API_RETURN(GRN_SUCCESS);
939 }
940
941 executor->fin(ctx, executor);
942 GRN_FREE(executor);
943
944 GRN_API_RETURN(GRN_SUCCESS);
945}
946