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#include "grn.h"
19#include "grn_db.h"
20#include "grn_ctx_impl.h"
21#include "grn_ctx_impl_mrb.h"
22#include <string.h>
23#include "grn_ii.h"
24#include "grn_geo.h"
25#include "grn_expr.h"
26#include "grn_expr_code.h"
27#include "grn_expr_executor.h"
28#include "grn_scanner.h"
29#include "grn_util.h"
30#include "grn_report.h"
31#include "grn_token_cursor.h"
32#include "grn_mrb.h"
33#include "mrb/mrb_expr.h"
34
35#ifdef GRN_WITH_ONIGMO
36# define GRN_SUPPORT_REGEXP
37#endif
38
39#ifdef GRN_SUPPORT_REGEXP
40# include "grn_normalizer.h"
41# include <onigmo.h>
42#endif
43
44static double grn_table_select_enough_filtered_ratio = 0.0;
45static int grn_table_select_max_n_enough_filtered_records = 1000;
46static grn_bool grn_table_select_and_min_skip_enable = GRN_TRUE;
47static grn_bool grn_scan_info_regexp_dot_asterisk_enable = GRN_TRUE;
48
49void
50grn_expr_init_from_env(void)
51{
52 {
53 char grn_table_select_enough_filtered_ratio_env[GRN_ENV_BUFFER_SIZE];
54 grn_getenv("GRN_TABLE_SELECT_ENOUGH_FILTERED_RATIO",
55 grn_table_select_enough_filtered_ratio_env,
56 GRN_ENV_BUFFER_SIZE);
57 if (grn_table_select_enough_filtered_ratio_env[0]) {
58 grn_table_select_enough_filtered_ratio =
59 atof(grn_table_select_enough_filtered_ratio_env);
60 }
61 }
62
63 {
64 char grn_table_select_max_n_enough_filtered_records_env[GRN_ENV_BUFFER_SIZE];
65 grn_getenv("GRN_TABLE_SELECT_MAX_N_ENOUGH_FILTERED_RECORDS",
66 grn_table_select_max_n_enough_filtered_records_env,
67 GRN_ENV_BUFFER_SIZE);
68 if (grn_table_select_max_n_enough_filtered_records_env[0]) {
69 grn_table_select_max_n_enough_filtered_records =
70 atoi(grn_table_select_max_n_enough_filtered_records_env);
71 }
72 }
73
74 {
75 char grn_table_select_and_min_skip_enable_env[GRN_ENV_BUFFER_SIZE];
76 grn_getenv("GRN_TABLE_SELECT_AND_MIN_SKIP_ENABLE",
77 grn_table_select_and_min_skip_enable_env,
78 GRN_ENV_BUFFER_SIZE);
79 if (strcmp(grn_table_select_and_min_skip_enable_env, "no") == 0) {
80 grn_table_select_and_min_skip_enable = GRN_FALSE;
81 } else {
82 grn_table_select_and_min_skip_enable = GRN_TRUE;
83 }
84 }
85
86 {
87 char grn_scan_info_regexp_dot_asterisk_enable_env[GRN_ENV_BUFFER_SIZE];
88 grn_getenv("GRN_SCAN_INFO_REGEXP_DOT_ASTERISK_ENABLE",
89 grn_scan_info_regexp_dot_asterisk_enable_env,
90 GRN_ENV_BUFFER_SIZE);
91 if (strcmp(grn_scan_info_regexp_dot_asterisk_enable_env, "no") == 0) {
92 grn_scan_info_regexp_dot_asterisk_enable = GRN_FALSE;
93 } else {
94 grn_scan_info_regexp_dot_asterisk_enable = GRN_TRUE;
95 }
96 }
97}
98
99grn_obj *
100grn_expr_alloc(grn_ctx *ctx, grn_obj *expr, grn_id domain, unsigned char flags)
101{
102 grn_obj *res = NULL;
103 grn_expr *e = (grn_expr *)expr;
104 if (e) {
105 if (e->values_curr >= e->values_size) {
106 // todo : expand values.
107 ERR(GRN_NO_MEMORY_AVAILABLE, "no more e->values");
108 return NULL;
109 }
110 res = &e->values[e->values_curr++];
111 if (e->values_curr > e->values_tail) { e->values_tail = e->values_curr; }
112 grn_obj_reinit(ctx, res, domain, flags);
113 }
114 return res;
115}
116
117grn_hash *
118grn_expr_get_vars(grn_ctx *ctx, grn_obj *expr, unsigned int *nvars)
119{
120 grn_hash *vars = NULL;
121 if (expr->header.type == GRN_PROC || expr->header.type == GRN_EXPR) {
122 grn_id id = DB_OBJ(expr)->id;
123 grn_expr *e = (grn_expr *)expr;
124 int added = 0;
125 grn_hash **vp;
126 if (grn_hash_add(ctx, ctx->impl->expr_vars, &id, sizeof(grn_id), (void **)&vp, &added)) {
127 if (!*vp) {
128 *vp = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, sizeof(grn_obj),
129 GRN_OBJ_KEY_VAR_SIZE|GRN_OBJ_TEMPORARY|GRN_HASH_TINY);
130 if (*vp) {
131 uint32_t i;
132 grn_obj *value;
133 grn_expr_var *v;
134 for (v = e->vars, i = e->nvars; i; v++, i--) {
135 grn_hash_add(ctx, *vp, v->name, v->name_size, (void **)&value, &added);
136 GRN_OBJ_INIT(value, v->value.header.type, 0, v->value.header.domain);
137 GRN_TEXT_PUT(ctx, value, GRN_TEXT_VALUE(&v->value), GRN_TEXT_LEN(&v->value));
138 }
139 }
140 }
141 vars = *vp;
142 }
143 }
144 *nvars = vars ? GRN_HASH_SIZE(vars) : 0;
145 return vars;
146}
147
148grn_rc
149grn_expr_clear_vars(grn_ctx *ctx, grn_obj *expr)
150{
151 if (expr->header.type == GRN_PROC || expr->header.type == GRN_EXPR) {
152 grn_hash **vp;
153 grn_id eid, id = DB_OBJ(expr)->id;
154 if ((eid = grn_hash_get(ctx, ctx->impl->expr_vars, &id, sizeof(grn_id), (void **)&vp))) {
155 if (*vp) {
156 grn_obj *value;
157 GRN_HASH_EACH(ctx, *vp, i, NULL, NULL, (void **)&value, {
158 GRN_OBJ_FIN(ctx, value);
159 });
160 grn_hash_close(ctx, *vp);
161 }
162 grn_hash_delete_by_id(ctx, ctx->impl->expr_vars, eid, NULL);
163 }
164 }
165 return ctx->rc;
166}
167
168grn_obj *
169grn_proc_get_info(grn_ctx *ctx, grn_user_data *user_data,
170 grn_expr_var **vars, unsigned int *nvars, grn_obj **caller)
171{
172 grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
173 if (caller) { *caller = pctx->caller; }
174 if (pctx->proc) {
175 if (vars) {
176 *vars = pctx->proc->vars;
177 // *vars = grn_expr_get_vars(ctx, (grn_obj *)pctx->proc, nvars);
178 }
179 if (nvars) { *nvars = pctx->proc->nvars; }
180 } else {
181 if (vars) { *vars = NULL; }
182 if (nvars) { *nvars = 0; }
183 }
184 return (grn_obj *)pctx->proc;
185}
186
187grn_obj *
188grn_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data)
189{
190 uint32_t n;
191 grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
192 if (pctx->proc) {
193 return (grn_obj *)grn_expr_get_vars(ctx, (grn_obj *)pctx->proc, &n);
194 } else {
195 return NULL;
196 }
197}
198
199grn_obj *
200grn_proc_get_var(grn_ctx *ctx, grn_user_data *user_data, const char *name, unsigned int name_size)
201{
202 grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
203 return pctx->proc ? grn_expr_get_var(ctx, (grn_obj *)pctx->proc, name, name_size) : NULL;
204}
205
206grn_obj *
207grn_proc_get_var_by_offset(grn_ctx *ctx, grn_user_data *user_data, unsigned int offset)
208{
209 grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
210 return pctx->proc ? grn_expr_get_var_by_offset(ctx, (grn_obj *)pctx->proc, offset) : NULL;
211}
212
213grn_obj *
214grn_proc_get_or_add_var(grn_ctx *ctx, grn_user_data *user_data,
215 const char *name, unsigned int name_size)
216{
217 grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
218 return pctx->proc ? grn_expr_get_or_add_var(ctx, (grn_obj *)pctx->proc, name, name_size) : NULL;
219}
220
221grn_obj *
222grn_proc_alloc(grn_ctx *ctx, grn_user_data *user_data, grn_id domain, unsigned char flags)
223{
224 grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
225 return pctx->caller ? grn_expr_alloc(ctx, (grn_obj *)pctx->caller, domain, flags) : NULL;
226}
227
228grn_proc_type
229grn_proc_get_type(grn_ctx *ctx, grn_obj *proc)
230{
231 grn_proc *proc_ = (grn_proc *)proc;
232 return proc_ ? proc_->type : GRN_PROC_INVALID;
233}
234
235grn_rc
236grn_proc_set_selector(grn_ctx *ctx, grn_obj *proc, grn_selector_func selector)
237{
238 grn_proc *proc_ = (grn_proc *)proc;
239 if (!grn_obj_is_function_proc(ctx, proc)) {
240 return GRN_INVALID_ARGUMENT;
241 }
242 proc_->callbacks.function.selector = selector;
243 return GRN_SUCCESS;
244}
245
246grn_rc
247grn_proc_set_selector_operator(grn_ctx *ctx, grn_obj *proc, grn_operator op)
248{
249 grn_proc *proc_ = (grn_proc *)proc;
250 if (!grn_obj_is_function_proc(ctx, proc)) {
251 return GRN_INVALID_ARGUMENT;
252 }
253 proc_->callbacks.function.selector_op = op;
254 return GRN_SUCCESS;
255}
256
257grn_operator
258grn_proc_get_selector_operator(grn_ctx *ctx, grn_obj *proc)
259{
260 grn_proc *proc_ = (grn_proc *)proc;
261 if (!grn_obj_is_function_proc(ctx, proc)) {
262 return GRN_OP_NOP;
263 }
264 return proc_->callbacks.function.selector_op;
265}
266
267grn_rc
268grn_proc_set_is_stable(grn_ctx *ctx, grn_obj *proc, grn_bool is_stable)
269{
270 grn_proc *proc_ = (grn_proc *)proc;
271 if (!grn_obj_is_function_proc(ctx, proc)) {
272 return GRN_INVALID_ARGUMENT;
273 }
274 proc_->callbacks.function.is_stable = is_stable;
275 return GRN_SUCCESS;
276}
277
278grn_bool
279grn_proc_is_stable(grn_ctx *ctx, grn_obj *proc)
280{
281 grn_proc *proc_ = (grn_proc *)proc;
282 if (!grn_obj_is_function_proc(ctx, proc)) {
283 return GRN_FALSE;
284 }
285 return proc_->callbacks.function.is_stable;
286}
287
288/* grn_expr */
289
290grn_obj *
291grn_ctx_pop(grn_ctx *ctx)
292{
293 if (ctx && ctx->impl && ctx->impl->stack_curr) {
294 return ctx->impl->stack[--ctx->impl->stack_curr];
295 }
296 return NULL;
297}
298
299grn_rc
300grn_ctx_push(grn_ctx *ctx, grn_obj *obj)
301{
302 if (ctx && ctx->impl && ctx->impl->stack_curr < GRN_STACK_SIZE) {
303 ctx->impl->stack[ctx->impl->stack_curr++] = obj;
304 return GRN_SUCCESS;
305 }
306 return GRN_STACK_OVER_FLOW;
307}
308
309grn_obj *
310grn_expr_alloc_const(grn_ctx *ctx, grn_obj *expr)
311{
312 grn_expr *e = (grn_expr *)expr;
313 uint32_t id = e->nconsts % GRN_EXPR_CONST_BLK_SIZE;
314 uint32_t blk_id = e->nconsts / GRN_EXPR_CONST_BLK_SIZE;
315
316 if (id == 0) {
317 uint32_t nblks = blk_id + 1;
318 grn_obj **blks = (grn_obj **)GRN_REALLOC(e->const_blks,
319 sizeof(grn_obj *) * nblks);
320 if (!blks) {
321 ERR(GRN_NO_MEMORY_AVAILABLE, "realloc failed");
322 return NULL;
323 }
324 e->const_blks = blks;
325 blks[blk_id] = GRN_MALLOCN(grn_obj, GRN_EXPR_CONST_BLK_SIZE);
326 if (!blks[blk_id]) {
327 ERR(GRN_NO_MEMORY_AVAILABLE, "malloc failed");
328 return NULL;
329 }
330 }
331 e->nconsts++;
332 return &e->const_blks[blk_id][id];
333}
334
335void
336grn_obj_pack(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
337{
338 grn_text_benc(ctx, buf, obj->header.type);
339 if (GRN_DB_OBJP(obj)) {
340 grn_text_benc(ctx, buf, DB_OBJ(obj)->id);
341 } else {
342 // todo : support vector, query, accessor, snip..
343 uint32_t vs = GRN_BULK_VSIZE(obj);
344 grn_text_benc(ctx, buf, obj->header.domain);
345 grn_text_benc(ctx, buf, vs);
346 if (vs) { GRN_TEXT_PUT(ctx, buf, GRN_BULK_HEAD(obj), vs); }
347 }
348}
349
350const uint8_t *
351grn_obj_unpack(grn_ctx *ctx, const uint8_t *p, const uint8_t *pe, uint8_t type, uint8_t flags, grn_obj *obj)
352{
353 grn_id domain;
354 uint32_t vs;
355 GRN_B_DEC(domain, p);
356 GRN_OBJ_INIT(obj, type, flags, domain);
357 GRN_B_DEC(vs, p);
358 if (pe < p + vs) {
359 ERR(GRN_INVALID_FORMAT, "benced image is corrupt");
360 return p;
361 }
362 grn_bulk_write(ctx, obj, (const char *)p, vs);
363 return p + vs;
364}
365
366typedef enum {
367 GRN_EXPR_PACK_TYPE_NULL = 0,
368 GRN_EXPR_PACK_TYPE_VARIABLE = 1,
369 GRN_EXPR_PACK_TYPE_OTHERS = 2
370} grn_expr_pack_type;
371
372void
373grn_expr_pack(grn_ctx *ctx, grn_obj *buf, grn_obj *expr)
374{
375 grn_expr_code *c;
376 grn_expr_var *v;
377 grn_expr *e = (grn_expr *)expr;
378 uint32_t i, j;
379 grn_text_benc(ctx, buf, e->nvars);
380 for (i = e->nvars, v = e->vars; i; i--, v++) {
381 grn_text_benc(ctx, buf, v->name_size);
382 if (v->name_size) { GRN_TEXT_PUT(ctx, buf, v->name, v->name_size); }
383 grn_obj_pack(ctx, buf, &v->value);
384 }
385 i = e->codes_curr;
386 grn_text_benc(ctx, buf, i);
387 for (c = e->codes; i; i--, c++) {
388 grn_text_benc(ctx, buf, c->op);
389 grn_text_benc(ctx, buf, c->nargs);
390 if (!c->value) {
391 grn_text_benc(ctx, buf, GRN_EXPR_PACK_TYPE_NULL);
392 } else {
393 for (j = 0, v = e->vars; j < e->nvars; j++, v++) {
394 if (&v->value == c->value) {
395 grn_text_benc(ctx, buf, GRN_EXPR_PACK_TYPE_VARIABLE);
396 grn_text_benc(ctx, buf, j);
397 break;
398 }
399 }
400 if (j == e->nvars) {
401 grn_text_benc(ctx, buf, GRN_EXPR_PACK_TYPE_OTHERS);
402 grn_obj_pack(ctx, buf, c->value);
403 }
404 }
405 }
406}
407
408const uint8_t *
409grn_expr_unpack(grn_ctx *ctx, const uint8_t *p, const uint8_t *pe, grn_obj *expr)
410{
411 grn_obj *v;
412 grn_expr_pack_type type;
413 uint32_t i, n, ns;
414 grn_expr_code *code;
415 grn_expr *e = (grn_expr *)expr;
416 GRN_B_DEC(n, p);
417 for (i = 0; i < n; i++) {
418 uint32_t object_type;
419 GRN_B_DEC(ns, p);
420 v = grn_expr_add_var(ctx, expr, ns ? (const char *)p : NULL, ns);
421 p += ns;
422 GRN_B_DEC(object_type, p);
423 if (GRN_TYPE <= object_type && object_type <= GRN_COLUMN_INDEX) { /* error */ }
424 p = grn_obj_unpack(ctx, p, pe, object_type, 0, v);
425 if (pe < p) {
426 ERR(GRN_INVALID_FORMAT, "benced image is corrupt");
427 return p;
428 }
429 }
430 GRN_B_DEC(n, p);
431 /* confirm e->codes_size >= n */
432 e->codes_curr = n;
433 for (i = 0, code = e->codes; i < n; i++, code++) {
434 GRN_B_DEC(code->op, p);
435 GRN_B_DEC(code->nargs, p);
436 GRN_B_DEC(type, p);
437 switch (type) {
438 case GRN_EXPR_PACK_TYPE_NULL :
439 code->value = NULL;
440 break;
441 case GRN_EXPR_PACK_TYPE_VARIABLE :
442 {
443 uint32_t offset;
444 GRN_B_DEC(offset, p);
445 code->value = &e->vars[i].value;
446 }
447 break;
448 case GRN_EXPR_PACK_TYPE_OTHERS :
449 {
450 uint32_t object_type;
451 GRN_B_DEC(object_type, p);
452 if (GRN_TYPE <= object_type && object_type <= GRN_COLUMN_INDEX) {
453 grn_id id;
454 GRN_B_DEC(id, p);
455 code->value = grn_ctx_at(ctx, id);
456 } else {
457 if (!(v = grn_expr_alloc_const(ctx, expr))) { return NULL; }
458 p = grn_obj_unpack(ctx, p, pe, object_type, GRN_OBJ_EXPRCONST, v);
459 code->value = v;
460 }
461 }
462 break;
463 }
464 if (pe < p) {
465 ERR(GRN_INVALID_FORMAT, "benced image is corrupt");
466 return p;
467 }
468 }
469 return p;
470}
471
472grn_obj *
473grn_expr_open(grn_ctx *ctx, grn_obj_spec *spec, const uint8_t *p, const uint8_t *pe)
474{
475 grn_expr *expr = NULL;
476 if ((expr = GRN_MALLOCN(grn_expr, 1))) {
477 int size = GRN_STACK_SIZE;
478 expr->const_blks = NULL;
479 expr->nconsts = 0;
480 GRN_TEXT_INIT(&expr->name_buf, 0);
481 GRN_TEXT_INIT(&expr->dfi, 0);
482 GRN_PTR_INIT(&expr->objs, GRN_OBJ_VECTOR, GRN_ID_NIL);
483 expr->vars = NULL;
484 expr->nvars = 0;
485 GRN_DB_OBJ_SET_TYPE(expr, GRN_EXPR);
486 if ((expr->values = GRN_MALLOCN(grn_obj, size))) {
487 int i;
488 for (i = 0; i < size; i++) {
489 GRN_OBJ_INIT(&expr->values[i], GRN_BULK, GRN_OBJ_EXPRVALUE, GRN_ID_NIL);
490 }
491 expr->values_curr = 0;
492 expr->values_tail = 0;
493 expr->values_size = size;
494 if ((expr->codes = GRN_MALLOCN(grn_expr_code, size))) {
495 expr->codes_curr = 0;
496 expr->codes_size = size;
497 expr->obj.header = spec->header;
498 if (grn_expr_unpack(ctx, p, pe, (grn_obj *)expr) == pe) {
499 goto exit;
500 } else {
501 ERR(GRN_INVALID_FORMAT, "benced image is corrupt");
502 }
503 GRN_FREE(expr->codes);
504 }
505 GRN_FREE(expr->values);
506 }
507 GRN_FREE(expr);
508 expr = NULL;
509 }
510exit :
511 return (grn_obj *)expr;
512}
513
514/* Pass ownership of `obj` to `expr`. */
515void
516grn_expr_take_obj(grn_ctx *ctx, grn_obj *expr, grn_obj *obj)
517{
518 grn_expr *e = (grn_expr *)expr;
519 GRN_PTR_PUT(ctx, &(e->objs), obj);
520}
521
522/* data flow info */
523typedef struct {
524 grn_expr_code *code;
525 grn_id domain;
526 unsigned char type;
527} grn_expr_dfi;
528
529static grn_expr_dfi *
530grn_expr_dfi_pop(grn_expr *expr)
531{
532 if (GRN_BULK_VSIZE(&expr->dfi) >= sizeof(grn_expr_dfi)) {
533 grn_expr_dfi *dfi;
534 GRN_BULK_INCR_LEN(&expr->dfi, -((ssize_t)(sizeof(grn_expr_dfi))));
535 dfi = (grn_expr_dfi *)GRN_BULK_CURR(&expr->dfi);
536 expr->code0 = dfi->code;
537 return dfi;
538 } else {
539 expr->code0 = NULL;
540 return NULL;
541 }
542}
543
544static void
545grn_expr_dfi_put(grn_ctx *ctx, grn_expr *expr, uint8_t type, grn_id domain,
546 grn_expr_code *code)
547{
548 grn_expr_dfi dfi;
549 dfi.type = type;
550 dfi.domain = domain;
551 dfi.code = code;
552 if (expr->code0) {
553 expr->code0->modify = code ? (code - expr->code0) : 0;
554 }
555 grn_bulk_write(ctx, &expr->dfi, (char *)&dfi, sizeof(grn_expr_dfi));
556 expr->code0 = NULL;
557}
558
559grn_obj *
560grn_expr_create(grn_ctx *ctx, const char *name, unsigned int name_size)
561{
562 grn_id id;
563 grn_obj *db;
564 grn_expr *expr = NULL;
565 if (!ctx || !ctx->impl || !(db = ctx->impl->db)) {
566 ERR(GRN_INVALID_ARGUMENT, "db not initialized");
567 return NULL;
568 }
569 if (name_size) {
570 ERR(GRN_FUNCTION_NOT_IMPLEMENTED,
571 "[expr][create] named expression isn't implemented yet");
572 return NULL;
573 }
574 GRN_API_ENTER;
575 if (grn_db_check_name(ctx, name, name_size)) {
576 GRN_DB_CHECK_NAME_ERR("[expr][create]", name, name_size);
577 GRN_API_RETURN(NULL);
578 }
579 if (!GRN_DB_P(db)) {
580 ERR(GRN_INVALID_ARGUMENT, "named expr is not supported");
581 GRN_API_RETURN(NULL);
582 }
583 id = grn_obj_register(ctx, db, name, name_size);
584 if (id && (expr = GRN_MALLOCN(grn_expr, 1))) {
585 int size = GRN_STACK_SIZE;
586 expr->const_blks = NULL;
587 expr->nconsts = 0;
588 GRN_TEXT_INIT(&expr->name_buf, 0);
589 GRN_TEXT_INIT(&expr->dfi, 0);
590 GRN_PTR_INIT(&expr->objs, GRN_OBJ_VECTOR, GRN_ID_NIL);
591 expr->code0 = NULL;
592 expr->vars = NULL;
593 expr->nvars = 0;
594 expr->cacheable = 1;
595 expr->taintable = 0;
596 expr->values_curr = 0;
597 expr->values_tail = 0;
598 expr->values_size = size;
599 expr->codes_curr = 0;
600 expr->codes_size = size;
601 GRN_DB_OBJ_SET_TYPE(expr, GRN_EXPR);
602 expr->obj.header.domain = GRN_ID_NIL;
603 expr->obj.range = GRN_ID_NIL;
604 if (!grn_db_obj_init(ctx, db, id, DB_OBJ(expr))) {
605 if ((expr->values = GRN_MALLOCN(grn_obj, size))) {
606 int i;
607 for (i = 0; i < size; i++) {
608 GRN_OBJ_INIT(&expr->values[i], GRN_BULK, GRN_OBJ_EXPRVALUE, GRN_ID_NIL);
609 }
610 if ((expr->codes = GRN_MALLOCN(grn_expr_code, size))) {
611 goto exit;
612 }
613 GRN_FREE(expr->values);
614 }
615 }
616 GRN_FREE(expr);
617 expr = NULL;
618 }
619exit :
620 GRN_API_RETURN((grn_obj *)expr);
621}
622
623grn_rc
624grn_expr_close(grn_ctx *ctx, grn_obj *expr)
625{
626 uint32_t i, j;
627 grn_expr *e = (grn_expr *)expr;
628 GRN_API_ENTER;
629 /*
630 if (e->obj.header.domain) {
631 grn_hash_delete(ctx, ctx->impl->qe, &e->obj.header.domain, sizeof(grn_id), NULL);
632 }
633 */
634 grn_expr_clear_vars(ctx, expr);
635 if (e->const_blks) {
636 uint32_t nblks = e->nconsts + GRN_EXPR_CONST_BLK_SIZE - 1;
637 nblks /= GRN_EXPR_CONST_BLK_SIZE;
638 for (i = 0; i < nblks; i++) {
639 uint32_t end;
640 if (i < nblks - 1) {
641 end = GRN_EXPR_CONST_BLK_SIZE;
642 } else {
643 end = ((e->nconsts - 1) % GRN_EXPR_CONST_BLK_SIZE) + 1;
644 }
645 for (j = 0; j < end; j++) {
646 grn_obj *const_obj = &e->const_blks[i][j];
647 grn_obj_close(ctx, const_obj);
648 }
649 GRN_FREE(e->const_blks[i]);
650 }
651 GRN_FREE(e->const_blks);
652 }
653 grn_obj_close(ctx, &e->name_buf);
654 grn_obj_close(ctx, &e->dfi);
655 for (;;) {
656 grn_obj *obj;
657 GRN_PTR_POP(&e->objs, obj);
658 if (obj) {
659#ifdef USE_MEMORY_DEBUG
660 grn_obj_unlink(ctx, obj);
661#else
662 if (obj->header.type) {
663 if (obj->header.type == GRN_TABLE_HASH_KEY &&
664 ((grn_hash *)obj)->value_size == sizeof(grn_obj)) {
665 grn_obj *value;
666 GRN_HASH_EACH(ctx, (grn_hash *)obj, id, NULL, NULL, (void **)&value, {
667 GRN_OBJ_FIN(ctx, value);
668 });
669 }
670 grn_obj_unlink(ctx, obj);
671 } else {
672 GRN_LOG(ctx, GRN_LOG_WARNING, "GRN_VOID object is tried to be unlinked");
673 }
674#endif
675 } else { break; }
676 }
677 grn_obj_close(ctx, &e->objs);
678 for (i = 0; i < e->nvars; i++) {
679 grn_obj_close(ctx, &e->vars[i].value);
680 }
681 if (e->vars) { GRN_FREE(e->vars); }
682 for (i = 0; i < e->values_tail; i++) {
683 grn_obj_close(ctx, &e->values[i]);
684 }
685 GRN_FREE(e->values);
686 GRN_FREE(e->codes);
687 GRN_FREE(e);
688 GRN_API_RETURN(ctx->rc);
689}
690
691grn_obj *
692grn_expr_add_var(grn_ctx *ctx, grn_obj *expr, const char *name, unsigned int name_size)
693{
694 uint32_t i;
695 char *p;
696 grn_expr_var *v;
697 grn_obj *res = NULL;
698 grn_expr *e = (grn_expr *)expr;
699 GRN_API_ENTER;
700 if (DB_OBJ(expr)->id & GRN_OBJ_TMP_OBJECT) {
701 res = grn_expr_get_or_add_var(ctx, expr, name, name_size);
702 } else {
703 if (!e->vars) {
704 if (!(e->vars = GRN_MALLOCN(grn_expr_var, GRN_STACK_SIZE))) {
705 ERR(GRN_NO_MEMORY_AVAILABLE, "malloc failed");
706 }
707 }
708 if (e->vars && e->nvars < GRN_STACK_SIZE) {
709 v = e->vars + e->nvars++;
710 if (name_size) {
711 GRN_TEXT_PUT(ctx, &e->name_buf, name, name_size);
712 } else {
713 uint32_t ol = GRN_TEXT_LEN(&e->name_buf);
714 GRN_TEXT_PUTC(ctx, &e->name_buf, '$');
715 grn_text_itoa(ctx, &e->name_buf, e->nvars);
716 name_size = GRN_TEXT_LEN(&e->name_buf) - ol;
717 }
718 v->name_size = name_size;
719 res = &v->value;
720 GRN_VOID_INIT(res);
721 for (i = e->nvars, p = GRN_TEXT_VALUE(&e->name_buf), v = e->vars; i; i--, v++) {
722 v->name = p;
723 p += v->name_size;
724 }
725 }
726 }
727 GRN_API_RETURN(res);
728}
729
730grn_obj *
731grn_expr_get_var(grn_ctx *ctx, grn_obj *expr, const char *name, unsigned int name_size)
732{
733 uint32_t n;
734 grn_obj *res = NULL;
735 grn_hash *vars = grn_expr_get_vars(ctx, expr, &n);
736 if (vars) { grn_hash_get(ctx, vars, name, name_size, (void **)&res); }
737 return res;
738}
739
740grn_obj *
741grn_expr_get_or_add_var(grn_ctx *ctx, grn_obj *expr, const char *name, unsigned int name_size)
742{
743 uint32_t n;
744 grn_obj *res = NULL;
745 grn_hash *vars = grn_expr_get_vars(ctx, expr, &n);
746 if (vars) {
747 int added = 0;
748 char name_buf[16];
749 if (!name_size) {
750 char *rest;
751 name_buf[0] = '$';
752 grn_itoa((int)GRN_HASH_SIZE(vars) + 1, name_buf + 1, name_buf + 16, &rest);
753 name_size = rest - name_buf;
754 name = name_buf;
755 }
756 grn_hash_add(ctx, vars, name, name_size, (void **)&res, &added);
757 if (added) { GRN_TEXT_INIT(res, 0); }
758 }
759 return res;
760}
761
762grn_obj *
763grn_expr_get_var_by_offset(grn_ctx *ctx, grn_obj *expr, unsigned int offset)
764{
765 uint32_t n;
766 grn_obj *res = NULL;
767 grn_hash *vars = grn_expr_get_vars(ctx, expr, &n);
768 if (vars) { res = (grn_obj *)grn_hash_get_value_(ctx, vars, offset + 1, NULL); }
769 return res;
770}
771
772#define EXPRVP(x) ((x)->header.impl_flags & GRN_OBJ_EXPRVALUE)
773
774#define CONSTP(obj) ((obj) && ((obj)->header.impl_flags & GRN_OBJ_EXPRCONST))
775
776#define PUSH_CODE(e,o,v,n,c) do {\
777 (c) = &(e)->codes[e->codes_curr++];\
778 (c)->value = (v);\
779 (c)->nargs = (n);\
780 (c)->op = (o);\
781 (c)->flags = 0;\
782 (c)->modify = 0;\
783} while (0)
784
785#define APPEND_UNARY_MINUS_OP(e) do { \
786 grn_expr_code *code_; \
787 grn_id domain; \
788 unsigned char type; \
789 grn_obj *x; \
790 dfi = grn_expr_dfi_pop(e); \
791 code_ = dfi->code; \
792 domain = dfi->domain; \
793 type = dfi->type; \
794 x = code_->value; \
795 if (CONSTP(x)) { \
796 switch (domain) { \
797 case GRN_DB_INT32: \
798 { \
799 int value; \
800 value = GRN_INT32_VALUE(x); \
801 if (value == (int)0x80000000) { \
802 domain = GRN_DB_INT64; \
803 x->header.domain = domain; \
804 GRN_INT64_SET(ctx, x, -((long long int)value)); \
805 } else { \
806 GRN_INT32_SET(ctx, x, -value); \
807 } \
808 } \
809 break; \
810 case GRN_DB_UINT32: \
811 { \
812 unsigned int value; \
813 value = GRN_UINT32_VALUE(x); \
814 if (value > (unsigned int)0x80000000) { \
815 domain = GRN_DB_INT64; \
816 x->header.domain = domain; \
817 GRN_INT64_SET(ctx, x, -((long long int)value)); \
818 } else { \
819 domain = GRN_DB_INT32; \
820 x->header.domain = domain; \
821 GRN_INT32_SET(ctx, x, -((int)value)); \
822 } \
823 } \
824 break; \
825 case GRN_DB_INT64: \
826 GRN_INT64_SET(ctx, x, -GRN_INT64_VALUE(x)); \
827 break; \
828 case GRN_DB_FLOAT: \
829 GRN_FLOAT_SET(ctx, x, -GRN_FLOAT_VALUE(x)); \
830 break; \
831 default: \
832 PUSH_CODE(e, op, obj, nargs, code); \
833 break; \
834 } \
835 } else { \
836 PUSH_CODE(e, op, obj, nargs, code); \
837 } \
838 grn_expr_dfi_put(ctx, e, type, domain, code_); \
839} while (0)
840
841#define PUSH_N_ARGS_ARITHMETIC_OP(e, op, obj, nargs, code) do { \
842 PUSH_CODE(e, op, obj, nargs, code); \
843 { \
844 int i = nargs; \
845 while (i--) { \
846 dfi = grn_expr_dfi_pop(e); \
847 } \
848 } \
849 grn_expr_dfi_put(ctx, e, type, domain, code); \
850} while (0)
851
852static void
853grn_expr_append_obj_resolve_const(grn_ctx *ctx,
854 grn_obj *obj,
855 grn_id to_domain)
856{
857 grn_obj dest;
858
859 GRN_OBJ_INIT(&dest, GRN_BULK, 0, to_domain);
860 if (!grn_obj_cast(ctx, obj, &dest, GRN_FALSE)) {
861 grn_obj_reinit(ctx, obj, to_domain, 0);
862 grn_bulk_write(ctx, obj, GRN_BULK_HEAD(&dest), GRN_BULK_VSIZE(&dest));
863 }
864 GRN_OBJ_FIN(ctx, &dest);
865}
866
867grn_obj *
868grn_expr_append_obj(grn_ctx *ctx, grn_obj *expr, grn_obj *obj, grn_operator op, int nargs)
869{
870 uint8_t type = GRN_VOID;
871 grn_id domain = GRN_ID_NIL;
872 grn_expr_dfi *dfi;
873 grn_expr_code *code;
874 grn_obj *res = NULL;
875 grn_expr *e = (grn_expr *)expr;
876 GRN_API_ENTER;
877 if (e->codes_curr >= e->codes_size) {
878 grn_expr_dfi *dfis = (grn_expr_dfi *)GRN_BULK_HEAD(&e->dfi);
879 size_t i, n_dfis = GRN_BULK_VSIZE(&e->dfi) / sizeof(grn_expr_dfi);
880 uint32_t new_codes_size = e->codes_size * 2;
881 size_t n_bytes = sizeof(grn_expr_code) * new_codes_size;
882 grn_expr_code *new_codes = (grn_expr_code *)GRN_MALLOC(n_bytes);
883 if (!new_codes) {
884 ERR(GRN_NO_MEMORY_AVAILABLE, "stack is full");
885 goto exit;
886 }
887 grn_memcpy(new_codes, e->codes, sizeof(grn_expr_code) * e->codes_size);
888 if (e->code0 >= e->codes && e->code0 < e->codes + e->codes_size) {
889 e->code0 = new_codes + (e->code0 - e->codes);
890 }
891 for (i = 0; i < n_dfis; i++) {
892 if (dfis[i].code >= e->codes && dfis[i].code < e->codes + e->codes_size) {
893 dfis[i].code = new_codes + (dfis[i].code - e->codes);
894 }
895 }
896 GRN_FREE(e->codes);
897 e->codes = new_codes;
898 e->codes_size = new_codes_size;
899 }
900 {
901 switch (op) {
902 case GRN_OP_PUSH :
903 if (obj) {
904 PUSH_CODE(e, op, obj, nargs, code);
905 grn_expr_dfi_put(ctx, e, obj->header.type, GRN_OBJ_GET_DOMAIN(obj),
906 code);
907 } else {
908 ERR(GRN_INVALID_ARGUMENT, "obj not assigned for GRN_OP_PUSH");
909 goto exit;
910 }
911 break;
912 case GRN_OP_NOP :
913 /* nop */
914 break;
915 case GRN_OP_POP :
916 if (obj) {
917 ERR(GRN_INVALID_ARGUMENT, "obj assigned for GRN_OP_POP");
918 goto exit;
919 } else {
920 PUSH_CODE(e, op, obj, nargs, code);
921 dfi = grn_expr_dfi_pop(e);
922 }
923 break;
924 case GRN_OP_CALL :
925 {
926 grn_obj *proc = NULL;
927 /*
928 * This is for keeping backward compatibility. We want to
929 * handle all "nargs" means that "N items on stack are used (N
930 * items are popped)" but "nargs" for OP_CALL is used as "N
931 * arguments" not "N items on stack are used" historically. It
932 * means that called function isn't included in "nargs".
933 *
934 * We adjust "nargs" here to handle "code->nargs" more easily.
935 * If we don't adjust "nargs" here, we need to care
936 * "code->nargs" at all locations that use "code->nargs". We
937 * need to use "code->nargs + 1" for OP_CALL and "code->nargs"
938 * for not OP_CALL to compute N items should be popped. It's
939 * wired. So we adjust "nargs" here.
940 */
941 nargs++;
942 if (e->codes_curr - (nargs - 1) > 0) {
943 int i;
944 grn_expr_code *code;
945 code = &(e->codes[e->codes_curr - 1]);
946 for (i = 0; i < nargs - 1; i++) {
947 int rest_n_codes = 1;
948 while (rest_n_codes > 0) {
949 rest_n_codes += code->nargs;
950 if (code->value) {
951 rest_n_codes--;
952 }
953 rest_n_codes--;
954 code--;
955 }
956 }
957 proc = code->value;
958 }
959 if (!proc) {
960 ERR(GRN_INVALID_ARGUMENT, "invalid function call expression");
961 goto exit;
962 }
963 if (!(grn_obj_is_function_proc(ctx, proc) ||
964 grn_obj_is_scorer_proc(ctx, proc) ||
965 grn_obj_is_window_function_proc(ctx, proc))) {
966 grn_obj buffer;
967
968 GRN_TEXT_INIT(&buffer, 0);
969 switch (proc->header.type) {
970 case GRN_TABLE_HASH_KEY:
971 case GRN_TABLE_PAT_KEY:
972 case GRN_TABLE_NO_KEY:
973 case GRN_COLUMN_FIX_SIZE:
974 case GRN_COLUMN_VAR_SIZE:
975 case GRN_COLUMN_INDEX:
976 grn_inspect_name(ctx, &buffer, proc);
977 break;
978 default:
979 grn_inspect(ctx, &buffer, proc);
980 break;
981 }
982 ERR(GRN_INVALID_ARGUMENT, "invalid function: <%.*s>",
983 (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
984 GRN_OBJ_FIN(ctx, &buffer);
985 goto exit;
986 }
987
988 PUSH_CODE(e, op, obj, nargs, code);
989 {
990 int i = nargs - 1;
991 while (i--) { dfi = grn_expr_dfi_pop(e); }
992 }
993 if (!obj) { dfi = grn_expr_dfi_pop(e); }
994 // todo : increment e->values_tail.
995 /* cannot identify type of return value */
996 grn_expr_dfi_put(ctx, e, type, domain, code);
997 if (!grn_proc_is_stable(ctx, proc)) {
998 e->cacheable = 0;
999 }
1000 }
1001 break;
1002 case GRN_OP_INTERN :
1003 if (obj && CONSTP(obj)) {
1004 grn_obj *value;
1005 value = grn_expr_get_var(ctx, expr, GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj));
1006 if (!value) { value = grn_ctx_get(ctx, GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj)); }
1007 if (value) {
1008 obj = value;
1009 op = GRN_OP_PUSH;
1010 type = obj->header.type;
1011 domain = GRN_OBJ_GET_DOMAIN(obj);
1012 }
1013 }
1014 PUSH_CODE(e, op, obj, nargs, code);
1015 grn_expr_dfi_put(ctx, e, type, domain, code);
1016 break;
1017 case GRN_OP_EQUAL :
1018 PUSH_CODE(e, op, obj, nargs, code);
1019 if (nargs) {
1020 grn_id xd, yd = GRN_ID_NIL;
1021 grn_obj *x, *y = NULL;
1022 int i = nargs - 1;
1023 if (obj) {
1024 xd = GRN_OBJ_GET_DOMAIN(obj);
1025 x = obj;
1026 } else {
1027 dfi = grn_expr_dfi_pop(e);
1028 x = dfi->code->value;
1029 xd = dfi->domain;
1030 }
1031 while (i--) {
1032 dfi = grn_expr_dfi_pop(e);
1033 y = dfi->code->value;
1034 yd = dfi->domain;
1035 }
1036 if (CONSTP(x)) {
1037 if (CONSTP(y)) {
1038 /* todo */
1039 } else {
1040 if (xd != yd) {
1041 grn_expr_append_obj_resolve_const(ctx, x, yd);
1042 }
1043 }
1044 } else {
1045 if (CONSTP(y)) {
1046 if (xd != yd) {
1047 grn_expr_append_obj_resolve_const(ctx, y, xd);
1048 }
1049 }
1050 }
1051 }
1052 grn_expr_dfi_put(ctx, e, type, domain, code);
1053 break;
1054 case GRN_OP_TABLE_CREATE :
1055 case GRN_OP_EXPR_GET_VAR :
1056 case GRN_OP_MATCH :
1057 case GRN_OP_NEAR :
1058 case GRN_OP_NEAR2 :
1059 case GRN_OP_SIMILAR :
1060 case GRN_OP_PREFIX :
1061 case GRN_OP_SUFFIX :
1062 case GRN_OP_NOT_EQUAL :
1063 case GRN_OP_LESS :
1064 case GRN_OP_GREATER :
1065 case GRN_OP_LESS_EQUAL :
1066 case GRN_OP_GREATER_EQUAL :
1067 case GRN_OP_GEO_DISTANCE1 :
1068 case GRN_OP_GEO_DISTANCE2 :
1069 case GRN_OP_GEO_DISTANCE3 :
1070 case GRN_OP_GEO_DISTANCE4 :
1071 case GRN_OP_GEO_WITHINP5 :
1072 case GRN_OP_GEO_WITHINP6 :
1073 case GRN_OP_GEO_WITHINP8 :
1074 case GRN_OP_OBJ_SEARCH :
1075 case GRN_OP_TABLE_SELECT :
1076 case GRN_OP_TABLE_SORT :
1077 case GRN_OP_TABLE_GROUP :
1078 case GRN_OP_JSON_PUT :
1079 case GRN_OP_GET_REF :
1080 case GRN_OP_ADJUST :
1081 case GRN_OP_TERM_EXTRACT :
1082 case GRN_OP_REGEXP :
1083 PUSH_CODE(e, op, obj, nargs, code);
1084 if (nargs) {
1085 int i = nargs - 1;
1086 if (!obj) { dfi = grn_expr_dfi_pop(e); }
1087 while (i--) { dfi = grn_expr_dfi_pop(e); }
1088 }
1089 grn_expr_dfi_put(ctx, e, type, domain, code);
1090 break;
1091 case GRN_OP_AND :
1092 case GRN_OP_OR :
1093 case GRN_OP_AND_NOT :
1094 PUSH_CODE(e, op, obj, nargs, code);
1095 if (nargs != 2) {
1096 GRN_LOG(ctx, GRN_LOG_WARNING, "nargs(%d) != 2 in relative op", nargs);
1097 }
1098 if (obj) {
1099 GRN_LOG(ctx, GRN_LOG_WARNING, "obj assigned to relative op");
1100 }
1101 {
1102 int i = nargs;
1103 while (i--) {
1104 dfi = grn_expr_dfi_pop(e);
1105 if (dfi) {
1106 dfi->code->flags |= GRN_EXPR_CODE_RELATIONAL_EXPRESSION;
1107 } else {
1108 ERR(GRN_SYNTAX_ERROR, "stack under flow in relative op");
1109 }
1110 }
1111 }
1112 grn_expr_dfi_put(ctx, e, type, domain, code);
1113 break;
1114 case GRN_OP_NOT :
1115 if (nargs == 1) {
1116 PUSH_CODE(e, op, obj, nargs, code);
1117 }
1118 break;
1119 case GRN_OP_PLUS :
1120 if (nargs > 1) {
1121 PUSH_N_ARGS_ARITHMETIC_OP(e, op, obj, nargs, code);
1122 }
1123 break;
1124 case GRN_OP_MINUS :
1125 if (nargs == 1) {
1126 APPEND_UNARY_MINUS_OP(e);
1127 } else {
1128 PUSH_N_ARGS_ARITHMETIC_OP(e, op, obj, nargs, code);
1129 }
1130 break;
1131 case GRN_OP_BITWISE_NOT :
1132 dfi = grn_expr_dfi_pop(e);
1133 if (dfi) {
1134 type = dfi->type;
1135 domain = dfi->domain;
1136 switch (domain) {
1137 case GRN_DB_UINT8 :
1138 domain = GRN_DB_INT16;
1139 break;
1140 case GRN_DB_UINT16 :
1141 domain = GRN_DB_INT32;
1142 break;
1143 case GRN_DB_UINT32 :
1144 case GRN_DB_UINT64 :
1145 domain = GRN_DB_INT64;
1146 break;
1147 }
1148 }
1149 PUSH_CODE(e, op, obj, nargs, code);
1150 grn_expr_dfi_put(ctx, e, type, domain, code);
1151 break;
1152 case GRN_OP_STAR :
1153 case GRN_OP_SLASH :
1154 case GRN_OP_MOD :
1155 case GRN_OP_SHIFTL :
1156 case GRN_OP_SHIFTR :
1157 case GRN_OP_SHIFTRR :
1158 case GRN_OP_BITWISE_OR :
1159 case GRN_OP_BITWISE_XOR :
1160 case GRN_OP_BITWISE_AND :
1161 PUSH_N_ARGS_ARITHMETIC_OP(e, op, obj, nargs, code);
1162 break;
1163 case GRN_OP_INCR :
1164 case GRN_OP_DECR :
1165 case GRN_OP_INCR_POST :
1166 case GRN_OP_DECR_POST :
1167 {
1168 dfi = grn_expr_dfi_pop(e);
1169 if (dfi) {
1170 type = dfi->type;
1171 domain = dfi->domain;
1172 if (dfi->code) {
1173 if (dfi->code->op == GRN_OP_GET_VALUE) {
1174 dfi->code->op = GRN_OP_GET_REF;
1175 }
1176 if (dfi->code->value && grn_obj_is_persistent(ctx, dfi->code->value)) {
1177 e->cacheable = 0;
1178 e->taintable = 1;
1179 }
1180 }
1181 }
1182 PUSH_CODE(e, op, obj, nargs, code);
1183 }
1184 grn_expr_dfi_put(ctx, e, type, domain, code);
1185 break;
1186 case GRN_OP_GET_VALUE :
1187 {
1188 grn_id vdomain = GRN_ID_NIL;
1189 if (obj) {
1190 if (nargs == 1) {
1191 grn_obj *v = grn_expr_get_var_by_offset(ctx, expr, 0);
1192 if (v) { vdomain = GRN_OBJ_GET_DOMAIN(v); }
1193 } else {
1194 dfi = grn_expr_dfi_pop(e);
1195 vdomain = dfi->domain;
1196 }
1197 if (vdomain && CONSTP(obj) && obj->header.type == GRN_BULK) {
1198 grn_obj *table = grn_ctx_at(ctx, vdomain);
1199 grn_obj *col = grn_obj_column(ctx, table, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj));
1200 if (col) {
1201 obj = col;
1202 type = col->header.type;
1203 domain = grn_obj_get_range(ctx, col);
1204 grn_expr_take_obj(ctx, (grn_obj *)e, col);
1205 }
1206 } else {
1207 domain = grn_obj_get_range(ctx, obj);
1208 }
1209 PUSH_CODE(e, op, obj, nargs, code);
1210 } else {
1211 grn_expr_dfi *dfi0;
1212 dfi0 = grn_expr_dfi_pop(e);
1213 if (nargs == 1) {
1214 grn_obj *v = grn_expr_get_var_by_offset(ctx, expr, 0);
1215 if (v) { vdomain = GRN_OBJ_GET_DOMAIN(v); }
1216 } else {
1217 dfi = grn_expr_dfi_pop(e);
1218 vdomain = dfi->domain;
1219 }
1220 if (dfi0->code->op == GRN_OP_PUSH) {
1221 dfi0->code->op = op;
1222 dfi0->code->nargs = nargs;
1223 obj = dfi0->code->value;
1224 if (vdomain && obj && CONSTP(obj) && obj->header.type == GRN_BULK) {
1225 grn_obj *table = grn_ctx_at(ctx, vdomain);
1226 grn_obj *col = grn_obj_column(ctx, table, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj));
1227 if (col) {
1228 dfi0->code->value = col;
1229 type = col->header.type;
1230 domain = grn_obj_get_range(ctx, col);
1231 grn_obj_unlink(ctx, col);
1232 }
1233 } else {
1234 domain = grn_obj_get_range(ctx, obj);
1235 }
1236 code = dfi0->code;
1237 } else {
1238 PUSH_CODE(e, op, obj, nargs, code);
1239 }
1240 }
1241 }
1242 grn_expr_dfi_put(ctx, e, type, domain, code);
1243 break;
1244 case GRN_OP_ASSIGN :
1245 case GRN_OP_STAR_ASSIGN :
1246 case GRN_OP_SLASH_ASSIGN :
1247 case GRN_OP_MOD_ASSIGN :
1248 case GRN_OP_PLUS_ASSIGN :
1249 case GRN_OP_MINUS_ASSIGN :
1250 case GRN_OP_SHIFTL_ASSIGN :
1251 case GRN_OP_SHIFTR_ASSIGN :
1252 case GRN_OP_SHIFTRR_ASSIGN :
1253 case GRN_OP_AND_ASSIGN :
1254 case GRN_OP_OR_ASSIGN :
1255 case GRN_OP_XOR_ASSIGN :
1256 {
1257 if (obj) {
1258 type = obj->header.type;
1259 domain = GRN_OBJ_GET_DOMAIN(obj);
1260 } else {
1261 dfi = grn_expr_dfi_pop(e);
1262 if (dfi) {
1263 type = dfi->type;
1264 domain = dfi->domain;
1265 }
1266 }
1267 dfi = grn_expr_dfi_pop(e);
1268 if (dfi && (dfi->code)) {
1269 if (dfi->code->op == GRN_OP_GET_VALUE) {
1270 dfi->code->op = GRN_OP_GET_REF;
1271 }
1272 if (dfi->code->value && grn_obj_is_persistent(ctx, dfi->code->value)) {
1273 e->cacheable = 0;
1274 e->taintable = 1;
1275 }
1276 }
1277 PUSH_CODE(e, op, obj, nargs, code);
1278 }
1279 grn_expr_dfi_put(ctx, e, type, domain, code);
1280 break;
1281 case GRN_OP_JUMP :
1282 dfi = grn_expr_dfi_pop(e);
1283 PUSH_CODE(e, op, obj, nargs, code);
1284 break;
1285 case GRN_OP_CJUMP :
1286 dfi = grn_expr_dfi_pop(e);
1287 PUSH_CODE(e, op, obj, nargs, code);
1288 break;
1289 case GRN_OP_COMMA :
1290 PUSH_CODE(e, op, obj, nargs, code);
1291 break;
1292 case GRN_OP_GET_MEMBER :
1293 dfi = grn_expr_dfi_pop(e);
1294 dfi = grn_expr_dfi_pop(e);
1295 if (dfi) {
1296 type = dfi->type;
1297 domain = dfi->domain;
1298 if (dfi->code) {
1299 if (dfi->code->op == GRN_OP_GET_VALUE) {
1300 dfi->code->op = GRN_OP_GET_REF;
1301 }
1302 }
1303 }
1304 PUSH_CODE(e, op, obj, nargs, code);
1305 grn_expr_dfi_put(ctx, e, type, domain, code);
1306 break;
1307 default :
1308 break;
1309 }
1310 }
1311exit :
1312 if (!ctx->rc) { res = obj; }
1313 GRN_API_RETURN(res);
1314}
1315#undef PUSH_N_ARGS_ARITHMETIC_OP
1316#undef APPEND_UNARY_MINUS_OP
1317
1318grn_obj *
1319grn_expr_append_const(grn_ctx *ctx, grn_obj *expr, grn_obj *obj,
1320 grn_operator op, int nargs)
1321{
1322 grn_obj *res = NULL;
1323 GRN_API_ENTER;
1324 if (!obj) {
1325 ERR(GRN_SYNTAX_ERROR, "constant is null");
1326 goto exit;
1327 }
1328 if (GRN_DB_OBJP(obj) || GRN_ACCESSORP(obj)) {
1329 res = obj;
1330 } else {
1331 if ((res = grn_expr_alloc_const(ctx, expr))) {
1332 switch (obj->header.type) {
1333 case GRN_VOID :
1334 case GRN_BULK :
1335 case GRN_UVECTOR :
1336 GRN_OBJ_INIT(res, obj->header.type, 0, obj->header.domain);
1337 grn_bulk_write(ctx, res, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj));
1338 break;
1339 default :
1340 res = NULL;
1341 ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "unsupported type");
1342 goto exit;
1343 }
1344 res->header.impl_flags |= GRN_OBJ_EXPRCONST;
1345 }
1346 }
1347 grn_expr_append_obj(ctx, expr, res, op, nargs); /* constant */
1348exit :
1349 GRN_API_RETURN(res);
1350}
1351
1352static grn_obj *
1353grn_expr_add_str(grn_ctx *ctx, grn_obj *expr, const char *str, unsigned int str_size)
1354{
1355 grn_obj *res = NULL;
1356 if ((res = grn_expr_alloc_const(ctx, expr))) {
1357 GRN_TEXT_INIT(res, 0);
1358 grn_bulk_write(ctx, res, str, str_size);
1359 res->header.impl_flags |= GRN_OBJ_EXPRCONST;
1360 }
1361 return res;
1362}
1363
1364grn_obj *
1365grn_expr_append_const_str(grn_ctx *ctx, grn_obj *expr, const char *str, unsigned int str_size,
1366 grn_operator op, int nargs)
1367{
1368 grn_obj *res;
1369 GRN_API_ENTER;
1370 res = grn_expr_add_str(ctx, expr, str, str_size);
1371 grn_expr_append_obj(ctx, expr, res, op, nargs); /* constant */
1372 GRN_API_RETURN(res);
1373}
1374
1375grn_obj *
1376grn_expr_append_const_int(grn_ctx *ctx, grn_obj *expr, int i,
1377 grn_operator op, int nargs)
1378{
1379 grn_obj *res = NULL;
1380 GRN_API_ENTER;
1381 if ((res = grn_expr_alloc_const(ctx, expr))) {
1382 GRN_INT32_INIT(res, 0);
1383 GRN_INT32_SET(ctx, res, i);
1384 res->header.impl_flags |= GRN_OBJ_EXPRCONST;
1385 }
1386 grn_expr_append_obj(ctx, expr, res, op, nargs); /* constant */
1387 GRN_API_RETURN(res);
1388}
1389
1390grn_rc
1391grn_expr_append_op(grn_ctx *ctx, grn_obj *expr, grn_operator op, int nargs)
1392{
1393 grn_expr_append_obj(ctx, expr, NULL, op, nargs);
1394 return ctx->rc;
1395}
1396
1397grn_rc
1398grn_expr_compile(grn_ctx *ctx, grn_obj *expr)
1399{
1400 grn_obj_spec_save(ctx, DB_OBJ(expr));
1401 return ctx->rc;
1402}
1403
1404grn_obj *
1405grn_expr_rewrite(grn_ctx *ctx, grn_obj *expr)
1406{
1407 grn_obj *rewritten = NULL;
1408
1409 GRN_API_ENTER;
1410
1411#ifdef GRN_WITH_MRUBY
1412 grn_ctx_impl_mrb_ensure_init(ctx);
1413 if (ctx->rc != GRN_SUCCESS) {
1414 GRN_API_RETURN(NULL);
1415 }
1416 if (ctx->impl->mrb.state) {
1417 rewritten = grn_mrb_expr_rewrite(ctx, expr);
1418 }
1419#endif
1420
1421 GRN_API_RETURN(rewritten);
1422}
1423
1424#define WITH_SPSAVE(block) do {\
1425 ctx->impl->stack_curr = sp - ctx->impl->stack;\
1426 e->values_curr = vp - e->values;\
1427 block\
1428 vp = e->values + e->values_curr;\
1429 sp = ctx->impl->stack + ctx->impl->stack_curr;\
1430 s0 = sp[-1];\
1431 s1 = sp[-2];\
1432} while (0)
1433
1434#define GEO_RESOLUTION 3600000
1435#define GEO_RADIOUS 6357303
1436#define GEO_BES_C1 6334834
1437#define GEO_BES_C2 6377397
1438#define GEO_BES_C3 0.006674
1439#define GEO_GRS_C1 6335439
1440#define GEO_GRS_C2 6378137
1441#define GEO_GRS_C3 0.006694
1442#define GEO_INT2RAD(x) ((M_PI * x) / (GEO_RESOLUTION * 180))
1443
1444#define VAR_SET_VALUE(ctx,var,value) do {\
1445 if (GRN_DB_OBJP(value)) {\
1446 (var)->header.type = GRN_PTR;\
1447 (var)->header.domain = DB_OBJ(value)->id;\
1448 GRN_PTR_SET(ctx, (var), (value));\
1449 } else {\
1450 (var)->header.type = (value)->header.type;\
1451 (var)->header.domain = (value)->header.domain;\
1452 GRN_TEXT_SET(ctx, (var), GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value));\
1453 }\
1454} while (0)
1455
1456grn_rc
1457grn_proc_call(grn_ctx *ctx, grn_obj *proc, int nargs, grn_obj *caller)
1458{
1459 grn_proc_ctx pctx;
1460 grn_obj *obj = NULL, **args;
1461 grn_proc *p = (grn_proc *)proc;
1462 if (nargs > ctx->impl->stack_curr) { return GRN_INVALID_ARGUMENT; }
1463 GRN_API_ENTER;
1464 if (grn_obj_is_selector_only_proc(ctx, proc)) {
1465 char name[GRN_TABLE_MAX_KEY_SIZE];
1466 int name_size;
1467 name_size = grn_obj_name(ctx, proc, name, GRN_TABLE_MAX_KEY_SIZE);
1468 ERR(GRN_FUNCTION_NOT_IMPLEMENTED,
1469 "selector only proc can't be called: <%.*s>",
1470 name_size, name);
1471 GRN_API_RETURN(ctx->rc);
1472 }
1473 args = ctx->impl->stack + ctx->impl->stack_curr - nargs;
1474 pctx.proc = p;
1475 pctx.caller = caller;
1476 pctx.user_data.ptr = NULL;
1477 if (p->funcs[PROC_INIT]) {
1478 grn_obj *sub_obj;
1479 sub_obj = p->funcs[PROC_INIT](ctx, nargs, args, &pctx.user_data);
1480 if (sub_obj) {
1481 obj = sub_obj;
1482 }
1483 }
1484 pctx.phase = PROC_NEXT;
1485 if (p->funcs[PROC_NEXT]) {
1486 grn_obj *sub_obj;
1487 sub_obj = p->funcs[PROC_NEXT](ctx, nargs, args, &pctx.user_data);
1488 if (sub_obj) {
1489 obj = sub_obj;
1490 }
1491 }
1492 pctx.phase = PROC_FIN;
1493 if (p->funcs[PROC_FIN]) {
1494 grn_obj *sub_obj;
1495 sub_obj = p->funcs[PROC_FIN](ctx, nargs, args, &pctx.user_data);
1496 if (sub_obj) {
1497 obj = sub_obj;
1498 }
1499 }
1500 ctx->impl->stack_curr -= nargs;
1501 grn_ctx_push(ctx, obj);
1502 GRN_API_RETURN(ctx->rc);
1503}
1504
1505#define PUSH1(v) do {\
1506 if (EXPRVP(v)) {\
1507 vp++;\
1508 if (vp - e->values > e->values_tail) { e->values_tail = vp - e->values; }\
1509 }\
1510 s1 = s0;\
1511 *sp++ = s0 = v;\
1512} while (0)
1513
1514#define POP1(v) do {\
1515 if (EXPRVP(s0)) { vp--; }\
1516 v = s0;\
1517 s0 = s1;\
1518 sp--;\
1519 if (sp < s_) { ERR(GRN_INVALID_ARGUMENT, "stack underflow"); goto exit; }\
1520 s1 = sp[-2];\
1521} while (0)
1522
1523#define ALLOC1(value) do {\
1524 s1 = s0;\
1525 *sp++ = s0 = value = vp++;\
1526 if (vp - e->values > e->values_tail) { e->values_tail = vp - e->values; }\
1527} while (0)
1528
1529#define POP1ALLOC1(arg,value) do {\
1530 arg = s0;\
1531 if (EXPRVP(s0)) {\
1532 value = s0;\
1533 } else {\
1534 if (sp < s_ + 1) { ERR(GRN_INVALID_ARGUMENT, "stack underflow"); goto exit; }\
1535 sp[-1] = s0 = value = vp++;\
1536 if (vp - e->values > e->values_tail) { e->values_tail = vp - e->values; }\
1537 s0->header.impl_flags |= GRN_OBJ_EXPRVALUE;\
1538 }\
1539} while (0)
1540
1541#define POP2ALLOC1(arg1,arg2,value) do {\
1542 if (EXPRVP(s0)) { vp--; }\
1543 if (EXPRVP(s1)) { vp--; }\
1544 arg2 = s0;\
1545 arg1 = s1;\
1546 sp--;\
1547 if (sp < s_ + 1) { ERR(GRN_INVALID_ARGUMENT, "stack underflow"); goto exit; }\
1548 s1 = sp[-2];\
1549 sp[-1] = s0 = value = vp++;\
1550 if (vp - e->values > e->values_tail) { e->values_tail = vp - e->values; }\
1551 s0->header.impl_flags |= GRN_OBJ_EXPRVALUE;\
1552} while (0)
1553
1554#define INTEGER_ARITHMETIC_OPERATION_PLUS(x, y) ((x) + (y))
1555#define FLOAT_ARITHMETIC_OPERATION_PLUS(x, y) ((double)(x) + (double)(y))
1556#define INTEGER_ARITHMETIC_OPERATION_MINUS(x, y) ((x) - (y))
1557#define FLOAT_ARITHMETIC_OPERATION_MINUS(x, y) ((double)(x) - (double)(y))
1558#define INTEGER_ARITHMETIC_OPERATION_STAR(x, y) ((x) * (y))
1559#define FLOAT_ARITHMETIC_OPERATION_STAR(x, y) ((double)(x) * (double)(y))
1560#define INTEGER_ARITHMETIC_OPERATION_SLASH(x, y) ((x) / (y))
1561#define FLOAT_ARITHMETIC_OPERATION_SLASH(x, y) ((double)(x) / (double)(y))
1562#define INTEGER_ARITHMETIC_OPERATION_MOD(x, y) ((x) % (y))
1563#define FLOAT_ARITHMETIC_OPERATION_MOD(x, y) (fmod((x), (y)))
1564#define INTEGER_ARITHMETIC_OPERATION_SHIFTL(x, y) ((x) << (y))
1565#define FLOAT_ARITHMETIC_OPERATION_SHIFTL(x, y) \
1566 ((long long int)(x) << (long long int)(y))
1567#define INTEGER_ARITHMETIC_OPERATION_SHIFTR(x, y) ((x) >> (y))
1568#define FLOAT_ARITHMETIC_OPERATION_SHIFTR(x, y) \
1569 ((long long int)(x) >> (long long int)(y))
1570#define INTEGER8_ARITHMETIC_OPERATION_SHIFTRR(x, y) \
1571 ((uint8_t)(x) >> (y))
1572#define INTEGER16_ARITHMETIC_OPERATION_SHIFTRR(x, y) \
1573 ((uint16_t)(x) >> (y))
1574#define INTEGER32_ARITHMETIC_OPERATION_SHIFTRR(x, y) \
1575 ((unsigned int)(x) >> (y))
1576#define INTEGER64_ARITHMETIC_OPERATION_SHIFTRR(x, y) \
1577 ((long long unsigned int)(x) >> (y))
1578#define FLOAT_ARITHMETIC_OPERATION_SHIFTRR(x, y) \
1579 ((long long unsigned int)(x) >> (long long unsigned int)(y))
1580
1581#define INTEGER_ARITHMETIC_OPERATION_BITWISE_OR(x, y) ((x) | (y))
1582#define FLOAT_ARITHMETIC_OPERATION_BITWISE_OR(x, y) \
1583 ((long long int)(x) | (long long int)(y))
1584#define INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR(x, y) ((x) ^ (y))
1585#define FLOAT_ARITHMETIC_OPERATION_BITWISE_XOR(x, y) \
1586 ((long long int)(x) ^ (long long int)(y))
1587#define INTEGER_ARITHMETIC_OPERATION_BITWISE_AND(x, y) ((x) & (y))
1588#define FLOAT_ARITHMETIC_OPERATION_BITWISE_AND(x, y) \
1589 ((long long int)(x) & (long long int)(y))
1590
1591#define INTEGER_UNARY_ARITHMETIC_OPERATION_MINUS(x) (-(x))
1592#define FLOAT_UNARY_ARITHMETIC_OPERATION_MINUS(x) (-(x))
1593#define INTEGER_UNARY_ARITHMETIC_OPERATION_BITWISE_NOT(x) (~(x))
1594#define FLOAT_UNARY_ARITHMETIC_OPERATION_BITWISE_NOT(x) \
1595 (~((long long int)(x)))
1596
1597#define TEXT_ARITHMETIC_OPERATION(operator) do { \
1598 long long int x_; \
1599 long long int y_; \
1600 \
1601 res->header.domain = GRN_DB_INT64; \
1602 \
1603 GRN_INT64_SET(ctx, res, 0); \
1604 grn_obj_cast(ctx, x, res, GRN_FALSE); \
1605 x_ = GRN_INT64_VALUE(res); \
1606 \
1607 GRN_INT64_SET(ctx, res, 0); \
1608 grn_obj_cast(ctx, y, res, GRN_FALSE); \
1609 y_ = GRN_INT64_VALUE(res); \
1610 \
1611 GRN_INT64_SET(ctx, res, x_ operator y_); \
1612} while (0)
1613
1614#define TEXT_UNARY_ARITHMETIC_OPERATION(unary_operator) do { \
1615 long long int x_; \
1616 \
1617 res->header.domain = GRN_DB_INT64; \
1618 \
1619 GRN_INT64_SET(ctx, res, 0); \
1620 grn_obj_cast(ctx, x, res, GRN_FALSE); \
1621 x_ = GRN_INT64_VALUE(res); \
1622 \
1623 GRN_INT64_SET(ctx, res, unary_operator x_); \
1624} while (0)
1625
1626#define ARITHMETIC_OPERATION_NO_CHECK(y) do {} while (0)
1627#define ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y) do { \
1628 if ((long long int)y == 0) { \
1629 ERR(GRN_INVALID_ARGUMENT, "divisor should not be 0"); \
1630 goto exit; \
1631 } \
1632} while (0)
1633
1634
1635#define NUMERIC_ARITHMETIC_OPERATION_DISPATCH(set, get, x_, y, res, \
1636 integer_operation, \
1637 float_operation, \
1638 right_expression_check, \
1639 invalid_type_error) do { \
1640 switch (y->header.domain) { \
1641 case GRN_DB_INT8 : \
1642 { \
1643 int8_t y_; \
1644 y_ = GRN_INT8_VALUE(y); \
1645 right_expression_check(y_); \
1646 set(ctx, res, integer_operation(x_, y_)); \
1647 } \
1648 break; \
1649 case GRN_DB_UINT8 : \
1650 { \
1651 uint8_t y_; \
1652 y_ = GRN_UINT8_VALUE(y); \
1653 right_expression_check(y_); \
1654 set(ctx, res, integer_operation(x_, y_)); \
1655 } \
1656 break; \
1657 case GRN_DB_INT16 : \
1658 { \
1659 int16_t y_; \
1660 y_ = GRN_INT16_VALUE(y); \
1661 right_expression_check(y_); \
1662 set(ctx, res, integer_operation(x_, y_)); \
1663 } \
1664 break; \
1665 case GRN_DB_UINT16 : \
1666 { \
1667 uint16_t y_; \
1668 y_ = GRN_UINT16_VALUE(y); \
1669 right_expression_check(y_); \
1670 set(ctx, res, integer_operation(x_, y_)); \
1671 } \
1672 break; \
1673 case GRN_DB_INT32 : \
1674 { \
1675 int y_; \
1676 y_ = GRN_INT32_VALUE(y); \
1677 right_expression_check(y_); \
1678 set(ctx, res, integer_operation(x_, y_)); \
1679 } \
1680 break; \
1681 case GRN_DB_UINT32 : \
1682 { \
1683 unsigned int y_; \
1684 y_ = GRN_UINT32_VALUE(y); \
1685 right_expression_check(y_); \
1686 set(ctx, res, integer_operation(x_, y_)); \
1687 } \
1688 break; \
1689 case GRN_DB_TIME : \
1690 { \
1691 long long int y_; \
1692 y_ = GRN_TIME_VALUE(y); \
1693 right_expression_check(y_); \
1694 set(ctx, res, integer_operation(x_, y_)); \
1695 } \
1696 break; \
1697 case GRN_DB_INT64 : \
1698 { \
1699 long long int y_; \
1700 y_ = GRN_INT64_VALUE(y); \
1701 right_expression_check(y_); \
1702 set(ctx, res, integer_operation(x_, y_)); \
1703 } \
1704 break; \
1705 case GRN_DB_UINT64 : \
1706 { \
1707 long long unsigned int y_; \
1708 y_ = GRN_UINT64_VALUE(y); \
1709 right_expression_check(y_); \
1710 set(ctx, res, integer_operation(x_, y_)); \
1711 } \
1712 break; \
1713 case GRN_DB_FLOAT : \
1714 { \
1715 double y_; \
1716 y_ = GRN_FLOAT_VALUE(y); \
1717 right_expression_check(y_); \
1718 res->header.domain = GRN_DB_FLOAT; \
1719 GRN_FLOAT_SET(ctx, res, float_operation(x_, y_)); \
1720 } \
1721 break; \
1722 case GRN_DB_SHORT_TEXT : \
1723 case GRN_DB_TEXT : \
1724 case GRN_DB_LONG_TEXT : \
1725 set(ctx, res, 0); \
1726 if (grn_obj_cast(ctx, y, res, GRN_FALSE)) { \
1727 ERR(GRN_INVALID_ARGUMENT, \
1728 "not a numerical format: <%.*s>", \
1729 (int)GRN_TEXT_LEN(y), GRN_TEXT_VALUE(y)); \
1730 goto exit; \
1731 } \
1732 set(ctx, res, integer_operation(x_, get(res))); \
1733 break; \
1734 default : \
1735 invalid_type_error; \
1736 break; \
1737 } \
1738} while (0)
1739
1740
1741#define ARITHMETIC_OPERATION_DISPATCH(x, y, res, \
1742 integer8_operation, \
1743 integer16_operation, \
1744 integer32_operation, \
1745 integer64_operation, \
1746 float_operation, \
1747 left_expression_check, \
1748 right_expression_check, \
1749 text_operation, \
1750 invalid_type_error) do { \
1751 switch (x->header.domain) { \
1752 case GRN_DB_INT8 : \
1753 { \
1754 int8_t x_; \
1755 x_ = GRN_INT8_VALUE(x); \
1756 left_expression_check(x_); \
1757 NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_INT8_SET, \
1758 GRN_INT8_VALUE, \
1759 x_, y, res, \
1760 integer8_operation, \
1761 float_operation, \
1762 right_expression_check, \
1763 invalid_type_error); \
1764 } \
1765 break; \
1766 case GRN_DB_UINT8 : \
1767 { \
1768 uint8_t x_; \
1769 x_ = GRN_UINT8_VALUE(x); \
1770 left_expression_check(x_); \
1771 NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT8_SET, \
1772 GRN_UINT8_VALUE, \
1773 x_, y, res, \
1774 integer8_operation, \
1775 float_operation, \
1776 right_expression_check, \
1777 invalid_type_error); \
1778 } \
1779 break; \
1780 case GRN_DB_INT16 : \
1781 { \
1782 int16_t x_; \
1783 x_ = GRN_INT16_VALUE(x); \
1784 left_expression_check(x_); \
1785 NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_INT16_SET, \
1786 GRN_INT16_VALUE, \
1787 x_, y, res, \
1788 integer16_operation, \
1789 float_operation, \
1790 right_expression_check, \
1791 invalid_type_error); \
1792 } \
1793 break; \
1794 case GRN_DB_UINT16 : \
1795 { \
1796 uint16_t x_; \
1797 x_ = GRN_UINT16_VALUE(x); \
1798 left_expression_check(x_); \
1799 NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT16_SET, \
1800 GRN_UINT16_VALUE, \
1801 x_, y, res, \
1802 integer16_operation, \
1803 float_operation, \
1804 right_expression_check, \
1805 invalid_type_error); \
1806 } \
1807 break; \
1808 case GRN_DB_INT32 : \
1809 { \
1810 int x_; \
1811 x_ = GRN_INT32_VALUE(x); \
1812 left_expression_check(x_); \
1813 NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_INT32_SET, \
1814 GRN_INT32_VALUE, \
1815 x_, y, res, \
1816 integer32_operation, \
1817 float_operation, \
1818 right_expression_check, \
1819 invalid_type_error); \
1820 } \
1821 break; \
1822 case GRN_DB_UINT32 : \
1823 { \
1824 unsigned int x_; \
1825 x_ = GRN_UINT32_VALUE(x); \
1826 left_expression_check(x_); \
1827 NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT32_SET, \
1828 GRN_UINT32_VALUE, \
1829 x_, y, res, \
1830 integer32_operation, \
1831 float_operation, \
1832 right_expression_check, \
1833 invalid_type_error); \
1834 } \
1835 break; \
1836 case GRN_DB_INT64 : \
1837 { \
1838 long long int x_; \
1839 x_ = GRN_INT64_VALUE(x); \
1840 left_expression_check(x_); \
1841 NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_INT64_SET, \
1842 GRN_INT64_VALUE, \
1843 x_, y, res, \
1844 integer64_operation, \
1845 float_operation, \
1846 right_expression_check, \
1847 invalid_type_error); \
1848 } \
1849 break; \
1850 case GRN_DB_TIME : \
1851 { \
1852 long long int x_; \
1853 x_ = GRN_TIME_VALUE(x); \
1854 left_expression_check(x_); \
1855 NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_TIME_SET, \
1856 GRN_TIME_VALUE, \
1857 x_, y, res, \
1858 integer64_operation, \
1859 float_operation, \
1860 right_expression_check, \
1861 invalid_type_error); \
1862 } \
1863 break; \
1864 case GRN_DB_UINT64 : \
1865 { \
1866 long long unsigned int x_; \
1867 x_ = GRN_UINT64_VALUE(x); \
1868 left_expression_check(x_); \
1869 NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT64_SET, \
1870 GRN_UINT64_VALUE, \
1871 x_, y, res, \
1872 integer64_operation, \
1873 float_operation, \
1874 right_expression_check, \
1875 invalid_type_error); \
1876 } \
1877 break; \
1878 case GRN_DB_FLOAT : \
1879 { \
1880 double x_; \
1881 x_ = GRN_FLOAT_VALUE(x); \
1882 left_expression_check(x_); \
1883 NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_FLOAT_SET, \
1884 GRN_FLOAT_VALUE, \
1885 x_, y, res, \
1886 float_operation, \
1887 float_operation, \
1888 right_expression_check, \
1889 invalid_type_error); \
1890 } \
1891 break; \
1892 case GRN_DB_SHORT_TEXT : \
1893 case GRN_DB_TEXT : \
1894 case GRN_DB_LONG_TEXT : \
1895 text_operation; \
1896 break; \
1897 default: \
1898 invalid_type_error; \
1899 break; \
1900 } \
1901 code++; \
1902} while (0)
1903
1904#define ARITHMETIC_BINARY_OPERATION_DISPATCH(operator, \
1905 integer8_operation, \
1906 integer16_operation, \
1907 integer32_operation, \
1908 integer64_operation, \
1909 float_operation, \
1910 left_expression_check, \
1911 right_expression_check, \
1912 text_operation, \
1913 invalid_type_error) do { \
1914 grn_obj *x, *y; \
1915 \
1916 POP2ALLOC1(x, y, res); \
1917 if (x->header.type == GRN_VECTOR || y->header.type == GRN_VECTOR) { \
1918 grn_obj inspected_x; \
1919 grn_obj inspected_y; \
1920 GRN_TEXT_INIT(&inspected_x, 0); \
1921 GRN_TEXT_INIT(&inspected_y, 0); \
1922 grn_inspect(ctx, &inspected_x, x); \
1923 grn_inspect(ctx, &inspected_y, y); \
1924 ERR(GRN_INVALID_ARGUMENT, \
1925 "<%s> doesn't support vector: <%.*s> %s <%.*s>", \
1926 operator, \
1927 (int)GRN_TEXT_LEN(&inspected_x), GRN_TEXT_VALUE(&inspected_x), \
1928 operator, \
1929 (int)GRN_TEXT_LEN(&inspected_y), GRN_TEXT_VALUE(&inspected_y)); \
1930 GRN_OBJ_FIN(ctx, &inspected_x); \
1931 GRN_OBJ_FIN(ctx, &inspected_y); \
1932 goto exit; \
1933 } \
1934 if (y != res) { \
1935 res->header.domain = x->header.domain; \
1936 } \
1937 ARITHMETIC_OPERATION_DISPATCH(x, y, res, \
1938 integer8_operation, \
1939 integer16_operation, \
1940 integer32_operation, \
1941 integer64_operation, \
1942 float_operation, \
1943 left_expression_check, \
1944 right_expression_check, \
1945 text_operation, \
1946 invalid_type_error); \
1947 if (y == res) { \
1948 res->header.domain = x->header.domain; \
1949 } \
1950} while (0)
1951
1952#define SIGNED_INTEGER_DIVISION_OPERATION_SLASH(x, y) \
1953 ((y == -1) ? -(x) : (x) / (y))
1954#define UNSIGNED_INTEGER_DIVISION_OPERATION_SLASH(x, y) ((x) / (y))
1955#define FLOAT_DIVISION_OPERATION_SLASH(x, y) ((double)(x) / (double)(y))
1956#define SIGNED_INTEGER_DIVISION_OPERATION_MOD(x, y) ((y == -1) ? 0 : (x) % (y))
1957#define UNSIGNED_INTEGER_DIVISION_OPERATION_MOD(x, y) ((x) % (y))
1958#define FLOAT_DIVISION_OPERATION_MOD(x, y) (fmod((x), (y)))
1959
1960#define DIVISION_OPERATION_DISPATCH_RIGHT(set, get, x_, y, res, \
1961 signed_integer_operation, \
1962 unsigned_integer_operation, \
1963 float_operation) do { \
1964 switch (y->header.domain) { \
1965 case GRN_DB_INT8 : \
1966 { \
1967 int y_; \
1968 y_ = GRN_INT8_VALUE(y); \
1969 ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \
1970 set(ctx, res, signed_integer_operation(x_, y_)); \
1971 } \
1972 break; \
1973 case GRN_DB_UINT8 : \
1974 { \
1975 int y_; \
1976 y_ = GRN_UINT8_VALUE(y); \
1977 ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \
1978 set(ctx, res, unsigned_integer_operation(x_, y_)); \
1979 } \
1980 break; \
1981 case GRN_DB_INT16 : \
1982 { \
1983 int y_; \
1984 y_ = GRN_INT16_VALUE(y); \
1985 ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \
1986 set(ctx, res, signed_integer_operation(x_, y_)); \
1987 } \
1988 break; \
1989 case GRN_DB_UINT16 : \
1990 { \
1991 int y_; \
1992 y_ = GRN_UINT16_VALUE(y); \
1993 ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \
1994 set(ctx, res, unsigned_integer_operation(x_, y_)); \
1995 } \
1996 break; \
1997 case GRN_DB_INT32 : \
1998 { \
1999 int y_; \
2000 y_ = GRN_INT32_VALUE(y); \
2001 ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \
2002 set(ctx, res, signed_integer_operation(x_, y_)); \
2003 } \
2004 break; \
2005 case GRN_DB_UINT32 : \
2006 { \
2007 unsigned int y_; \
2008 y_ = GRN_UINT32_VALUE(y); \
2009 ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \
2010 set(ctx, res, unsigned_integer_operation(x_, y_)); \
2011 } \
2012 break; \
2013 case GRN_DB_TIME : \
2014 { \
2015 long long int y_; \
2016 y_ = GRN_TIME_VALUE(y); \
2017 ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \
2018 set(ctx, res, signed_integer_operation(x_, y_)); \
2019 } \
2020 break; \
2021 case GRN_DB_INT64 : \
2022 { \
2023 long long int y_; \
2024 y_ = GRN_INT64_VALUE(y); \
2025 ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \
2026 set(ctx, res, signed_integer_operation(x_, y_)); \
2027 } \
2028 break; \
2029 case GRN_DB_UINT64 : \
2030 { \
2031 long long unsigned int y_; \
2032 y_ = GRN_UINT64_VALUE(y); \
2033 ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \
2034 set(ctx, res, unsigned_integer_operation(x_, y_)); \
2035 } \
2036 break; \
2037 case GRN_DB_FLOAT : \
2038 { \
2039 double y_; \
2040 y_ = GRN_FLOAT_VALUE(y); \
2041 ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \
2042 res->header.domain = GRN_DB_FLOAT; \
2043 GRN_FLOAT_SET(ctx, res, float_operation(x_, y_)); \
2044 } \
2045 break; \
2046 case GRN_DB_SHORT_TEXT : \
2047 case GRN_DB_TEXT : \
2048 case GRN_DB_LONG_TEXT : \
2049 set(ctx, res, 0); \
2050 if (grn_obj_cast(ctx, y, res, GRN_FALSE)) { \
2051 ERR(GRN_INVALID_ARGUMENT, \
2052 "not a numerical format: <%.*s>", \
2053 (int)GRN_TEXT_LEN(y), GRN_TEXT_VALUE(y)); \
2054 goto exit; \
2055 } \
2056 /* The following "+ 0" is needed to suppress warnings that say */ \
2057 /* comparison is always false due to limited range of data type */ \
2058 set(ctx, res, signed_integer_operation(x_, (get(res) + 0))); \
2059 break; \
2060 default : \
2061 break; \
2062 } \
2063} while (0)
2064
2065#define DIVISION_OPERATION_DISPATCH_LEFT(x, y, res, \
2066 signed_integer_operation, \
2067 unsigned_integer_operation, \
2068 float_operation, \
2069 invalid_type_error) do { \
2070 switch (x->header.domain) { \
2071 case GRN_DB_INT8 : \
2072 { \
2073 int x_; \
2074 x_ = GRN_INT8_VALUE(x); \
2075 DIVISION_OPERATION_DISPATCH_RIGHT(GRN_INT8_SET, \
2076 GRN_INT8_VALUE, \
2077 x_, y, res, \
2078 signed_integer_operation, \
2079 unsigned_integer_operation, \
2080 float_operation); \
2081 } \
2082 break; \
2083 case GRN_DB_UINT8 : \
2084 { \
2085 int x_; \
2086 x_ = GRN_UINT8_VALUE(x); \
2087 DIVISION_OPERATION_DISPATCH_RIGHT(GRN_UINT8_SET, \
2088 (int)GRN_UINT8_VALUE, \
2089 x_, y, res, \
2090 signed_integer_operation, \
2091 unsigned_integer_operation, \
2092 float_operation); \
2093 } \
2094 break; \
2095 case GRN_DB_INT16 : \
2096 { \
2097 int x_; \
2098 x_ = GRN_INT16_VALUE(x); \
2099 DIVISION_OPERATION_DISPATCH_RIGHT(GRN_INT16_SET, \
2100 GRN_INT16_VALUE, \
2101 x_, y, res, \
2102 signed_integer_operation, \
2103 unsigned_integer_operation, \
2104 float_operation); \
2105 } \
2106 break; \
2107 case GRN_DB_UINT16 : \
2108 { \
2109 int x_; \
2110 x_ = GRN_UINT16_VALUE(x); \
2111 DIVISION_OPERATION_DISPATCH_RIGHT(GRN_UINT16_SET, \
2112 (int)GRN_UINT16_VALUE, \
2113 x_, y, res, \
2114 signed_integer_operation, \
2115 unsigned_integer_operation, \
2116 float_operation); \
2117 } \
2118 break; \
2119 case GRN_DB_INT32 : \
2120 { \
2121 int x_; \
2122 x_ = GRN_INT32_VALUE(x); \
2123 DIVISION_OPERATION_DISPATCH_RIGHT(GRN_INT32_SET, \
2124 GRN_INT32_VALUE, \
2125 x_, y, res, \
2126 signed_integer_operation, \
2127 unsigned_integer_operation, \
2128 float_operation); \
2129 } \
2130 break; \
2131 case GRN_DB_UINT32 : \
2132 { \
2133 unsigned int x_; \
2134 x_ = GRN_UINT32_VALUE(x); \
2135 DIVISION_OPERATION_DISPATCH_RIGHT(GRN_UINT32_SET, \
2136 GRN_UINT32_VALUE, \
2137 x_, y, res, \
2138 unsigned_integer_operation, \
2139 unsigned_integer_operation, \
2140 float_operation); \
2141 } \
2142 break; \
2143 case GRN_DB_INT64 : \
2144 { \
2145 long long int x_; \
2146 x_ = GRN_INT64_VALUE(x); \
2147 DIVISION_OPERATION_DISPATCH_RIGHT(GRN_INT64_SET, \
2148 GRN_INT64_VALUE, \
2149 x_, y, res, \
2150 signed_integer_operation, \
2151 unsigned_integer_operation, \
2152 float_operation); \
2153 } \
2154 break; \
2155 case GRN_DB_TIME : \
2156 { \
2157 long long int x_; \
2158 x_ = GRN_TIME_VALUE(x); \
2159 DIVISION_OPERATION_DISPATCH_RIGHT(GRN_TIME_SET, \
2160 GRN_TIME_VALUE, \
2161 x_, y, res, \
2162 signed_integer_operation, \
2163 unsigned_integer_operation, \
2164 float_operation); \
2165 } \
2166 break; \
2167 case GRN_DB_UINT64 : \
2168 { \
2169 long long unsigned int x_; \
2170 x_ = GRN_UINT64_VALUE(x); \
2171 DIVISION_OPERATION_DISPATCH_RIGHT(GRN_UINT64_SET, \
2172 GRN_UINT64_VALUE, \
2173 x_, y, res, \
2174 unsigned_integer_operation, \
2175 unsigned_integer_operation, \
2176 float_operation); \
2177 } \
2178 break; \
2179 case GRN_DB_FLOAT : \
2180 { \
2181 double x_; \
2182 x_ = GRN_FLOAT_VALUE(x); \
2183 DIVISION_OPERATION_DISPATCH_RIGHT(GRN_FLOAT_SET, \
2184 GRN_FLOAT_VALUE, \
2185 x_, y, res, \
2186 float_operation, \
2187 float_operation, \
2188 float_operation); \
2189 } \
2190 break; \
2191 case GRN_DB_SHORT_TEXT : \
2192 case GRN_DB_TEXT : \
2193 case GRN_DB_LONG_TEXT : \
2194 invalid_type_error; \
2195 break; \
2196 default: \
2197 break; \
2198 } \
2199 code++; \
2200} while (0)
2201
2202#define DIVISION_OPERATION_DISPATCH(signed_integer_operation, \
2203 unsigned_integer_operation, \
2204 float_operation, \
2205 invalid_type_error) do { \
2206 grn_obj *x, *y; \
2207 \
2208 POP2ALLOC1(x, y, res); \
2209 if (y != res) { \
2210 res->header.domain = x->header.domain; \
2211 } \
2212 DIVISION_OPERATION_DISPATCH_LEFT(x, y, res, \
2213 signed_integer_operation, \
2214 unsigned_integer_operation, \
2215 float_operation, \
2216 invalid_type_error); \
2217 if (y == res) { \
2218 res->header.domain = x->header.domain; \
2219 } \
2220} while (0)
2221
2222#define ARITHMETIC_UNARY_OPERATION_DISPATCH(integer_operation, \
2223 float_operation, \
2224 left_expression_check, \
2225 right_expression_check, \
2226 text_operation, \
2227 invalid_type_error) do { \
2228 grn_obj *x; \
2229 POP1ALLOC1(x, res); \
2230 res->header.domain = x->header.domain; \
2231 switch (x->header.domain) { \
2232 case GRN_DB_INT8 : \
2233 { \
2234 int8_t x_; \
2235 x_ = GRN_INT8_VALUE(x); \
2236 left_expression_check(x_); \
2237 GRN_INT8_SET(ctx, res, integer_operation(x_)); \
2238 } \
2239 break; \
2240 case GRN_DB_UINT8 : \
2241 { \
2242 int16_t x_; \
2243 x_ = GRN_UINT8_VALUE(x); \
2244 left_expression_check(x_); \
2245 GRN_INT16_SET(ctx, res, integer_operation(x_)); \
2246 res->header.domain = GRN_DB_INT16; \
2247 } \
2248 break; \
2249 case GRN_DB_INT16 : \
2250 { \
2251 int16_t x_; \
2252 x_ = GRN_INT16_VALUE(x); \
2253 left_expression_check(x_); \
2254 GRN_INT16_SET(ctx, res, integer_operation(x_)); \
2255 } \
2256 break; \
2257 case GRN_DB_UINT16 : \
2258 { \
2259 int x_; \
2260 x_ = GRN_UINT16_VALUE(x); \
2261 left_expression_check(x_); \
2262 GRN_INT32_SET(ctx, res, integer_operation(x_)); \
2263 res->header.domain = GRN_DB_INT32; \
2264 } \
2265 break; \
2266 case GRN_DB_INT32 : \
2267 { \
2268 int x_; \
2269 x_ = GRN_INT32_VALUE(x); \
2270 left_expression_check(x_); \
2271 GRN_INT32_SET(ctx, res, integer_operation(x_)); \
2272 } \
2273 break; \
2274 case GRN_DB_UINT32 : \
2275 { \
2276 long long int x_; \
2277 x_ = GRN_UINT32_VALUE(x); \
2278 left_expression_check(x_); \
2279 GRN_INT64_SET(ctx, res, integer_operation(x_)); \
2280 res->header.domain = GRN_DB_INT64; \
2281 } \
2282 break; \
2283 case GRN_DB_INT64 : \
2284 { \
2285 long long int x_; \
2286 x_ = GRN_INT64_VALUE(x); \
2287 left_expression_check(x_); \
2288 GRN_INT64_SET(ctx, res, integer_operation(x_)); \
2289 } \
2290 break; \
2291 case GRN_DB_TIME : \
2292 { \
2293 long long int x_; \
2294 x_ = GRN_TIME_VALUE(x); \
2295 left_expression_check(x_); \
2296 GRN_TIME_SET(ctx, res, integer_operation(x_)); \
2297 } \
2298 break; \
2299 case GRN_DB_UINT64 : \
2300 { \
2301 long long unsigned int x_; \
2302 x_ = GRN_UINT64_VALUE(x); \
2303 left_expression_check(x_); \
2304 if (x_ > (long long unsigned int)INT64_MAX) { \
2305 ERR(GRN_INVALID_ARGUMENT, \
2306 "too large UInt64 value to inverse sign: " \
2307 "<%" GRN_FMT_LLU ">", \
2308 x_); \
2309 goto exit; \
2310 } else { \
2311 long long int signed_x_; \
2312 signed_x_ = x_; \
2313 GRN_INT64_SET(ctx, res, integer_operation(signed_x_)); \
2314 res->header.domain = GRN_DB_INT64; \
2315 } \
2316 } \
2317 break; \
2318 case GRN_DB_FLOAT : \
2319 { \
2320 double x_; \
2321 x_ = GRN_FLOAT_VALUE(x); \
2322 left_expression_check(x_); \
2323 GRN_FLOAT_SET(ctx, res, float_operation(x_)); \
2324 } \
2325 break; \
2326 case GRN_DB_SHORT_TEXT : \
2327 case GRN_DB_TEXT : \
2328 case GRN_DB_LONG_TEXT : \
2329 text_operation; \
2330 break; \
2331 default: \
2332 invalid_type_error; \
2333 break; \
2334 } \
2335 code++; \
2336} while (0)
2337
2338#define EXEC_OPERATE(operate_sentence, assign_sentence) \
2339 operate_sentence \
2340 assign_sentence
2341
2342#define EXEC_OPERATE_POST(operate_sentence, assign_sentence) \
2343 assign_sentence \
2344 operate_sentence
2345
2346#define UNARY_OPERATE_AND_ASSIGN_DISPATCH(exec_operate, delta, \
2347 set_flags) do { \
2348 grn_obj *var, *col, value; \
2349 grn_id rid; \
2350 \
2351 POP1ALLOC1(var, res); \
2352 if (var->header.type != GRN_PTR) { \
2353 ERR(GRN_INVALID_ARGUMENT, "invalid variable type: 0x%0x", \
2354 var->header.type); \
2355 goto exit; \
2356 } \
2357 if (GRN_BULK_VSIZE(var) != (sizeof(grn_obj *) + sizeof(grn_id))) { \
2358 ERR(GRN_INVALID_ARGUMENT, \
2359 "invalid variable size: " \
2360 "expected: %" GRN_FMT_SIZE \
2361 "actual: %" GRN_FMT_SIZE, \
2362 (sizeof(grn_obj *) + sizeof(grn_id)), GRN_BULK_VSIZE(var)); \
2363 goto exit; \
2364 } \
2365 col = GRN_PTR_VALUE(var); \
2366 rid = *(grn_id *)(GRN_BULK_HEAD(var) + sizeof(grn_obj *)); \
2367 res->header.type = GRN_VOID; \
2368 res->header.domain = DB_OBJ(col)->range; \
2369 switch (DB_OBJ(col)->range) { \
2370 case GRN_DB_INT32 : \
2371 GRN_INT32_INIT(&value, 0); \
2372 GRN_INT32_SET(ctx, &value, delta); \
2373 break; \
2374 case GRN_DB_UINT32 : \
2375 GRN_UINT32_INIT(&value, 0); \
2376 GRN_UINT32_SET(ctx, &value, delta); \
2377 break; \
2378 case GRN_DB_INT64 : \
2379 GRN_INT64_INIT(&value, 0); \
2380 GRN_INT64_SET(ctx, &value, delta); \
2381 break; \
2382 case GRN_DB_UINT64 : \
2383 GRN_UINT64_INIT(&value, 0); \
2384 GRN_UINT64_SET(ctx, &value, delta); \
2385 break; \
2386 case GRN_DB_FLOAT : \
2387 GRN_FLOAT_INIT(&value, 0); \
2388 GRN_FLOAT_SET(ctx, &value, delta); \
2389 break; \
2390 case GRN_DB_TIME : \
2391 GRN_TIME_INIT(&value, 0); \
2392 GRN_TIME_SET(ctx, &value, GRN_TIME_PACK(delta, 0)); \
2393 break; \
2394 default: \
2395 ERR(GRN_INVALID_ARGUMENT, \
2396 "invalid increment target type: %d " \
2397 "(FIXME: type name is needed)", DB_OBJ(col)->range); \
2398 goto exit; \
2399 break; \
2400 } \
2401 exec_operate(grn_obj_set_value(ctx, col, rid, &value, set_flags);, \
2402 grn_obj_get_value(ctx, col, rid, res);); \
2403 code++; \
2404} while (0)
2405
2406#define ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(integer8_operation, \
2407 integer16_operation, \
2408 integer32_operation, \
2409 integer64_operation, \
2410 float_operation, \
2411 left_expression_check, \
2412 right_expression_check,\
2413 text_operation) do { \
2414 grn_obj *value, *var, *res; \
2415 if (code->value) { \
2416 value = code->value; \
2417 POP1ALLOC1(var, res); \
2418 } else { \
2419 POP2ALLOC1(var, value, res); \
2420 } \
2421 if (var->header.type == GRN_PTR && \
2422 GRN_BULK_VSIZE(var) == (sizeof(grn_obj *) + sizeof(grn_id))) { \
2423 grn_obj *col = GRN_PTR_VALUE(var); \
2424 grn_id rid = *(grn_id *)(GRN_BULK_HEAD(var) + sizeof(grn_obj *)); \
2425 grn_obj variable_value, casted_value; \
2426 grn_id domain; \
2427 \
2428 value = GRN_OBJ_RESOLVE(ctx, value); \
2429 \
2430 domain = grn_obj_get_range(ctx, col); \
2431 GRN_OBJ_INIT(&variable_value, GRN_BULK, 0, domain); \
2432 grn_obj_get_value(ctx, col, rid, &variable_value); \
2433 \
2434 GRN_OBJ_INIT(&casted_value, GRN_BULK, 0, domain); \
2435 if (grn_obj_cast(ctx, value, &casted_value, GRN_FALSE)) { \
2436 ERR(GRN_INVALID_ARGUMENT, "invalid value: string"); \
2437 GRN_OBJ_FIN(ctx, &variable_value); \
2438 GRN_OBJ_FIN(ctx, &casted_value); \
2439 POP1(res); \
2440 goto exit; \
2441 } \
2442 grn_obj_reinit(ctx, res, domain, 0); \
2443 ARITHMETIC_OPERATION_DISPATCH((&variable_value), (&casted_value), \
2444 res, \
2445 integer8_operation, \
2446 integer16_operation, \
2447 integer32_operation, \
2448 integer64_operation, \
2449 float_operation, \
2450 left_expression_check, \
2451 right_expression_check, \
2452 text_operation,); \
2453 grn_obj_set_value(ctx, col, rid, res, GRN_OBJ_SET); \
2454 GRN_OBJ_FIN(ctx, (&variable_value)); \
2455 GRN_OBJ_FIN(ctx, (&casted_value)); \
2456 } else { \
2457 ERR(GRN_INVALID_ARGUMENT, "left hand expression isn't column."); \
2458 POP1(res); \
2459 } \
2460} while (0)
2461
2462inline static void
2463grn_expr_exec_get_member_vector(grn_ctx *ctx,
2464 grn_obj *expr,
2465 grn_obj *column_and_record_id,
2466 grn_obj *index,
2467 grn_obj *result)
2468{
2469 grn_obj *column;
2470 grn_id record_id;
2471 grn_obj values;
2472 int i;
2473
2474 column = GRN_PTR_VALUE(column_and_record_id);
2475 record_id = *((grn_id *)(&(GRN_PTR_VALUE_AT(column_and_record_id, 1))));
2476 GRN_TEXT_INIT(&values, 0);
2477 grn_obj_get_value(ctx, column, record_id, &values);
2478
2479 i = GRN_UINT32_VALUE(index);
2480 if (values.header.type == GRN_UVECTOR) {
2481 int n_elements = 0;
2482 grn_obj *range;
2483 grn_id range_id = DB_OBJ(column)->range;
2484
2485 grn_obj_reinit(ctx, result, range_id, 0);
2486 range = grn_ctx_at(ctx, range_id);
2487 if (range) {
2488 switch (range->header.type) {
2489 case GRN_TYPE :
2490 n_elements = GRN_BULK_VSIZE(&values) / grn_type_size(ctx, range);
2491 break;
2492 case GRN_TABLE_HASH_KEY :
2493 case GRN_TABLE_PAT_KEY :
2494 case GRN_TABLE_DAT_KEY :
2495 case GRN_TABLE_NO_KEY :
2496 n_elements = GRN_BULK_VSIZE(&values) / sizeof(grn_id);
2497 break;
2498 }
2499 }
2500 if (n_elements > i) {
2501#define GET_UVECTOR_ELEMENT_AS(type) do { \
2502 GRN_ ## type ## _SET(ctx, \
2503 result, \
2504 GRN_ ## type ## _VALUE_AT(&values, i)); \
2505 } while (GRN_FALSE)
2506 switch (values.header.domain) {
2507 case GRN_DB_BOOL :
2508 GET_UVECTOR_ELEMENT_AS(BOOL);
2509 break;
2510 case GRN_DB_INT8 :
2511 GET_UVECTOR_ELEMENT_AS(INT8);
2512 break;
2513 case GRN_DB_UINT8 :
2514 GET_UVECTOR_ELEMENT_AS(UINT8);
2515 break;
2516 case GRN_DB_INT16 :
2517 GET_UVECTOR_ELEMENT_AS(INT16);
2518 break;
2519 case GRN_DB_UINT16 :
2520 GET_UVECTOR_ELEMENT_AS(UINT16);
2521 break;
2522 case GRN_DB_INT32 :
2523 GET_UVECTOR_ELEMENT_AS(INT32);
2524 break;
2525 case GRN_DB_UINT32 :
2526 GET_UVECTOR_ELEMENT_AS(UINT32);
2527 break;
2528 case GRN_DB_INT64 :
2529 GET_UVECTOR_ELEMENT_AS(INT64);
2530 break;
2531 case GRN_DB_UINT64 :
2532 GET_UVECTOR_ELEMENT_AS(UINT64);
2533 break;
2534 case GRN_DB_FLOAT :
2535 GET_UVECTOR_ELEMENT_AS(FLOAT);
2536 break;
2537 case GRN_DB_TIME :
2538 GET_UVECTOR_ELEMENT_AS(TIME);
2539 break;
2540 default :
2541 GET_UVECTOR_ELEMENT_AS(RECORD);
2542 break;
2543 }
2544#undef GET_UVECTOR_ELEMENT_AS
2545 }
2546 } else {
2547 if (values.u.v.n_sections > i) {
2548 const char *content;
2549 unsigned int content_length;
2550 grn_id domain;
2551
2552 content_length = grn_vector_get_element(ctx, &values, i,
2553 &content, NULL, &domain);
2554 grn_obj_reinit(ctx, result, domain, 0);
2555 grn_bulk_write(ctx, result, content, content_length);
2556 }
2557 }
2558
2559 GRN_OBJ_FIN(ctx, &values);
2560}
2561
2562inline static void
2563grn_expr_exec_get_member_table(grn_ctx *ctx,
2564 grn_obj *expr,
2565 grn_obj *table,
2566 grn_obj *key,
2567 grn_obj *result)
2568{
2569 grn_id id;
2570
2571 if (table->header.domain == key->header.domain) {
2572 id = grn_table_get(ctx, table, GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key));
2573 } else {
2574 grn_obj casted_key;
2575 GRN_OBJ_INIT(&casted_key, GRN_BULK, 0, table->header.domain);
2576 if (grn_obj_cast(ctx, key, &casted_key, GRN_FALSE) == GRN_SUCCESS) {
2577 id = grn_table_get(ctx, table,
2578 GRN_BULK_HEAD(&casted_key),
2579 GRN_BULK_VSIZE(&casted_key));
2580 } else {
2581 id = GRN_ID_NIL;
2582 }
2583 GRN_OBJ_FIN(ctx, &casted_key);
2584 }
2585
2586 grn_obj_reinit(ctx, result, DB_OBJ(table)->id, 0);
2587 GRN_RECORD_SET(ctx, result, id);
2588}
2589
2590static inline grn_bool
2591grn_expr_exec_is_simple_expr(grn_ctx *ctx, grn_obj *expr)
2592{
2593 grn_expr *e = (grn_expr *)expr;
2594
2595 if (expr->header.type != GRN_EXPR) {
2596 return GRN_FALSE;
2597 }
2598
2599 if (e->codes_curr != 1) {
2600 return GRN_FALSE;
2601 }
2602
2603 switch (e->codes[0].op) {
2604 case GRN_OP_PUSH :
2605 return GRN_TRUE;
2606 default :
2607 return GRN_FALSE;
2608 }
2609}
2610
2611static inline grn_obj *
2612grn_expr_exec_simple(grn_ctx *ctx, grn_obj *expr)
2613{
2614 grn_expr *e = (grn_expr *)expr;
2615
2616 return e->codes[0].value;
2617}
2618
2619grn_obj *
2620grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
2621{
2622 grn_obj *val = NULL;
2623 uint32_t stack_curr = ctx->impl->stack_curr;
2624 GRN_API_ENTER;
2625 if (grn_expr_exec_is_simple_expr(ctx, expr)) {
2626 val = grn_expr_exec_simple(ctx, expr);
2627 GRN_API_RETURN(val);
2628 }
2629 if (expr->header.type == GRN_PROC) {
2630 grn_proc *proc = (grn_proc *)expr;
2631 if (proc->type == GRN_PROC_COMMAND) {
2632 grn_command_input *input;
2633 input = grn_command_input_open(ctx, expr);
2634 grn_command_run(ctx, expr, input);
2635 grn_command_input_close(ctx, input);
2636 GRN_API_RETURN(NULL);
2637 } else {
2638 grn_proc_call(ctx, expr, nargs, expr);
2639 }
2640 } else {
2641 grn_expr *e = (grn_expr *)expr;
2642 register grn_obj **s_ = ctx->impl->stack;
2643 register grn_obj *s0 = NULL;
2644 register grn_obj *s1 = NULL;
2645 register grn_obj **sp;
2646 register grn_obj *vp = e->values;
2647 grn_obj *res = NULL, *v0 = grn_expr_get_var_by_offset(ctx, expr, 0);
2648 grn_expr_code *code = e->codes, *ce = &e->codes[e->codes_curr];
2649 sp = s_ + stack_curr;
2650 while (code < ce) {
2651 switch (code->op) {
2652 case GRN_OP_NOP :
2653 code++;
2654 break;
2655 case GRN_OP_PUSH :
2656 PUSH1(code->value);
2657 code++;
2658 break;
2659 case GRN_OP_POP :
2660 {
2661 grn_obj *obj;
2662 POP1(obj);
2663 code++;
2664 }
2665 break;
2666 case GRN_OP_GET_REF :
2667 {
2668 grn_obj *col, *rec;
2669 if (code->nargs == 1) {
2670 rec = v0;
2671 if (code->value) {
2672 col = code->value;
2673 ALLOC1(res);
2674 } else {
2675 POP1ALLOC1(col, res);
2676 }
2677 } else {
2678 if (code->value) {
2679 col = code->value;
2680 POP1ALLOC1(rec, res);
2681 } else {
2682 POP2ALLOC1(rec, col, res);
2683 }
2684 }
2685 if (col->header.type == GRN_BULK) {
2686 grn_obj *table = grn_ctx_at(ctx, GRN_OBJ_GET_DOMAIN(rec));
2687 col = grn_obj_column(ctx, table, GRN_BULK_HEAD(col), GRN_BULK_VSIZE(col));
2688 if (col) { grn_expr_take_obj(ctx, (grn_obj *)e, col); }
2689 }
2690 if (col) {
2691 res->header.type = GRN_PTR;
2692 res->header.domain = GRN_ID_NIL;
2693 GRN_PTR_SET(ctx, res, col);
2694 GRN_UINT32_PUT(ctx, res, GRN_RECORD_VALUE(rec));
2695 } else {
2696 ERR(GRN_INVALID_ARGUMENT, "col resolve failed");
2697 goto exit;
2698 }
2699 code++;
2700 }
2701 break;
2702 case GRN_OP_CALL :
2703 {
2704 grn_obj *proc;
2705 if (code->value) {
2706 if (sp < s_ + code->nargs - 1) {
2707 ERR(GRN_INVALID_ARGUMENT, "stack error");
2708 goto exit;
2709 }
2710 proc = code->value;
2711 WITH_SPSAVE({
2712 grn_proc_call(ctx, proc, code->nargs - 1, expr);
2713 });
2714 } else {
2715 int offset = code->nargs;
2716 if (sp < s_ + offset) {
2717 ERR(GRN_INVALID_ARGUMENT, "stack error");
2718 goto exit;
2719 }
2720 proc = sp[-offset];
2721 if (grn_obj_is_window_function_proc(ctx, proc)) {
2722 grn_obj inspected;
2723 GRN_TEXT_INIT(&inspected, 0);
2724 grn_inspect(ctx, &inspected, proc);
2725 ERR(GRN_INVALID_ARGUMENT,
2726 "window function can't be executed for each record: %.*s",
2727 (int)GRN_TEXT_LEN(&inspected),
2728 GRN_TEXT_VALUE(&inspected));
2729 GRN_OBJ_FIN(ctx, &inspected);
2730 goto exit;
2731 } else {
2732 WITH_SPSAVE({
2733 grn_proc_call(ctx, proc, code->nargs - 1, expr);
2734 });
2735 }
2736 if (ctx->rc) {
2737 goto exit;
2738 }
2739 POP1(res);
2740 {
2741 grn_obj *proc_;
2742 POP1(proc_);
2743 if (proc != proc_) {
2744 GRN_LOG(ctx, GRN_LOG_WARNING, "stack may be corrupt");
2745 }
2746 }
2747 PUSH1(res);
2748 }
2749 }
2750 code++;
2751 break;
2752 case GRN_OP_INTERN :
2753 {
2754 grn_obj *obj;
2755 POP1(obj);
2756 obj = GRN_OBJ_RESOLVE(ctx, obj);
2757 res = grn_expr_get_var(ctx, expr, GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj));
2758 if (!res) { res = grn_ctx_get(ctx, GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj)); }
2759 if (!res) {
2760 ERR(GRN_INVALID_ARGUMENT, "intern failed");
2761 goto exit;
2762 }
2763 PUSH1(res);
2764 }
2765 code++;
2766 break;
2767 case GRN_OP_TABLE_CREATE :
2768 {
2769 grn_obj *value_type, *key_type, *flags, *name;
2770 POP1(value_type);
2771 value_type = GRN_OBJ_RESOLVE(ctx, value_type);
2772 POP1(key_type);
2773 key_type = GRN_OBJ_RESOLVE(ctx, key_type);
2774 POP1(flags);
2775 flags = GRN_OBJ_RESOLVE(ctx, flags);
2776 POP1(name);
2777 name = GRN_OBJ_RESOLVE(ctx, name);
2778 res = grn_table_create(ctx, GRN_TEXT_VALUE(name), GRN_TEXT_LEN(name),
2779 NULL, GRN_UINT32_VALUE(flags),
2780 key_type, value_type);
2781 PUSH1(res);
2782 }
2783 code++;
2784 break;
2785 case GRN_OP_EXPR_GET_VAR :
2786 {
2787 grn_obj *name, *expr;
2788 POP1(name);
2789 name = GRN_OBJ_RESOLVE(ctx, name);
2790 POP1(expr);
2791 expr = GRN_OBJ_RESOLVE(ctx, expr);
2792 switch (name->header.domain) {
2793 case GRN_DB_INT32 :
2794 res = grn_expr_get_var_by_offset(ctx, expr, (unsigned int) GRN_INT32_VALUE(name));
2795 break;
2796 case GRN_DB_UINT32 :
2797 res = grn_expr_get_var_by_offset(ctx, expr, (unsigned int) GRN_UINT32_VALUE(name));
2798 break;
2799 case GRN_DB_INT64 :
2800 res = grn_expr_get_var_by_offset(ctx, expr, (unsigned int) GRN_INT64_VALUE(name));
2801 break;
2802 case GRN_DB_UINT64 :
2803 res = grn_expr_get_var_by_offset(ctx, expr, (unsigned int) GRN_UINT64_VALUE(name));
2804 break;
2805 case GRN_DB_SHORT_TEXT :
2806 case GRN_DB_TEXT :
2807 case GRN_DB_LONG_TEXT :
2808 res = grn_expr_get_var(ctx, expr, GRN_TEXT_VALUE(name), GRN_TEXT_LEN(name));
2809 break;
2810 default :
2811 ERR(GRN_INVALID_ARGUMENT, "invalid type");
2812 goto exit;
2813 }
2814 PUSH1(res);
2815 }
2816 code++;
2817 break;
2818 case GRN_OP_ASSIGN :
2819 {
2820 grn_obj *value, *var;
2821 if (code->value) {
2822 value = code->value;
2823 } else {
2824 POP1(value);
2825 }
2826 value = GRN_OBJ_RESOLVE(ctx, value);
2827 POP1(var);
2828 // var = GRN_OBJ_RESOLVE(ctx, var);
2829 if (var->header.type == GRN_PTR &&
2830 GRN_BULK_VSIZE(var) == (sizeof(grn_obj *) + sizeof(grn_id))) {
2831 grn_obj *col = GRN_PTR_VALUE(var);
2832 grn_id rid = *(grn_id *)(GRN_BULK_HEAD(var) + sizeof(grn_obj *));
2833 grn_obj_set_value(ctx, col, rid, value, GRN_OBJ_SET);
2834 } else {
2835 VAR_SET_VALUE(ctx, var, value);
2836 }
2837 PUSH1(value);
2838 }
2839 code++;
2840 break;
2841 case GRN_OP_STAR_ASSIGN :
2842 ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(
2843 INTEGER_ARITHMETIC_OPERATION_STAR,
2844 INTEGER_ARITHMETIC_OPERATION_STAR,
2845 INTEGER_ARITHMETIC_OPERATION_STAR,
2846 INTEGER_ARITHMETIC_OPERATION_STAR,
2847 FLOAT_ARITHMETIC_OPERATION_STAR,
2848 ARITHMETIC_OPERATION_NO_CHECK,
2849 ARITHMETIC_OPERATION_NO_CHECK,
2850 {
2851 ERR(GRN_INVALID_ARGUMENT, "variable *= \"string\" isn't supported");
2852 goto exit;
2853 });
2854 break;
2855 case GRN_OP_SLASH_ASSIGN :
2856 ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(
2857 INTEGER_ARITHMETIC_OPERATION_SLASH,
2858 INTEGER_ARITHMETIC_OPERATION_SLASH,
2859 INTEGER_ARITHMETIC_OPERATION_SLASH,
2860 INTEGER_ARITHMETIC_OPERATION_SLASH,
2861 FLOAT_ARITHMETIC_OPERATION_SLASH,
2862 ARITHMETIC_OPERATION_NO_CHECK,
2863 ARITHMETIC_OPERATION_NO_CHECK,
2864 {
2865 ERR(GRN_INVALID_ARGUMENT, "variable /= \"string\" isn't supported");
2866 goto exit;
2867 });
2868 break;
2869 case GRN_OP_MOD_ASSIGN :
2870 ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(
2871 INTEGER_ARITHMETIC_OPERATION_MOD,
2872 INTEGER_ARITHMETIC_OPERATION_MOD,
2873 INTEGER_ARITHMETIC_OPERATION_MOD,
2874 INTEGER_ARITHMETIC_OPERATION_MOD,
2875 FLOAT_ARITHMETIC_OPERATION_MOD,
2876 ARITHMETIC_OPERATION_NO_CHECK,
2877 ARITHMETIC_OPERATION_NO_CHECK,
2878 {
2879 ERR(GRN_INVALID_ARGUMENT, "variable %%= \"string\" isn't supported");
2880 goto exit;
2881 });
2882 break;
2883 case GRN_OP_PLUS_ASSIGN :
2884 ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(
2885 INTEGER_ARITHMETIC_OPERATION_PLUS,
2886 INTEGER_ARITHMETIC_OPERATION_PLUS,
2887 INTEGER_ARITHMETIC_OPERATION_PLUS,
2888 INTEGER_ARITHMETIC_OPERATION_PLUS,
2889 FLOAT_ARITHMETIC_OPERATION_PLUS,
2890 ARITHMETIC_OPERATION_NO_CHECK,
2891 ARITHMETIC_OPERATION_NO_CHECK,
2892 {
2893 ERR(GRN_INVALID_ARGUMENT, "variable += \"string\" isn't supported");
2894 goto exit;
2895 });
2896 break;
2897 case GRN_OP_MINUS_ASSIGN :
2898 ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(
2899 INTEGER_ARITHMETIC_OPERATION_MINUS,
2900 INTEGER_ARITHMETIC_OPERATION_MINUS,
2901 INTEGER_ARITHMETIC_OPERATION_MINUS,
2902 INTEGER_ARITHMETIC_OPERATION_MINUS,
2903 FLOAT_ARITHMETIC_OPERATION_MINUS,
2904 ARITHMETIC_OPERATION_NO_CHECK,
2905 ARITHMETIC_OPERATION_NO_CHECK,
2906 {
2907 ERR(GRN_INVALID_ARGUMENT, "variable -= \"string\" isn't supported");
2908 goto exit;
2909 });
2910 break;
2911 case GRN_OP_SHIFTL_ASSIGN :
2912 ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(
2913 INTEGER_ARITHMETIC_OPERATION_SHIFTL,
2914 INTEGER_ARITHMETIC_OPERATION_SHIFTL,
2915 INTEGER_ARITHMETIC_OPERATION_SHIFTL,
2916 INTEGER_ARITHMETIC_OPERATION_SHIFTL,
2917 FLOAT_ARITHMETIC_OPERATION_SHIFTL,
2918 ARITHMETIC_OPERATION_NO_CHECK,
2919 ARITHMETIC_OPERATION_NO_CHECK,
2920 {
2921 ERR(GRN_INVALID_ARGUMENT, "variable <<= \"string\" isn't supported");
2922 goto exit;
2923 });
2924 break;
2925 case GRN_OP_SHIFTR_ASSIGN :
2926 ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(
2927 INTEGER_ARITHMETIC_OPERATION_SHIFTR,
2928 INTEGER_ARITHMETIC_OPERATION_SHIFTR,
2929 INTEGER_ARITHMETIC_OPERATION_SHIFTR,
2930 INTEGER_ARITHMETIC_OPERATION_SHIFTR,
2931 FLOAT_ARITHMETIC_OPERATION_SHIFTR,
2932 ARITHMETIC_OPERATION_NO_CHECK,
2933 ARITHMETIC_OPERATION_NO_CHECK,
2934 {
2935 ERR(GRN_INVALID_ARGUMENT, "variable >>= \"string\" isn't supported");
2936 goto exit;
2937 });
2938 break;
2939 case GRN_OP_SHIFTRR_ASSIGN :
2940 ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(
2941 INTEGER8_ARITHMETIC_OPERATION_SHIFTRR,
2942 INTEGER16_ARITHMETIC_OPERATION_SHIFTRR,
2943 INTEGER32_ARITHMETIC_OPERATION_SHIFTRR,
2944 INTEGER64_ARITHMETIC_OPERATION_SHIFTRR,
2945 FLOAT_ARITHMETIC_OPERATION_SHIFTRR,
2946 ARITHMETIC_OPERATION_NO_CHECK,
2947 ARITHMETIC_OPERATION_NO_CHECK,
2948 {
2949 ERR(GRN_INVALID_ARGUMENT,
2950 "variable >>>= \"string\" isn't supported");
2951 goto exit;
2952 });
2953 break;
2954 case GRN_OP_AND_ASSIGN :
2955 ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(
2956 INTEGER_ARITHMETIC_OPERATION_BITWISE_AND,
2957 INTEGER_ARITHMETIC_OPERATION_BITWISE_AND,
2958 INTEGER_ARITHMETIC_OPERATION_BITWISE_AND,
2959 INTEGER_ARITHMETIC_OPERATION_BITWISE_AND,
2960 FLOAT_ARITHMETIC_OPERATION_BITWISE_AND,
2961 ARITHMETIC_OPERATION_NO_CHECK,
2962 ARITHMETIC_OPERATION_NO_CHECK,
2963 {
2964 ERR(GRN_INVALID_ARGUMENT, "variable &= \"string\" isn't supported");
2965 goto exit;
2966 });
2967 break;
2968 case GRN_OP_OR_ASSIGN :
2969 ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(
2970 INTEGER_ARITHMETIC_OPERATION_BITWISE_OR,
2971 INTEGER_ARITHMETIC_OPERATION_BITWISE_OR,
2972 INTEGER_ARITHMETIC_OPERATION_BITWISE_OR,
2973 INTEGER_ARITHMETIC_OPERATION_BITWISE_OR,
2974 FLOAT_ARITHMETIC_OPERATION_BITWISE_OR,
2975 ARITHMETIC_OPERATION_NO_CHECK,
2976 ARITHMETIC_OPERATION_NO_CHECK,
2977 {
2978 ERR(GRN_INVALID_ARGUMENT, "variable |= \"string\" isn't supported");
2979 goto exit;
2980 });
2981 break;
2982 case GRN_OP_XOR_ASSIGN :
2983 ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(
2984 INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR,
2985 INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR,
2986 INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR,
2987 INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR,
2988 FLOAT_ARITHMETIC_OPERATION_BITWISE_XOR,
2989 ARITHMETIC_OPERATION_NO_CHECK,
2990 ARITHMETIC_OPERATION_NO_CHECK,
2991 {
2992 ERR(GRN_INVALID_ARGUMENT, "variable ^= \"string\" isn't supported");
2993 goto exit;
2994 });
2995 break;
2996 case GRN_OP_JUMP :
2997 code += code->nargs + 1;
2998 break;
2999 case GRN_OP_CJUMP :
3000 {
3001 grn_obj *v;
3002 POP1(v);
3003 if (!grn_obj_is_true(ctx, v)) {
3004 code += code->nargs;
3005 }
3006 }
3007 code++;
3008 break;
3009 case GRN_OP_GET_VALUE :
3010 {
3011 grn_obj *col, *rec;
3012 do {
3013 if (code->nargs == 1) {
3014 rec = v0;
3015 if (code->value) {
3016 col = code->value;
3017 ALLOC1(res);
3018 } else {
3019 POP1ALLOC1(col, res);
3020 }
3021 } else {
3022 if (code->value) {
3023 col = code->value;
3024 POP1ALLOC1(rec, res);
3025 } else {
3026 POP2ALLOC1(rec, col, res);
3027 }
3028 }
3029 if (col->header.type == GRN_BULK) {
3030 grn_obj *table = grn_ctx_at(ctx, GRN_OBJ_GET_DOMAIN(rec));
3031 col = grn_obj_column(ctx, table, GRN_BULK_HEAD(col), GRN_BULK_VSIZE(col));
3032 if (col) { grn_expr_take_obj(ctx, (grn_obj *)expr, col); }
3033 }
3034 if (!col) {
3035 ERR(GRN_INVALID_ARGUMENT, "col resolve failed");
3036 goto exit;
3037 }
3038 grn_obj_reinit_for(ctx, res, col);
3039 grn_obj_get_value(ctx, col, GRN_RECORD_VALUE(rec), res);
3040 code++;
3041 } while (code < ce && code->op == GRN_OP_GET_VALUE);
3042 }
3043 break;
3044 case GRN_OP_OBJ_SEARCH :
3045 {
3046 grn_obj *op, *query, *index;
3047 // todo : grn_search_optarg optarg;
3048 POP1(op);
3049 op = GRN_OBJ_RESOLVE(ctx, op);
3050 POP1(res);
3051 res = GRN_OBJ_RESOLVE(ctx, res);
3052 POP1(query);
3053 query = GRN_OBJ_RESOLVE(ctx, query);
3054 POP1(index);
3055 index = GRN_OBJ_RESOLVE(ctx, index);
3056 grn_obj_search(ctx, index, query, res,
3057 (grn_operator)GRN_UINT32_VALUE(op), NULL);
3058 }
3059 code++;
3060 break;
3061 case GRN_OP_TABLE_SELECT :
3062 {
3063 grn_obj *op, *res, *expr, *table;
3064 POP1(op);
3065 op = GRN_OBJ_RESOLVE(ctx, op);
3066 POP1(res);
3067 res = GRN_OBJ_RESOLVE(ctx, res);
3068 POP1(expr);
3069 expr = GRN_OBJ_RESOLVE(ctx, expr);
3070 POP1(table);
3071 table = GRN_OBJ_RESOLVE(ctx, table);
3072 WITH_SPSAVE({
3073 grn_table_select(ctx, table, expr, res, (grn_operator)GRN_UINT32_VALUE(op));
3074 });
3075 PUSH1(res);
3076 }
3077 code++;
3078 break;
3079 case GRN_OP_TABLE_SORT :
3080 {
3081 grn_obj *keys_, *res, *limit, *table;
3082 POP1(keys_);
3083 keys_ = GRN_OBJ_RESOLVE(ctx, keys_);
3084 POP1(res);
3085 res = GRN_OBJ_RESOLVE(ctx, res);
3086 POP1(limit);
3087 limit = GRN_OBJ_RESOLVE(ctx, limit);
3088 POP1(table);
3089 table = GRN_OBJ_RESOLVE(ctx, table);
3090 {
3091 grn_table_sort_key *keys;
3092 const char *p = GRN_BULK_HEAD(keys_), *tokbuf[256];
3093 int n = grn_str_tok(p, GRN_BULK_VSIZE(keys_), ' ', tokbuf, 256, NULL);
3094 if ((keys = GRN_MALLOCN(grn_table_sort_key, n))) {
3095 int i, n_keys = 0;
3096 for (i = 0; i < n; i++) {
3097 uint32_t len = (uint32_t) (tokbuf[i] - p);
3098 grn_obj *col = grn_obj_column(ctx, table, p, len);
3099 if (col) {
3100 keys[n_keys].key = col;
3101 keys[n_keys].flags = GRN_TABLE_SORT_ASC;
3102 keys[n_keys].offset = 0;
3103 n_keys++;
3104 } else {
3105 if (p[0] == ':' && p[1] == 'd' && len == 2 && n_keys) {
3106 keys[n_keys - 1].flags |= GRN_TABLE_SORT_DESC;
3107 }
3108 }
3109 p = tokbuf[i] + 1;
3110 }
3111 WITH_SPSAVE({
3112 grn_table_sort(ctx, table, 0, GRN_INT32_VALUE(limit), res, keys, n_keys);
3113 });
3114 for (i = 0; i < n_keys; i++) {
3115 grn_obj_unlink(ctx, keys[i].key);
3116 }
3117 GRN_FREE(keys);
3118 }
3119 }
3120 }
3121 code++;
3122 break;
3123 case GRN_OP_TABLE_GROUP :
3124 {
3125 grn_obj *res, *keys_, *table;
3126 POP1(res);
3127 res = GRN_OBJ_RESOLVE(ctx, res);
3128 POP1(keys_);
3129 keys_ = GRN_OBJ_RESOLVE(ctx, keys_);
3130 POP1(table);
3131 table = GRN_OBJ_RESOLVE(ctx, table);
3132 {
3133 grn_table_sort_key *keys;
3134 grn_table_group_result results;
3135 const char *p = GRN_BULK_HEAD(keys_), *tokbuf[256];
3136 int n = grn_str_tok(p, GRN_BULK_VSIZE(keys_), ' ', tokbuf, 256, NULL);
3137 if ((keys = GRN_MALLOCN(grn_table_sort_key, n))) {
3138 int i, n_keys = 0;
3139 for (i = 0; i < n; i++) {
3140 uint32_t len = (uint32_t) (tokbuf[i] - p);
3141 grn_obj *col = grn_obj_column(ctx, table, p, len);
3142 if (col) {
3143 keys[n_keys].key = col;
3144 keys[n_keys].flags = GRN_TABLE_SORT_ASC;
3145 keys[n_keys].offset = 0;
3146 n_keys++;
3147 } else if (n_keys) {
3148 if (p[0] == ':' && p[1] == 'd' && len == 2) {
3149 keys[n_keys - 1].flags |= GRN_TABLE_SORT_DESC;
3150 } else {
3151 keys[n_keys - 1].offset = grn_atoi(p, p + len, NULL);
3152 }
3153 }
3154 p = tokbuf[i] + 1;
3155 }
3156 /* todo : support multi-results */
3157 results.table = res;
3158 results.key_begin = 0;
3159 results.key_end = 0;
3160 results.limit = 0;
3161 results.flags = 0;
3162 results.op = GRN_OP_OR;
3163 WITH_SPSAVE({
3164 grn_table_group(ctx, table, keys, n_keys, &results, 1);
3165 });
3166 for (i = 0; i < n_keys; i++) {
3167 grn_obj_unlink(ctx, keys[i].key);
3168 }
3169 GRN_FREE(keys);
3170 }
3171 }
3172 }
3173 code++;
3174 break;
3175 case GRN_OP_JSON_PUT :
3176 {
3177 grn_obj_format format;
3178 grn_obj *str, *table, *res;
3179 POP1(res);
3180 res = GRN_OBJ_RESOLVE(ctx, res);
3181 POP1(str);
3182 str = GRN_OBJ_RESOLVE(ctx, str);
3183 POP1(table);
3184 table = GRN_OBJ_RESOLVE(ctx, table);
3185 GRN_OBJ_FORMAT_INIT(&format, grn_table_size(ctx, table), 0, -1, 0);
3186 format.flags = 0;
3187 grn_obj_columns(ctx, table,
3188 GRN_TEXT_VALUE(str), GRN_TEXT_LEN(str), &format.columns);
3189 grn_text_otoj(ctx, res, table, &format);
3190 GRN_OBJ_FORMAT_FIN(ctx, &format);
3191 }
3192 code++;
3193 break;
3194 case GRN_OP_AND :
3195 {
3196 grn_obj *x, *y;
3197 grn_obj *result = NULL;
3198 POP2ALLOC1(x, y, res);
3199 if (grn_obj_is_true(ctx, x)) {
3200 if (grn_obj_is_true(ctx, y)) {
3201 result = y;
3202 }
3203 }
3204 if (result) {
3205 if (res != result) {
3206 grn_obj_reinit(ctx, res, result->header.domain, 0);
3207 grn_obj_cast(ctx, result, res, GRN_FALSE);
3208 }
3209 } else {
3210 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3211 GRN_BOOL_SET(ctx, res, GRN_FALSE);
3212 }
3213 }
3214 code++;
3215 break;
3216 case GRN_OP_OR :
3217 {
3218 grn_obj *x, *y;
3219 grn_obj *result;
3220 POP2ALLOC1(x, y, res);
3221 if (grn_obj_is_true(ctx, x)) {
3222 result = x;
3223 } else {
3224 if (grn_obj_is_true(ctx, y)) {
3225 result = y;
3226 } else {
3227 result = NULL;
3228 }
3229 }
3230 if (result) {
3231 if (res != result) {
3232 grn_obj_reinit(ctx, res, result->header.domain, 0);
3233 grn_obj_cast(ctx, result, res, GRN_FALSE);
3234 }
3235 } else {
3236 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3237 GRN_BOOL_SET(ctx, res, GRN_FALSE);
3238 }
3239 }
3240 code++;
3241 break;
3242 case GRN_OP_AND_NOT :
3243 {
3244 grn_obj *x, *y;
3245 grn_bool is_true;
3246 POP2ALLOC1(x, y, res);
3247 if (!grn_obj_is_true(ctx, x) || grn_obj_is_true(ctx, y)) {
3248 is_true = GRN_FALSE;
3249 } else {
3250 is_true = GRN_TRUE;
3251 }
3252 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3253 GRN_BOOL_SET(ctx, res, is_true);
3254 }
3255 code++;
3256 break;
3257 case GRN_OP_ADJUST :
3258 {
3259 /* todo */
3260 }
3261 code++;
3262 break;
3263 case GRN_OP_MATCH :
3264 {
3265 grn_obj *x, *y;
3266 grn_bool matched;
3267 POP1(y);
3268 POP1(x);
3269 WITH_SPSAVE({
3270 matched = grn_operator_exec_match(ctx, x, y);
3271 });
3272 ALLOC1(res);
3273 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3274 GRN_BOOL_SET(ctx, res, matched);
3275 }
3276 code++;
3277 break;
3278 case GRN_OP_EQUAL :
3279 {
3280 grn_bool is_equal;
3281 grn_obj *x, *y;
3282 POP2ALLOC1(x, y, res);
3283 is_equal = grn_operator_exec_equal(ctx, x, y);
3284 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3285 GRN_BOOL_SET(ctx, res, is_equal);
3286 }
3287 code++;
3288 break;
3289 case GRN_OP_NOT_EQUAL :
3290 {
3291 grn_bool is_not_equal;
3292 grn_obj *x, *y;
3293 POP2ALLOC1(x, y, res);
3294 is_not_equal = grn_operator_exec_not_equal(ctx, x, y);
3295 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3296 GRN_BOOL_SET(ctx, res, is_not_equal);
3297 }
3298 code++;
3299 break;
3300 case GRN_OP_PREFIX :
3301 {
3302 grn_obj *x, *y;
3303 grn_bool matched;
3304 POP1(y);
3305 POP1(x);
3306 WITH_SPSAVE({
3307 matched = grn_operator_exec_prefix(ctx, x, y);
3308 });
3309 ALLOC1(res);
3310 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3311 GRN_BOOL_SET(ctx, res, matched);
3312 }
3313 code++;
3314 break;
3315 case GRN_OP_SUFFIX :
3316 {
3317 grn_obj *x, *y;
3318 grn_bool matched = GRN_FALSE;
3319 POP2ALLOC1(x, y, res);
3320 if (GRN_TEXT_LEN(x) >= GRN_TEXT_LEN(y) &&
3321 !memcmp(GRN_TEXT_VALUE(x) + GRN_TEXT_LEN(x) - GRN_TEXT_LEN(y),
3322 GRN_TEXT_VALUE(y), GRN_TEXT_LEN(y))) {
3323 matched = GRN_TRUE;
3324 }
3325 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3326 GRN_BOOL_SET(ctx, res, matched);
3327 }
3328 code++;
3329 break;
3330 case GRN_OP_LESS :
3331 {
3332 grn_bool r;
3333 grn_obj *x, *y;
3334 POP2ALLOC1(x, y, res);
3335 r = grn_operator_exec_less(ctx, x, y);
3336 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3337 GRN_BOOL_SET(ctx, res, r);
3338 }
3339 code++;
3340 break;
3341 case GRN_OP_GREATER :
3342 {
3343 grn_bool r;
3344 grn_obj *x, *y;
3345 POP2ALLOC1(x, y, res);
3346 r = grn_operator_exec_greater(ctx, x, y);
3347 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3348 GRN_BOOL_SET(ctx, res, r);
3349 }
3350 code++;
3351 break;
3352 case GRN_OP_LESS_EQUAL :
3353 {
3354 grn_bool r;
3355 grn_obj *x, *y;
3356 POP2ALLOC1(x, y, res);
3357 r = grn_operator_exec_less_equal(ctx, x, y);
3358 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3359 GRN_BOOL_SET(ctx, res, r);
3360 }
3361 code++;
3362 break;
3363 case GRN_OP_GREATER_EQUAL :
3364 {
3365 grn_bool r;
3366 grn_obj *x, *y;
3367 POP2ALLOC1(x, y, res);
3368 r = grn_operator_exec_greater_equal(ctx, x, y);
3369 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3370 GRN_BOOL_SET(ctx, res, r);
3371 }
3372 code++;
3373 break;
3374 case GRN_OP_GEO_DISTANCE1 :
3375 {
3376 grn_obj *value;
3377 double lng1, lat1, lng2, lat2, x, y, d;
3378 POP1(value);
3379 lng1 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3380 POP1(value);
3381 lat1 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3382 POP1(value);
3383 lng2 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3384 POP1ALLOC1(value, res);
3385 lat2 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3386 x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5);
3387 y = (lat2 - lat1);
3388 d = sqrt((x * x) + (y * y)) * GEO_RADIOUS;
3389 res->header.type = GRN_BULK;
3390 res->header.domain = GRN_DB_FLOAT;
3391 GRN_FLOAT_SET(ctx, res, d);
3392 }
3393 code++;
3394 break;
3395 case GRN_OP_GEO_DISTANCE2 :
3396 {
3397 grn_obj *value;
3398 double lng1, lat1, lng2, lat2, x, y, d;
3399 POP1(value);
3400 lng1 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3401 POP1(value);
3402 lat1 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3403 POP1(value);
3404 lng2 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3405 POP1ALLOC1(value, res);
3406 lat2 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3407 x = sin(fabs(lng2 - lng1) * 0.5);
3408 y = sin(fabs(lat2 - lat1) * 0.5);
3409 d = asin(sqrt((y * y) + cos(lat1) * cos(lat2) * x * x)) * 2 * GEO_RADIOUS;
3410 res->header.type = GRN_BULK;
3411 res->header.domain = GRN_DB_FLOAT;
3412 GRN_FLOAT_SET(ctx, res, d);
3413 }
3414 code++;
3415 break;
3416 case GRN_OP_GEO_DISTANCE3 :
3417 {
3418 grn_obj *value;
3419 double lng1, lat1, lng2, lat2, p, q, m, n, x, y, d;
3420 POP1(value);
3421 lng1 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3422 POP1(value);
3423 lat1 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3424 POP1(value);
3425 lng2 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3426 POP1ALLOC1(value, res);
3427 lat2 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3428 p = (lat1 + lat2) * 0.5;
3429 q = (1 - GEO_BES_C3 * sin(p) * sin(p));
3430 m = GEO_BES_C1 / sqrt(q * q * q);
3431 n = GEO_BES_C2 / sqrt(q);
3432 x = n * cos(p) * fabs(lng1 - lng2);
3433 y = m * fabs(lat1 - lat2);
3434 d = sqrt((x * x) + (y * y));
3435 res->header.type = GRN_BULK;
3436 res->header.domain = GRN_DB_FLOAT;
3437 GRN_FLOAT_SET(ctx, res, d);
3438 }
3439 code++;
3440 break;
3441 case GRN_OP_GEO_DISTANCE4 :
3442 {
3443 grn_obj *value;
3444 double lng1, lat1, lng2, lat2, p, q, m, n, x, y, d;
3445 POP1(value);
3446 lng1 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3447 POP1(value);
3448 lat1 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3449 POP1(value);
3450 lng2 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3451 POP1ALLOC1(value, res);
3452 lat2 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3453 p = (lat1 + lat2) * 0.5;
3454 q = (1 - GEO_GRS_C3 * sin(p) * sin(p));
3455 m = GEO_GRS_C1 / sqrt(q * q * q);
3456 n = GEO_GRS_C2 / sqrt(q);
3457 x = n * cos(p) * fabs(lng1 - lng2);
3458 y = m * fabs(lat1 - lat2);
3459 d = sqrt((x * x) + (y * y));
3460 res->header.type = GRN_BULK;
3461 res->header.domain = GRN_DB_FLOAT;
3462 GRN_FLOAT_SET(ctx, res, d);
3463 }
3464 code++;
3465 break;
3466 case GRN_OP_GEO_WITHINP5 :
3467 {
3468 int r;
3469 grn_obj *value;
3470 double lng0, lat0, lng1, lat1, x, y, d;
3471 POP1(value);
3472 lng0 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3473 POP1(value);
3474 lat0 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3475 POP1(value);
3476 lng1 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3477 POP1(value);
3478 lat1 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3479 POP1ALLOC1(value, res);
3480 x = (lng1 - lng0) * cos((lat0 + lat1) * 0.5);
3481 y = (lat1 - lat0);
3482 d = sqrt((x * x) + (y * y)) * GEO_RADIOUS;
3483 switch (value->header.domain) {
3484 case GRN_DB_INT32 :
3485 r = d <= GRN_INT32_VALUE(value);
3486 break;
3487 case GRN_DB_FLOAT :
3488 r = d <= GRN_FLOAT_VALUE(value);
3489 break;
3490 default :
3491 r = 0;
3492 break;
3493 }
3494 GRN_INT32_SET(ctx, res, r);
3495 res->header.type = GRN_BULK;
3496 res->header.domain = GRN_DB_INT32;
3497 }
3498 code++;
3499 break;
3500 case GRN_OP_GEO_WITHINP6 :
3501 {
3502 int r;
3503 grn_obj *value;
3504 double lng0, lat0, lng1, lat1, lng2, lat2, x, y, d;
3505 POP1(value);
3506 lng0 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3507 POP1(value);
3508 lat0 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3509 POP1(value);
3510 lng1 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3511 POP1(value);
3512 lat1 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3513 POP1(value);
3514 lng2 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3515 POP1ALLOC1(value, res);
3516 lat2 = GEO_INT2RAD(GRN_INT32_VALUE(value));
3517 x = (lng1 - lng0) * cos((lat0 + lat1) * 0.5);
3518 y = (lat1 - lat0);
3519 d = (x * x) + (y * y);
3520 x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5);
3521 y = (lat2 - lat1);
3522 r = d <= (x * x) + (y * y);
3523 GRN_INT32_SET(ctx, res, r);
3524 res->header.type = GRN_BULK;
3525 res->header.domain = GRN_DB_INT32;
3526 }
3527 code++;
3528 break;
3529 case GRN_OP_GEO_WITHINP8 :
3530 {
3531 int r;
3532 grn_obj *value;
3533 int64_t ln0, la0, ln1, la1, ln2, la2, ln3, la3;
3534 POP1(value);
3535 ln0 = GRN_INT32_VALUE(value);
3536 POP1(value);
3537 la0 = GRN_INT32_VALUE(value);
3538 POP1(value);
3539 ln1 = GRN_INT32_VALUE(value);
3540 POP1(value);
3541 la1 = GRN_INT32_VALUE(value);
3542 POP1(value);
3543 ln2 = GRN_INT32_VALUE(value);
3544 POP1(value);
3545 la2 = GRN_INT32_VALUE(value);
3546 POP1(value);
3547 ln3 = GRN_INT32_VALUE(value);
3548 POP1ALLOC1(value, res);
3549 la3 = GRN_INT32_VALUE(value);
3550 r = ((ln2 <= ln0) && (ln0 <= ln3) && (la2 <= la0) && (la0 <= la3));
3551 GRN_INT32_SET(ctx, res, r);
3552 res->header.type = GRN_BULK;
3553 res->header.domain = GRN_DB_INT32;
3554 }
3555 code++;
3556 break;
3557 case GRN_OP_PLUS :
3558 ARITHMETIC_BINARY_OPERATION_DISPATCH(
3559 "+",
3560 INTEGER_ARITHMETIC_OPERATION_PLUS,
3561 INTEGER_ARITHMETIC_OPERATION_PLUS,
3562 INTEGER_ARITHMETIC_OPERATION_PLUS,
3563 INTEGER_ARITHMETIC_OPERATION_PLUS,
3564 FLOAT_ARITHMETIC_OPERATION_PLUS,
3565 ARITHMETIC_OPERATION_NO_CHECK,
3566 ARITHMETIC_OPERATION_NO_CHECK,
3567 {
3568 if (x == res) {
3569 grn_obj_cast(ctx, y, res, GRN_FALSE);
3570 } else if (y == res) {
3571 grn_obj buffer;
3572 GRN_TEXT_INIT(&buffer, 0);
3573 grn_obj_cast(ctx, x, &buffer, GRN_FALSE);
3574 grn_obj_cast(ctx, y, &buffer, GRN_FALSE);
3575 GRN_BULK_REWIND(res);
3576 grn_obj_cast(ctx, &buffer, res, GRN_FALSE);
3577 GRN_OBJ_FIN(ctx, &buffer);
3578 } else {
3579 GRN_BULK_REWIND(res);
3580 grn_obj_cast(ctx, x, res, GRN_FALSE);
3581 grn_obj_cast(ctx, y, res, GRN_FALSE);
3582 }
3583 }
3584 ,);
3585 break;
3586 case GRN_OP_MINUS :
3587 if (code->nargs == 1) {
3588 ARITHMETIC_UNARY_OPERATION_DISPATCH(
3589 INTEGER_UNARY_ARITHMETIC_OPERATION_MINUS,
3590 FLOAT_UNARY_ARITHMETIC_OPERATION_MINUS,
3591 ARITHMETIC_OPERATION_NO_CHECK,
3592 ARITHMETIC_OPERATION_NO_CHECK,
3593 {
3594 long long int x_;
3595
3596 res->header.type = GRN_BULK;
3597 res->header.domain = GRN_DB_INT64;
3598
3599 GRN_INT64_SET(ctx, res, 0);
3600 grn_obj_cast(ctx, x, res, GRN_FALSE);
3601 x_ = GRN_INT64_VALUE(res);
3602
3603 GRN_INT64_SET(ctx, res, -x_);
3604 }
3605 ,);
3606 } else {
3607 ARITHMETIC_BINARY_OPERATION_DISPATCH(
3608 "-",
3609 INTEGER_ARITHMETIC_OPERATION_MINUS,
3610 INTEGER_ARITHMETIC_OPERATION_MINUS,
3611 INTEGER_ARITHMETIC_OPERATION_MINUS,
3612 INTEGER_ARITHMETIC_OPERATION_MINUS,
3613 FLOAT_ARITHMETIC_OPERATION_MINUS,
3614 ARITHMETIC_OPERATION_NO_CHECK,
3615 ARITHMETIC_OPERATION_NO_CHECK,
3616 {
3617 ERR(GRN_INVALID_ARGUMENT,
3618 "\"string\" - \"string\" "
3619 "isn't supported");
3620 goto exit;
3621 }
3622 ,);
3623 }
3624 break;
3625 case GRN_OP_STAR :
3626 ARITHMETIC_BINARY_OPERATION_DISPATCH(
3627 "*",
3628 INTEGER_ARITHMETIC_OPERATION_STAR,
3629 INTEGER_ARITHMETIC_OPERATION_STAR,
3630 INTEGER_ARITHMETIC_OPERATION_STAR,
3631 INTEGER_ARITHMETIC_OPERATION_STAR,
3632 FLOAT_ARITHMETIC_OPERATION_STAR,
3633 ARITHMETIC_OPERATION_NO_CHECK,
3634 ARITHMETIC_OPERATION_NO_CHECK,
3635 {
3636 ERR(GRN_INVALID_ARGUMENT,
3637 "\"string\" * \"string\" "
3638 "isn't supported");
3639 goto exit;
3640 }
3641 ,);
3642 break;
3643 case GRN_OP_SLASH :
3644 DIVISION_OPERATION_DISPATCH(
3645 SIGNED_INTEGER_DIVISION_OPERATION_SLASH,
3646 UNSIGNED_INTEGER_DIVISION_OPERATION_SLASH,
3647 FLOAT_DIVISION_OPERATION_SLASH,
3648 {
3649 ERR(GRN_INVALID_ARGUMENT,
3650 "\"string\" / \"string\" "
3651 "isn't supported");
3652 goto exit;
3653 });
3654 break;
3655 case GRN_OP_MOD :
3656 DIVISION_OPERATION_DISPATCH(
3657 SIGNED_INTEGER_DIVISION_OPERATION_MOD,
3658 UNSIGNED_INTEGER_DIVISION_OPERATION_MOD,
3659 FLOAT_DIVISION_OPERATION_MOD,
3660 {
3661 ERR(GRN_INVALID_ARGUMENT,
3662 "\"string\" %% \"string\" "
3663 "isn't supported");
3664 goto exit;
3665 });
3666 break;
3667 case GRN_OP_BITWISE_NOT :
3668 ARITHMETIC_UNARY_OPERATION_DISPATCH(
3669 INTEGER_UNARY_ARITHMETIC_OPERATION_BITWISE_NOT,
3670 FLOAT_UNARY_ARITHMETIC_OPERATION_BITWISE_NOT,
3671 ARITHMETIC_OPERATION_NO_CHECK,
3672 ARITHMETIC_OPERATION_NO_CHECK,
3673 TEXT_UNARY_ARITHMETIC_OPERATION(~),);
3674 break;
3675 case GRN_OP_BITWISE_OR :
3676 ARITHMETIC_BINARY_OPERATION_DISPATCH(
3677 "|",
3678 INTEGER_ARITHMETIC_OPERATION_BITWISE_OR,
3679 INTEGER_ARITHMETIC_OPERATION_BITWISE_OR,
3680 INTEGER_ARITHMETIC_OPERATION_BITWISE_OR,
3681 INTEGER_ARITHMETIC_OPERATION_BITWISE_OR,
3682 FLOAT_ARITHMETIC_OPERATION_BITWISE_OR,
3683 ARITHMETIC_OPERATION_NO_CHECK,
3684 ARITHMETIC_OPERATION_NO_CHECK,
3685 TEXT_ARITHMETIC_OPERATION(|),);
3686 break;
3687 case GRN_OP_BITWISE_XOR :
3688 ARITHMETIC_BINARY_OPERATION_DISPATCH(
3689 "^",
3690 INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR,
3691 INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR,
3692 INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR,
3693 INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR,
3694 FLOAT_ARITHMETIC_OPERATION_BITWISE_XOR,
3695 ARITHMETIC_OPERATION_NO_CHECK,
3696 ARITHMETIC_OPERATION_NO_CHECK,
3697 TEXT_ARITHMETIC_OPERATION(^),);
3698 break;
3699 case GRN_OP_BITWISE_AND :
3700 ARITHMETIC_BINARY_OPERATION_DISPATCH(
3701 "&",
3702 INTEGER_ARITHMETIC_OPERATION_BITWISE_AND,
3703 INTEGER_ARITHMETIC_OPERATION_BITWISE_AND,
3704 INTEGER_ARITHMETIC_OPERATION_BITWISE_AND,
3705 INTEGER_ARITHMETIC_OPERATION_BITWISE_AND,
3706 FLOAT_ARITHMETIC_OPERATION_BITWISE_AND,
3707 ARITHMETIC_OPERATION_NO_CHECK,
3708 ARITHMETIC_OPERATION_NO_CHECK,
3709 TEXT_ARITHMETIC_OPERATION(&),);
3710 break;
3711 case GRN_OP_SHIFTL :
3712 ARITHMETIC_BINARY_OPERATION_DISPATCH(
3713 "<<",
3714 INTEGER_ARITHMETIC_OPERATION_SHIFTL,
3715 INTEGER_ARITHMETIC_OPERATION_SHIFTL,
3716 INTEGER_ARITHMETIC_OPERATION_SHIFTL,
3717 INTEGER_ARITHMETIC_OPERATION_SHIFTL,
3718 FLOAT_ARITHMETIC_OPERATION_SHIFTL,
3719 ARITHMETIC_OPERATION_NO_CHECK,
3720 ARITHMETIC_OPERATION_NO_CHECK,
3721 TEXT_ARITHMETIC_OPERATION(<<),);
3722 break;
3723 case GRN_OP_SHIFTR :
3724 ARITHMETIC_BINARY_OPERATION_DISPATCH(
3725 ">>",
3726 INTEGER_ARITHMETIC_OPERATION_SHIFTR,
3727 INTEGER_ARITHMETIC_OPERATION_SHIFTR,
3728 INTEGER_ARITHMETIC_OPERATION_SHIFTR,
3729 INTEGER_ARITHMETIC_OPERATION_SHIFTR,
3730 FLOAT_ARITHMETIC_OPERATION_SHIFTR,
3731 ARITHMETIC_OPERATION_NO_CHECK,
3732 ARITHMETIC_OPERATION_NO_CHECK,
3733 TEXT_ARITHMETIC_OPERATION(>>),);
3734 break;
3735 case GRN_OP_SHIFTRR :
3736 ARITHMETIC_BINARY_OPERATION_DISPATCH(
3737 ">>>",
3738 INTEGER8_ARITHMETIC_OPERATION_SHIFTRR,
3739 INTEGER16_ARITHMETIC_OPERATION_SHIFTRR,
3740 INTEGER32_ARITHMETIC_OPERATION_SHIFTRR,
3741 INTEGER64_ARITHMETIC_OPERATION_SHIFTRR,
3742 FLOAT_ARITHMETIC_OPERATION_SHIFTRR,
3743 ARITHMETIC_OPERATION_NO_CHECK,
3744 ARITHMETIC_OPERATION_NO_CHECK,
3745 {
3746 long long unsigned int x_;
3747 long long unsigned int y_;
3748
3749 res->header.type = GRN_BULK;
3750 res->header.domain = GRN_DB_INT64;
3751
3752 GRN_INT64_SET(ctx, res, 0);
3753 grn_obj_cast(ctx, x, res, GRN_FALSE);
3754 x_ = GRN_INT64_VALUE(res);
3755
3756 GRN_INT64_SET(ctx, res, 0);
3757 grn_obj_cast(ctx, y, res, GRN_FALSE);
3758 y_ = GRN_INT64_VALUE(res);
3759
3760 GRN_INT64_SET(ctx, res, x_ >> y_);
3761 }
3762 ,);
3763 break;
3764 case GRN_OP_INCR :
3765 UNARY_OPERATE_AND_ASSIGN_DISPATCH(EXEC_OPERATE, 1, GRN_OBJ_INCR);
3766 break;
3767 case GRN_OP_DECR :
3768 UNARY_OPERATE_AND_ASSIGN_DISPATCH(EXEC_OPERATE, 1, GRN_OBJ_DECR);
3769 break;
3770 case GRN_OP_INCR_POST :
3771 UNARY_OPERATE_AND_ASSIGN_DISPATCH(EXEC_OPERATE_POST, 1, GRN_OBJ_INCR);
3772 break;
3773 case GRN_OP_DECR_POST :
3774 UNARY_OPERATE_AND_ASSIGN_DISPATCH(EXEC_OPERATE_POST, 1, GRN_OBJ_DECR);
3775 break;
3776 case GRN_OP_NOT :
3777 {
3778 grn_obj *value;
3779 grn_bool value_boolean;
3780 POP1ALLOC1(value, res);
3781 GRN_OBJ_IS_TRUE(ctx, value, value_boolean);
3782 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3783 GRN_BOOL_SET(ctx, res, !value_boolean);
3784 }
3785 code++;
3786 break;
3787 case GRN_OP_GET_MEMBER :
3788 {
3789 grn_obj *receiver, *index_or_key;
3790 POP2ALLOC1(receiver, index_or_key, res);
3791 if (receiver->header.type == GRN_PTR) {
3792 grn_obj *index = index_or_key;
3793 grn_expr_exec_get_member_vector(ctx, expr, receiver, index, res);
3794 } else {
3795 grn_obj *key = index_or_key;
3796 grn_expr_exec_get_member_table(ctx, expr, receiver, key, res);
3797 }
3798 code++;
3799 }
3800 break;
3801 case GRN_OP_REGEXP :
3802 {
3803 grn_obj *target, *pattern;
3804 grn_bool matched;
3805 POP1(pattern);
3806 POP1(target);
3807 WITH_SPSAVE({
3808 matched = grn_operator_exec_regexp(ctx, target, pattern);
3809 });
3810 ALLOC1(res);
3811 grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3812 GRN_BOOL_SET(ctx, res, matched);
3813 }
3814 code++;
3815 break;
3816 default :
3817 ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "not implemented operator assigned");
3818 goto exit;
3819 break;
3820 }
3821 }
3822 ctx->impl->stack_curr = sp - s_;
3823 }
3824 if (ctx->impl->stack_curr + nargs > stack_curr) {
3825 val = grn_ctx_pop(ctx);
3826 }
3827exit :
3828 if (ctx->impl->stack_curr + nargs > stack_curr) {
3829 /*
3830 GRN_LOG(ctx, GRN_LOG_WARNING, "nargs=%d stack balance=%d",
3831 nargs, stack_curr - ctx->impl->stack_curr);
3832 */
3833 ctx->impl->stack_curr = stack_curr - nargs;
3834 }
3835 GRN_API_RETURN(val);
3836}
3837
3838grn_obj *
3839grn_expr_get_value(grn_ctx *ctx, grn_obj *expr, int offset)
3840{
3841 grn_obj *res = NULL;
3842 grn_expr *e = (grn_expr *)expr;
3843 GRN_API_ENTER;
3844 if (0 <= offset && offset < e->values_size) {
3845 res = &e->values[offset];
3846 }
3847 GRN_API_RETURN(res);
3848}
3849
3850#define DEFAULT_WEIGHT 5
3851#define DEFAULT_DECAYSTEP 2
3852#define DEFAULT_MAX_INTERVAL 10
3853#define DEFAULT_SIMILARITY_THRESHOLD 0
3854#define DEFAULT_TERM_EXTRACT_POLICY 0
3855#define DEFAULT_WEIGHT_VECTOR_SIZE 4096
3856
3857#define GRN_SCAN_INFO_MAX_N_ARGS 128
3858
3859struct _grn_scan_info {
3860 uint32_t start;
3861 uint32_t end;
3862 int32_t nargs;
3863 int flags;
3864 grn_operator op;
3865 grn_operator logical_op;
3866 grn_obj wv;
3867 grn_obj index;
3868 grn_obj *query;
3869 grn_obj *args[GRN_SCAN_INFO_MAX_N_ARGS];
3870 int max_interval;
3871 int similarity_threshold;
3872 grn_obj scorers;
3873 grn_obj scorer_args_exprs;
3874 grn_obj scorer_args_expr_offsets;
3875 struct {
3876 grn_bool specified;
3877 int start;
3878 } position;
3879};
3880
3881#define SI_FREE(si) do {\
3882 GRN_OBJ_FIN(ctx, &(si)->wv);\
3883 GRN_OBJ_FIN(ctx, &(si)->index);\
3884 GRN_OBJ_FIN(ctx, &(si)->scorers);\
3885 GRN_OBJ_FIN(ctx, &(si)->scorer_args_exprs);\
3886 GRN_OBJ_FIN(ctx, &(si)->scorer_args_expr_offsets);\
3887 GRN_FREE(si);\
3888} while (0)
3889
3890#define SI_ALLOC_RAW(si, st) do {\
3891 if (((si) = GRN_MALLOCN(scan_info, 1))) {\
3892 GRN_INT32_INIT(&(si)->wv, GRN_OBJ_VECTOR);\
3893 GRN_PTR_INIT(&(si)->index, GRN_OBJ_VECTOR, GRN_ID_NIL);\
3894 (si)->logical_op = GRN_OP_OR;\
3895 (si)->flags = SCAN_PUSH;\
3896 (si)->nargs = 0;\
3897 (si)->max_interval = DEFAULT_MAX_INTERVAL;\
3898 (si)->similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD;\
3899 (si)->start = (st);\
3900 (si)->query = NULL;\
3901 GRN_PTR_INIT(&(si)->scorers, GRN_OBJ_VECTOR, GRN_ID_NIL);\
3902 GRN_PTR_INIT(&(si)->scorer_args_exprs, GRN_OBJ_VECTOR, GRN_ID_NIL);\
3903 GRN_UINT32_INIT(&(si)->scorer_args_expr_offsets, GRN_OBJ_VECTOR);\
3904 (si)->position.specified = GRN_FALSE;\
3905 (si)->position.start = 0;\
3906 }\
3907} while (0)
3908
3909#define SI_ALLOC(si, i, st) do {\
3910 SI_ALLOC_RAW(si, st);\
3911 if (!(si)) {\
3912 int j;\
3913 for (j = 0; j < i; j++) { SI_FREE(sis[j]); }\
3914 GRN_FREE(sis);\
3915 return NULL;\
3916 }\
3917} while (0)
3918
3919static scan_info **
3920put_logical_op(grn_ctx *ctx, scan_info **sis, int *ip, grn_operator op, int start)
3921{
3922 int nparens = 1, ndifops = 0, i = *ip, j = i, r = 0;
3923 while (j--) {
3924 scan_info *s_ = sis[j];
3925 if (s_->flags & SCAN_POP) {
3926 ndifops++;
3927 nparens++;
3928 } else {
3929 if (s_->flags & SCAN_PUSH) {
3930 if (!(--nparens)) {
3931 if (!r) {
3932 if (ndifops) {
3933 if (j && op != GRN_OP_AND_NOT) {
3934 nparens = 1;
3935 ndifops = 0;
3936 r = j;
3937 } else {
3938 SI_ALLOC(s_, i, start);
3939 s_->flags = SCAN_POP;
3940 s_->logical_op = op;
3941 sis[i++] = s_;
3942 *ip = i;
3943 break;
3944 }
3945 } else {
3946 s_->flags &= ~SCAN_PUSH;
3947 s_->logical_op = op;
3948 break;
3949 }
3950 } else {
3951 if (ndifops) {
3952 SI_ALLOC(s_, i, start);
3953 s_->flags = SCAN_POP;
3954 s_->logical_op = op;
3955 sis[i++] = s_;
3956 *ip = i;
3957 } else {
3958 s_->flags &= ~SCAN_PUSH;
3959 s_->logical_op = op;
3960 grn_memcpy(&sis[i], &sis[j], sizeof(scan_info *) * (r - j));
3961 grn_memmove(&sis[j], &sis[r], sizeof(scan_info *) * (i - r));
3962 grn_memcpy(&sis[i + j - r], &sis[i], sizeof(scan_info *) * (r - j));
3963 }
3964 break;
3965 }
3966 }
3967 } else {
3968 if ((op == GRN_OP_AND_NOT) || (op != s_->logical_op)) {
3969 ndifops++;
3970 }
3971 }
3972 }
3973 }
3974 if (j < 0) {
3975 ERR(GRN_INVALID_ARGUMENT, "unmatched nesting level");
3976 for (j = 0; j < i; j++) { SI_FREE(sis[j]); }
3977 GRN_FREE(sis);
3978 return NULL;
3979 }
3980 return sis;
3981}
3982
3983/* TODO: Remove me if nobody doesn't want to reuse the implementation again. */
3984#if 0
3985static const char *opstrs[] = {
3986 "PUSH",
3987 "POP",
3988 "NOP",
3989 "CALL",
3990 "INTERN",
3991 "GET_REF",
3992 "GET_VALUE",
3993 "AND",
3994 "AND_NOT",
3995 "OR",
3996 "ASSIGN",
3997 "STAR_ASSIGN",
3998 "SLASH_ASSIGN",
3999 "MOD_ASSIGN",
4000 "PLUS_ASSIGN",
4001 "MINUS_ASSIGN",
4002 "SHIFTL_ASSIGN",
4003 "SHIFTR_ASSIGN",
4004 "SHIFTRR_ASSIGN",
4005 "AND_ASSIGN",
4006 "XOR_ASSIGN",
4007 "OR_ASSIGN",
4008 "JUMP",
4009 "CJUMP",
4010 "COMMA",
4011 "BITWISE_OR",
4012 "BITWISE_XOR",
4013 "BITWISE_AND",
4014 "BITWISE_NOT",
4015 "EQUAL",
4016 "NOT_EQUAL",
4017 "LESS",
4018 "GREATER",
4019 "LESS_EQUAL",
4020 "GREATER_EQUAL",
4021 "IN",
4022 "MATCH",
4023 "NEAR",
4024 "NEAR2",
4025 "SIMILAR",
4026 "TERM_EXTRACT",
4027 "SHIFTL",
4028 "SHIFTR",
4029 "SHIFTRR",
4030 "PLUS",
4031 "MINUS",
4032 "STAR",
4033 "SLASH",
4034 "MOD",
4035 "DELETE",
4036 "INCR",
4037 "DECR",
4038 "INCR_POST",
4039 "DECR_POST",
4040 "NOT",
4041 "ADJUST",
4042 "EXACT",
4043 "LCP",
4044 "PARTIAL",
4045 "UNSPLIT",
4046 "PREFIX",
4047 "SUFFIX",
4048 "GEO_DISTANCE1",
4049 "GEO_DISTANCE2",
4050 "GEO_DISTANCE3",
4051 "GEO_DISTANCE4",
4052 "GEO_WITHINP5",
4053 "GEO_WITHINP6",
4054 "GEO_WITHINP8",
4055 "OBJ_SEARCH",
4056 "EXPR_GET_VAR",
4057 "TABLE_CREATE",
4058 "TABLE_SELECT",
4059 "TABLE_SORT",
4060 "TABLE_GROUP",
4061 "JSON_PUT"
4062};
4063
4064static void
4065put_value(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
4066{
4067 int len;
4068 char namebuf[GRN_TABLE_MAX_KEY_SIZE];
4069 if ((len = grn_column_name(ctx, obj, namebuf, GRN_TABLE_MAX_KEY_SIZE))) {
4070 GRN_TEXT_PUT(ctx, buf, namebuf, len);
4071 } else {
4072 grn_text_otoj(ctx, buf, obj, NULL);
4073 }
4074}
4075
4076static grn_rc
4077grn_expr_inspect_internal(grn_ctx *ctx, grn_obj *buf, grn_obj *expr)
4078{
4079 uint32_t i, j;
4080 grn_expr_var *var;
4081 grn_expr_code *code;
4082 grn_expr *e = (grn_expr *)expr;
4083 grn_hash *vars = grn_expr_get_vars(ctx, expr, &i);
4084 GRN_TEXT_PUTS(ctx, buf, "noname");
4085 GRN_TEXT_PUTC(ctx, buf, '(');
4086 {
4087 int i = 0;
4088 grn_obj *value;
4089 const char *name;
4090 uint32_t name_len;
4091 GRN_HASH_EACH(ctx, vars, id, &name, &name_len, &value, {
4092 if (i++) { GRN_TEXT_PUTC(ctx, buf, ','); }
4093 GRN_TEXT_PUT(ctx, buf, name, name_len);
4094 GRN_TEXT_PUTC(ctx, buf, ':');
4095 put_value(ctx, buf, value);
4096 });
4097 }
4098 GRN_TEXT_PUTC(ctx, buf, ')');
4099 GRN_TEXT_PUTC(ctx, buf, '{');
4100 for (j = 0, code = e->codes; j < e->codes_curr; j++, code++) {
4101 if (j) { GRN_TEXT_PUTC(ctx, buf, ','); }
4102 grn_text_itoa(ctx, buf, code->modify);
4103 if (code->op == GRN_OP_PUSH) {
4104 for (i = 0, var = e->vars; i < e->nvars; i++, var++) {
4105 if (&var->value == code->value) {
4106 GRN_TEXT_PUTC(ctx, buf, '?');
4107 if (var->name_size) {
4108 GRN_TEXT_PUT(ctx, buf, var->name, var->name_size);
4109 } else {
4110 grn_text_itoa(ctx, buf, (int)i);
4111 }
4112 break;
4113 }
4114 }
4115 if (i == e->nvars) {
4116 put_value(ctx, buf, code->value);
4117 }
4118 } else {
4119 if (code->value) {
4120 put_value(ctx, buf, code->value);
4121 GRN_TEXT_PUTC(ctx, buf, ' ');
4122 }
4123 GRN_TEXT_PUTS(ctx, buf, opstrs[code->op]);
4124 }
4125 }
4126 GRN_TEXT_PUTC(ctx, buf, '}');
4127 return GRN_SUCCESS;
4128}
4129
4130#define EXPRLOG(name,expr) do {\
4131 grn_obj strbuf;\
4132 GRN_TEXT_INIT(&strbuf, 0);\
4133 grn_expr_inspect_internal(ctx, &strbuf, (expr));\
4134 GRN_TEXT_PUTC(ctx, &strbuf, '\0');\
4135 GRN_LOG(ctx, GRN_LOG_NOTICE, "%s=(%s)", (name), GRN_TEXT_VALUE(&strbuf));\
4136 GRN_OBJ_FIN(ctx, &strbuf);\
4137} while (0)
4138#endif
4139
4140
4141static void
4142scan_info_put_index(grn_ctx *ctx, scan_info *si,
4143 grn_obj *index, uint32_t sid, int32_t weight,
4144 grn_obj *scorer,
4145 grn_obj *scorer_args_expr,
4146 uint32_t scorer_args_expr_offset)
4147{
4148 GRN_PTR_PUT(ctx, &si->index, index);
4149 GRN_UINT32_PUT(ctx, &si->wv, sid);
4150 GRN_INT32_PUT(ctx, &si->wv, weight);
4151 GRN_PTR_PUT(ctx, &si->scorers, scorer);
4152 GRN_PTR_PUT(ctx, &si->scorer_args_exprs, scorer_args_expr);
4153 GRN_UINT32_PUT(ctx, &si->scorer_args_expr_offsets, scorer_args_expr_offset);
4154 {
4155 int i, ni = (GRN_BULK_VSIZE(&si->index) / sizeof(grn_obj *)) - 1;
4156 grn_obj **pi = &GRN_PTR_VALUE_AT(&si->index, ni);
4157 for (i = 0; i < ni; i++, pi--) {
4158 if (index == pi[-1]) {
4159 if (i) {
4160 int32_t *pw = &GRN_INT32_VALUE_AT(&si->wv, (ni - i) * 2);
4161 grn_memmove(pw + 2, pw, sizeof(int32_t) * 2 * i);
4162 pw[0] = (int32_t) sid;
4163 pw[1] = weight;
4164 grn_memmove(pi + 1, pi, sizeof(grn_obj *) * i);
4165 pi[0] = index;
4166 }
4167 return;
4168 }
4169 }
4170 }
4171}
4172
4173static int32_t
4174get_weight(grn_ctx *ctx, grn_expr_code *ec, uint32_t *offset)
4175{
4176 if (ec->modify == 2 && ec[2].op == GRN_OP_STAR &&
4177 ec[1].value && ec[1].value->header.type == GRN_BULK) {
4178 if (offset) {
4179 *offset = 2;
4180 }
4181 if (ec[1].value->header.domain == GRN_DB_INT32 ||
4182 ec[1].value->header.domain == GRN_DB_UINT32) {
4183 return GRN_INT32_VALUE(ec[1].value);
4184 } else {
4185 int32_t weight = 1;
4186 grn_obj weight_buffer;
4187 GRN_INT32_INIT(&weight_buffer, 0);
4188 if (!grn_obj_cast(ctx, ec[1].value, &weight_buffer, GRN_FALSE)) {
4189 weight = GRN_INT32_VALUE(&weight_buffer);
4190 }
4191 grn_obj_unlink(ctx, &weight_buffer);
4192 return weight;
4193 }
4194 } else {
4195 if (offset) {
4196 *offset = 0;
4197 }
4198 return 1;
4199 }
4200}
4201
4202scan_info *
4203grn_scan_info_open(grn_ctx *ctx, int start)
4204{
4205 scan_info *si = GRN_MALLOCN(scan_info, 1);
4206
4207 if (!si) {
4208 return NULL;
4209 }
4210
4211 GRN_INT32_INIT(&si->wv, GRN_OBJ_VECTOR);
4212 GRN_PTR_INIT(&si->index, GRN_OBJ_VECTOR, GRN_ID_NIL);
4213 si->logical_op = GRN_OP_OR;
4214 si->flags = SCAN_PUSH;
4215 si->nargs = 0;
4216 si->max_interval = DEFAULT_MAX_INTERVAL;
4217 si->similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD;
4218 si->start = start;
4219 GRN_PTR_INIT(&si->scorers, GRN_OBJ_VECTOR, GRN_ID_NIL);
4220 GRN_PTR_INIT(&si->scorer_args_exprs, GRN_OBJ_VECTOR, GRN_ID_NIL);
4221 GRN_UINT32_INIT(&si->scorer_args_expr_offsets, GRN_OBJ_VECTOR);
4222 si->position.specified = GRN_FALSE;
4223 si->position.start = 0;
4224
4225 return si;
4226}
4227
4228void
4229grn_scan_info_close(grn_ctx *ctx, scan_info *si)
4230{
4231 SI_FREE(si);
4232}
4233
4234void
4235grn_scan_info_put_index(grn_ctx *ctx, scan_info *si,
4236 grn_obj *index, uint32_t sid, int32_t weight,
4237 grn_obj *scorer,
4238 grn_obj *scorer_args_expr,
4239 uint32_t scorer_args_expr_offset)
4240{
4241 scan_info_put_index(ctx, si, index, sid, weight,
4242 scorer,
4243 scorer_args_expr,
4244 scorer_args_expr_offset);
4245}
4246
4247scan_info **
4248grn_scan_info_put_logical_op(grn_ctx *ctx, scan_info **sis, int *ip,
4249 grn_operator op, int start)
4250{
4251 return put_logical_op(ctx, sis, ip, op, start);
4252}
4253
4254int32_t
4255grn_expr_code_get_weight(grn_ctx *ctx, grn_expr_code *ec, uint32_t *offset)
4256{
4257 return get_weight(ctx, ec, offset);
4258}
4259
4260int
4261grn_scan_info_get_flags(scan_info *si)
4262{
4263 return si->flags;
4264}
4265
4266void
4267grn_scan_info_set_flags(scan_info *si, int flags)
4268{
4269 si->flags = flags;
4270}
4271
4272grn_operator
4273grn_scan_info_get_logical_op(scan_info *si)
4274{
4275 return si->logical_op;
4276}
4277
4278void
4279grn_scan_info_set_logical_op(scan_info *si, grn_operator logical_op)
4280{
4281 si->logical_op = logical_op;
4282}
4283
4284grn_operator
4285grn_scan_info_get_op(scan_info *si)
4286{
4287 return si->op;
4288}
4289
4290void
4291grn_scan_info_set_op(scan_info *si, grn_operator op)
4292{
4293 si->op = op;
4294}
4295
4296void
4297grn_scan_info_set_end(scan_info *si, uint32_t end)
4298{
4299 si->end = end;
4300}
4301
4302void
4303grn_scan_info_set_query(scan_info *si, grn_obj *query)
4304{
4305 si->query = query;
4306}
4307
4308int
4309grn_scan_info_get_max_interval(scan_info *si)
4310{
4311 return si->max_interval;
4312}
4313
4314void
4315grn_scan_info_set_max_interval(scan_info *si, int max_interval)
4316{
4317 si->max_interval = max_interval;
4318}
4319
4320int
4321grn_scan_info_get_similarity_threshold(scan_info *si)
4322{
4323 return si->similarity_threshold;
4324}
4325
4326void
4327grn_scan_info_set_similarity_threshold(scan_info *si, int similarity_threshold)
4328{
4329 si->similarity_threshold = similarity_threshold;
4330}
4331
4332grn_bool
4333grn_scan_info_push_arg(scan_info *si, grn_obj *arg)
4334{
4335 if (si->nargs >= GRN_SCAN_INFO_MAX_N_ARGS) {
4336 return GRN_FALSE;
4337 }
4338
4339 si->args[si->nargs++] = arg;
4340 return GRN_TRUE;
4341}
4342
4343grn_obj *
4344grn_scan_info_get_arg(grn_ctx *ctx, scan_info *si, int i)
4345{
4346 if (i >= si->nargs) {
4347 return NULL;
4348 }
4349 return si->args[i];
4350}
4351
4352int
4353grn_scan_info_get_start_position(scan_info *si)
4354{
4355 return si->position.start;
4356}
4357
4358void
4359grn_scan_info_set_start_position(scan_info *si, int start)
4360{
4361 si->position.specified = GRN_TRUE;
4362 si->position.start = start;
4363}
4364
4365void
4366grn_scan_info_reset_position(scan_info *si)
4367{
4368 si->position.specified = GRN_FALSE;
4369}
4370
4371static uint32_t
4372scan_info_build_match_expr_codes_find_index(grn_ctx *ctx, scan_info *si,
4373 grn_expr *expr, uint32_t i,
4374 grn_obj **index,
4375 int *sid)
4376{
4377 grn_expr_code *ec;
4378 uint32_t offset = 1;
4379 grn_index_datum index_datum;
4380 unsigned int n_index_data = 0;
4381
4382 ec = &(expr->codes[i]);
4383 switch (ec->value->header.type) {
4384 case GRN_ACCESSOR :
4385 n_index_data = grn_column_find_index_data(ctx, ec->value, si->op,
4386 &index_datum, 1);
4387 if (n_index_data > 0) {
4388 grn_accessor *a = (grn_accessor *)(ec->value);
4389 *sid = index_datum.section;
4390 if (a->next && a->obj != index_datum.index) {
4391 *index = ec->value;
4392 } else {
4393 *index = index_datum.index;
4394 }
4395 }
4396 break;
4397 case GRN_COLUMN_FIX_SIZE :
4398 case GRN_COLUMN_VAR_SIZE :
4399 n_index_data = grn_column_find_index_data(ctx, ec->value, si->op,
4400 &index_datum, 1);
4401 if (n_index_data > 0) {
4402 *index = index_datum.index;
4403 *sid = index_datum.section;
4404 }
4405 break;
4406 case GRN_COLUMN_INDEX :
4407 {
4408 uint32_t n_rest_codes;
4409
4410 *index = ec->value;
4411
4412 n_rest_codes = expr->codes_curr - i;
4413 if (n_rest_codes >= 2 &&
4414 ec[1].value &&
4415 (ec[1].value->header.domain == GRN_DB_INT32 ||
4416 ec[1].value->header.domain == GRN_DB_UINT32) &&
4417 ec[2].op == GRN_OP_GET_MEMBER) {
4418 if (ec[1].value->header.domain == GRN_DB_INT32) {
4419 *sid = GRN_INT32_VALUE(ec[1].value) + 1;
4420 } else {
4421 *sid = GRN_UINT32_VALUE(ec[1].value) + 1;
4422 }
4423 offset += 2;
4424 }
4425 }
4426 break;
4427 default :
4428 break;
4429 }
4430
4431 return offset;
4432}
4433
4434static uint32_t
4435scan_info_build_match_expr_codes(grn_ctx *ctx,
4436 scan_info *si,
4437 grn_expr *expr,
4438 uint32_t i,
4439 int32_t weight)
4440{
4441 grn_expr_code *ec;
4442 grn_obj *index = NULL;
4443 int sid = 0;
4444 uint32_t offset = 0;
4445
4446 ec = &(expr->codes[i]);
4447 if (!ec->value) {
4448 return i + 1;
4449 }
4450
4451 switch (ec->value->header.type) {
4452 case GRN_ACCESSOR :
4453 case GRN_COLUMN_FIX_SIZE :
4454 case GRN_COLUMN_VAR_SIZE :
4455 case GRN_COLUMN_INDEX :
4456 offset = scan_info_build_match_expr_codes_find_index(ctx, si, expr, i,
4457 &index, &sid);
4458 i += offset - 1;
4459 if (index) {
4460 if (ec->value->header.type == GRN_ACCESSOR) {
4461 si->flags |= SCAN_ACCESSOR;
4462 }
4463 scan_info_put_index(ctx, si, index, sid,
4464 get_weight(ctx, &(expr->codes[i]), &offset) + weight,
4465 NULL, NULL, 0);
4466 i += offset;
4467 }
4468 break;
4469 case GRN_PROC :
4470 if (!grn_obj_is_scorer_proc(ctx, ec->value)) {
4471 grn_obj inspected;
4472 GRN_TEXT_INIT(&inspected, 0);
4473 grn_inspect(ctx, &inspected, ec->value);
4474 ERR(GRN_INVALID_ARGUMENT,
4475 "procedure must be scorer: <%.*s>",
4476 (int)GRN_TEXT_LEN(&inspected),
4477 GRN_TEXT_VALUE(&inspected));
4478 GRN_OBJ_FIN(ctx, &inspected);
4479 return expr->codes_curr;
4480 }
4481 i++;
4482 offset = scan_info_build_match_expr_codes_find_index(ctx, si, expr, i,
4483 &index, &sid);
4484 i += offset;
4485 if (index) {
4486 uint32_t scorer_args_expr_offset = 0;
4487 if (expr->codes[i].op != GRN_OP_CALL) {
4488 scorer_args_expr_offset = i;
4489 }
4490 while (i < expr->codes_curr && expr->codes[i].op != GRN_OP_CALL) {
4491 i++;
4492 }
4493 scan_info_put_index(ctx, si, index, sid,
4494 get_weight(ctx, &(expr->codes[i]), &offset) + weight,
4495 ec->value,
4496 (grn_obj *)expr,
4497 scorer_args_expr_offset);
4498 i += offset;
4499 }
4500 break;
4501 default :
4502 {
4503 char name[GRN_TABLE_MAX_KEY_SIZE];
4504 int name_size;
4505 name_size = grn_obj_name(ctx, ec->value, name, GRN_TABLE_MAX_KEY_SIZE);
4506 ERR(GRN_INVALID_ARGUMENT,
4507 "invalid match target: <%.*s>",
4508 name_size, name);
4509 return expr->codes_curr;
4510 }
4511 break;
4512 }
4513
4514 return i + 1;
4515}
4516
4517static void
4518scan_info_build_match_expr(grn_ctx *ctx,
4519 scan_info *si,
4520 grn_expr *expr,
4521 int32_t weight)
4522{
4523 uint32_t i;
4524 i = 0;
4525 while (i < expr->codes_curr) {
4526 i = scan_info_build_match_expr_codes(ctx, si, expr, i, weight);
4527 }
4528}
4529
4530static grn_bool
4531is_index_searchable_regexp(grn_ctx *ctx, grn_obj *regexp)
4532{
4533 const char *regexp_raw;
4534 const char *regexp_raw_end;
4535 grn_bool escaping = GRN_FALSE;
4536 grn_bool dot = GRN_FALSE;
4537
4538 if (!(regexp->header.domain == GRN_DB_SHORT_TEXT ||
4539 regexp->header.domain == GRN_DB_TEXT ||
4540 regexp->header.domain == GRN_DB_LONG_TEXT)) {
4541 return GRN_FALSE;
4542 }
4543
4544 regexp_raw = GRN_TEXT_VALUE(regexp);
4545 regexp_raw_end = regexp_raw + GRN_TEXT_LEN(regexp);
4546
4547 while (regexp_raw < regexp_raw_end) {
4548 unsigned int char_len;
4549
4550 char_len = grn_charlen(ctx, regexp_raw, regexp_raw_end);
4551 if (char_len == 0) {
4552 return GRN_FALSE;
4553 }
4554
4555 if (char_len == 1) {
4556 if (escaping) {
4557 escaping = GRN_FALSE;
4558 switch (regexp_raw[0]) {
4559 case 'Z' :
4560 case 'b' :
4561 case 'B' :
4562 case 'd' :
4563 case 'D' :
4564 case 'h' :
4565 case 'H' :
4566 case 'p' :
4567 case 's' :
4568 case 'S' :
4569 case 'w' :
4570 case 'W' :
4571 case 'X' :
4572 case 'k' :
4573 case 'g' :
4574 case '1' :
4575 case '2' :
4576 case '3' :
4577 case '4' :
4578 case '5' :
4579 case '6' :
4580 case '7' :
4581 case '8' :
4582 case '9' :
4583 return GRN_FALSE;
4584 default :
4585 break;
4586 }
4587 } else {
4588 switch (regexp_raw[0]) {
4589 case '.' :
4590 escaping = GRN_FALSE;
4591 if (dot) {
4592 return GRN_FALSE;
4593 }
4594 dot = GRN_TRUE;
4595 break;
4596 case '*' :
4597 escaping = GRN_FALSE;
4598 if (!dot) {
4599 return GRN_FALSE;
4600 }
4601 if (!grn_scan_info_regexp_dot_asterisk_enable) {
4602 return GRN_FALSE;
4603 }
4604 dot = GRN_FALSE;
4605 break;
4606 case '[' :
4607 case ']' :
4608 case '|' :
4609 case '?' :
4610 case '+' :
4611 case '{' :
4612 case '}' :
4613 case '^' :
4614 case '$' :
4615 case '(' :
4616 case ')' :
4617 escaping = GRN_FALSE;
4618 return GRN_FALSE;
4619 case '\\' :
4620 if (dot) {
4621 return GRN_FALSE;
4622 }
4623 escaping = GRN_TRUE;
4624 break;
4625 default :
4626 if (dot) {
4627 return GRN_FALSE;
4628 }
4629 escaping = GRN_FALSE;
4630 break;
4631 }
4632 }
4633 } else {
4634 escaping = GRN_FALSE;
4635 }
4636
4637 regexp_raw += char_len;
4638 }
4639
4640 return GRN_TRUE;
4641}
4642
4643static void
4644scan_info_build_match(grn_ctx *ctx, scan_info *si, int32_t weight)
4645{
4646 grn_obj **p, **pe;
4647
4648 if (si->op == GRN_OP_REGEXP) {
4649 p = si->args;
4650 pe = si->args + si->nargs;
4651 for (; p < pe; p++) {
4652 if ((*p)->header.type == GRN_BULK &&
4653 !is_index_searchable_regexp(ctx, *p)) {
4654 return;
4655 }
4656 }
4657 }
4658
4659 p = si->args;
4660 pe = si->args + si->nargs;
4661 for (; p < pe; p++) {
4662 if ((*p)->header.type == GRN_EXPR) {
4663 scan_info_build_match_expr(ctx, si, (grn_expr *)(*p), weight);
4664 } else if ((*p)->header.type == GRN_COLUMN_INDEX) {
4665 scan_info_put_index(ctx, si, *p, 0, 1 + weight, NULL, NULL, 0);
4666 } else if (grn_obj_is_proc(ctx, *p)) {
4667 break;
4668 } else if (GRN_DB_OBJP(*p)) {
4669 grn_index_datum index_datum;
4670 unsigned int n_index_data;
4671 n_index_data = grn_column_find_index_data(ctx, *p, si->op,
4672 &index_datum, 1);
4673 if (n_index_data > 0) {
4674 scan_info_put_index(ctx, si,
4675 index_datum.index, index_datum.section, 1 + weight,
4676 NULL, NULL, 0);
4677 }
4678 } else if (GRN_ACCESSORP(*p)) {
4679 grn_index_datum index_datum;
4680 unsigned int n_index_data;
4681 si->flags |= SCAN_ACCESSOR;
4682 n_index_data = grn_column_find_index_data(ctx, *p, si->op,
4683 &index_datum, 1);
4684 if (n_index_data > 0) {
4685 grn_obj *index;
4686 if (((grn_accessor *)(*p))->next) {
4687 index = *p;
4688 } else {
4689 index = index_datum.index;
4690 }
4691 scan_info_put_index(ctx, si,
4692 index, index_datum.section, 1 + weight,
4693 NULL, NULL, 0);
4694 }
4695 } else {
4696 switch (si->op) {
4697 case GRN_OP_NEAR :
4698 case GRN_OP_NEAR2 :
4699 if (si->nargs == 3 &&
4700 *p == si->args[2] &&
4701 (*p)->header.domain == GRN_DB_INT32) {
4702 si->max_interval = GRN_INT32_VALUE(*p);
4703 } else {
4704 si->query = *p;
4705 }
4706 break;
4707 case GRN_OP_SIMILAR :
4708 if (si->nargs == 3 &&
4709 *p == si->args[2] &&
4710 (*p)->header.domain == GRN_DB_INT32) {
4711 si->similarity_threshold = GRN_INT32_VALUE(*p);
4712 } else {
4713 si->query = *p;
4714 }
4715 break;
4716 default :
4717 si->query = *p;
4718 break;
4719 }
4720 }
4721 }
4722}
4723
4724static grn_bool
4725grn_scan_info_build_full_not(grn_ctx *ctx,
4726 scan_info **sis,
4727 int *i,
4728 grn_expr_code *codes,
4729 grn_expr_code *code,
4730 grn_expr_code *code_end,
4731 grn_operator *next_code_op)
4732{
4733 scan_info *last_si;
4734
4735 if (*i == 0) {
4736 return GRN_TRUE;
4737 }
4738
4739 last_si = sis[*i - 1];
4740 switch (last_si->op) {
4741 case GRN_OP_LESS :
4742 last_si->op = GRN_OP_GREATER_EQUAL;
4743 last_si->end++;
4744 break;
4745 case GRN_OP_LESS_EQUAL :
4746 last_si->op = GRN_OP_GREATER;
4747 last_si->end++;
4748 break;
4749 case GRN_OP_GREATER :
4750 last_si->op = GRN_OP_LESS_EQUAL;
4751 last_si->end++;
4752 break;
4753 case GRN_OP_GREATER_EQUAL :
4754 last_si->op = GRN_OP_LESS;
4755 last_si->end++;
4756 break;
4757 case GRN_OP_NOT_EQUAL :
4758 last_si->op = GRN_OP_EQUAL;
4759 last_si->end++;
4760 break;
4761 default :
4762 if (*i == 1) {
4763 if (GRN_BULK_VSIZE(&(last_si->index)) > 0) {
4764 scan_info *all_records_si = NULL;
4765 SI_ALLOC_RAW(all_records_si, 0);
4766 if (!all_records_si) {
4767 return GRN_FALSE;
4768 }
4769 all_records_si->op = GRN_OP_CALL;
4770 all_records_si->args[all_records_si->nargs++] =
4771 grn_ctx_get(ctx, "all_records", -1);
4772 last_si->logical_op = GRN_OP_AND_NOT;
4773 last_si->flags &= ~SCAN_PUSH;
4774 sis[*i] = sis[*i - 1];
4775 sis[*i - 1] = all_records_si;
4776 (*i)++;
4777 } else {
4778 if (last_si->op == GRN_OP_EQUAL) {
4779 last_si->op = GRN_OP_NOT_EQUAL;
4780 last_si->end++;
4781 } else {
4782 return GRN_FALSE;
4783 }
4784 }
4785 } else {
4786 grn_expr_code *next_code = code + 1;
4787
4788 if (next_code >= code_end) {
4789 return GRN_FALSE;
4790 }
4791
4792 switch (next_code->op) {
4793 case GRN_OP_AND :
4794 *next_code_op = GRN_OP_AND_NOT;
4795 break;
4796 case GRN_OP_AND_NOT :
4797 *next_code_op = GRN_OP_AND;
4798 break;
4799 case GRN_OP_OR :
4800 {
4801 scan_info *all_records_si = NULL;
4802 SI_ALLOC_RAW(all_records_si, 0);
4803 if (!all_records_si) {
4804 return GRN_FALSE;
4805 }
4806 all_records_si->op = GRN_OP_CALL;
4807 all_records_si->args[all_records_si->nargs++] =
4808 grn_ctx_get(ctx, "all_records", -1);
4809 sis[*i] = sis[*i - 1];
4810 sis[*i - 1] = all_records_si;
4811 (*i)++;
4812 put_logical_op(ctx, sis, i, GRN_OP_AND_NOT, code - codes);
4813 }
4814 break;
4815 default :
4816 return GRN_FALSE;
4817 break;
4818 }
4819 }
4820 }
4821
4822 return GRN_TRUE;
4823}
4824
4825static scan_info **
4826grn_scan_info_build_full(grn_ctx *ctx, grn_obj *expr, int *n,
4827 grn_operator op, grn_bool record_exist)
4828{
4829 grn_obj *var;
4830 scan_stat stat;
4831 int i, m = 0, o = 0;
4832 int n_nots = 0;
4833 scan_info **sis, *si = NULL;
4834 grn_expr_code *c, *ce;
4835 grn_expr *e = (grn_expr *)expr;
4836 grn_operator next_code_op;
4837
4838 if (!(var = grn_expr_get_var_by_offset(ctx, expr, 0))) { return NULL; }
4839 for (stat = SCAN_START, c = e->codes, ce = &e->codes[e->codes_curr]; c < ce; c++) {
4840 switch (c->op) {
4841 case GRN_OP_MATCH :
4842 case GRN_OP_NEAR :
4843 case GRN_OP_NEAR2 :
4844 case GRN_OP_SIMILAR :
4845 case GRN_OP_PREFIX :
4846 case GRN_OP_SUFFIX :
4847 case GRN_OP_EQUAL :
4848 case GRN_OP_NOT_EQUAL :
4849 case GRN_OP_LESS :
4850 case GRN_OP_GREATER :
4851 case GRN_OP_LESS_EQUAL :
4852 case GRN_OP_GREATER_EQUAL :
4853 case GRN_OP_GEO_WITHINP5 :
4854 case GRN_OP_GEO_WITHINP6 :
4855 case GRN_OP_GEO_WITHINP8 :
4856 case GRN_OP_TERM_EXTRACT :
4857 case GRN_OP_REGEXP :
4858 if (stat < SCAN_COL1 || SCAN_CONST < stat) { return NULL; }
4859 stat = SCAN_START;
4860 m++;
4861 break;
4862 case GRN_OP_BITWISE_OR :
4863 case GRN_OP_BITWISE_XOR :
4864 case GRN_OP_BITWISE_AND :
4865 case GRN_OP_BITWISE_NOT :
4866 case GRN_OP_SHIFTL :
4867 case GRN_OP_SHIFTR :
4868 case GRN_OP_SHIFTRR :
4869 case GRN_OP_PLUS :
4870 case GRN_OP_MINUS :
4871 case GRN_OP_STAR :
4872 case GRN_OP_MOD :
4873 if (stat < SCAN_COL1 || SCAN_CONST < stat) { return NULL; }
4874 stat = SCAN_START;
4875 if (m != o + 1) { return NULL; }
4876 break;
4877 case GRN_OP_AND :
4878 case GRN_OP_OR :
4879 case GRN_OP_AND_NOT :
4880 case GRN_OP_ADJUST :
4881 switch (stat) {
4882 case SCAN_START :
4883 o++;
4884 if (o >= m) { return NULL; }
4885 break;
4886 case SCAN_CONST :
4887 o++;
4888 m++;
4889 if (o >= m) { return NULL; }
4890 stat = SCAN_START;
4891 break;
4892 default :
4893 return NULL;
4894 break;
4895 }
4896 break;
4897 case GRN_OP_PUSH :
4898 {
4899 grn_bool is_completed_term = GRN_FALSE;
4900 if (c->modify > 0) {
4901 switch ((c + c->modify)->op) {
4902 case GRN_OP_AND :
4903 case GRN_OP_OR :
4904 case GRN_OP_AND_NOT :
4905 case GRN_OP_ADJUST :
4906 is_completed_term = GRN_TRUE;
4907 break;
4908 default :
4909 is_completed_term = GRN_FALSE;
4910 break;
4911 }
4912 }
4913 if (is_completed_term) {
4914 m++;
4915 stat = SCAN_START;
4916 } else {
4917 stat = (c->value == var) ? SCAN_VAR : SCAN_CONST;
4918 }
4919 }
4920 break;
4921 case GRN_OP_GET_VALUE :
4922 switch (stat) {
4923 case SCAN_START :
4924 case SCAN_CONST :
4925 case SCAN_VAR :
4926 stat = SCAN_COL1;
4927 break;
4928 case SCAN_COL1 :
4929 stat = SCAN_COL2;
4930 break;
4931 case SCAN_COL2 :
4932 break;
4933 default :
4934 return NULL;
4935 break;
4936 }
4937 break;
4938 case GRN_OP_CALL :
4939 if ((c->flags & GRN_EXPR_CODE_RELATIONAL_EXPRESSION) || c + 1 == ce) {
4940 stat = SCAN_START;
4941 m++;
4942 } else {
4943 stat = SCAN_COL2;
4944 }
4945 break;
4946 case GRN_OP_GET_REF :
4947 switch (stat) {
4948 case SCAN_START :
4949 stat = SCAN_COL1;
4950 break;
4951 default :
4952 return NULL;
4953 break;
4954 }
4955 break;
4956 case GRN_OP_GET_MEMBER :
4957 switch (stat) {
4958 case SCAN_CONST :
4959 {
4960 grn_expr_code *prev_c = c - 1;
4961 if (prev_c->value->header.domain < GRN_DB_INT8 ||
4962 prev_c->value->header.domain > GRN_DB_UINT64) {
4963 return NULL;
4964 }
4965 }
4966 stat = SCAN_COL1;
4967 break;
4968 default :
4969 return NULL;
4970 break;
4971 }
4972 break;
4973 case GRN_OP_NOT :
4974 n_nots++;
4975 break;
4976 default :
4977 return NULL;
4978 break;
4979 }
4980 }
4981 if (stat || m != o + 1) { return NULL; }
4982 if (!(sis = GRN_MALLOCN(scan_info *, m + m + o + n_nots))) { return NULL; }
4983
4984 next_code_op = -1;
4985 for (i = 0, stat = SCAN_START, c = e->codes, ce = &e->codes[e->codes_curr]; c < ce; c++) {
4986 grn_operator code_op;
4987 if (next_code_op == -1) {
4988 code_op = c->op;
4989 } else {
4990 code_op = next_code_op;
4991 next_code_op = -1;
4992 }
4993 switch (code_op) {
4994 case GRN_OP_MATCH :
4995 case GRN_OP_NEAR :
4996 case GRN_OP_NEAR2 :
4997 case GRN_OP_SIMILAR :
4998 case GRN_OP_PREFIX :
4999 case GRN_OP_SUFFIX :
5000 case GRN_OP_EQUAL :
5001 case GRN_OP_NOT_EQUAL :
5002 case GRN_OP_LESS :
5003 case GRN_OP_GREATER :
5004 case GRN_OP_LESS_EQUAL :
5005 case GRN_OP_GREATER_EQUAL :
5006 case GRN_OP_GEO_WITHINP5 :
5007 case GRN_OP_GEO_WITHINP6 :
5008 case GRN_OP_GEO_WITHINP8 :
5009 case GRN_OP_TERM_EXTRACT :
5010 case GRN_OP_REGEXP :
5011 stat = SCAN_START;
5012 si->op = code_op;
5013 si->end = c - e->codes;
5014 sis[i++] = si;
5015 {
5016 int32_t weight = 0;
5017 if (c->value && c->value->header.domain == GRN_DB_INT32) {
5018 weight = GRN_INT32_VALUE(c->value);
5019 }
5020 scan_info_build_match(ctx, si, weight);
5021 }
5022 if (ctx->rc != GRN_SUCCESS) {
5023 int j;
5024 for (j = 0; j < i; j++) { SI_FREE(sis[j]); }
5025 GRN_FREE(sis);
5026 return NULL;
5027 }
5028 si = NULL;
5029 break;
5030 case GRN_OP_AND :
5031 case GRN_OP_OR :
5032 case GRN_OP_AND_NOT :
5033 case GRN_OP_ADJUST :
5034 if (stat == SCAN_CONST) {
5035 si->op = GRN_OP_PUSH;
5036 si->end = si->start;
5037 sis[i++] = si;
5038 si = NULL;
5039 }
5040 if (!put_logical_op(ctx, sis, &i, code_op, c - e->codes)) { return NULL; }
5041 stat = SCAN_START;
5042 break;
5043 case GRN_OP_PUSH :
5044 if (!si) { SI_ALLOC(si, i, c - e->codes); }
5045 if (c->value == var) {
5046 stat = SCAN_VAR;
5047 } else {
5048 if (si->nargs < GRN_SCAN_INFO_MAX_N_ARGS) {
5049 si->args[si->nargs++] = c->value;
5050 }
5051 if (stat == SCAN_START) { si->flags |= SCAN_PRE_CONST; }
5052 stat = SCAN_CONST;
5053 }
5054 if (c->modify > 0) {
5055 grn_bool is_completed_term = GRN_FALSE;
5056 switch ((c + c->modify)->op) {
5057 case GRN_OP_AND :
5058 case GRN_OP_OR :
5059 case GRN_OP_AND_NOT :
5060 case GRN_OP_ADJUST :
5061 is_completed_term = GRN_TRUE;
5062 break;
5063 default :
5064 is_completed_term = GRN_FALSE;
5065 break;
5066 }
5067 if (is_completed_term) {
5068 si->op = GRN_OP_PUSH;
5069 si->end = si->start;
5070 sis[i++] = si;
5071 si = NULL;
5072 stat = SCAN_START;
5073 }
5074 }
5075 break;
5076 case GRN_OP_GET_VALUE :
5077 switch (stat) {
5078 case SCAN_START :
5079 if (!si) { SI_ALLOC(si, i, c - e->codes); }
5080 // fallthru
5081 case SCAN_CONST :
5082 case SCAN_VAR :
5083 stat = SCAN_COL1;
5084 if (si->nargs < GRN_SCAN_INFO_MAX_N_ARGS) {
5085 si->args[si->nargs++] = c->value;
5086 }
5087 break;
5088 case SCAN_COL1 :
5089 {
5090 int j;
5091 grn_obj inspected;
5092 GRN_TEXT_INIT(&inspected, 0);
5093 GRN_TEXT_PUTS(ctx, &inspected, "<");
5094 grn_inspect_name(ctx, &inspected, c->value);
5095 GRN_TEXT_PUTS(ctx, &inspected, ">: <");
5096 grn_inspect(ctx, &inspected, expr);
5097 GRN_TEXT_PUTS(ctx, &inspected, ">");
5098 ERR(GRN_INVALID_ARGUMENT,
5099 "invalid expression: can't use column as a value: %.*s",
5100 (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected));
5101 GRN_OBJ_FIN(ctx, &inspected);
5102 SI_FREE(si);
5103 for (j = 0; j < i; j++) { SI_FREE(sis[j]); }
5104 GRN_FREE(sis);
5105 return NULL;
5106 }
5107 stat = SCAN_COL2;
5108 break;
5109 case SCAN_COL2 :
5110 break;
5111 default :
5112 break;
5113 }
5114 break;
5115 case GRN_OP_CALL :
5116 if (!si) { SI_ALLOC(si, i, c - e->codes); }
5117 if ((c->flags & GRN_EXPR_CODE_RELATIONAL_EXPRESSION) || c + 1 == ce) {
5118 stat = SCAN_START;
5119 si->op = code_op;
5120 si->end = c - e->codes;
5121 sis[i++] = si;
5122 /* better index resolving framework for functions should be implemented */
5123 if (grn_obj_is_selector_proc(ctx, si->args[0])) {
5124 grn_obj *selector;
5125 grn_obj **p;
5126 grn_obj **pe;
5127 grn_operator selector_op;
5128
5129 selector = si->args[0];
5130 p = si->args + 1;
5131 pe = si->args + si->nargs;
5132 selector_op = grn_proc_get_selector_operator(ctx, selector);
5133 for (; p < pe; p++) {
5134 if (GRN_DB_OBJP(*p)) {
5135 grn_index_datum index_datum;
5136 unsigned int n_index_data;
5137 n_index_data = grn_column_find_index_data(ctx, *p, selector_op,
5138 &index_datum, 1);
5139 if (n_index_data > 0) {
5140 scan_info_put_index(ctx, si,
5141 index_datum.index, index_datum.section, 1,
5142 NULL, NULL, 0);
5143 }
5144 } else if (GRN_ACCESSORP(*p)) {
5145 grn_index_datum index_datum;
5146 unsigned int n_index_data;
5147 si->flags |= SCAN_ACCESSOR;
5148 n_index_data = grn_column_find_index_data(ctx, *p, selector_op,
5149 &index_datum, 1);
5150 if (n_index_data > 0) {
5151 scan_info_put_index(ctx, si,
5152 index_datum.index, index_datum.section, 1,
5153 NULL, NULL, 0);
5154 }
5155 } else {
5156 si->query = *p;
5157 }
5158 }
5159 }
5160 si = NULL;
5161 } else {
5162 stat = SCAN_COL2;
5163 }
5164 break;
5165 case GRN_OP_GET_REF :
5166 switch (stat) {
5167 case SCAN_START :
5168 if (!si) { SI_ALLOC(si, i, c - e->codes); }
5169 stat = SCAN_COL1;
5170 if (si->nargs < GRN_SCAN_INFO_MAX_N_ARGS) {
5171 si->args[si->nargs++] = c->value;
5172 }
5173 break;
5174 default :
5175 break;
5176 }
5177 break;
5178 case GRN_OP_GET_MEMBER :
5179 {
5180 grn_obj *start_position;
5181 grn_obj buffer;
5182 start_position = si->args[--si->nargs];
5183 GRN_INT32_INIT(&buffer, 0);
5184 grn_obj_cast(ctx, start_position, &buffer, GRN_FALSE);
5185 grn_scan_info_set_start_position(si, GRN_INT32_VALUE(&buffer));
5186 GRN_OBJ_FIN(ctx, &buffer);
5187 }
5188 stat = SCAN_COL1;
5189 break;
5190 case GRN_OP_NOT :
5191 {
5192 grn_bool valid;
5193 valid = grn_scan_info_build_full_not(ctx,
5194 sis,
5195 &i,
5196 e->codes,
5197 c,
5198 ce,
5199 &next_code_op);
5200 if (!valid) {
5201 int j;
5202 for (j = 0; j < i; j++) {
5203 SI_FREE(sis[j]);
5204 }
5205 GRN_FREE(sis);
5206 return NULL;
5207 }
5208 }
5209 break;
5210 default :
5211 break;
5212 }
5213 }
5214 if (op == GRN_OP_OR && !record_exist) {
5215 // for debug
5216 if (!(sis[0]->flags & SCAN_PUSH) || (sis[0]->logical_op != op)) {
5217 int j;
5218 ERR(GRN_INVALID_ARGUMENT, "invalid expr");
5219 for (j = 0; j < i; j++) { SI_FREE(sis[j]); }
5220 GRN_FREE(sis);
5221 return NULL;
5222 } else {
5223 sis[0]->flags &= ~SCAN_PUSH;
5224 sis[0]->logical_op = op;
5225 }
5226 } else {
5227 if (!put_logical_op(ctx, sis, &i, op, c - e->codes)) { return NULL; }
5228 }
5229 *n = i;
5230 return sis;
5231}
5232
5233static scan_info **
5234grn_scan_info_build_simple_open(grn_ctx *ctx, int *n, grn_operator logical_op)
5235{
5236 scan_info **sis;
5237 scan_info *si;
5238
5239 sis = GRN_MALLOCN(scan_info *, 1);
5240 if (!sis) {
5241 ERR(GRN_NO_MEMORY_AVAILABLE,
5242 "[scan_info][build] failed to allocate memory for scan_info **");
5243 return NULL;
5244 }
5245
5246 si = grn_scan_info_open(ctx, 0);
5247 if (!si) {
5248 ERR(GRN_NO_MEMORY_AVAILABLE,
5249 "[scan_info][build] failed to allocate memory for scan_info *");
5250 GRN_FREE(sis);
5251 return NULL;
5252 }
5253
5254 si->flags &= ~SCAN_PUSH;
5255 si->logical_op = logical_op;
5256
5257 sis[0] = si;
5258 *n = 1;
5259
5260 return sis;
5261}
5262
5263static scan_info **
5264grn_scan_info_build_simple_value(grn_ctx *ctx,
5265 grn_obj *expr,
5266 int *n,
5267 grn_operator logical_op,
5268 grn_bool record_exist)
5269{
5270 grn_expr *e = (grn_expr *)expr;
5271 scan_info **sis;
5272 scan_info *si;
5273 grn_expr_code *target = e->codes;
5274
5275 switch (target->op) {
5276 case GRN_OP_PUSH :
5277 case GRN_OP_GET_VALUE :
5278 break;
5279 default :
5280 return NULL;
5281 break;
5282 }
5283
5284 sis = grn_scan_info_build_simple_open(ctx, n, logical_op);
5285 if (!sis) {
5286 return NULL;
5287 }
5288
5289 si = sis[0];
5290 si->end = 0;
5291 si->op = target->op;
5292 return sis;
5293}
5294
5295static scan_info **
5296grn_scan_info_build_simple_operation(grn_ctx *ctx,
5297 grn_obj *expr,
5298 int *n,
5299 grn_operator logical_op,
5300 grn_bool record_exist)
5301{
5302 grn_expr *e = (grn_expr *)expr;
5303 grn_expr_code *target;
5304 grn_expr_code *constant;
5305 grn_expr_code *operator;
5306 scan_info **sis;
5307 scan_info *si;
5308
5309 target = e->codes + 0;
5310 constant = e->codes + 1;
5311 operator = e->codes + 2;
5312
5313 if (target->op != GRN_OP_GET_VALUE) {
5314 return NULL;
5315 }
5316 if (target->nargs != 1) {
5317 return NULL;
5318 }
5319 if (!target->value) {
5320 return NULL;
5321 }
5322
5323 if (constant->op != GRN_OP_PUSH) {
5324 return NULL;
5325 }
5326 if (constant->nargs != 1) {
5327 return NULL;
5328 }
5329 if (!constant->value) {
5330 return NULL;
5331 }
5332
5333 if (operator->nargs != 2) {
5334 return NULL;
5335 }
5336 switch (operator->op) {
5337 case GRN_OP_MATCH :
5338 case GRN_OP_NEAR :
5339 case GRN_OP_SIMILAR :
5340 case GRN_OP_PREFIX :
5341 case GRN_OP_SUFFIX :
5342 case GRN_OP_EQUAL :
5343 case GRN_OP_NOT_EQUAL :
5344 case GRN_OP_LESS :
5345 case GRN_OP_GREATER :
5346 case GRN_OP_LESS_EQUAL :
5347 case GRN_OP_GREATER_EQUAL :
5348 case GRN_OP_TERM_EXTRACT :
5349 case GRN_OP_REGEXP :
5350 break;
5351 default :
5352 return NULL;
5353 break;
5354 }
5355
5356 sis = grn_scan_info_build_simple_open(ctx, n, logical_op);
5357 if (!sis) {
5358 return NULL;
5359 }
5360
5361 si = sis[0];
5362 si->end = 2;
5363 si->op = operator->op;
5364 si->args[si->nargs++] = target->value;
5365 si->args[si->nargs++] = constant->value;
5366 {
5367 int32_t weight = 0;
5368 if (operator->value && operator->value->header.domain == GRN_DB_INT32) {
5369 weight = GRN_INT32_VALUE(operator->value);
5370 }
5371 scan_info_build_match(ctx, si, weight);
5372 }
5373 return sis;
5374}
5375
5376static scan_info **
5377grn_scan_info_build_simple_and_operations(grn_ctx *ctx,
5378 grn_obj *expr,
5379 int *n,
5380 grn_operator logical_op,
5381 grn_bool record_exist)
5382{
5383 grn_expr *e = (grn_expr *)expr;
5384 scan_info **sis = NULL;
5385 int n_sis = 0;
5386 int i;
5387 int nth_sis;
5388
5389 for (i = 0, nth_sis = 0; i < e->codes_curr; i += 3, nth_sis++) {
5390 grn_expr_code *target = e->codes + i;
5391 grn_expr_code *constant = e->codes + i + 1;
5392 grn_expr_code *operator = e->codes + i + 2;
5393
5394 if (target->op != GRN_OP_GET_VALUE) {
5395 return NULL;
5396 }
5397 if (target->nargs != 1) {
5398 return NULL;
5399 }
5400 if (!target->value) {
5401 return NULL;
5402 }
5403
5404 if (constant->op != GRN_OP_PUSH) {
5405 return NULL;
5406 }
5407 if (constant->nargs != 1) {
5408 return NULL;
5409 }
5410 if (!constant->value) {
5411 return NULL;
5412 }
5413
5414 if (operator->nargs != 2) {
5415 return NULL;
5416 }
5417 switch (operator->op) {
5418 case GRN_OP_MATCH :
5419 case GRN_OP_NEAR :
5420 case GRN_OP_SIMILAR :
5421 case GRN_OP_PREFIX :
5422 case GRN_OP_SUFFIX :
5423 case GRN_OP_EQUAL :
5424 case GRN_OP_NOT_EQUAL :
5425 case GRN_OP_LESS :
5426 case GRN_OP_GREATER :
5427 case GRN_OP_LESS_EQUAL :
5428 case GRN_OP_GREATER_EQUAL :
5429 case GRN_OP_TERM_EXTRACT :
5430 case GRN_OP_REGEXP :
5431 break;
5432 default :
5433 return NULL;
5434 break;
5435 }
5436
5437 if (nth_sis > 0) {
5438 grn_expr_code *logical_operator = e->codes + i + 3;
5439
5440 if (logical_operator->op != GRN_OP_AND) {
5441 return NULL;
5442 }
5443 if (logical_operator->nargs != 2) {
5444 return NULL;
5445 }
5446
5447 i++;
5448 }
5449 }
5450 n_sis = nth_sis;
5451
5452 sis = GRN_CALLOC(sizeof(scan_info *) * n_sis);
5453 if (!sis) {
5454 return NULL;
5455 }
5456
5457 for (i = 0, nth_sis = 0; i < e->codes_curr; i += 3, nth_sis++) {
5458 grn_expr_code *target = e->codes + i;
5459 grn_expr_code *constant = e->codes + i + 1;
5460 grn_expr_code *operator = e->codes + i + 2;
5461 scan_info *si;
5462
5463 sis[nth_sis] = si = grn_scan_info_open(ctx, i);
5464 if (!si) {
5465 goto exit;
5466 }
5467 si->args[si->nargs++] = target->value;
5468 si->args[si->nargs++] = constant->value;
5469 si->op = operator->op;
5470 si->end = i + 2;
5471 si->flags &= ~SCAN_PUSH;
5472 if (nth_sis == 0) {
5473 si->logical_op = logical_op;
5474 } else {
5475 si->logical_op = GRN_OP_AND;
5476 }
5477 {
5478 int32_t weight = 0;
5479 if (operator->value && operator->value->header.domain == GRN_DB_INT32) {
5480 weight = GRN_INT32_VALUE(operator->value);
5481 }
5482 scan_info_build_match(ctx, si, weight);
5483 }
5484
5485 if (nth_sis > 0) {
5486 i++;
5487 }
5488 }
5489
5490 *n = n_sis;
5491 return sis;
5492
5493exit :
5494 if (n_sis > 0) {
5495 for (i = 0; i < n_sis; i++) {
5496 scan_info *si = sis[i];
5497 if (si) {
5498 grn_scan_info_close(ctx, si);
5499 }
5500 }
5501 GRN_FREE(sis);
5502 }
5503
5504 return NULL;
5505}
5506
5507static scan_info **
5508grn_scan_info_build_simple(grn_ctx *ctx, grn_obj *expr, int *n,
5509 grn_operator logical_op, grn_bool record_exist)
5510{
5511 grn_expr *e = (grn_expr *)expr;
5512
5513 if (e->codes_curr == 1) {
5514 return grn_scan_info_build_simple_value(ctx,
5515 expr,
5516 n,
5517 logical_op,
5518 record_exist);
5519 } else if (e->codes_curr == 3) {
5520 return grn_scan_info_build_simple_operation(ctx,
5521 expr,
5522 n,
5523 logical_op,
5524 record_exist);
5525 } else if (e->codes_curr % 4 == 3) {
5526 return grn_scan_info_build_simple_and_operations(ctx,
5527 expr,
5528 n,
5529 logical_op,
5530 record_exist);
5531 }
5532
5533 return NULL;
5534}
5535
5536scan_info **
5537grn_scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n,
5538 grn_operator op, grn_bool record_exist)
5539{
5540 scan_info **sis;
5541
5542 sis = grn_scan_info_build_simple(ctx, expr, n, op, record_exist);
5543#ifdef GRN_WITH_MRUBY
5544 if (!sis) {
5545 grn_ctx_impl_mrb_ensure_init(ctx);
5546 if (ctx->rc != GRN_SUCCESS) {
5547 return NULL;
5548 }
5549 if (ctx->impl->mrb.state) {
5550 return grn_mrb_scan_info_build(ctx, expr, n, op, record_exist);
5551 }
5552 }
5553#endif
5554 if (!sis) {
5555 sis = grn_scan_info_build_full(ctx, expr, n, op, record_exist);
5556 }
5557 return sis;
5558}
5559
5560void
5561grn_inspect_scan_info_list(grn_ctx *ctx, grn_obj *buffer, scan_info **sis, int n)
5562{
5563 int i;
5564
5565 for (i = 0; i < n; i++) {
5566 scan_info *si = sis[i];
5567
5568 grn_text_printf(ctx, buffer, "[%d]\n", i);
5569 grn_text_printf(ctx, buffer,
5570 " op: <%s>\n",
5571 grn_operator_to_string(si->op));
5572 grn_text_printf(ctx, buffer,
5573 " logical_op: <%s>\n",
5574 grn_operator_to_string(si->logical_op));
5575
5576 if (si->op == GRN_OP_CALL) {
5577 int i;
5578 for (i = 0; i < si->nargs; i++) {
5579 grn_text_printf(ctx, buffer, " args[%d]: <", i);
5580 grn_inspect(ctx, buffer, si->args[i]);
5581 GRN_TEXT_PUTS(ctx, buffer, ">\n");
5582 }
5583 } else {
5584 GRN_TEXT_PUTS(ctx, buffer, " index: <");
5585 grn_inspect(ctx, buffer, &(si->index));
5586 GRN_TEXT_PUTS(ctx, buffer, ">\n");
5587
5588 GRN_TEXT_PUTS(ctx, buffer, " query: <");
5589 grn_inspect(ctx, buffer, si->query);
5590 GRN_TEXT_PUTS(ctx, buffer, ">\n");
5591 }
5592
5593 grn_text_printf(ctx, buffer,
5594 " expr: <%d..%d>\n", si->start, si->end);
5595 }
5596}
5597
5598void
5599grn_p_scan_info_list(grn_ctx *ctx, scan_info **sis, int n)
5600{
5601 grn_obj inspected;
5602 GRN_TEXT_INIT(&inspected, 0);
5603 grn_inspect_scan_info_list(ctx, &inspected, sis, n);
5604 printf("%.*s\n",
5605 (int)GRN_TEXT_LEN(&inspected),
5606 GRN_TEXT_VALUE(&inspected));
5607 GRN_OBJ_FIN(ctx, &inspected);
5608}
5609
5610inline static int32_t
5611exec_result_to_score(grn_ctx *ctx, grn_obj *result, grn_obj *score_buffer)
5612{
5613 if (!result) {
5614 return 0;
5615 }
5616
5617 switch (result->header.type) {
5618 case GRN_VOID :
5619 return 0;
5620 case GRN_BULK :
5621 switch (result->header.domain) {
5622 case GRN_DB_BOOL :
5623 return GRN_BOOL_VALUE(result) ? 1 : 0;
5624 case GRN_DB_INT32 :
5625 return GRN_INT32_VALUE(result);
5626 default :
5627 GRN_BULK_REWIND(score_buffer);
5628 if (grn_obj_cast(ctx, result, score_buffer, GRN_FALSE) != GRN_SUCCESS) {
5629 return 1;
5630 }
5631 return GRN_INT32_VALUE(score_buffer);
5632 }
5633 case GRN_UVECTOR :
5634 case GRN_PVECTOR :
5635 case GRN_VECTOR :
5636 return 1;
5637 default :
5638 return 1; /* TODO: 1 is reasonable? */
5639 }
5640}
5641
5642static void
5643grn_table_select_sequential(grn_ctx *ctx, grn_obj *table, grn_obj *expr,
5644 grn_obj *v, grn_obj *res, grn_operator op)
5645{
5646 grn_obj *result;
5647 grn_obj score_buffer;
5648 int32_t score;
5649 grn_id id, *idp;
5650 grn_table_cursor *tc;
5651 grn_hash_cursor *hc;
5652 grn_hash *s = (grn_hash *)res;
5653 grn_expr_executor *executor;
5654
5655 executor = grn_expr_executor_open(ctx, expr);
5656 if (!executor) {
5657 return;
5658 }
5659 GRN_INT32_INIT(&score_buffer, 0);
5660 switch (op) {
5661 case GRN_OP_OR :
5662 if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) {
5663 while ((id = grn_table_cursor_next(ctx, tc))) {
5664 result = grn_expr_executor_exec(ctx, executor, id);
5665 if (ctx->rc) {
5666 break;
5667 }
5668 score = exec_result_to_score(ctx, result, &score_buffer);
5669 if (score > 0) {
5670 grn_rset_recinfo *ri;
5671 if (grn_hash_add(ctx, s, &id, s->key_size, (void **)&ri, NULL)) {
5672 grn_table_add_subrec(res, ri, score, (grn_rset_posinfo *)&id, 1);
5673 }
5674 }
5675 }
5676 grn_table_cursor_close(ctx, tc);
5677 }
5678 break;
5679 case GRN_OP_AND :
5680 if ((hc = grn_hash_cursor_open(ctx, s, NULL, 0, NULL, 0, 0, -1, 0))) {
5681 while (grn_hash_cursor_next(ctx, hc)) {
5682 grn_hash_cursor_get_key(ctx, hc, (void **) &idp);
5683 result = grn_expr_executor_exec(ctx, executor, *idp);
5684 if (ctx->rc) {
5685 break;
5686 }
5687 score = exec_result_to_score(ctx, result, &score_buffer);
5688 if (score > 0) {
5689 grn_rset_recinfo *ri;
5690 grn_hash_cursor_get_value(ctx, hc, (void **) &ri);
5691 grn_table_add_subrec(res, ri, score, (grn_rset_posinfo *)idp, 1);
5692 } else {
5693 grn_hash_cursor_delete(ctx, hc, NULL);
5694 }
5695 }
5696 grn_hash_cursor_close(ctx, hc);
5697 }
5698 break;
5699 case GRN_OP_AND_NOT :
5700 if ((hc = grn_hash_cursor_open(ctx, s, NULL, 0, NULL, 0, 0, -1, 0))) {
5701 while (grn_hash_cursor_next(ctx, hc)) {
5702 grn_hash_cursor_get_key(ctx, hc, (void **) &idp);
5703 result = grn_expr_executor_exec(ctx, executor, *idp);
5704 if (ctx->rc) {
5705 break;
5706 }
5707 score = exec_result_to_score(ctx, result, &score_buffer);
5708 if (score > 0) {
5709 grn_hash_cursor_delete(ctx, hc, NULL);
5710 }
5711 }
5712 grn_hash_cursor_close(ctx, hc);
5713 }
5714 break;
5715 case GRN_OP_ADJUST :
5716 if ((hc = grn_hash_cursor_open(ctx, s, NULL, 0, NULL, 0, 0, -1, 0))) {
5717 while (grn_hash_cursor_next(ctx, hc)) {
5718 grn_hash_cursor_get_key(ctx, hc, (void **) &idp);
5719 result = grn_expr_executor_exec(ctx, executor, *idp);
5720 if (ctx->rc) {
5721 break;
5722 }
5723 score = exec_result_to_score(ctx, result, &score_buffer);
5724 if (score > 0) {
5725 grn_rset_recinfo *ri;
5726 grn_hash_cursor_get_value(ctx, hc, (void **) &ri);
5727 grn_table_add_subrec(res, ri, score, (grn_rset_posinfo *)idp, 1);
5728 }
5729 }
5730 grn_hash_cursor_close(ctx, hc);
5731 }
5732 break;
5733 default :
5734 break;
5735 }
5736 GRN_OBJ_FIN(ctx, &score_buffer);
5737 grn_expr_executor_close(ctx, executor);
5738}
5739
5740static inline void
5741grn_table_select_index_report(grn_ctx *ctx, const char *tag, grn_obj *index)
5742{
5743 grn_report_index(ctx, "[table][select]", tag, index);
5744}
5745
5746static inline void
5747grn_table_select_index_not_used_report(grn_ctx *ctx,
5748 const char *tag,
5749 grn_obj *index,
5750 const char *reason)
5751{
5752 grn_report_index_not_used(ctx, "[table][select]", tag, index, reason);
5753}
5754
5755static inline grn_bool
5756grn_table_select_index_use_sequential_search(grn_ctx *ctx,
5757 grn_obj *table,
5758 grn_obj *res,
5759 grn_operator logical_op,
5760 const char *tag,
5761 grn_obj *index)
5762{
5763 int n_records;
5764 int n_filtered_records;
5765 double filtered_ratio;
5766 grn_obj reason;
5767
5768 if (logical_op != GRN_OP_AND) {
5769 return GRN_FALSE;
5770 }
5771
5772 n_records = grn_table_size(ctx, table);
5773 n_filtered_records = grn_table_size(ctx, res);
5774 if (n_records == 0) {
5775 filtered_ratio = 1.0;
5776 } else {
5777 filtered_ratio = (double)n_filtered_records / (double)n_records;
5778 }
5779
5780 if (filtered_ratio >= grn_table_select_enough_filtered_ratio) {
5781 return GRN_FALSE;
5782 }
5783
5784 if (n_filtered_records > grn_table_select_max_n_enough_filtered_records) {
5785 return GRN_FALSE;
5786 }
5787
5788 GRN_TEXT_INIT(&reason, 0);
5789 grn_text_printf(ctx, &reason,
5790 "enough filtered: %.2f%%(%d/%d) < %.2f%% && %d <= %d",
5791 filtered_ratio * 100,
5792 n_filtered_records,
5793 n_records,
5794 grn_table_select_enough_filtered_ratio * 100,
5795 n_filtered_records,
5796 grn_table_select_max_n_enough_filtered_records);
5797 GRN_TEXT_PUTC(ctx, &reason, '\0');
5798 grn_table_select_index_not_used_report(ctx,
5799 tag,
5800 index,
5801 GRN_TEXT_VALUE(&reason));
5802 GRN_OBJ_FIN(ctx, &reason);
5803 return GRN_TRUE;
5804}
5805
5806static inline grn_bool
5807grn_table_select_index_equal(grn_ctx *ctx,
5808 grn_obj *table,
5809 grn_obj *index,
5810 scan_info *si,
5811 grn_obj *res)
5812{
5813 grn_bool processed = GRN_FALSE;
5814
5815 if (GRN_BULK_VSIZE(si->query) == 0) {
5816 /* We can't use index for empty value. */
5817 return GRN_FALSE;
5818 }
5819
5820 if (si->flags & SCAN_ACCESSOR) {
5821 if (index->header.type == GRN_ACCESSOR && !((grn_accessor *)index)->next) {
5822 grn_obj dest;
5823 grn_accessor *a = (grn_accessor *)index;
5824 grn_posting posting;
5825 posting.sid = 1;
5826 posting.pos = 0;
5827 posting.weight = 0;
5828 switch (a->action) {
5829 case GRN_ACCESSOR_GET_ID :
5830 grn_table_select_index_report(ctx, "[equal][accessor][id]", table);
5831 GRN_UINT32_INIT(&dest, 0);
5832 if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) {
5833 posting.rid = GRN_UINT32_VALUE(&dest);
5834 if (posting.rid) {
5835 if (posting.rid == grn_table_at(ctx, table, posting.rid)) {
5836 grn_ii_posting_add(ctx, &posting, (grn_hash *)res,
5837 si->logical_op);
5838 }
5839 }
5840 processed = GRN_TRUE;
5841 }
5842 grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op);
5843 GRN_OBJ_FIN(ctx, &dest);
5844 break;
5845 case GRN_ACCESSOR_GET_KEY :
5846 grn_table_select_index_report(ctx, "[equal][accessor][key]", table);
5847 GRN_OBJ_INIT(&dest, GRN_BULK, 0, table->header.domain);
5848 if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) {
5849 if ((posting.rid = grn_table_get(ctx, table,
5850 GRN_BULK_HEAD(&dest),
5851 GRN_BULK_VSIZE(&dest)))) {
5852 grn_ii_posting_add(ctx, &posting, (grn_hash *)res,
5853 si->logical_op);
5854 }
5855 processed = GRN_TRUE;
5856 }
5857 grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op);
5858 GRN_OBJ_FIN(ctx, &dest);
5859 break;
5860 }
5861 }
5862 } else {
5863 const char *tag = "[equal]";
5864 grn_obj *domain = grn_ctx_at(ctx, index->header.domain);
5865
5866 if (domain) {
5867 grn_bool optimizable = GRN_FALSE;
5868
5869 if (domain->header.domain == GRN_DB_SHORT_TEXT) {
5870 grn_obj *normalizer = NULL;
5871 grn_table_get_info(ctx, domain, NULL, NULL, NULL, &normalizer, NULL);
5872 if (normalizer == grn_ctx_get(ctx, "NormalizerAuto", -1)) {
5873 optimizable = GRN_TRUE;
5874 }
5875 } else {
5876 optimizable = GRN_TRUE;
5877 }
5878 if (optimizable &&
5879 grn_table_select_index_use_sequential_search(ctx,
5880 table,
5881 res,
5882 si->logical_op,
5883 tag,
5884 index)) {
5885 domain = NULL;
5886 }
5887 }
5888
5889 if (domain) {
5890 grn_id tid;
5891
5892 grn_table_select_index_report(ctx, tag, index);
5893
5894 if (GRN_OBJ_GET_DOMAIN(si->query) == DB_OBJ(domain)->id) {
5895 tid = GRN_RECORD_VALUE(si->query);
5896 } else {
5897 tid = grn_table_get(ctx, domain,
5898 GRN_BULK_HEAD(si->query),
5899 GRN_BULK_VSIZE(si->query));
5900 }
5901 if (tid != GRN_ID_NIL) {
5902 uint32_t sid;
5903 int32_t weight;
5904 grn_ii *ii = (grn_ii *)index;
5905 grn_ii_cursor *ii_cursor;
5906
5907 sid = GRN_UINT32_VALUE_AT(&(si->wv), 0);
5908 weight = GRN_INT32_VALUE_AT(&(si->wv), 1);
5909 ii_cursor = grn_ii_cursor_open(ctx, ii, tid,
5910 GRN_ID_NIL, GRN_ID_MAX,
5911 ii->n_elements, 0);
5912 if (ii_cursor) {
5913 grn_posting *posting;
5914 while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) {
5915 grn_posting new_posting;
5916
5917 if (!(sid == 0 || posting->sid == sid)) {
5918 continue;
5919 }
5920
5921 if (si->position.specified) {
5922 while ((posting = grn_ii_cursor_next_pos(ctx, ii_cursor))) {
5923 if (posting->pos == si->position.start) {
5924 break;
5925 }
5926 }
5927 if (!posting) {
5928 continue;
5929 }
5930 }
5931
5932 new_posting = *posting;
5933 new_posting.weight *= weight;
5934 grn_ii_posting_add(ctx, &new_posting, (grn_hash *)res,
5935 si->logical_op);
5936 }
5937 grn_ii_cursor_close(ctx, ii_cursor);
5938 }
5939 }
5940 processed = GRN_TRUE;
5941 }
5942 if (processed) {
5943 grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op);
5944 }
5945 }
5946
5947 return processed;
5948}
5949
5950static inline grn_bool
5951grn_table_select_index_not_equal(grn_ctx *ctx,
5952 grn_obj *table,
5953 grn_obj *index,
5954 scan_info *si,
5955 grn_obj *res)
5956{
5957 grn_bool processed = GRN_FALSE;
5958
5959 if (GRN_BULK_VSIZE(si->query) == 0) {
5960 /* We can't use index for empty value. */
5961 return GRN_FALSE;
5962 }
5963
5964 if (si->logical_op != GRN_OP_AND) {
5965 /* We can't use index for OR and AND_NOT. */
5966 return GRN_FALSE;
5967 }
5968
5969 if (si->flags & SCAN_ACCESSOR) {
5970 if (index->header.type == GRN_ACCESSOR && !((grn_accessor *)index)->next) {
5971 grn_obj dest;
5972 grn_accessor *a = (grn_accessor *)index;
5973 grn_id id;
5974 switch (a->action) {
5975 case GRN_ACCESSOR_GET_ID :
5976 grn_table_select_index_report(ctx, "[not-equal][accessor][id]", table);
5977 GRN_UINT32_INIT(&dest, 0);
5978 if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) {
5979 id = GRN_UINT32_VALUE(&dest);
5980 if (id != GRN_ID_NIL) {
5981 if (id == grn_table_at(ctx, table, id)) {
5982 grn_hash_delete(ctx, (grn_hash *)res, &id, sizeof(grn_id), NULL);
5983 }
5984 }
5985 processed = GRN_TRUE;
5986 }
5987 GRN_OBJ_FIN(ctx, &dest);
5988 break;
5989 case GRN_ACCESSOR_GET_KEY :
5990 grn_table_select_index_report(ctx, "[not-equal][accessor][key]", table);
5991 GRN_OBJ_INIT(&dest, GRN_BULK, 0, table->header.domain);
5992 if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) {
5993 id = grn_table_get(ctx, table,
5994 GRN_BULK_HEAD(&dest),
5995 GRN_BULK_VSIZE(&dest));
5996 if (id != GRN_ID_NIL) {
5997 grn_hash_delete(ctx, (grn_hash *)res, &id, sizeof(grn_id), NULL);
5998 }
5999 processed = GRN_TRUE;
6000 }
6001 GRN_OBJ_FIN(ctx, &dest);
6002 break;
6003 }
6004 }
6005 } else {
6006 grn_obj *domain = grn_ctx_at(ctx, index->header.domain);
6007 if (domain) {
6008 grn_id tid;
6009 if (GRN_OBJ_GET_DOMAIN(si->query) == DB_OBJ(domain)->id) {
6010 tid = GRN_RECORD_VALUE(si->query);
6011 } else {
6012 tid = grn_table_get(ctx, domain,
6013 GRN_BULK_HEAD(si->query),
6014 GRN_BULK_VSIZE(si->query));
6015 }
6016 if (tid == GRN_ID_NIL) {
6017 processed = GRN_TRUE;
6018 } else {
6019 uint32_t sid;
6020 int32_t weight;
6021 grn_ii *ii = (grn_ii *)index;
6022 grn_ii_cursor *ii_cursor;
6023
6024 grn_table_select_index_report(ctx, "[not-equal]", index);
6025
6026 sid = GRN_UINT32_VALUE_AT(&(si->wv), 0);
6027 weight = GRN_INT32_VALUE_AT(&(si->wv), 1);
6028 ii_cursor = grn_ii_cursor_open(ctx, ii, tid,
6029 GRN_ID_NIL, GRN_ID_MAX,
6030 ii->n_elements, 0);
6031 if (ii_cursor) {
6032 grn_posting *posting;
6033 while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) {
6034 if (!(sid == 0 || posting->sid == sid)) {
6035 continue;
6036 }
6037
6038 if (si->position.specified) {
6039 while ((posting = grn_ii_cursor_next_pos(ctx, ii_cursor))) {
6040 if (posting->pos == si->position.start) {
6041 break;
6042 }
6043 }
6044 if (!posting) {
6045 continue;
6046 }
6047 }
6048
6049 grn_hash_delete(ctx, (grn_hash *)res,
6050 &(posting->rid), sizeof(grn_id),
6051 NULL);
6052 }
6053 grn_ii_cursor_close(ctx, ii_cursor);
6054 processed = GRN_TRUE;
6055 }
6056 }
6057 }
6058 }
6059
6060 return processed;
6061}
6062
6063static grn_bool
6064grn_table_select_index_prefix(grn_ctx *ctx,
6065 grn_obj *table,
6066 grn_obj *index,
6067 scan_info *si,
6068 grn_obj *res)
6069{
6070 grn_bool processed = GRN_FALSE;
6071 if (si->flags & SCAN_ACCESSOR) {
6072 if (index->header.type == GRN_ACCESSOR &&
6073 !((grn_accessor *)index)->next) {
6074 grn_obj dest;
6075 grn_accessor *a = (grn_accessor *)index;
6076 grn_posting posting;
6077 posting.sid = 1;
6078 posting.pos = 0;
6079 posting.weight = 0;
6080 switch (a->action) {
6081 case GRN_ACCESSOR_GET_ID :
6082 /* todo */
6083 break;
6084 case GRN_ACCESSOR_GET_KEY :
6085 if (si->op == GRN_OP_SUFFIX) {
6086 grn_table_select_index_report(ctx,
6087 "[suffix][accessor][key]", table);
6088 } else {
6089 grn_table_select_index_report(ctx,
6090 "[prefix][accessor][key]", table);
6091 }
6092 GRN_OBJ_INIT(&dest, GRN_BULK, 0, table->header.domain);
6093 if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) {
6094 grn_hash *pres;
6095 if ((pres = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
6096 GRN_OBJ_TABLE_HASH_KEY))) {
6097 grn_id *key;
6098 grn_table_search(ctx, table,
6099 GRN_BULK_HEAD(&dest), GRN_BULK_VSIZE(&dest),
6100 si->op, (grn_obj *)pres, GRN_OP_OR);
6101 GRN_HASH_EACH(ctx, pres, id, &key, NULL, NULL, {
6102 posting.rid = *key;
6103 grn_ii_posting_add(ctx, &posting, (grn_hash *)res,
6104 si->logical_op);
6105 });
6106 grn_hash_close(ctx, pres);
6107 }
6108 processed = GRN_TRUE;
6109 }
6110 grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op);
6111 GRN_OBJ_FIN(ctx, &dest);
6112 }
6113 }
6114 } else {
6115 grn_obj **indexes = &GRN_PTR_VALUE(&si->index);
6116 int i, n_indexes = GRN_BULK_VSIZE(&si->index)/sizeof(grn_obj *);
6117 for (i = 0; i < n_indexes; i++) {
6118 grn_obj *index = indexes[i];
6119 grn_obj *lexicon = grn_ctx_at(ctx, index->header.domain);
6120 if (lexicon) {
6121 grn_hash *keys;
6122 if ((keys = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
6123 GRN_OBJ_TABLE_HASH_KEY))) {
6124 grn_id *key;
6125 if (si->op == GRN_OP_SUFFIX) {
6126 grn_table_select_index_report(ctx, "[suffix]", index);
6127 } else {
6128 grn_table_select_index_report(ctx, "[prefix]", index);
6129 }
6130 grn_table_search(ctx, lexicon,
6131 GRN_BULK_HEAD(si->query),
6132 GRN_BULK_VSIZE(si->query),
6133 si->op, (grn_obj *)keys, GRN_OP_OR);
6134 grn_obj_unlink(ctx, lexicon);
6135 GRN_HASH_EACH(ctx, keys, id, &key, NULL, NULL, {
6136 grn_ii_at(ctx, (grn_ii *)index, *key, (grn_hash *)res, si->logical_op);
6137 });
6138 grn_hash_close(ctx, keys);
6139 }
6140 grn_obj_unlink(ctx, lexicon);
6141 }
6142 }
6143 grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op);
6144 processed = GRN_TRUE;
6145 }
6146 return processed;
6147}
6148
6149static grn_bool
6150grn_table_select_index_suffix(grn_ctx *ctx,
6151 grn_obj *table,
6152 grn_obj *index,
6153 scan_info *si,
6154 grn_obj *res)
6155{
6156 grn_obj *domain;
6157 if (si->flags & SCAN_ACCESSOR) {
6158 domain = table;
6159 } else {
6160 domain = grn_ctx_at(ctx, index->header.domain);
6161 }
6162 if (domain->header.type != GRN_TABLE_PAT_KEY) {
6163 return GRN_FALSE;
6164 }
6165 if (!(domain->header.flags & GRN_OBJ_KEY_WITH_SIS)) {
6166 return GRN_FALSE;
6167 }
6168 return grn_table_select_index_prefix(ctx, table, index, si, res);
6169}
6170
6171static inline grn_bool
6172grn_table_select_index_match(grn_ctx *ctx,
6173 grn_obj *table,
6174 grn_obj *index,
6175 scan_info *si,
6176 grn_obj *res,
6177 grn_id *min_id)
6178{
6179 grn_obj wv, **ip = &GRN_PTR_VALUE(&si->index);
6180 int j;
6181 int n_indexes = GRN_BULK_VSIZE(&si->index)/sizeof(grn_obj *);
6182 int32_t *wp = &GRN_INT32_VALUE(&si->wv);
6183 grn_search_optarg optarg;
6184 grn_bool minimum_min_id_is_set = GRN_FALSE;
6185 grn_id minimum_min_id = GRN_ID_NIL;
6186 unsigned int previous_n_hits = grn_table_size(ctx, res);
6187
6188 GRN_INT32_INIT(&wv, GRN_OBJ_VECTOR);
6189 if (si->op == GRN_OP_MATCH) {
6190 optarg.mode = GRN_OP_EXACT;
6191 } else {
6192 optarg.mode = si->op;
6193 }
6194 optarg.max_interval = 0;
6195 optarg.similarity_threshold = 0;
6196 switch (si->op) {
6197 case GRN_OP_NEAR :
6198 case GRN_OP_NEAR2 :
6199 optarg.max_interval = si->max_interval;
6200 break;
6201 case GRN_OP_SIMILAR :
6202 optarg.similarity_threshold = si->similarity_threshold;
6203 break;
6204 default :
6205 break;
6206 }
6207 optarg.weight_vector = (int *)GRN_BULK_HEAD(&wv);
6208 /* optarg.vector_size = GRN_BULK_VSIZE(&si->wv); */
6209 optarg.vector_size = 1;
6210 optarg.proc = NULL;
6211 optarg.max_size = 0;
6212 optarg.match_info.flags |= GRN_MATCH_INFO_GET_MIN_RECORD_ID;
6213 ctx->flags |= GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND;
6214 for (j = 0; j < n_indexes; j++, ip++, wp += 2) {
6215 uint32_t sid = (uint32_t) wp[0];
6216 int32_t weight = wp[1];
6217 if (grn_table_select_and_min_skip_enable) {
6218 optarg.match_info.min = *min_id;
6219 } else {
6220 optarg.match_info.min = GRN_ID_NIL;
6221 }
6222 if (sid) {
6223 int weight_index = sid - 1;
6224 int current_vector_size;
6225 current_vector_size = GRN_BULK_VSIZE(&wv)/sizeof(int32_t);
6226 if (weight_index < current_vector_size) {
6227 ((int *)GRN_BULK_HEAD(&wv))[weight_index] = weight;
6228 } else {
6229 GRN_INT32_SET_AT(ctx, &wv, weight_index, weight);
6230 }
6231 optarg.weight_vector = &GRN_INT32_VALUE(&wv);
6232 optarg.vector_size = GRN_BULK_VSIZE(&wv)/sizeof(int32_t);
6233 } else {
6234 optarg.weight_vector = NULL;
6235 optarg.vector_size = weight;
6236 }
6237 optarg.scorer = GRN_PTR_VALUE_AT(&(si->scorers), j);
6238 optarg.scorer_args_expr =
6239 GRN_PTR_VALUE_AT(&(si->scorer_args_exprs), j);
6240 optarg.scorer_args_expr_offset =
6241 GRN_UINT32_VALUE_AT(&(si->scorer_args_expr_offsets), j);
6242 if (j < n_indexes - 1) {
6243 if (sid && ip[0] == ip[1]) { continue; }
6244 } else {
6245 ctx->flags &= ~GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND;
6246 }
6247 grn_obj_search(ctx, ip[0], si->query, res, si->logical_op, &optarg);
6248 if (optarg.weight_vector) {
6249 int i;
6250 for (i = 0; i < optarg.vector_size; i++) {
6251 optarg.weight_vector[i] = 0;
6252 }
6253 }
6254 GRN_BULK_REWIND(&wv);
6255 if (!minimum_min_id_is_set ||
6256 optarg.match_info.min < minimum_min_id) {
6257 minimum_min_id_is_set = GRN_TRUE;
6258 minimum_min_id = optarg.match_info.min;
6259 }
6260 }
6261 if ((si->logical_op == GRN_OP_AND) ||
6262 (si->logical_op == GRN_OP_OR && previous_n_hits == 0)) {
6263 *min_id = minimum_min_id;
6264 } else {
6265 *min_id = GRN_ID_NIL;
6266 }
6267 GRN_OBJ_FIN(ctx, &wv);
6268
6269 return GRN_TRUE;
6270}
6271
6272static inline grn_bool
6273grn_table_select_index_call_selector(grn_ctx *ctx,
6274 grn_obj *table,
6275 grn_obj *index,
6276 scan_info *si,
6277 grn_obj *selector,
6278 grn_obj *res)
6279{
6280 grn_bool processed = GRN_FALSE;
6281 grn_proc *proc = (grn_proc *)selector;
6282 grn_rc rc;
6283
6284 if (grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) {
6285 char name[GRN_TABLE_MAX_KEY_SIZE];
6286 int name_size;
6287 char tag[GRN_TABLE_MAX_KEY_SIZE];
6288 name_size = grn_obj_name(ctx,
6289 (grn_obj *)selector,
6290 name,
6291 GRN_TABLE_MAX_KEY_SIZE);
6292 grn_snprintf(tag, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE,
6293 "[selector][%.*s]",
6294 name_size, name);
6295 grn_table_select_index_report(ctx, tag, index);
6296 }
6297
6298 if (index && index->header.type == GRN_ACCESSOR) {
6299 grn_operator selector_op;
6300 grn_obj *accessor = index;
6301 grn_accessor *a = (grn_accessor *)accessor;
6302
6303 selector_op = grn_proc_get_selector_operator(ctx, selector);
6304 if (a->next) {
6305 unsigned int accessor_deep = 0;
6306 grn_obj *base_table = NULL;
6307 grn_obj *base_index = NULL;
6308 grn_obj *base_res = NULL;
6309
6310 for (; a; a = a->next) {
6311 if (a->next) {
6312 accessor_deep++;
6313 } else {
6314 grn_index_datum index_data;
6315 unsigned int n_index_datum;
6316
6317 if (grn_obj_is_table(ctx, a->obj)) {
6318 base_table = a->obj;
6319 } else {
6320 base_table = grn_ctx_at(ctx, a->obj->header.domain);
6321 }
6322 n_index_datum = grn_column_find_index_data(ctx,
6323 a->obj,
6324 selector_op,
6325 &index_data,
6326 1);
6327 if (n_index_datum > 0) {
6328 base_index = index_data.index;
6329 }
6330 base_res = grn_table_create(ctx, NULL, 0, NULL,
6331 GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC,
6332 base_table, NULL);
6333 }
6334 }
6335 rc = proc->callbacks.function.selector(ctx,
6336 base_table,
6337 base_index,
6338 si->nargs,
6339 si->args,
6340 base_res,
6341 GRN_OP_OR);
6342 if (rc == GRN_SUCCESS) {
6343 grn_accessor_resolve(ctx,
6344 accessor,
6345 accessor_deep,
6346 base_res,
6347 res,
6348 si->logical_op);
6349 }
6350 grn_obj_close(ctx, base_res);
6351 } else {
6352 grn_index_datum index_data;
6353 unsigned int n_index_datum;
6354 grn_obj *target_index = NULL;
6355
6356 n_index_datum = grn_column_find_index_data(ctx,
6357 a->obj,
6358 selector_op,
6359 &index_data,
6360 1);
6361 if (n_index_datum > 0) {
6362 target_index = index_data.index;
6363 }
6364 rc = proc->callbacks.function.selector(ctx,
6365 table,
6366 target_index,
6367 si->nargs,
6368 si->args,
6369 res,
6370 si->logical_op);
6371 }
6372 } else {
6373 rc = proc->callbacks.function.selector(ctx,
6374 table,
6375 index,
6376 si->nargs,
6377 si->args,
6378 res,
6379 si->logical_op);
6380 }
6381
6382 if (rc) {
6383 /* TODO: report error */
6384 } else {
6385 processed = GRN_TRUE;
6386 }
6387
6388 return processed;
6389}
6390
6391static inline grn_bool
6392grn_table_select_index_range_key(grn_ctx *ctx,
6393 grn_obj *table,
6394 scan_info *si,
6395 grn_operator logical_op,
6396 grn_obj *res)
6397{
6398 const char *tag = "[range][key]";
6399 grn_bool processed = GRN_FALSE;
6400 grn_obj key;
6401
6402 if (grn_table_select_index_use_sequential_search(ctx,
6403 table,
6404 res,
6405 logical_op,
6406 tag,
6407 table)) {
6408 return GRN_FALSE;
6409 }
6410
6411 GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain);
6412 if (grn_obj_cast(ctx, si->query, &key, GRN_FALSE) == GRN_SUCCESS) {
6413 grn_table_cursor *cursor;
6414 const void *min = NULL, *max = NULL;
6415 unsigned int min_size = 0, max_size = 0;
6416 int offset = 0;
6417 int limit = -1;
6418 int flags = GRN_CURSOR_ASCENDING;
6419
6420 grn_table_select_index_report(ctx, tag, table);
6421
6422 switch (si->op) {
6423 case GRN_OP_LESS :
6424 flags |= GRN_CURSOR_LT;
6425 max = GRN_BULK_HEAD(&key);
6426 max_size = GRN_BULK_VSIZE(&key);
6427 break;
6428 case GRN_OP_GREATER :
6429 flags |= GRN_CURSOR_GT;
6430 min = GRN_BULK_HEAD(&key);
6431 min_size = GRN_BULK_VSIZE(&key);
6432 break;
6433 case GRN_OP_LESS_EQUAL :
6434 flags |= GRN_CURSOR_LE;
6435 max = GRN_BULK_HEAD(&key);
6436 max_size = GRN_BULK_VSIZE(&key);
6437 break;
6438 case GRN_OP_GREATER_EQUAL :
6439 flags |= GRN_CURSOR_GE;
6440 min = GRN_BULK_HEAD(&key);
6441 min_size = GRN_BULK_VSIZE(&key);
6442 break;
6443 default :
6444 break;
6445 }
6446 cursor = grn_table_cursor_open(ctx, table,
6447 min, min_size, max, max_size,
6448 offset, limit, flags);
6449 if (cursor) {
6450 uint32_t sid;
6451 int32_t weight;
6452
6453 sid = GRN_UINT32_VALUE_AT(&(si->wv), 0);
6454 weight = GRN_INT32_VALUE_AT(&(si->wv), 1);
6455
6456 if (sid == 0) {
6457 grn_posting posting = {0};
6458
6459 posting.weight = weight - 1;
6460 while ((posting.rid = grn_table_cursor_next(ctx, cursor))) {
6461 grn_ii_posting_add(ctx, &posting, (grn_hash *)res, logical_op);
6462 }
6463 }
6464 processed = GRN_TRUE;
6465 grn_table_cursor_close(ctx, cursor);
6466 }
6467
6468 grn_ii_resolve_sel_and(ctx, (grn_hash *)res, logical_op);
6469 }
6470 GRN_OBJ_FIN(ctx, &key);
6471
6472 return processed;
6473}
6474
6475static inline grn_bool
6476grn_table_select_index_range_column(grn_ctx *ctx, grn_obj *table,
6477 grn_obj *index,
6478 scan_info *si, grn_operator logical_op,
6479 grn_obj *res)
6480{
6481 const char *tag = "[range]";
6482 grn_bool processed = GRN_FALSE;
6483 grn_obj *index_table;
6484 grn_obj range;
6485
6486 index_table = grn_ctx_at(ctx, index->header.domain);
6487 if (!index_table) {
6488 return GRN_FALSE;
6489 }
6490
6491 if (grn_table_select_index_use_sequential_search(ctx,
6492 table,
6493 res,
6494 logical_op,
6495 tag,
6496 index_table)) {
6497 grn_obj_unlink(ctx, index_table);
6498 return GRN_FALSE;
6499 }
6500
6501 GRN_OBJ_INIT(&range, GRN_BULK, 0, index_table->header.domain);
6502 if (grn_obj_cast(ctx, si->query, &range, GRN_FALSE) == GRN_SUCCESS) {
6503 grn_table_cursor *cursor;
6504 const void *min = NULL, *max = NULL;
6505 unsigned int min_size = 0, max_size = 0;
6506 int offset = 0;
6507 int limit = -1;
6508 int flags = GRN_CURSOR_ASCENDING;
6509
6510 grn_table_select_index_report(ctx, "[range]", index);
6511
6512 switch (si->op) {
6513 case GRN_OP_LESS :
6514 flags |= GRN_CURSOR_LT;
6515 max = GRN_BULK_HEAD(&range);
6516 max_size = GRN_BULK_VSIZE(&range);
6517 break;
6518 case GRN_OP_GREATER :
6519 flags |= GRN_CURSOR_GT;
6520 min = GRN_BULK_HEAD(&range);
6521 min_size = GRN_BULK_VSIZE(&range);
6522 break;
6523 case GRN_OP_LESS_EQUAL :
6524 flags |= GRN_CURSOR_LE;
6525 max = GRN_BULK_HEAD(&range);
6526 max_size = GRN_BULK_VSIZE(&range);
6527 break;
6528 case GRN_OP_GREATER_EQUAL :
6529 flags |= GRN_CURSOR_GE;
6530 min = GRN_BULK_HEAD(&range);
6531 min_size = GRN_BULK_VSIZE(&range);
6532 break;
6533 default :
6534 break;
6535 }
6536 cursor = grn_table_cursor_open(ctx, index_table,
6537 min, min_size, max, max_size,
6538 offset, limit, flags);
6539 if (cursor) {
6540 grn_id tid;
6541 uint32_t sid;
6542 int32_t weight;
6543 grn_ii *ii = (grn_ii *)index;
6544
6545 sid = GRN_UINT32_VALUE_AT(&(si->wv), 0);
6546 weight = GRN_INT32_VALUE_AT(&(si->wv), 1);
6547 while ((tid = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
6548 grn_ii_cursor *ii_cursor;
6549
6550 ii_cursor = grn_ii_cursor_open(ctx, ii, tid,
6551 GRN_ID_NIL, GRN_ID_MAX,
6552 ii->n_elements, 0);
6553 if (ii_cursor) {
6554 grn_posting *posting;
6555 while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) {
6556 grn_posting new_posting;
6557
6558 if (!(sid == 0 || posting->sid == sid)) {
6559 continue;
6560 }
6561
6562 if (si->position.specified) {
6563 while ((posting = grn_ii_cursor_next_pos(ctx, ii_cursor))) {
6564 if (posting->pos == si->position.start) {
6565 break;
6566 }
6567 }
6568 if (!posting) {
6569 continue;
6570 }
6571 }
6572
6573 new_posting = *posting;
6574 new_posting.weight *= weight;
6575 grn_ii_posting_add(ctx, &new_posting, (grn_hash *)res, logical_op);
6576 }
6577 }
6578 grn_ii_cursor_close(ctx, ii_cursor);
6579 }
6580 processed = GRN_TRUE;
6581 grn_table_cursor_close(ctx, cursor);
6582 }
6583
6584 grn_ii_resolve_sel_and(ctx, (grn_hash *)res, logical_op);
6585 }
6586 GRN_OBJ_FIN(ctx, &range);
6587
6588 grn_obj_unlink(ctx, index_table);
6589
6590 return processed;
6591}
6592
6593static inline grn_bool
6594grn_table_select_index_range_accessor(grn_ctx *ctx,
6595 grn_obj *table,
6596 grn_obj *accessor,
6597 scan_info *si,
6598 grn_operator op,
6599 grn_obj *res)
6600{
6601 grn_rc rc;
6602 grn_accessor *a;
6603 grn_obj *last_obj = NULL;
6604 int n_accessors;
6605 grn_bool have_resolver = GRN_FALSE;
6606 grn_obj *base_res = NULL;
6607
6608 for (a = (grn_accessor *)accessor; a; a = a->next) {
6609 if (!a->next) {
6610 last_obj = a->obj;
6611 }
6612 }
6613 n_accessors = 0;
6614 for (a = (grn_accessor *)accessor; a; a = a->next) {
6615 n_accessors++;
6616 if (GRN_OBJ_INDEX_COLUMNP(a->obj) ||
6617 grn_obj_is_table(ctx, a->obj)) {
6618 have_resolver = GRN_TRUE;
6619 break;
6620 }
6621 }
6622
6623 {
6624 grn_obj *index;
6625 grn_obj *range;
6626
6627 if (grn_obj_is_table(ctx, last_obj)) {
6628 index = last_obj;
6629 range = last_obj;
6630 base_res = grn_table_create(ctx, NULL, 0, NULL,
6631 GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC,
6632 range,
6633 NULL);
6634 if (!base_res) {
6635 return GRN_FALSE;
6636 }
6637 if (!grn_table_select_index_range_key(ctx, last_obj, si, GRN_OP_OR,
6638 base_res)) {
6639 grn_obj_unlink(ctx, base_res);
6640 return GRN_FALSE;
6641 }
6642 } else {
6643 if (grn_column_index(ctx, last_obj, si->op, &index, 1, NULL) == 0) {
6644 return GRN_FALSE;
6645 }
6646
6647 range = grn_ctx_at(ctx, DB_OBJ(index)->range);
6648 base_res = grn_table_create(ctx, NULL, 0, NULL,
6649 GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC,
6650 range,
6651 NULL);
6652 if (!base_res) {
6653 return GRN_FALSE;
6654 }
6655 if (!grn_table_select_index_range_column(ctx, table, index, si, GRN_OP_OR,
6656 base_res)) {
6657 grn_obj_unlink(ctx, base_res);
6658 return GRN_FALSE;
6659 }
6660 }
6661 grn_table_select_index_report(ctx, "[range][accessor]", index);
6662 }
6663
6664 if (n_accessors == 1 && have_resolver) {
6665 rc = grn_accessor_resolve(ctx, accessor, 1, base_res, res, op);
6666 } else {
6667 rc = grn_accessor_resolve(ctx, accessor, n_accessors - 1, base_res, res, op);
6668 }
6669 grn_obj_unlink(ctx, base_res);
6670
6671 return rc == GRN_SUCCESS;
6672}
6673
6674static inline grn_bool
6675grn_table_select_index_range(grn_ctx *ctx, grn_obj *table, grn_obj *index,
6676 scan_info *si, grn_obj *res)
6677{
6678 if (si->flags & SCAN_ACCESSOR) {
6679 switch (index->header.type) {
6680 case GRN_TABLE_PAT_KEY :
6681 case GRN_TABLE_DAT_KEY :
6682 /* table == index */
6683 return grn_table_select_index_range_key(ctx, table, si,
6684 si->logical_op, res);
6685 case GRN_ACCESSOR :
6686 return grn_table_select_index_range_accessor(ctx, table, index, si,
6687 si->logical_op, res);
6688 default :
6689 return GRN_FALSE;
6690 }
6691 } else {
6692 return grn_table_select_index_range_column(ctx, table, index, si,
6693 si->logical_op, res);
6694 }
6695}
6696
6697static inline grn_bool
6698grn_table_select_index(grn_ctx *ctx, grn_obj *table, scan_info *si,
6699 grn_obj *res, grn_id *min_id)
6700{
6701 grn_bool processed = GRN_FALSE;
6702 if (!si->query) {
6703 if (si->op != GRN_OP_CALL || !grn_obj_is_selector_proc(ctx, si->args[0])) {
6704 return processed;
6705 }
6706 }
6707 if (GRN_BULK_VSIZE(&si->index)) {
6708 grn_obj *index = GRN_PTR_VALUE(&si->index);
6709 switch (si->op) {
6710 case GRN_OP_EQUAL :
6711 processed = grn_table_select_index_equal(ctx, table, index, si, res);
6712 break;
6713 case GRN_OP_NOT_EQUAL :
6714 processed = grn_table_select_index_not_equal(ctx, table, index, si, res);
6715 break;
6716 case GRN_OP_PREFIX :
6717 processed = grn_table_select_index_prefix(ctx, table, index, si, res);
6718 break;
6719 case GRN_OP_SUFFIX :
6720 processed = grn_table_select_index_suffix(ctx, table, index, si, res);
6721 break;
6722 case GRN_OP_MATCH :
6723 case GRN_OP_NEAR :
6724 case GRN_OP_NEAR2 :
6725 case GRN_OP_SIMILAR :
6726 case GRN_OP_REGEXP :
6727 processed = grn_table_select_index_match(ctx,
6728 table,
6729 index,
6730 si,
6731 res,
6732 min_id);
6733 break;
6734 case GRN_OP_TERM_EXTRACT :
6735 if (si->flags & SCAN_ACCESSOR) {
6736 if (index->header.type == GRN_ACCESSOR &&
6737 !((grn_accessor *)index)->next) {
6738 grn_accessor *a = (grn_accessor *)index;
6739 switch (a->action) {
6740 case GRN_ACCESSOR_GET_KEY :
6741 grn_table_select_index_report(ctx, "[term-extract][accessor][key]",
6742 table);
6743 grn_table_search(ctx, table,
6744 GRN_TEXT_VALUE(si->query), GRN_TEXT_LEN(si->query),
6745 GRN_OP_TERM_EXTRACT, res, si->logical_op);
6746 processed = GRN_TRUE;
6747 break;
6748 }
6749 }
6750 }
6751 break;
6752 case GRN_OP_CALL :
6753 if (grn_obj_is_selector_proc(ctx, si->args[0])) {
6754 processed = grn_table_select_index_call_selector(ctx,
6755 table,
6756 index,
6757 si,
6758 si->args[0],
6759 res);
6760 }
6761 break;
6762 case GRN_OP_LESS :
6763 case GRN_OP_GREATER :
6764 case GRN_OP_LESS_EQUAL :
6765 case GRN_OP_GREATER_EQUAL :
6766 processed = grn_table_select_index_range(ctx, table, index, si, res);
6767 break;
6768 default :
6769 /* todo : implement */
6770 /* todo : handle SCAN_PRE_CONST */
6771 break;
6772 }
6773 } else {
6774 switch (si->op) {
6775 case GRN_OP_CALL :
6776 if (grn_obj_is_selector_proc(ctx, si->args[0])) {
6777 grn_rc rc;
6778 grn_proc *proc = (grn_proc *)(si->args[0]);
6779 if (grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) {
6780 char proc_name[GRN_TABLE_MAX_KEY_SIZE];
6781 int proc_name_size;
6782 char tag[GRN_TABLE_MAX_KEY_SIZE];
6783 proc_name_size = grn_obj_name(ctx, (grn_obj *)proc,
6784 proc_name, GRN_TABLE_MAX_KEY_SIZE);
6785 proc_name[proc_name_size] = '\0';
6786 grn_snprintf(tag, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE,
6787 "[selector][no-index][%s]", proc_name);
6788 grn_table_select_index_report(ctx, tag, table);
6789 }
6790 rc = proc->callbacks.function.selector(ctx,
6791 table,
6792 NULL,
6793 si->nargs,
6794 si->args,
6795 res,
6796 si->logical_op);
6797 if (rc) {
6798 if (rc == GRN_FUNCTION_NOT_IMPLEMENTED) {
6799 ERRCLR(ctx);
6800 } else {
6801 /* TODO: report error */
6802 }
6803 } else {
6804 processed = GRN_TRUE;
6805 }
6806 }
6807 default :
6808 break;
6809 }
6810 }
6811 return processed;
6812}
6813
6814grn_obj *
6815grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr,
6816 grn_obj *res, grn_operator op)
6817{
6818 grn_obj *v;
6819 unsigned int res_size;
6820 grn_bool res_created = GRN_FALSE;
6821 if (res) {
6822 if (res->header.type != GRN_TABLE_HASH_KEY ||
6823 (res->header.domain != DB_OBJ(table)->id)) {
6824 ERR(GRN_INVALID_ARGUMENT, "hash table required");
6825 return NULL;
6826 }
6827 } else {
6828 if (!(res = grn_table_create(ctx, NULL, 0, NULL,
6829 GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, table, NULL))) {
6830 return NULL;
6831 }
6832 res_created = GRN_TRUE;
6833 }
6834 if (!(v = grn_expr_get_var_by_offset(ctx, expr, 0))) {
6835 ERR(GRN_INVALID_ARGUMENT, "at least one variable must be defined");
6836 return NULL;
6837 }
6838 GRN_API_ENTER;
6839 res_size = GRN_HASH_SIZE((grn_hash *)res);
6840 if (op == GRN_OP_OR || res_size) {
6841 int i;
6842 grn_scanner *scanner;
6843 scanner = grn_scanner_open(ctx, expr, op, res_size > 0);
6844 if (scanner) {
6845 grn_obj res_stack;
6846 grn_expr *e = (grn_expr *)scanner->expr;
6847 grn_expr_code *codes = e->codes;
6848 uint32_t codes_curr = e->codes_curr;
6849 grn_id min_id = GRN_ID_NIL;
6850 v = grn_expr_get_var_by_offset(ctx, (grn_obj *)e, 0);
6851 GRN_PTR_INIT(&res_stack, GRN_OBJ_VECTOR, GRN_ID_NIL);
6852 for (i = 0; i < scanner->n_sis; i++) {
6853 scan_info *si = scanner->sis[i];
6854 if (si->flags & SCAN_POP) {
6855 grn_obj *res_;
6856 GRN_PTR_POP(&res_stack, res_);
6857 grn_table_setoperation(ctx, res_, res, res_, si->logical_op);
6858 grn_obj_close(ctx, res);
6859 res = res_;
6860 min_id = GRN_ID_NIL;
6861 } else {
6862 grn_bool processed = GRN_FALSE;
6863 if (si->flags & SCAN_PUSH) {
6864 grn_obj *res_ = NULL;
6865 res_ = grn_table_create(ctx, NULL, 0, NULL,
6866 GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, table, NULL);
6867 if (!res_) {
6868 break;
6869 }
6870 GRN_PTR_PUT(ctx, &res_stack, res);
6871 res = res_;
6872 min_id = GRN_ID_NIL;
6873 }
6874 if (si->logical_op != GRN_OP_AND) {
6875 min_id = GRN_ID_NIL;
6876 }
6877 processed = grn_table_select_index(ctx, table, si, res, &min_id);
6878 if (!processed) {
6879 if (ctx->rc) { break; }
6880 e->codes = codes + si->start;
6881 e->codes_curr = si->end - si->start + 1;
6882 grn_table_select_sequential(ctx, table, (grn_obj *)e, v,
6883 res, si->logical_op);
6884 min_id = GRN_ID_NIL;
6885 }
6886 }
6887 GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE,
6888 ":", "filter(%d)", grn_table_size(ctx, res));
6889 if (ctx->rc) {
6890 if (res_created) {
6891 grn_obj_close(ctx, res);
6892 }
6893 res = NULL;
6894 break;
6895 }
6896 }
6897
6898 i = 0;
6899 if (!res_created) { i++; }
6900 for (; i < GRN_BULK_VSIZE(&res_stack) / sizeof(grn_obj *); i++) {
6901 grn_obj *stacked_res;
6902 stacked_res = *((grn_obj **)GRN_BULK_HEAD(&res_stack) + i);
6903 grn_obj_close(ctx, stacked_res);
6904 }
6905 GRN_OBJ_FIN(ctx, &res_stack);
6906 e->codes = codes;
6907 e->codes_curr = codes_curr;
6908
6909 grn_scanner_close(ctx, scanner);
6910 } else {
6911 if (!ctx->rc) {
6912 grn_table_select_sequential(ctx, table, expr, v, res, op);
6913 if (ctx->rc) {
6914 if (res_created) {
6915 grn_obj_close(ctx, res);
6916 }
6917 res = NULL;
6918 }
6919 }
6920 }
6921 }
6922 GRN_API_RETURN(res);
6923}
6924
6925/* grn_expr_parse */
6926
6927grn_obj *
6928grn_ptr_value_at(grn_obj *obj, int offset)
6929{
6930 int size = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *);
6931 if (offset < 0) { offset = size + offset; }
6932 return (0 <= offset && offset < size)
6933 ? (((grn_obj **)GRN_BULK_HEAD(obj))[offset])
6934 : NULL;
6935}
6936
6937int32_t
6938grn_int32_value_at(grn_obj *obj, int offset)
6939{
6940 int size = GRN_BULK_VSIZE(obj) / sizeof(int32_t);
6941 if (offset < 0) { offset = size + offset; }
6942 return (0 <= offset && offset < size)
6943 ? (((int32_t *)GRN_BULK_HEAD(obj))[offset])
6944 : 0;
6945}
6946
6947/* grn_expr_create_from_str */
6948
6949#include "grn_snip.h"
6950
6951typedef struct {
6952 grn_ctx *ctx;
6953 grn_obj *e;
6954 grn_obj *v;
6955 const char *str;
6956 const char *cur;
6957 const char *str_end;
6958 grn_obj *table;
6959 grn_obj *default_column;
6960 grn_obj buf;
6961 grn_obj token_stack;
6962 grn_obj column_stack;
6963 grn_obj op_stack;
6964 grn_obj mode_stack;
6965 grn_obj max_interval_stack;
6966 grn_obj similarity_threshold_stack;
6967 grn_obj weight_stack;
6968 grn_operator default_op;
6969 grn_select_optarg opt;
6970 grn_operator default_mode;
6971 grn_expr_flags flags;
6972 grn_expr_flags default_flags;
6973 int escalation_threshold;
6974 int escalation_decaystep;
6975 int weight_offset;
6976 grn_hash *weight_set;
6977 snip_cond *snip_conds;
6978 grn_hash *object_literal;
6979 int paren_depth;
6980 struct {
6981 const char *string;
6982 size_t string_length;
6983 int token;
6984 int weight;
6985 } pending_token;
6986} efs_info;
6987
6988typedef struct {
6989 grn_operator op;
6990 int weight;
6991} efs_op;
6992
6993inline static void
6994skip_space(grn_ctx *ctx, efs_info *q)
6995{
6996 unsigned int len;
6997 while (q->cur < q->str_end && grn_isspace(q->cur, ctx->encoding)) {
6998 /* null check and length check */
6999 if (!(len = grn_charlen(ctx, q->cur, q->str_end))) {
7000 q->cur = q->str_end;
7001 break;
7002 }
7003 q->cur += len;
7004 }
7005}
7006
7007static grn_bool
7008parse_query_op(efs_info *q, efs_op *op, grn_operator *mode, int *option)
7009{
7010 grn_bool found = GRN_TRUE;
7011 const char *start, *end = q->cur;
7012 switch (*end) {
7013 case 'S' :
7014 *mode = GRN_OP_SIMILAR;
7015 start = ++end;
7016 *option = grn_atoi(start, q->str_end, (const char **)&end);
7017 if (start == end) { *option = DEFAULT_SIMILARITY_THRESHOLD; }
7018 q->cur = end;
7019 break;
7020 case 'N' :
7021 *mode = GRN_OP_NEAR;
7022 start = ++end;
7023 *option = grn_atoi(start, q->str_end, (const char **)&end);
7024 if (start == end) { *option = DEFAULT_MAX_INTERVAL; }
7025 q->cur = end;
7026 break;
7027 case 'n' :
7028 *mode = GRN_OP_NEAR2;
7029 start = ++end;
7030 *option = grn_atoi(start, q->str_end, (const char **)&end);
7031 if (start == end) { *option = DEFAULT_MAX_INTERVAL; }
7032 q->cur = end;
7033 break;
7034 case 'T' :
7035 *mode = GRN_OP_TERM_EXTRACT;
7036 start = ++end;
7037 *option = grn_atoi(start, q->str_end, (const char **)&end);
7038 if (start == end) { *option = DEFAULT_TERM_EXTRACT_POLICY; }
7039 q->cur = end;
7040 break;
7041 case 'X' : /* force exact mode */
7042 op->op = GRN_OP_AND;
7043 *mode = GRN_OP_EXACT;
7044 *option = 0;
7045 start = ++end;
7046 q->cur = end;
7047 break;
7048 default :
7049 found = GRN_FALSE;
7050 break;
7051 }
7052 return found;
7053}
7054
7055#define DISABLE_UNUSED_CODE 1
7056#ifndef DISABLE_UNUSED_CODE
7057static const char *
7058get_weight_vector(grn_ctx *ctx, efs_info *query, const char *source)
7059{
7060 const char *p;
7061
7062 if (!query->opt.weight_vector &&
7063 !query->weight_set &&
7064 !(query->opt.weight_vector = GRN_CALLOC(sizeof(int) * DEFAULT_WEIGHT_VECTOR_SIZE))) {
7065 GRN_LOG(ctx, GRN_LOG_ALERT, "get_weight_vector malloc fail");
7066 return source;
7067 }
7068 for (p = source; p < query->str_end; ) {
7069 unsigned int key;
7070 int value;
7071
7072 /* key, key is not zero */
7073 key = grn_atoui(p, query->str_end, &p);
7074 if (!key || key > GRN_ID_MAX) { break; }
7075
7076 /* value */
7077 if (*p == ':') {
7078 p++;
7079 value = grn_atoi(p, query->str_end, &p);
7080 } else {
7081 value = 1;
7082 }
7083
7084 if (query->weight_set) {
7085 int *pval;
7086 if (grn_hash_add(ctx, query->weight_set, &key, sizeof(unsigned int), (void **)&pval, NULL)) {
7087 *pval = value;
7088 }
7089 } else if (key < DEFAULT_WEIGHT_VECTOR_SIZE) {
7090 query->opt.weight_vector[key - 1] = value;
7091 } else {
7092 GRN_FREE(query->opt.weight_vector);
7093 query->opt.weight_vector = NULL;
7094 if (!(query->weight_set = grn_hash_create(ctx, NULL, sizeof(unsigned int), sizeof(int),
7095 0))) {
7096 return source;
7097 }
7098 p = source; /* reparse */
7099 continue;
7100 }
7101 if (*p != ',') { break; }
7102 p++;
7103 }
7104 return p;
7105}
7106
7107static void
7108get_pragma(grn_ctx *ctx, efs_info *q)
7109{
7110 const char *start, *end = q->cur;
7111 while (end < q->str_end && *end == GRN_QUERY_PREFIX) {
7112 if (++end >= q->str_end) { break; }
7113 switch (*end) {
7114 case 'E' :
7115 start = ++end;
7116 q->escalation_threshold = grn_atoi(start, q->str_end, (const char **)&end);
7117 while (end < q->str_end && (('0' <= *end && *end <= '9') || *end == '-')) { end++; }
7118 if (*end == ',') {
7119 start = ++end;
7120 q->escalation_decaystep = grn_atoi(start, q->str_end, (const char **)&end);
7121 }
7122 q->cur = end;
7123 break;
7124 case 'D' :
7125 start = ++end;
7126 while (end < q->str_end && *end != GRN_QUERY_PREFIX && !grn_isspace(end, ctx->encoding)) {
7127 end++;
7128 }
7129 if (end > start) {
7130 switch (*start) {
7131 case 'O' :
7132 q->default_op = GRN_OP_OR;
7133 break;
7134 case GRN_QUERY_AND :
7135 q->default_op = GRN_OP_AND;
7136 break;
7137 case GRN_QUERY_AND_NOT :
7138 q->default_op = GRN_OP_AND_NOT;
7139 break;
7140 case GRN_QUERY_ADJ_INC :
7141 q->default_op = GRN_OP_ADJUST;
7142 break;
7143 }
7144 }
7145 q->cur = end;
7146 break;
7147 case 'W' :
7148 start = ++end;
7149 end = (char *)get_weight_vector(ctx, q, start);
7150 q->cur = end;
7151 break;
7152 }
7153 }
7154}
7155
7156static int
7157section_weight_cb(grn_ctx *ctx, grn_hash *r, const void *rid, int sid, void *arg)
7158{
7159 int *w;
7160 grn_hash *s = (grn_hash *)arg;
7161 if (s && grn_hash_get(ctx, s, &sid, sizeof(grn_id), (void **)&w)) {
7162 return *w;
7163 } else {
7164 return 0;
7165 }
7166}
7167#endif
7168
7169#include "grn_ecmascript.h"
7170#include "grn_ecmascript.c"
7171
7172static grn_rc
7173grn_expr_parser_open(grn_ctx *ctx)
7174{
7175 if (!ctx->impl->parser) {
7176 ctx->impl->parser = grn_expr_parserAlloc(malloc);
7177 }
7178 return ctx->rc;
7179}
7180
7181#define PARSE(token) grn_expr_parser(ctx->impl->parser, (token), 0, q)
7182
7183static void
7184parse_query_accept_string(grn_ctx *ctx, efs_info *efsi,
7185 const char *str, unsigned int str_size)
7186{
7187 grn_obj *column, *token;
7188 grn_operator mode;
7189 int32_t weight;
7190
7191 GRN_PTR_PUT(ctx, &efsi->token_stack,
7192 grn_expr_add_str(ctx, efsi->e, str, str_size));
7193 {
7194 efs_info *q = efsi;
7195 PARSE(GRN_EXPR_TOKEN_QSTRING);
7196 }
7197
7198 GRN_PTR_POP(&efsi->token_stack, token);
7199 column = grn_ptr_value_at(&efsi->column_stack, -1);
7200 grn_expr_append_const(efsi->ctx, efsi->e, column, GRN_OP_GET_VALUE, 1);
7201 grn_expr_append_obj(efsi->ctx, efsi->e, token, GRN_OP_PUSH, 1);
7202
7203 mode = grn_int32_value_at(&efsi->mode_stack, -1);
7204 weight = grn_int32_value_at(&efsi->weight_stack, -1);
7205 switch (mode) {
7206 case GRN_OP_ASSIGN :
7207 grn_expr_append_op(efsi->ctx, efsi->e, mode, 2);
7208 break;
7209 case GRN_OP_NEAR :
7210 case GRN_OP_NEAR2 :
7211 {
7212 int max_interval;
7213 max_interval = grn_int32_value_at(&efsi->max_interval_stack, -1);
7214 grn_expr_append_const_int(efsi->ctx, efsi->e, max_interval,
7215 GRN_OP_PUSH, 1);
7216 if (weight == 0) {
7217 grn_expr_append_op(efsi->ctx, efsi->e, mode, 3);
7218 } else {
7219 grn_expr_append_const_int(efsi->ctx, efsi->e, weight, mode, 3);
7220 }
7221 }
7222 break;
7223 case GRN_OP_SIMILAR :
7224 {
7225 int similarity_threshold;
7226 similarity_threshold =
7227 grn_int32_value_at(&efsi->similarity_threshold_stack, -1);
7228 grn_expr_append_const_int(efsi->ctx, efsi->e, similarity_threshold,
7229 GRN_OP_PUSH, 1);
7230 if (weight == 0) {
7231 grn_expr_append_op(efsi->ctx, efsi->e, mode, 3);
7232 } else {
7233 grn_expr_append_const_int(efsi->ctx, efsi->e, weight, mode, 3);
7234 }
7235 }
7236 break;
7237 default :
7238 if (weight == 0) {
7239 grn_expr_append_op(efsi->ctx, efsi->e, mode, 2);
7240 } else {
7241 grn_expr_append_const_int(efsi->ctx, efsi->e, weight, mode, 2);
7242 }
7243 break;
7244 }
7245}
7246
7247static void
7248parse_query_flush_pending_token(grn_ctx *ctx, efs_info *q)
7249{
7250 const char *cur_keep;
7251
7252 if (!(q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR)) {
7253 return;
7254 }
7255
7256 if (q->pending_token.string_length == 0) {
7257 return;
7258 }
7259
7260 cur_keep = q->cur;
7261 q->cur = q->pending_token.string;
7262 if (q->pending_token.token == GRN_EXPR_TOKEN_ADJUST ||
7263 q->pending_token.token == GRN_EXPR_TOKEN_NEGATIVE) {
7264 GRN_INT32_PUT(ctx, &q->weight_stack, q->pending_token.weight);
7265 }
7266 PARSE(q->pending_token.token);
7267 q->cur = cur_keep;
7268
7269 q->pending_token.string = NULL;
7270 q->pending_token.string_length = 0;
7271 q->pending_token.token = 0;
7272 q->pending_token.weight = 0;
7273}
7274
7275static void
7276parse_query_accept_logical_op(grn_ctx *ctx,
7277 efs_info *q,
7278 const char *string,
7279 unsigned int string_length,
7280 int token)
7281{
7282 if (!(q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR)) {
7283 PARSE(token);
7284 return;
7285 }
7286
7287 if (q->pending_token.string_length > 0) {
7288 parse_query_accept_string(ctx,
7289 q,
7290 q->pending_token.string,
7291 q->pending_token.string_length);
7292 }
7293
7294 q->pending_token.string = string;
7295 q->pending_token.string_length = string_length;
7296 q->pending_token.token = token;
7297}
7298
7299static void
7300parse_query_accept_adjust(grn_ctx *ctx,
7301 efs_info *q,
7302 const char *string,
7303 unsigned int string_length,
7304 int token,
7305 int weight)
7306{
7307 if (!(q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR)) {
7308 GRN_INT32_PUT(ctx, &q->weight_stack, weight);
7309 PARSE(token);
7310 return;
7311 }
7312
7313 if (q->pending_token.string_length > 0) {
7314 parse_query_accept_string(ctx,
7315 q,
7316 q->pending_token.string,
7317 q->pending_token.string_length);
7318 }
7319
7320 q->pending_token.string = string;
7321 q->pending_token.string_length = string_length;
7322 q->pending_token.token = token;
7323 q->pending_token.weight = weight;
7324}
7325
7326static grn_rc
7327parse_query_word(grn_ctx *ctx, efs_info *q)
7328{
7329 const char *end;
7330 unsigned int len;
7331 GRN_BULK_REWIND(&q->buf);
7332 for (end = q->cur;; ) {
7333 /* null check and length check */
7334 if (!(len = grn_charlen(ctx, end, q->str_end))) {
7335 q->cur = q->str_end;
7336 break;
7337 }
7338 if (grn_isspace(end, ctx->encoding) ||
7339 *end == GRN_QUERY_PARENL || *end == GRN_QUERY_PARENR) {
7340 q->cur = end;
7341 break;
7342 }
7343 if (q->flags & GRN_EXPR_ALLOW_COLUMN && *end == GRN_QUERY_COLUMN) {
7344 grn_operator mode;
7345 grn_obj *c = grn_obj_column(ctx, q->table,
7346 GRN_TEXT_VALUE(&q->buf),
7347 GRN_TEXT_LEN(&q->buf));
7348 if (c && end + 1 < q->str_end) {
7349 switch (end[1]) {
7350 case '!' :
7351 mode = GRN_OP_NOT_EQUAL;
7352 q->cur = end + 2;
7353 break;
7354 case '=' :
7355 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
7356 mode = GRN_OP_ASSIGN;
7357 q->cur = end + 2;
7358 } else {
7359 mode = GRN_OP_EQUAL;
7360 q->cur = end + 1;
7361 }
7362 break;
7363 case '<' :
7364 if (end + 2 < q->str_end && end[2] == '=') {
7365 mode = GRN_OP_LESS_EQUAL;
7366 q->cur = end + 3;
7367 } else {
7368 mode = GRN_OP_LESS;
7369 q->cur = end + 2;
7370 }
7371 break;
7372 case '>' :
7373 if (end + 2 < q->str_end && end[2] == '=') {
7374 mode = GRN_OP_GREATER_EQUAL;
7375 q->cur = end + 3;
7376 } else {
7377 mode = GRN_OP_GREATER;
7378 q->cur = end + 2;
7379 }
7380 break;
7381 case '@' :
7382 mode = GRN_OP_MATCH;
7383 q->cur = end + 2;
7384 break;
7385 case '^' :
7386 mode = GRN_OP_PREFIX;
7387 q->cur = end + 2;
7388 break;
7389 case '$' :
7390 mode = GRN_OP_SUFFIX;
7391 q->cur = end + 2;
7392 break;
7393 case '~' :
7394 mode = GRN_OP_REGEXP;
7395 q->cur = end + 2;
7396 break;
7397 default :
7398 mode = GRN_OP_EQUAL;
7399 q->cur = end + 1;
7400 break;
7401 }
7402 } else if (q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR) {
7403 GRN_TEXT_PUT(ctx, &q->buf, end, len);
7404 end += len;
7405 continue;
7406 } else {
7407 ERR(GRN_INVALID_ARGUMENT, "column lookup failed");
7408 q->cur = q->str_end;
7409 return ctx->rc;
7410 }
7411 parse_query_flush_pending_token(ctx, q);
7412 PARSE(GRN_EXPR_TOKEN_IDENTIFIER);
7413 PARSE(GRN_EXPR_TOKEN_RELATIVE_OP);
7414
7415 grn_expr_take_obj(ctx, q->e, c);
7416 GRN_PTR_PUT(ctx, &q->column_stack, c);
7417 GRN_INT32_PUT(ctx, &q->mode_stack, mode);
7418
7419 return GRN_SUCCESS;
7420 } else if (GRN_TEXT_LEN(&q->buf) > 0 && *end == GRN_QUERY_PREFIX) {
7421 q->cur = end + 1;
7422 GRN_INT32_PUT(ctx, &q->mode_stack, GRN_OP_PREFIX);
7423 break;
7424 } else if (*end == GRN_QUERY_ESCAPE) {
7425 end += len;
7426 if (!(len = grn_charlen(ctx, end, q->str_end))) {
7427 q->cur = q->str_end;
7428 break;
7429 }
7430 }
7431 GRN_TEXT_PUT(ctx, &q->buf, end, len);
7432 end += len;
7433 }
7434 parse_query_flush_pending_token(ctx, q);
7435 parse_query_accept_string(ctx,
7436 q,
7437 GRN_TEXT_VALUE(&q->buf),
7438 GRN_TEXT_LEN(&q->buf));
7439
7440 return GRN_SUCCESS;
7441}
7442
7443static grn_rc
7444parse_query(grn_ctx *ctx, efs_info *q)
7445{
7446 int option = 0;
7447 grn_operator mode;
7448 efs_op op_, *op = &op_;
7449 grn_bool first_token = GRN_TRUE;
7450 grn_bool only_first_and = GRN_FALSE;
7451 grn_bool block_started = GRN_FALSE;
7452
7453 op->op = q->default_op;
7454 op->weight = DEFAULT_WEIGHT;
7455 while (!ctx->rc) {
7456 skip_space(ctx, q);
7457
7458 if (q->cur >= q->str_end) { goto exit; }
7459 if (*q->cur == '\0') { goto exit; }
7460
7461 only_first_and = GRN_FALSE;
7462 switch (*q->cur) {
7463 case GRN_QUERY_PARENR :
7464 if (q->paren_depth == 0 && q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR) {
7465 const char parenr = GRN_QUERY_PARENR;
7466 parse_query_flush_pending_token(ctx, q);
7467 parse_query_accept_string(ctx, q, &parenr, 1);
7468 } else {
7469 parse_query_flush_pending_token(ctx, q);
7470 PARSE(GRN_EXPR_TOKEN_PARENR);
7471 q->paren_depth--;
7472 }
7473 q->cur++;
7474 break;
7475 case GRN_QUERY_QUOTEL :
7476 q->cur++;
7477
7478 {
7479 grn_bool closed = GRN_FALSE;
7480 const char *start, *s;
7481 start = s = q->cur;
7482 GRN_BULK_REWIND(&q->buf);
7483 while (1) {
7484 unsigned int len;
7485 if (s >= q->str_end) {
7486 q->cur = s;
7487 break;
7488 }
7489 len = grn_charlen(ctx, s, q->str_end);
7490 if (len == 0) {
7491 /* invalid string containing malformed multibyte char */
7492 goto exit;
7493 } else if (len == 1) {
7494 if (*s == GRN_QUERY_QUOTER) {
7495 q->cur = s + 1;
7496 closed = GRN_TRUE;
7497 break;
7498 } else if (*s == GRN_QUERY_ESCAPE && s + 1 < q->str_end) {
7499 s++;
7500 len = grn_charlen(ctx, s, q->str_end);
7501 }
7502 }
7503 GRN_TEXT_PUT(ctx, &q->buf, s, len);
7504 s += len;
7505 }
7506 if (!closed && (q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR)) {
7507 q->cur = start - 1;
7508 parse_query_word(ctx, q);
7509 } else {
7510 parse_query_flush_pending_token(ctx, q);
7511 parse_query_accept_string(ctx,
7512 q,
7513 GRN_TEXT_VALUE(&q->buf),
7514 GRN_TEXT_LEN(&q->buf));
7515 }
7516 }
7517
7518 break;
7519 case GRN_QUERY_PREFIX :
7520 q->cur++;
7521 if (parse_query_op(q, op, &mode, &option)) {
7522 switch (mode) {
7523 case GRN_OP_NEAR :
7524 case GRN_OP_NEAR2 :
7525 GRN_INT32_PUT(ctx, &q->max_interval_stack, option);
7526 break;
7527 case GRN_OP_SIMILAR :
7528 GRN_INT32_PUT(ctx, &q->similarity_threshold_stack, option);
7529 break;
7530 default :
7531 break;
7532 }
7533 GRN_INT32_PUT(ctx, &q->mode_stack, mode);
7534 parse_query_flush_pending_token(ctx, q);
7535 PARSE(GRN_EXPR_TOKEN_RELATIVE_OP);
7536 } else {
7537 q->cur--;
7538 parse_query_word(ctx, q);
7539 }
7540 break;
7541 case GRN_QUERY_AND :
7542 if (first_token) {
7543 only_first_and = GRN_TRUE;
7544 } else {
7545 op->op = GRN_OP_AND;
7546 parse_query_accept_logical_op(ctx,
7547 q,
7548 q->cur, 1,
7549 GRN_EXPR_TOKEN_LOGICAL_AND);
7550 }
7551 q->cur++;
7552 break;
7553 case GRN_QUERY_AND_NOT :
7554 if (first_token) {
7555 if (q->flags & GRN_EXPR_ALLOW_LEADING_NOT) {
7556 grn_obj *all_records = grn_ctx_get(ctx, "all_records", 11);
7557 if (all_records) {
7558 /* dummy token */
7559 PARSE(GRN_EXPR_TOKEN_QSTRING);
7560 grn_expr_append_obj(ctx, q->e, all_records, GRN_OP_PUSH, 1);
7561 grn_expr_append_op(ctx, q->e, GRN_OP_CALL, 0);
7562 }
7563 } else if (q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR) {
7564 parse_query_flush_pending_token(ctx, q);
7565 parse_query_accept_string(ctx, q, q->cur, 1);
7566 q->cur++;
7567 break;
7568 }
7569 }
7570 op->op = GRN_OP_AND_NOT;
7571 parse_query_accept_logical_op(ctx,
7572 q,
7573 q->cur, 1,
7574 GRN_EXPR_TOKEN_LOGICAL_AND_NOT);
7575 q->cur++;
7576 break;
7577 case GRN_QUERY_ADJ_INC :
7578 if (op->weight < 127) { op->weight++; }
7579 op->op = GRN_OP_ADJUST;
7580 parse_query_accept_adjust(ctx,
7581 q,
7582 q->cur, 1,
7583 GRN_EXPR_TOKEN_ADJUST,
7584 op->weight);
7585 q->cur++;
7586 break;
7587 case GRN_QUERY_ADJ_DEC :
7588 if (op->weight > -128) { op->weight--; }
7589 op->op = GRN_OP_ADJUST;
7590 parse_query_accept_adjust(ctx,
7591 q,
7592 q->cur, 1,
7593 GRN_EXPR_TOKEN_ADJUST,
7594 op->weight);
7595 q->cur++;
7596 break;
7597 case GRN_QUERY_ADJ_NEG :
7598 if (first_token) {
7599 parse_query_flush_pending_token(ctx, q);
7600 parse_query_accept_string(ctx, q, q->cur, 1);
7601 } else {
7602 op->op = GRN_OP_ADJUST;
7603 parse_query_accept_adjust(ctx,
7604 q,
7605 q->cur, 1,
7606 GRN_EXPR_TOKEN_NEGATIVE,
7607 -DEFAULT_WEIGHT);
7608 }
7609 q->cur++;
7610 break;
7611 case GRN_QUERY_PARENL :
7612 parse_query_flush_pending_token(ctx, q);
7613 PARSE(GRN_EXPR_TOKEN_PARENL);
7614 q->cur++;
7615 q->paren_depth++;
7616 block_started = GRN_TRUE;
7617 break;
7618 case 'O' :
7619 if (q->cur + 2 < q->str_end && q->cur[1] == 'R' && q->cur[2] == ' ') {
7620 if (first_token && (q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR)) {
7621 parse_query_flush_pending_token(ctx, q);
7622 parse_query_accept_string(ctx, q, q->cur, 2);
7623 } else {
7624 parse_query_accept_logical_op(ctx,
7625 q,
7626 q->cur, 2,
7627 GRN_EXPR_TOKEN_LOGICAL_OR);
7628 }
7629 q->cur += 2;
7630 break;
7631 }
7632 /* fallthru */
7633 default :
7634 parse_query_word(ctx, q);
7635 break;
7636 }
7637 first_token = block_started;
7638 block_started = GRN_FALSE;
7639 }
7640exit :
7641 if (q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR) {
7642 if (q->pending_token.string_length > 0) {
7643 parse_query_accept_string(ctx,
7644 q,
7645 q->pending_token.string,
7646 q->pending_token.string_length);
7647 } else if (only_first_and) {
7648 const char query_and[] = {GRN_QUERY_AND};
7649 parse_query_accept_string(ctx,
7650 q,
7651 query_and,
7652 1);
7653 }
7654 if (q->paren_depth > 0) {
7655 int paren_depth = q->paren_depth;
7656 while (paren_depth > 0) {
7657 const char parenl = GRN_QUERY_PARENL;
7658 parse_query_accept_string(ctx, q, &parenl, 1);
7659 PARSE(GRN_EXPR_TOKEN_PARENR);
7660 paren_depth--;
7661 }
7662 }
7663 }
7664 PARSE(0);
7665 return GRN_SUCCESS;
7666}
7667
7668static grn_rc
7669get_string(grn_ctx *ctx, efs_info *q, char quote)
7670{
7671 const char *s;
7672 unsigned int len;
7673 grn_rc rc = GRN_END_OF_DATA;
7674 GRN_BULK_REWIND(&q->buf);
7675 for (s = q->cur + 1; s < q->str_end; s += len) {
7676 if (!(len = grn_charlen(ctx, s, q->str_end))) { break; }
7677 if (len == 1) {
7678 if (*s == quote) {
7679 s++;
7680 rc = GRN_SUCCESS;
7681 break;
7682 }
7683 if (*s == GRN_QUERY_ESCAPE && s + 1 < q->str_end) {
7684 s++;
7685 if (!(len = grn_charlen(ctx, s, q->str_end))) { break; }
7686 }
7687 }
7688 GRN_TEXT_PUT(ctx, &q->buf, s, len);
7689 }
7690 q->cur = s;
7691 return rc;
7692}
7693
7694static grn_obj *
7695resolve_top_level_name(grn_ctx *ctx, const char *name, unsigned int name_size)
7696{
7697 unsigned int i;
7698 unsigned int first_delimiter_position = 0;
7699 unsigned int n_delimiters = 0;
7700 grn_obj *top_level_object;
7701 grn_obj *object;
7702
7703 for (i = 0; i < name_size; i++) {
7704 if (name[i] != GRN_DB_DELIMITER) {
7705 continue;
7706 }
7707
7708 if (n_delimiters == 0) {
7709 first_delimiter_position = i;
7710 }
7711 n_delimiters++;
7712 }
7713
7714 if (n_delimiters < 2) {
7715 return grn_ctx_get(ctx, name, name_size);
7716 }
7717
7718 top_level_object = grn_ctx_get(ctx, name, first_delimiter_position);
7719 if (!top_level_object) {
7720 return NULL;
7721 }
7722 object = grn_obj_column(ctx, top_level_object,
7723 name + first_delimiter_position + 1,
7724 name_size - first_delimiter_position - 1);
7725 grn_obj_unlink(ctx, top_level_object);
7726 return object;
7727}
7728
7729static grn_rc
7730get_identifier(grn_ctx *ctx, efs_info *q, grn_obj *name_resolve_context)
7731{
7732 const char *s;
7733 unsigned int len;
7734 grn_rc rc = GRN_SUCCESS;
7735 for (s = q->cur; s < q->str_end; s += len) {
7736 if (!(len = grn_charlen(ctx, s, q->str_end))) {
7737 rc = GRN_END_OF_DATA;
7738 goto exit;
7739 }
7740 if (grn_isspace(s, ctx->encoding)) { goto done; }
7741 if (len == 1) {
7742 switch (*s) {
7743 case '\0' : case '(' : case ')' : case '{' : case '}' :
7744 case '[' : case ']' : case ',' : case ':' : case '@' :
7745 case '?' : case '"' : case '*' : case '+' : case '-' :
7746 case '|' : case '/' : case '%' : case '!' : case '^' :
7747 case '&' : case '>' : case '<' : case '=' : case '~' :
7748 /* case '.' : */
7749 goto done;
7750 break;
7751 }
7752 }
7753 }
7754done :
7755 len = s - q->cur;
7756 switch (*q->cur) {
7757 case 'd' :
7758 if (len == 6 && !memcmp(q->cur, "delete", 6)) {
7759 PARSE(GRN_EXPR_TOKEN_DELETE);
7760 goto exit;
7761 }
7762 break;
7763 case 'f' :
7764 if (len == 5 && !memcmp(q->cur, "false", 5)) {
7765 grn_obj buf;
7766 PARSE(GRN_EXPR_TOKEN_BOOLEAN);
7767 GRN_BOOL_INIT(&buf, 0);
7768 GRN_BOOL_SET(ctx, &buf, 0);
7769 grn_expr_append_const(ctx, q->e, &buf, GRN_OP_PUSH, 1);
7770 GRN_OBJ_FIN(ctx, &buf);
7771 goto exit;
7772 }
7773 break;
7774 case 'i' :
7775 if (len == 2 && !memcmp(q->cur, "in", 2)) {
7776 PARSE(GRN_EXPR_TOKEN_IN);
7777 goto exit;
7778 }
7779 break;
7780 case 'n' :
7781 if (len == 4 && !memcmp(q->cur, "null", 4)) {
7782 grn_obj buf;
7783 PARSE(GRN_EXPR_TOKEN_NULL);
7784 GRN_VOID_INIT(&buf);
7785 grn_expr_append_const(ctx, q->e, &buf, GRN_OP_PUSH, 1);
7786 GRN_OBJ_FIN(ctx, &buf);
7787 goto exit;
7788 }
7789 break;
7790 case 't' :
7791 if (len == 4 && !memcmp(q->cur, "true", 4)) {
7792 grn_obj buf;
7793 PARSE(GRN_EXPR_TOKEN_BOOLEAN);
7794 GRN_BOOL_INIT(&buf, 0);
7795 GRN_BOOL_SET(ctx, &buf, 1);
7796 grn_expr_append_const(ctx, q->e, &buf, GRN_OP_PUSH, 1);
7797 GRN_OBJ_FIN(ctx, &buf);
7798 goto exit;
7799 }
7800 break;
7801 }
7802 {
7803 grn_obj *obj;
7804 const char *name = q->cur;
7805 unsigned int name_size = s - q->cur;
7806 if (name_resolve_context) {
7807 if ((obj = grn_obj_column(ctx, name_resolve_context, name, name_size))) {
7808 if (obj->header.type == GRN_ACCESSOR) {
7809 grn_expr_take_obj(ctx, q->e, obj);
7810 }
7811 PARSE(GRN_EXPR_TOKEN_IDENTIFIER);
7812 grn_expr_append_obj(ctx, q->e, obj, GRN_OP_GET_VALUE, 2);
7813 goto exit;
7814 }
7815 }
7816 if ((obj = grn_expr_get_var(ctx, q->e, name, name_size))) {
7817 PARSE(GRN_EXPR_TOKEN_IDENTIFIER);
7818 grn_expr_append_obj(ctx, q->e, obj, GRN_OP_PUSH, 1);
7819 goto exit;
7820 }
7821 if ((obj = grn_obj_column(ctx, q->table, name, name_size))) {
7822 if (obj->header.type == GRN_ACCESSOR) {
7823 grn_expr_take_obj(ctx, q->e, obj);
7824 }
7825 PARSE(GRN_EXPR_TOKEN_IDENTIFIER);
7826 grn_expr_append_obj(ctx, q->e, obj, GRN_OP_GET_VALUE, 1);
7827 goto exit;
7828 }
7829 if ((obj = resolve_top_level_name(ctx, name, name_size))) {
7830 if (obj->header.type == GRN_ACCESSOR) {
7831 grn_expr_take_obj(ctx, q->e, obj);
7832 }
7833 PARSE(GRN_EXPR_TOKEN_IDENTIFIER);
7834 grn_expr_append_obj(ctx, q->e, obj, GRN_OP_PUSH, 1);
7835 goto exit;
7836 }
7837 if (q->flags & GRN_EXPR_SYNTAX_OUTPUT_COLUMNS) {
7838 PARSE(GRN_EXPR_TOKEN_NONEXISTENT_COLUMN);
7839 } else {
7840 rc = GRN_SYNTAX_ERROR;
7841 ERR(rc,
7842 "[expr][parse] unknown identifier: <%.*s>",
7843 (int)name_size,
7844 name);
7845 }
7846 }
7847exit :
7848 q->cur = s;
7849 return rc;
7850}
7851
7852static void
7853set_tos_minor_to_curr(grn_ctx *ctx, efs_info *q)
7854{
7855 yyParser *parser = ctx->impl->parser;
7856 yyStackEntry *yytos = parser->yytos;
7857 yytos->minor.yy0 = ((grn_expr *)(q->e))->codes_curr;
7858}
7859
7860static grn_obj *
7861parse_script_extract_name_resolve_context(grn_ctx *ctx, efs_info *q)
7862{
7863 grn_expr *expr = (grn_expr *)(q->e);
7864 grn_expr_code *code_start;
7865 grn_expr_code *code_last;
7866
7867 if (expr->codes_curr == 0) {
7868 return NULL;
7869 }
7870
7871 code_start = expr->codes;
7872 code_last = code_start + (expr->codes_curr - 1);
7873 switch (code_last->op) {
7874 case GRN_OP_GET_MEMBER :
7875 {
7876 unsigned int n_used_codes_for_key;
7877 grn_expr_code *code_key;
7878 grn_expr_code *code_receiver;
7879
7880 code_key = code_last - 1;
7881 if (code_key < code_start) {
7882 return NULL;
7883 }
7884
7885 n_used_codes_for_key = grn_expr_code_n_used_codes(ctx,
7886 code_start,
7887 code_key);
7888 if (n_used_codes_for_key == 0) {
7889 return NULL;
7890 }
7891 code_receiver = code_key - n_used_codes_for_key;
7892 if (code_receiver < code_start) {
7893 return NULL;
7894 }
7895 return code_receiver->value;
7896 }
7897 break;
7898 default :
7899 /* TODO: Support other operators. */
7900 return NULL;
7901 break;
7902 }
7903}
7904
7905static grn_rc
7906parse_script(grn_ctx *ctx, efs_info *q)
7907{
7908 grn_rc rc = GRN_SUCCESS;
7909 grn_obj *name_resolve_context = NULL;
7910 for (;;) {
7911 grn_obj *current_name_resolve_context = name_resolve_context;
7912 name_resolve_context = NULL;
7913 skip_space(ctx, q);
7914 if (q->cur >= q->str_end) { rc = GRN_END_OF_DATA; goto exit; }
7915 switch (*q->cur) {
7916 case '\0' :
7917 rc = GRN_END_OF_DATA;
7918 goto exit;
7919 break;
7920 case '(' :
7921 PARSE(GRN_EXPR_TOKEN_PARENL);
7922 q->cur++;
7923 break;
7924 case ')' :
7925 PARSE(GRN_EXPR_TOKEN_PARENR);
7926 q->cur++;
7927 break;
7928 case '{' :
7929 PARSE(GRN_EXPR_TOKEN_BRACEL);
7930 q->cur++;
7931 break;
7932 case '}' :
7933 PARSE(GRN_EXPR_TOKEN_BRACER);
7934 q->cur++;
7935 break;
7936 case '[' :
7937 PARSE(GRN_EXPR_TOKEN_BRACKETL);
7938 q->cur++;
7939 break;
7940 case ']' :
7941 PARSE(GRN_EXPR_TOKEN_BRACKETR);
7942 q->cur++;
7943 break;
7944 case ',' :
7945 PARSE(GRN_EXPR_TOKEN_COMMA);
7946 q->cur++;
7947 break;
7948 case '.' :
7949 PARSE(GRN_EXPR_TOKEN_DOT);
7950 name_resolve_context = parse_script_extract_name_resolve_context(ctx, q);
7951 q->cur++;
7952 break;
7953 case ':' :
7954 PARSE(GRN_EXPR_TOKEN_COLON);
7955 q->cur++;
7956 set_tos_minor_to_curr(ctx, q);
7957 grn_expr_append_op(ctx, q->e, GRN_OP_JUMP, 0);
7958 break;
7959 case '@' :
7960 switch (q->cur[1]) {
7961 case '^' :
7962 PARSE(GRN_EXPR_TOKEN_PREFIX);
7963 q->cur += 2;
7964 break;
7965 case '$' :
7966 PARSE(GRN_EXPR_TOKEN_SUFFIX);
7967 q->cur += 2;
7968 break;
7969 case '~' :
7970 PARSE(GRN_EXPR_TOKEN_REGEXP);
7971 q->cur += 2;
7972 break;
7973 default :
7974 PARSE(GRN_EXPR_TOKEN_MATCH);
7975 q->cur++;
7976 break;
7977 }
7978 break;
7979 case '~' :
7980 PARSE(GRN_EXPR_TOKEN_BITWISE_NOT);
7981 q->cur++;
7982 break;
7983 case '?' :
7984 PARSE(GRN_EXPR_TOKEN_QUESTION);
7985 q->cur++;
7986 set_tos_minor_to_curr(ctx, q);
7987 grn_expr_append_op(ctx, q->e, GRN_OP_CJUMP, 0);
7988 break;
7989 case '"' :
7990 if ((rc = get_string(ctx, q, '"'))) { goto exit; }
7991 PARSE(GRN_EXPR_TOKEN_STRING);
7992 grn_expr_append_const(ctx, q->e, &q->buf, GRN_OP_PUSH, 1);
7993 break;
7994 case '\'' :
7995 if ((rc = get_string(ctx, q, '\''))) { goto exit; }
7996 PARSE(GRN_EXPR_TOKEN_STRING);
7997 grn_expr_append_const(ctx, q->e, &q->buf, GRN_OP_PUSH, 1);
7998 break;
7999 case '*' :
8000 switch (q->cur[1]) {
8001 case 'N' :
8002 {
8003 const char *next_start = q->cur + 2;
8004 const char *end;
8005 int max_interval;
8006 max_interval = grn_atoi(next_start, q->str_end, &end);
8007 if (end == next_start) {
8008 max_interval = DEFAULT_MAX_INTERVAL;
8009 } else {
8010 next_start = end;
8011 }
8012 GRN_INT32_PUT(ctx, &q->max_interval_stack, max_interval);
8013 PARSE(GRN_EXPR_TOKEN_NEAR);
8014 q->cur = next_start;
8015 }
8016 break;
8017 case 'S' :
8018 PARSE(GRN_EXPR_TOKEN_SIMILAR);
8019 q->cur += 2;
8020 break;
8021 case 'T' :
8022 PARSE(GRN_EXPR_TOKEN_TERM_EXTRACT);
8023 q->cur += 2;
8024 break;
8025 case '>' :
8026 PARSE(GRN_EXPR_TOKEN_ADJUST);
8027 q->cur += 2;
8028 break;
8029 case '<' :
8030 PARSE(GRN_EXPR_TOKEN_ADJUST);
8031 q->cur += 2;
8032 break;
8033 case '~' :
8034 PARSE(GRN_EXPR_TOKEN_ADJUST);
8035 q->cur += 2;
8036 break;
8037 case '=' :
8038 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8039 PARSE(GRN_EXPR_TOKEN_STAR_ASSIGN);
8040 q->cur += 2;
8041 } else {
8042 ERR(GRN_UPDATE_NOT_ALLOWED,
8043 "'*=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8044 }
8045 break;
8046 default :
8047 PARSE(GRN_EXPR_TOKEN_STAR);
8048 q->cur++;
8049 break;
8050 }
8051 break;
8052 case '+' :
8053 switch (q->cur[1]) {
8054 case '+' :
8055 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8056 PARSE(GRN_EXPR_TOKEN_INCR);
8057 q->cur += 2;
8058 } else {
8059 ERR(GRN_UPDATE_NOT_ALLOWED,
8060 "'++' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8061 }
8062 break;
8063 case '=' :
8064 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8065 PARSE(GRN_EXPR_TOKEN_PLUS_ASSIGN);
8066 q->cur += 2;
8067 } else {
8068 ERR(GRN_UPDATE_NOT_ALLOWED,
8069 "'+=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8070 }
8071 break;
8072 default :
8073 PARSE(GRN_EXPR_TOKEN_PLUS);
8074 q->cur++;
8075 break;
8076 }
8077 break;
8078 case '-' :
8079 switch (q->cur[1]) {
8080 case '-' :
8081 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8082 PARSE(GRN_EXPR_TOKEN_DECR);
8083 q->cur += 2;
8084 } else {
8085 ERR(GRN_UPDATE_NOT_ALLOWED,
8086 "'--' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8087 }
8088 break;
8089 case '=' :
8090 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8091 PARSE(GRN_EXPR_TOKEN_MINUS_ASSIGN);
8092 q->cur += 2;
8093 } else {
8094 ERR(GRN_UPDATE_NOT_ALLOWED,
8095 "'-=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8096 }
8097 break;
8098 default :
8099 PARSE(GRN_EXPR_TOKEN_MINUS);
8100 q->cur++;
8101 break;
8102 }
8103 break;
8104 case '|' :
8105 switch (q->cur[1]) {
8106 case '|' :
8107 PARSE(GRN_EXPR_TOKEN_LOGICAL_OR);
8108 q->cur += 2;
8109 break;
8110 case '=' :
8111 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8112 PARSE(GRN_EXPR_TOKEN_OR_ASSIGN);
8113 q->cur += 2;
8114 } else {
8115 ERR(GRN_UPDATE_NOT_ALLOWED,
8116 "'|=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8117 }
8118 break;
8119 default :
8120 PARSE(GRN_EXPR_TOKEN_BITWISE_OR);
8121 q->cur++;
8122 break;
8123 }
8124 break;
8125 case '/' :
8126 switch (q->cur[1]) {
8127 case '=' :
8128 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8129 PARSE(GRN_EXPR_TOKEN_SLASH_ASSIGN);
8130 q->cur += 2;
8131 } else {
8132 ERR(GRN_UPDATE_NOT_ALLOWED,
8133 "'/=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8134 }
8135 break;
8136 default :
8137 PARSE(GRN_EXPR_TOKEN_SLASH);
8138 q->cur++;
8139 break;
8140 }
8141 break;
8142 case '%' :
8143 switch (q->cur[1]) {
8144 case '=' :
8145 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8146 PARSE(GRN_EXPR_TOKEN_MOD_ASSIGN);
8147 q->cur += 2;
8148 } else {
8149 ERR(GRN_UPDATE_NOT_ALLOWED,
8150 "'%%=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8151 }
8152 break;
8153 default :
8154 PARSE(GRN_EXPR_TOKEN_MOD);
8155 q->cur++;
8156 break;
8157 }
8158 break;
8159 case '!' :
8160 switch (q->cur[1]) {
8161 case '=' :
8162 PARSE(GRN_EXPR_TOKEN_NOT_EQUAL);
8163 q->cur += 2;
8164 break;
8165 default :
8166 PARSE(GRN_EXPR_TOKEN_NOT);
8167 q->cur++;
8168 break;
8169 }
8170 break;
8171 case '^' :
8172 switch (q->cur[1]) {
8173 case '=' :
8174 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8175 q->cur += 2;
8176 PARSE(GRN_EXPR_TOKEN_XOR_ASSIGN);
8177 } else {
8178 ERR(GRN_UPDATE_NOT_ALLOWED,
8179 "'^=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8180 }
8181 break;
8182 default :
8183 PARSE(GRN_EXPR_TOKEN_BITWISE_XOR);
8184 q->cur++;
8185 break;
8186 }
8187 break;
8188 case '&' :
8189 switch (q->cur[1]) {
8190 case '&' :
8191 PARSE(GRN_EXPR_TOKEN_LOGICAL_AND);
8192 q->cur += 2;
8193 break;
8194 case '=' :
8195 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8196 PARSE(GRN_EXPR_TOKEN_AND_ASSIGN);
8197 q->cur += 2;
8198 } else {
8199 ERR(GRN_UPDATE_NOT_ALLOWED,
8200 "'&=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8201 }
8202 break;
8203 case '!' :
8204 PARSE(GRN_EXPR_TOKEN_LOGICAL_AND_NOT);
8205 q->cur += 2;
8206 break;
8207 default :
8208 PARSE(GRN_EXPR_TOKEN_BITWISE_AND);
8209 q->cur++;
8210 break;
8211 }
8212 break;
8213 case '>' :
8214 switch (q->cur[1]) {
8215 case '>' :
8216 switch (q->cur[2]) {
8217 case '>' :
8218 switch (q->cur[3]) {
8219 case '=' :
8220 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8221 PARSE(GRN_EXPR_TOKEN_SHIFTRR_ASSIGN);
8222 q->cur += 4;
8223 } else {
8224 ERR(GRN_UPDATE_NOT_ALLOWED,
8225 "'>>>=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8226 }
8227 break;
8228 default :
8229 PARSE(GRN_EXPR_TOKEN_SHIFTRR);
8230 q->cur += 3;
8231 break;
8232 }
8233 break;
8234 case '=' :
8235 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8236 PARSE(GRN_EXPR_TOKEN_SHIFTR_ASSIGN);
8237 q->cur += 3;
8238 } else {
8239 ERR(GRN_UPDATE_NOT_ALLOWED,
8240 "'>>=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8241 }
8242 break;
8243 default :
8244 PARSE(GRN_EXPR_TOKEN_SHIFTR);
8245 q->cur += 2;
8246 break;
8247 }
8248 break;
8249 case '=' :
8250 PARSE(GRN_EXPR_TOKEN_GREATER_EQUAL);
8251 q->cur += 2;
8252 break;
8253 default :
8254 PARSE(GRN_EXPR_TOKEN_GREATER);
8255 q->cur++;
8256 break;
8257 }
8258 break;
8259 case '<' :
8260 switch (q->cur[1]) {
8261 case '<' :
8262 switch (q->cur[2]) {
8263 case '=' :
8264 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8265 PARSE(GRN_EXPR_TOKEN_SHIFTL_ASSIGN);
8266 q->cur += 3;
8267 } else {
8268 ERR(GRN_UPDATE_NOT_ALLOWED,
8269 "'<<=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8270 }
8271 break;
8272 default :
8273 PARSE(GRN_EXPR_TOKEN_SHIFTL);
8274 q->cur += 2;
8275 break;
8276 }
8277 break;
8278 case '=' :
8279 PARSE(GRN_EXPR_TOKEN_LESS_EQUAL);
8280 q->cur += 2;
8281 break;
8282 default :
8283 PARSE(GRN_EXPR_TOKEN_LESS);
8284 q->cur++;
8285 break;
8286 }
8287 break;
8288 case '=' :
8289 switch (q->cur[1]) {
8290 case '=' :
8291 PARSE(GRN_EXPR_TOKEN_EQUAL);
8292 q->cur += 2;
8293 break;
8294 default :
8295 if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
8296 PARSE(GRN_EXPR_TOKEN_ASSIGN);
8297 q->cur++;
8298 } else {
8299 ERR(GRN_UPDATE_NOT_ALLOWED,
8300 "'=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str);
8301 }
8302 break;
8303 }
8304 break;
8305 case '0' : case '1' : case '2' : case '3' : case '4' :
8306 case '5' : case '6' : case '7' : case '8' : case '9' :
8307 {
8308 const char *rest;
8309 int64_t int64 = grn_atoll(q->cur, q->str_end, &rest);
8310 // checks to see grn_atoll was appropriate
8311 // (NOTE: *q->cur begins with a digit. Thus, grn_atoll parses at least
8312 // one char.)
8313 if (q->str_end != rest &&
8314 (*rest == '.' || *rest == 'e' || *rest == 'E' ||
8315 (*rest >= '0' && *rest <= '9'))) {
8316 char *rest_float;
8317 double d = strtod(q->cur, &rest_float);
8318 grn_obj floatbuf;
8319 GRN_FLOAT_INIT(&floatbuf, 0);
8320 GRN_FLOAT_SET(ctx, &floatbuf, d);
8321 grn_expr_append_const(ctx, q->e, &floatbuf, GRN_OP_PUSH, 1);
8322 rest = rest_float;
8323 } else {
8324 const char *rest64 = rest;
8325 grn_atoui(q->cur, q->str_end, &rest);
8326 // checks to see grn_atoi failed (see above NOTE)
8327 if ((int64 > UINT32_MAX) ||
8328 (q->str_end != rest && *rest >= '0' && *rest <= '9')) {
8329 grn_obj int64buf;
8330 GRN_INT64_INIT(&int64buf, 0);
8331 GRN_INT64_SET(ctx, &int64buf, int64);
8332 grn_expr_append_const(ctx, q->e, &int64buf, GRN_OP_PUSH, 1);
8333 rest = rest64;
8334 } else if (int64 > INT32_MAX || int64 < INT32_MIN) {
8335 grn_obj int64buf;
8336 GRN_INT64_INIT(&int64buf, 0);
8337 GRN_INT64_SET(ctx, &int64buf, int64);
8338 grn_expr_append_const(ctx, q->e, &int64buf, GRN_OP_PUSH, 1);
8339 } else {
8340 grn_obj int32buf;
8341 GRN_INT32_INIT(&int32buf, 0);
8342 GRN_INT32_SET(ctx, &int32buf, (int32_t)int64);
8343 grn_expr_append_const(ctx, q->e, &int32buf, GRN_OP_PUSH, 1);
8344 }
8345 }
8346 PARSE(GRN_EXPR_TOKEN_DECIMAL);
8347 q->cur = rest;
8348 }
8349 break;
8350 default :
8351 if ((rc = get_identifier(ctx, q, current_name_resolve_context))) {
8352 goto exit;
8353 }
8354 break;
8355 }
8356 if (ctx->rc) { rc = ctx->rc; break; }
8357 }
8358exit :
8359 PARSE(0);
8360 return rc;
8361}
8362
8363grn_rc
8364grn_expr_parse(grn_ctx *ctx, grn_obj *expr,
8365 const char *str, unsigned int str_size,
8366 grn_obj *default_column, grn_operator default_mode,
8367 grn_operator default_op, grn_expr_flags flags)
8368{
8369 efs_info efsi;
8370 if (grn_expr_parser_open(ctx)) { return ctx->rc; }
8371 GRN_API_ENTER;
8372 efsi.ctx = ctx;
8373 efsi.str = str;
8374 if ((efsi.v = grn_expr_get_var_by_offset(ctx, expr, 0)) &&
8375 (efsi.table = grn_ctx_at(ctx, efsi.v->header.domain))) {
8376 GRN_TEXT_INIT(&efsi.buf, 0);
8377 GRN_INT32_INIT(&efsi.op_stack, GRN_OBJ_VECTOR);
8378 GRN_INT32_INIT(&efsi.mode_stack, GRN_OBJ_VECTOR);
8379 GRN_INT32_INIT(&efsi.max_interval_stack, GRN_OBJ_VECTOR);
8380 GRN_INT32_INIT(&efsi.similarity_threshold_stack, GRN_OBJ_VECTOR);
8381 GRN_INT32_INIT(&efsi.weight_stack, GRN_OBJ_VECTOR);
8382 GRN_PTR_INIT(&efsi.column_stack, GRN_OBJ_VECTOR, GRN_ID_NIL);
8383 GRN_PTR_INIT(&efsi.token_stack, GRN_OBJ_VECTOR, GRN_ID_NIL);
8384 efsi.e = expr;
8385 efsi.str = str;
8386 efsi.cur = str;
8387 efsi.str_end = str + str_size;
8388 efsi.default_column = default_column;
8389 GRN_PTR_PUT(ctx, &efsi.column_stack, default_column);
8390 GRN_INT32_PUT(ctx, &efsi.op_stack, default_op);
8391 GRN_INT32_PUT(ctx, &efsi.mode_stack, default_mode);
8392 GRN_INT32_PUT(ctx, &efsi.weight_stack, 0);
8393 efsi.default_flags = efsi.flags = flags;
8394 efsi.escalation_threshold = GRN_DEFAULT_MATCH_ESCALATION_THRESHOLD;
8395 efsi.escalation_decaystep = DEFAULT_DECAYSTEP;
8396 efsi.weight_offset = 0;
8397 memset(&(efsi.opt), 0, sizeof(grn_select_optarg));
8398 efsi.opt.weight_vector = NULL;
8399 efsi.weight_set = NULL;
8400 efsi.object_literal = NULL;
8401 efsi.paren_depth = 0;
8402 efsi.pending_token.string = NULL;
8403 efsi.pending_token.string_length = 0;
8404 efsi.pending_token.token = 0;
8405
8406 if (flags & (GRN_EXPR_SYNTAX_SCRIPT |
8407 GRN_EXPR_SYNTAX_OUTPUT_COLUMNS |
8408 GRN_EXPR_SYNTAX_ADJUSTER)) {
8409 efs_info *q = &efsi;
8410 if (flags & GRN_EXPR_SYNTAX_OUTPUT_COLUMNS) {
8411 PARSE(GRN_EXPR_TOKEN_START_OUTPUT_COLUMNS);
8412 } else if (flags & GRN_EXPR_SYNTAX_ADJUSTER) {
8413 PARSE(GRN_EXPR_TOKEN_START_ADJUSTER);
8414 }
8415 parse_script(ctx, &efsi);
8416 } else {
8417 parse_query(ctx, &efsi);
8418 }
8419
8420 /*
8421 grn_obj strbuf;
8422 GRN_TEXT_INIT(&strbuf, 0);
8423 grn_expr_inspect_internal(ctx, &strbuf, expr);
8424 GRN_TEXT_PUTC(ctx, &strbuf, '\0');
8425 GRN_LOG(ctx, GRN_LOG_NOTICE, "query=(%s)", GRN_TEXT_VALUE(&strbuf));
8426 GRN_OBJ_FIN(ctx, &strbuf);
8427 */
8428
8429 /*
8430 efsi.opt.vector_size = DEFAULT_WEIGHT_VECTOR_SIZE;
8431 efsi.opt.func = efsi.weight_set ? section_weight_cb : NULL;
8432 efsi.opt.func_arg = efsi.weight_set;
8433 efsi.snip_conds = NULL;
8434 */
8435 GRN_OBJ_FIN(ctx, &efsi.op_stack);
8436 GRN_OBJ_FIN(ctx, &efsi.mode_stack);
8437 GRN_OBJ_FIN(ctx, &efsi.max_interval_stack);
8438 GRN_OBJ_FIN(ctx, &efsi.similarity_threshold_stack);
8439 GRN_OBJ_FIN(ctx, &efsi.weight_stack);
8440 GRN_OBJ_FIN(ctx, &efsi.column_stack);
8441 GRN_OBJ_FIN(ctx, &efsi.token_stack);
8442 GRN_OBJ_FIN(ctx, &efsi.buf);
8443 if (efsi.object_literal) {
8444 grn_obj *value;
8445 GRN_HASH_EACH(ctx, efsi.object_literal, i, NULL, NULL, (void **)&value, {
8446 GRN_OBJ_FIN(ctx, value);
8447 });
8448 grn_hash_close(ctx, efsi.object_literal);
8449 }
8450 } else {
8451 ERR(GRN_INVALID_ARGUMENT, "variable is not defined correctly");
8452 }
8453 GRN_API_RETURN(ctx->rc);
8454}
8455
8456grn_rc
8457grn_expr_parser_close(grn_ctx *ctx)
8458{
8459 if (ctx->impl->parser) {
8460 yyParser *parser = (yyParser *)ctx->impl->parser;
8461 ctx->impl->parser = NULL;
8462 grn_expr_parserFree(parser, free);
8463 }
8464 return ctx->rc;
8465}
8466
8467typedef grn_rc (*grn_expr_syntax_expand_term_func)(grn_ctx *ctx,
8468 const char *term,
8469 unsigned int term_len,
8470 grn_obj *substituted_term,
8471 grn_user_data *user_data);
8472static grn_rc
8473grn_expr_syntax_expand_term_by_func(grn_ctx *ctx,
8474 const char *term, unsigned int term_len,
8475 grn_obj *expanded_term,
8476 grn_user_data *user_data)
8477{
8478 grn_rc rc;
8479 grn_obj *expander = user_data->ptr;
8480 grn_obj grn_term;
8481 grn_obj *caller;
8482 grn_obj *rc_object;
8483 int nargs = 0;
8484
8485 GRN_TEXT_INIT(&grn_term, GRN_OBJ_DO_SHALLOW_COPY);
8486 GRN_TEXT_SET(ctx, &grn_term, term, term_len);
8487 grn_ctx_push(ctx, &grn_term);
8488 nargs++;
8489 grn_ctx_push(ctx, expanded_term);
8490 nargs++;
8491
8492 caller = grn_expr_create(ctx, NULL, 0);
8493 rc = grn_proc_call(ctx, expander, nargs, caller);
8494 GRN_OBJ_FIN(ctx, &grn_term);
8495 rc_object = grn_ctx_pop(ctx);
8496 rc = GRN_INT32_VALUE(rc_object);
8497 grn_obj_unlink(ctx, caller);
8498
8499 return rc;
8500}
8501
8502typedef struct {
8503 grn_obj *table;
8504 grn_obj *column;
8505} grn_expr_syntax_expand_term_by_column_data;
8506
8507static grn_rc
8508grn_expr_syntax_expand_term_by_column(grn_ctx *ctx,
8509 const char *term, unsigned int term_len,
8510 grn_obj *expanded_term,
8511 grn_user_data *user_data)
8512{
8513 grn_rc rc = GRN_END_OF_DATA;
8514 grn_id id;
8515 grn_expr_syntax_expand_term_by_column_data *data = user_data->ptr;
8516 grn_obj *table, *column;
8517
8518 table = data->table;
8519 column = data->column;
8520 if ((id = grn_table_get(ctx, table, term, term_len))) {
8521 if ((column->header.type == GRN_COLUMN_VAR_SIZE) &&
8522 ((column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_VECTOR)) {
8523 unsigned int i, n;
8524 grn_obj values;
8525 GRN_TEXT_INIT(&values, GRN_OBJ_VECTOR);
8526 grn_obj_get_value(ctx, column, id, &values);
8527 n = grn_vector_size(ctx, &values);
8528 if (n > 1) { GRN_TEXT_PUTC(ctx, expanded_term, '('); }
8529 for (i = 0; i < n; i++) {
8530 const char *value;
8531 unsigned int length;
8532 if (i > 0) {
8533 GRN_TEXT_PUTS(ctx, expanded_term, " OR ");
8534 }
8535 if (n > 1) { GRN_TEXT_PUTC(ctx, expanded_term, '('); }
8536 length = grn_vector_get_element(ctx, &values, i, &value, NULL, NULL);
8537 GRN_TEXT_PUT(ctx, expanded_term, value, length);
8538 if (n > 1) { GRN_TEXT_PUTC(ctx, expanded_term, ')'); }
8539 }
8540 if (n > 1) { GRN_TEXT_PUTC(ctx, expanded_term, ')'); }
8541 GRN_OBJ_FIN(ctx, &values);
8542 } else {
8543 grn_obj_get_value(ctx, column, id, expanded_term);
8544 }
8545 rc = GRN_SUCCESS;
8546 }
8547 return rc;
8548}
8549
8550typedef struct {
8551 grn_obj *table;
8552 grn_obj *term_column;
8553 grn_obj *expanded_term_column;
8554} grn_expr_syntax_expand_term_by_table_data;
8555
8556static grn_rc
8557grn_expr_syntax_expand_term_by_table(grn_ctx *ctx,
8558 const char *term, unsigned int term_len,
8559 grn_obj *expanded_term,
8560 grn_user_data *user_data)
8561{
8562 grn_rc rc = GRN_END_OF_DATA;
8563 grn_expr_syntax_expand_term_by_table_data *data = user_data->ptr;
8564 grn_obj *table;
8565 grn_obj *term_column;
8566 grn_obj *expanded_term_column;
8567 grn_obj *expression;
8568 grn_obj *variable;
8569 grn_obj *found_terms;
8570 int n_terms;
8571
8572 table = data->table;
8573 term_column = data->term_column;
8574 expanded_term_column = data->expanded_term_column;
8575
8576 GRN_EXPR_CREATE_FOR_QUERY(ctx, table, expression, variable);
8577 if (ctx->rc != GRN_SUCCESS) {
8578 ERR(ctx->rc,
8579 "[query][expand][table] "
8580 "failed to create expression: <%s>",
8581 ctx->errbuf);
8582 return ctx->rc;
8583 }
8584 grn_expr_append_const(ctx, expression, term_column, GRN_OP_GET_VALUE, 1);
8585 grn_expr_append_const_str(ctx, expression, term, term_len, GRN_OP_PUSH, 1);
8586 grn_expr_append_op(ctx, expression, GRN_OP_EQUAL, 2);
8587 if (ctx->rc != GRN_SUCCESS) {
8588 grn_obj_close(ctx, expression);
8589 ERR(ctx->rc,
8590 "[query][expand][table] "
8591 "failed to build expression: <%s>",
8592 ctx->errbuf);
8593 return ctx->rc;
8594 }
8595
8596 found_terms = grn_table_select(ctx, table, expression, NULL, GRN_OP_OR);
8597 grn_obj_close(ctx, expression);
8598 if (!found_terms) {
8599 ERR(ctx->rc,
8600 "[query][expand][table] "
8601 "failed to find term: <%.*s>: <%s>",
8602 (int)term_len,
8603 term,
8604 ctx->errbuf);
8605 return ctx->rc;
8606 }
8607
8608 n_terms = grn_table_size(ctx, found_terms);
8609 if (n_terms == 0) {
8610 grn_obj_close(ctx, found_terms);
8611 return rc;
8612 }
8613
8614 {
8615 int nth_term;
8616
8617 GRN_TEXT_PUTC(ctx, expanded_term, '(');
8618 nth_term = 0;
8619 GRN_TABLE_EACH_BEGIN(ctx, found_terms, cursor, id) {
8620 void *key;
8621 grn_id record_id;
8622
8623 grn_table_cursor_get_key(ctx, cursor, &key);
8624 record_id = *((grn_id *)key);
8625 if (grn_obj_is_vector_column(ctx, expanded_term_column)) {
8626 unsigned int j, n_values;
8627 grn_obj values;
8628 GRN_TEXT_INIT(&values, GRN_OBJ_VECTOR);
8629 grn_obj_get_value(ctx, expanded_term_column, record_id, &values);
8630 n_values = grn_vector_size(ctx, &values);
8631 n_terms += n_values - 1;
8632 for (j = 0; j < n_values; j++) {
8633 const char *value;
8634 unsigned int length;
8635 if (nth_term > 0) {
8636 GRN_TEXT_PUTS(ctx, expanded_term, " OR ");
8637 }
8638 if (n_terms > 1) {
8639 GRN_TEXT_PUTC(ctx, expanded_term, '(');
8640 }
8641 length = grn_vector_get_element(ctx, &values, j, &value, NULL, NULL);
8642 GRN_TEXT_PUT(ctx, expanded_term, value, length);
8643 if (n_terms > 1) {
8644 GRN_TEXT_PUTC(ctx, expanded_term, ')');
8645 }
8646 nth_term++;
8647 }
8648 GRN_OBJ_FIN(ctx, &values);
8649 } else {
8650 if (nth_term > 0) {
8651 GRN_TEXT_PUTS(ctx, expanded_term, " OR ");
8652 }
8653 if (n_terms > 1) { GRN_TEXT_PUTC(ctx, expanded_term, '('); }
8654 grn_obj_get_value(ctx, expanded_term_column, record_id, expanded_term);
8655 if (n_terms > 1) { GRN_TEXT_PUTC(ctx, expanded_term, ')'); }
8656 nth_term++;
8657 }
8658 } GRN_TABLE_EACH_END(ctx, cursor);
8659 GRN_TEXT_PUTC(ctx, expanded_term, ')');
8660 }
8661 rc = GRN_SUCCESS;
8662 grn_obj_close(ctx, found_terms);
8663
8664 return rc;
8665}
8666
8667static grn_rc
8668grn_expr_syntax_expand_query_terms(grn_ctx *ctx,
8669 const char *query, unsigned int query_size,
8670 grn_expr_flags flags,
8671 grn_obj *expanded_query,
8672 grn_expr_syntax_expand_term_func expand_term_func,
8673 grn_user_data *user_data)
8674{
8675 grn_obj buf;
8676 unsigned int len;
8677 const char *start, *cur = query, *query_end = query + (size_t)query_size;
8678 GRN_TEXT_INIT(&buf, 0);
8679 for (;;) {
8680 while (cur < query_end && grn_isspace(cur, ctx->encoding)) {
8681 if (!(len = grn_charlen(ctx, cur, query_end))) { goto exit; }
8682 GRN_TEXT_PUT(ctx, expanded_query, cur, len);
8683 cur += len;
8684 }
8685 if (query_end <= cur) { break; }
8686 switch (*cur) {
8687 case '\0' :
8688 goto exit;
8689 break;
8690 case GRN_QUERY_AND :
8691 case GRN_QUERY_ADJ_INC :
8692 case GRN_QUERY_ADJ_DEC :
8693 case GRN_QUERY_ADJ_NEG :
8694 case GRN_QUERY_AND_NOT :
8695 case GRN_QUERY_PARENL :
8696 case GRN_QUERY_PARENR :
8697 case GRN_QUERY_PREFIX :
8698 GRN_TEXT_PUTC(ctx, expanded_query, *cur);
8699 cur++;
8700 break;
8701 case GRN_QUERY_QUOTEL :
8702 GRN_BULK_REWIND(&buf);
8703 for (start = cur++; cur < query_end; cur += len) {
8704 if (!(len = grn_charlen(ctx, cur, query_end))) {
8705 goto exit;
8706 } else if (len == 1) {
8707 if (*cur == GRN_QUERY_QUOTER) {
8708 cur++;
8709 break;
8710 } else if (cur + 1 < query_end && *cur == GRN_QUERY_ESCAPE) {
8711 cur++;
8712 len = grn_charlen(ctx, cur, query_end);
8713 }
8714 }
8715 GRN_TEXT_PUT(ctx, &buf, cur, len);
8716 }
8717 if (expand_term_func(ctx, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf),
8718 expanded_query, user_data)) {
8719 GRN_TEXT_PUT(ctx, expanded_query, start, cur - start);
8720 }
8721 break;
8722 case 'O' :
8723 if (cur + 2 <= query_end && cur[1] == 'R' &&
8724 (cur + 2 == query_end || grn_isspace(cur + 2, ctx->encoding))) {
8725 GRN_TEXT_PUT(ctx, expanded_query, cur, 2);
8726 cur += 2;
8727 break;
8728 }
8729 /* fallthru */
8730 default :
8731 for (start = cur; cur < query_end; cur += len) {
8732 if (!(len = grn_charlen(ctx, cur, query_end))) {
8733 goto exit;
8734 } else if (grn_isspace(cur, ctx->encoding)) {
8735 break;
8736 } else if (len == 1) {
8737 if (*cur == GRN_QUERY_PARENL ||
8738 *cur == GRN_QUERY_PARENR ||
8739 *cur == GRN_QUERY_PREFIX) {
8740 break;
8741 } else if (flags & GRN_EXPR_ALLOW_COLUMN && *cur == GRN_QUERY_COLUMN) {
8742 if (cur + 1 < query_end) {
8743 switch (cur[1]) {
8744 case '!' :
8745 case '@' :
8746 case '^' :
8747 case '$' :
8748 cur += 2;
8749 break;
8750 case '=' :
8751 cur += (flags & GRN_EXPR_ALLOW_UPDATE) ? 2 : 1;
8752 break;
8753 case '<' :
8754 case '>' :
8755 cur += (cur + 2 < query_end && cur[2] == '=') ? 3 : 2;
8756 break;
8757 default :
8758 cur += 1;
8759 break;
8760 }
8761 } else {
8762 cur += 1;
8763 }
8764 GRN_TEXT_PUT(ctx, expanded_query, start, cur - start);
8765 start = cur;
8766 break;
8767 }
8768 }
8769 }
8770 if (start < cur) {
8771 if (expand_term_func(ctx, start, cur - start,
8772 expanded_query, user_data)) {
8773 GRN_TEXT_PUT(ctx, expanded_query, start, cur - start);
8774 }
8775 }
8776 break;
8777 }
8778 }
8779exit :
8780 GRN_OBJ_FIN(ctx, &buf);
8781 return GRN_SUCCESS;
8782}
8783
8784grn_rc
8785grn_expr_syntax_expand_query(grn_ctx *ctx,
8786 const char *query, int query_size,
8787 grn_expr_flags flags,
8788 grn_obj *expander,
8789 grn_obj *expanded_query)
8790{
8791 GRN_API_ENTER;
8792
8793 if (query_size < 0) {
8794 query_size = strlen(query);
8795 }
8796
8797 switch (expander->header.type) {
8798 case GRN_PROC :
8799 if (((grn_proc *)expander)->type == GRN_PROC_FUNCTION) {
8800 grn_user_data user_data;
8801 user_data.ptr = expander;
8802 grn_expr_syntax_expand_query_terms(ctx,
8803 query, query_size,
8804 flags,
8805 expanded_query,
8806 grn_expr_syntax_expand_term_by_func,
8807 &user_data);
8808 } else {
8809 char name[GRN_TABLE_MAX_KEY_SIZE];
8810 int name_size;
8811 name_size = grn_obj_name(ctx, expander, name, GRN_TABLE_MAX_KEY_SIZE);
8812 ERR(GRN_INVALID_ARGUMENT,
8813 "[query][expand][proc] "
8814 "proc query expander must be a function proc: <%.*s>",
8815 name_size, name);
8816 }
8817 break;
8818 case GRN_COLUMN_FIX_SIZE :
8819 case GRN_COLUMN_VAR_SIZE :
8820 {
8821 grn_obj *expansion_table;
8822 expansion_table = grn_column_table(ctx, expander);
8823 if (expansion_table) {
8824 grn_user_data user_data;
8825 grn_expr_syntax_expand_term_by_column_data data;
8826 user_data.ptr = &data;
8827 data.table = expansion_table;
8828 data.column = expander;
8829 grn_expr_syntax_expand_query_terms(ctx,
8830 query, query_size,
8831 flags,
8832 expanded_query,
8833 grn_expr_syntax_expand_term_by_column,
8834 &user_data);
8835 } else {
8836 char name[GRN_TABLE_MAX_KEY_SIZE];
8837 int name_size;
8838 name_size = grn_obj_name(ctx, expander, name, GRN_TABLE_MAX_KEY_SIZE);
8839 ERR(GRN_INVALID_ARGUMENT,
8840 "[query][expand][column] "
8841 "failed to get table of query expansion column: <%.*s>",
8842 name_size, name);
8843 }
8844 }
8845 break;
8846 default :
8847 {
8848 char name[GRN_TABLE_MAX_KEY_SIZE];
8849 int name_size;
8850 grn_obj type_name;
8851
8852 name_size = grn_obj_name(ctx, expander, name, GRN_TABLE_MAX_KEY_SIZE);
8853 GRN_TEXT_INIT(&type_name, 0);
8854 grn_inspect_type(ctx, &type_name, expander->header.type);
8855 ERR(GRN_INVALID_ARGUMENT,
8856 "[query][expand] "
8857 "query expander must be a data column or function proc: <%.*s>(%.*s)",
8858 name_size, name,
8859 (int)GRN_TEXT_LEN(&type_name), GRN_TEXT_VALUE(&type_name));
8860 GRN_OBJ_FIN(ctx, &type_name);
8861 }
8862 break;
8863 }
8864
8865 GRN_API_RETURN(ctx->rc);
8866}
8867
8868grn_rc
8869grn_expr_syntax_expand_query_by_table(grn_ctx *ctx,
8870 const char *query, int query_size,
8871 grn_expr_flags flags,
8872 grn_obj *term_column,
8873 grn_obj *expanded_term_column,
8874 grn_obj *expanded_query)
8875{
8876 grn_obj *table;
8877 grn_bool term_column_is_key;
8878
8879 GRN_API_ENTER;
8880
8881 if (query_size < 0) {
8882 query_size = strlen(query);
8883 }
8884
8885 if (!grn_obj_is_data_column(ctx, expanded_term_column)) {
8886 grn_obj inspected;
8887 GRN_TEXT_INIT(&inspected, 0);
8888 grn_inspect(ctx, &inspected, expanded_term_column);
8889 ERR(GRN_INVALID_ARGUMENT,
8890 "[query][expand][table] "
8891 "expanded term column must be a data column: <%.*s>",
8892 (int)GRN_TEXT_LEN(&inspected),
8893 GRN_TEXT_VALUE(&inspected));
8894 GRN_OBJ_FIN(ctx, &inspected);
8895 GRN_API_RETURN(ctx->rc);
8896 }
8897 table = grn_column_table(ctx, expanded_term_column);
8898
8899 if (!term_column) {
8900 term_column_is_key = GRN_TRUE;
8901 } else {
8902 if (grn_obj_is_key_accessor(ctx, term_column)) {
8903 term_column_is_key = GRN_TRUE;
8904 } else if (grn_obj_is_data_column(ctx, term_column)) {
8905 term_column_is_key = GRN_FALSE;
8906 } else {
8907 grn_obj inspected;
8908 GRN_TEXT_INIT(&inspected, 0);
8909 grn_inspect(ctx, &inspected, term_column);
8910 ERR(GRN_INVALID_ARGUMENT,
8911 "[query][expand][table] "
8912 "term column must be NULL, _key or a data column: <%.*s>",
8913 (int)GRN_TEXT_LEN(&inspected),
8914 GRN_TEXT_VALUE(&inspected));
8915 GRN_OBJ_FIN(ctx, &inspected);
8916 GRN_API_RETURN(ctx->rc);
8917 }
8918 if (term_column->header.domain != expanded_term_column->header.domain) {
8919 grn_obj inspected_term_column;
8920 grn_obj inspected_expanded_term_column;
8921 GRN_TEXT_INIT(&inspected_term_column, 0);
8922 GRN_TEXT_INIT(&inspected_expanded_term_column, 0);
8923 grn_inspect(ctx, &inspected_term_column, term_column);
8924 grn_inspect(ctx, &inspected_expanded_term_column, expanded_term_column);
8925 ERR(GRN_INVALID_ARGUMENT,
8926 "[query][expand][table] "
8927 "term column and expanded term column must belong to the same table: "
8928 "term column: <%.*s>, "
8929 "expanded term column: <%*.s>",
8930 (int)GRN_TEXT_LEN(&inspected_term_column),
8931 GRN_TEXT_VALUE(&inspected_term_column),
8932 (int)GRN_TEXT_LEN(&inspected_expanded_term_column),
8933 GRN_TEXT_VALUE(&inspected_expanded_term_column));
8934 GRN_OBJ_FIN(ctx, &inspected_term_column);
8935 GRN_OBJ_FIN(ctx, &inspected_expanded_term_column);
8936 GRN_API_RETURN(ctx->rc);
8937 }
8938 }
8939
8940 if (term_column_is_key) {
8941 grn_user_data user_data;
8942 grn_expr_syntax_expand_term_by_column_data data;
8943 user_data.ptr = &data;
8944 data.table = table;
8945 data.column = expanded_term_column;
8946 grn_expr_syntax_expand_query_terms(ctx,
8947 query, query_size,
8948 flags,
8949 expanded_query,
8950 grn_expr_syntax_expand_term_by_column,
8951 &user_data);
8952 } else {
8953 grn_user_data user_data;
8954 grn_expr_syntax_expand_term_by_table_data data;
8955 user_data.ptr = &data;
8956 data.table = table;
8957 data.term_column = term_column;
8958 data.expanded_term_column = expanded_term_column;
8959 grn_expr_syntax_expand_query_terms(ctx,
8960 query, query_size,
8961 flags,
8962 expanded_query,
8963 grn_expr_syntax_expand_term_by_table,
8964 &user_data);
8965 }
8966
8967 GRN_API_RETURN(ctx->rc);
8968}
8969
8970grn_rc
8971grn_expr_get_keywords(grn_ctx *ctx, grn_obj *expr, grn_obj *keywords)
8972{
8973 int i, n;
8974 scan_info **sis, *si;
8975 GRN_API_ENTER;
8976 if ((sis = grn_scan_info_build(ctx, expr, &n, GRN_OP_OR, GRN_FALSE))) {
8977 int butp = 0, nparens = 0, npbut = 0;
8978 grn_obj but_stack;
8979 GRN_UINT32_INIT(&but_stack, GRN_OBJ_VECTOR);
8980 for (i = n; i--;) {
8981 si = sis[i];
8982 if (si->flags & SCAN_POP) {
8983 nparens++;
8984 if (si->logical_op == GRN_OP_AND_NOT) {
8985 GRN_UINT32_PUT(ctx, &but_stack, npbut);
8986 npbut = nparens;
8987 butp = 1 - butp;
8988 }
8989 } else {
8990 if (butp == (si->logical_op == GRN_OP_AND_NOT) &&
8991 si->query) {
8992 switch (si->op) {
8993 case GRN_OP_MATCH :
8994 if (keywords->header.type == GRN_PVECTOR) {
8995 GRN_PTR_PUT(ctx, keywords, si->query);
8996 } else {
8997 grn_vector_add_element(ctx,
8998 keywords,
8999 GRN_TEXT_VALUE(si->query),
9000 GRN_TEXT_LEN(si->query),
9001 0,
9002 GRN_DB_TEXT);
9003 }
9004 break;
9005 case GRN_OP_SIMILAR :
9006 if (keywords->header.type == GRN_VECTOR &&
9007 GRN_BULK_VSIZE(&(si->index)) > 0) {
9008 grn_token_cursor *token_cursor;
9009 unsigned int token_flags = 0;
9010 grn_obj *index = GRN_PTR_VALUE(&(si->index));
9011 grn_obj *lexicon;
9012
9013 lexicon = grn_ctx_at(ctx, index->header.domain);
9014 token_cursor = grn_token_cursor_open(ctx,
9015 lexicon,
9016 GRN_TEXT_VALUE(si->query),
9017 GRN_TEXT_LEN(si->query),
9018 GRN_TOKENIZE_GET,
9019 token_flags);
9020 if (token_cursor) {
9021 grn_obj *source_table;
9022 uint32_t n_records_threshold;
9023 source_table = grn_ctx_at(ctx, grn_obj_get_range(ctx, index));
9024 n_records_threshold = grn_table_size(ctx, source_table) / 2;
9025 while (token_cursor->status != GRN_TOKEN_CURSOR_DONE) {
9026 grn_id token_id;
9027 uint32_t n_estimated_records;
9028 token_id = grn_token_cursor_next(ctx, token_cursor);
9029 if (token_id == GRN_ID_NIL) {
9030 continue;
9031 }
9032 n_estimated_records =
9033 grn_ii_estimate_size(ctx, (grn_ii *)index, token_id);
9034 if (n_estimated_records >= n_records_threshold) {
9035 continue;
9036 }
9037 grn_vector_add_element(ctx,
9038 keywords,
9039 token_cursor->curr,
9040 token_cursor->curr_size,
9041 0,
9042 GRN_DB_TEXT);
9043 }
9044 grn_token_cursor_close(ctx, token_cursor);
9045 }
9046 }
9047 break;
9048 default :
9049 break;
9050 }
9051 }
9052 if (si->flags & SCAN_PUSH) {
9053 if (nparens == npbut) {
9054 butp = 1 - butp;
9055 GRN_UINT32_POP(&but_stack, npbut);
9056 }
9057 nparens--;
9058 }
9059 }
9060 }
9061 GRN_OBJ_FIN(ctx, &but_stack);
9062 for (i = n; i--;) { SI_FREE(sis[i]); }
9063 GRN_FREE(sis);
9064 }
9065 GRN_API_RETURN(GRN_SUCCESS);
9066}
9067
9068grn_rc
9069grn_expr_snip_add_conditions(grn_ctx *ctx, grn_obj *expr, grn_obj *snip,
9070 unsigned int n_tags,
9071 const char **opentags, unsigned int *opentag_lens,
9072 const char **closetags, unsigned int *closetag_lens)
9073{
9074 grn_rc rc;
9075 grn_obj keywords;
9076
9077 GRN_API_ENTER;
9078
9079 GRN_PTR_INIT(&keywords, GRN_OBJ_VECTOR, GRN_ID_NIL);
9080 rc = grn_expr_get_keywords(ctx, expr, &keywords);
9081 if (rc != GRN_SUCCESS) {
9082 GRN_OBJ_FIN(ctx, &keywords);
9083 GRN_API_RETURN(rc);
9084 }
9085
9086 if (n_tags) {
9087 int i;
9088 for (i = 0;; i = (i + 1) % n_tags) {
9089 grn_obj *keyword;
9090 GRN_PTR_POP(&keywords, keyword);
9091 if (!keyword) { break; }
9092 grn_snip_add_cond(ctx, snip,
9093 GRN_TEXT_VALUE(keyword), GRN_TEXT_LEN(keyword),
9094 opentags[i], opentag_lens[i],
9095 closetags[i], closetag_lens[i]);
9096 }
9097 } else {
9098 for (;;) {
9099 grn_obj *keyword;
9100 GRN_PTR_POP(&keywords, keyword);
9101 if (!keyword) { break; }
9102 grn_snip_add_cond(ctx, snip,
9103 GRN_TEXT_VALUE(keyword), GRN_TEXT_LEN(keyword),
9104 NULL, 0, NULL, 0);
9105 }
9106 }
9107 GRN_OBJ_FIN(ctx, &keywords);
9108
9109 GRN_API_RETURN(GRN_SUCCESS);
9110}
9111
9112grn_obj *
9113grn_expr_snip(grn_ctx *ctx, grn_obj *expr, int flags,
9114 unsigned int width, unsigned int max_results,
9115 unsigned int n_tags,
9116 const char **opentags, unsigned int *opentag_lens,
9117 const char **closetags, unsigned int *closetag_lens,
9118 grn_snip_mapping *mapping)
9119{
9120 grn_obj *res = NULL;
9121 GRN_API_ENTER;
9122 if ((res = grn_snip_open(ctx, flags, width, max_results,
9123 NULL, 0, NULL, 0, mapping))) {
9124 grn_expr_snip_add_conditions(ctx, expr, res,
9125 n_tags,
9126 opentags, opentag_lens,
9127 closetags, closetag_lens);
9128 }
9129 GRN_API_RETURN(res);
9130}
9131
9132/*
9133 So far, grn_column_filter() is nothing but a very rough prototype.
9134 Although GRN_COLUMN_EACH() can accelerate many range queries,
9135 the following stuff must be resolved one by one.
9136
9137 * support accessors as column
9138 * support tables which have deleted records
9139 * support various operators
9140 * support various column types
9141*/
9142grn_rc
9143grn_column_filter(grn_ctx *ctx, grn_obj *column,
9144 grn_operator operator,
9145 grn_obj *value, grn_obj *result_set,
9146 grn_operator set_operation)
9147{
9148 uint32_t *vp;
9149 grn_posting posting;
9150 uint32_t value_ = grn_atoui(GRN_TEXT_VALUE(value), GRN_BULK_CURR(value), NULL);
9151 posting.sid = 1;
9152 posting.pos = 0;
9153 posting.weight = 0;
9154 GRN_COLUMN_EACH(ctx, column, id, vp, {
9155 if (*vp < value_) {
9156 posting.rid = id;
9157 grn_ii_posting_add(ctx, &posting, (grn_hash *)result_set, set_operation);
9158 }
9159 });
9160 grn_ii_resolve_sel_and(ctx, (grn_hash *)result_set, set_operation);
9161 return ctx->rc;
9162}
9163
9164grn_rc
9165grn_expr_syntax_escape(grn_ctx *ctx, const char *string, int string_size,
9166 const char *target_characters,
9167 char escape_character,
9168 grn_obj *escaped_string)
9169{
9170 grn_rc rc = GRN_SUCCESS;
9171 const char *current, *string_end;
9172
9173 if (!string) {
9174 return GRN_INVALID_ARGUMENT;
9175 }
9176
9177 GRN_API_ENTER;
9178 if (string_size < 0) {
9179 string_size = strlen(string);
9180 }
9181 string_end = string + string_size;
9182
9183 current = string;
9184 while (current < string_end) {
9185 unsigned int char_size;
9186 char_size = grn_charlen(ctx, current, string_end);
9187 switch (char_size) {
9188 case 0 :
9189 /* string includes malformed multibyte character. */
9190 return GRN_INVALID_ARGUMENT;
9191 break;
9192 case 1 :
9193 if (strchr(target_characters, *current)) {
9194 GRN_TEXT_PUTC(ctx, escaped_string, escape_character);
9195 }
9196 GRN_TEXT_PUT(ctx, escaped_string, current, char_size);
9197 current += char_size;
9198 break;
9199 default :
9200 GRN_TEXT_PUT(ctx, escaped_string, current, char_size);
9201 current += char_size;
9202 break;
9203 }
9204 }
9205
9206 GRN_API_RETURN(rc);
9207}
9208
9209grn_rc
9210grn_expr_syntax_escape_query(grn_ctx *ctx, const char *query, int query_size,
9211 grn_obj *escaped_query)
9212{
9213 const char target_characters[] = {
9214 GRN_QUERY_AND,
9215 GRN_QUERY_AND_NOT,
9216 GRN_QUERY_ADJ_INC,
9217 GRN_QUERY_ADJ_DEC,
9218 GRN_QUERY_ADJ_NEG,
9219 GRN_QUERY_PREFIX,
9220 GRN_QUERY_PARENL,
9221 GRN_QUERY_PARENR,
9222 GRN_QUERY_QUOTEL,
9223 GRN_QUERY_ESCAPE,
9224 GRN_QUERY_COLUMN,
9225 '\0',
9226 };
9227 return grn_expr_syntax_escape(ctx, query, query_size,
9228 target_characters, GRN_QUERY_ESCAPE,
9229 escaped_query);
9230}
9231
9232grn_rc
9233grn_expr_dump_plan(grn_ctx *ctx, grn_obj *expr, grn_obj *buffer)
9234{
9235 int n;
9236 scan_info **sis;
9237
9238 GRN_API_ENTER;
9239 sis = grn_scan_info_build(ctx, expr, &n, GRN_OP_OR, GRN_FALSE);
9240 if (sis) {
9241 int i;
9242 grn_inspect_scan_info_list(ctx, buffer, sis, n);
9243 for (i = 0; i < n; i++) {
9244 SI_FREE(sis[i]);
9245 }
9246 GRN_FREE(sis);
9247 } else {
9248 GRN_TEXT_PUTS(ctx, buffer, "sequential search\n");
9249 }
9250 GRN_API_RETURN(GRN_SUCCESS);
9251}
9252
9253static unsigned int
9254grn_expr_estimate_size_raw(grn_ctx *ctx, grn_obj *expr, grn_obj *table)
9255{
9256 return grn_table_size(ctx, table);
9257}
9258
9259unsigned int
9260grn_expr_estimate_size(grn_ctx *ctx, grn_obj *expr)
9261{
9262 grn_obj *table;
9263 grn_obj *variable;
9264 unsigned int size;
9265
9266 variable = grn_expr_get_var_by_offset(ctx, expr, 0);
9267 if (!variable) {
9268 ERR(GRN_INVALID_ARGUMENT, "at least one variable must be defined");
9269 return 0;
9270 }
9271
9272 table = grn_ctx_at(ctx, variable->header.domain);
9273 if (!table) {
9274 ERR(GRN_INVALID_ARGUMENT,
9275 "variable refers unknown domain: <%u>", variable->header.domain);
9276 return 0;
9277 }
9278
9279 GRN_API_ENTER;
9280#ifdef GRN_WITH_MRUBY
9281 grn_ctx_impl_mrb_ensure_init(ctx);
9282 if (ctx->rc != GRN_SUCCESS) {
9283 GRN_API_RETURN(0);
9284 }
9285 if (ctx->impl->mrb.state) {
9286 size = grn_mrb_expr_estimate_size(ctx, expr, table);
9287 } else {
9288 size = grn_expr_estimate_size_raw(ctx, expr, table);
9289 }
9290#else
9291 size = grn_expr_estimate_size_raw(ctx, expr, table);
9292#endif
9293 GRN_API_RETURN(size);
9294}
9295