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 | |
32 | typedef 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 | |
70 | typedef grn_obj *(*grn_expr_executor_exec_func)(grn_ctx *ctx, |
71 | grn_expr_executor *executor, |
72 | grn_id id); |
73 | typedef void (*grn_expr_executor_fin_func)(grn_ctx *ctx, |
74 | grn_expr_executor *executor); |
75 | |
76 | struct _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 | |
84 | static void |
85 | grn_expr_executor_init_general(grn_ctx *ctx, |
86 | grn_expr_executor *executor) |
87 | { |
88 | } |
89 | |
90 | static grn_obj * |
91 | grn_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 | |
99 | static void |
100 | grn_expr_executor_fin_general(grn_ctx *ctx, |
101 | grn_expr_executor *executor) |
102 | { |
103 | } |
104 | |
105 | static grn_bool |
106 | grn_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 | |
127 | static void |
128 | grn_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 | |
149 | static grn_obj * |
150 | grn_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 | |
157 | static void |
158 | grn_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 | |
164 | static grn_bool |
165 | grn_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 | |
186 | static void |
187 | grn_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 | |
196 | static grn_obj * |
197 | grn_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 | |
209 | static void |
210 | grn_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 |
217 | static grn_bool |
218 | grn_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 | |
289 | static void |
290 | grn_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 | |
355 | static grn_obj * |
356 | grn_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 | |
407 | static void |
408 | grn_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 | |
422 | static grn_bool |
423 | grn_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 | |
451 | static void |
452 | grn_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 | |
470 | static grn_obj * |
471 | grn_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 | |
513 | static void |
514 | grn_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 | |
527 | static grn_bool |
528 | grn_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 | |
596 | static void |
597 | grn_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 | |
635 | static grn_obj * |
636 | grn_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 | |
671 | static void |
672 | grn_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 | |
682 | static grn_bool |
683 | grn_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 | |
739 | static void |
740 | grn_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 | |
797 | static grn_obj * |
798 | grn_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 | |
829 | static void |
830 | grn_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 | |
838 | grn_expr_executor * |
839 | grn_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 | |
916 | grn_obj * |
917 | grn_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 | |
932 | grn_rc |
933 | grn_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 | |