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 | |
44 | static double grn_table_select_enough_filtered_ratio = 0.0; |
45 | static int grn_table_select_max_n_enough_filtered_records = 1000; |
46 | static grn_bool grn_table_select_and_min_skip_enable = GRN_TRUE; |
47 | static grn_bool grn_scan_info_regexp_dot_asterisk_enable = GRN_TRUE; |
48 | |
49 | void |
50 | grn_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 | |
99 | grn_obj * |
100 | grn_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 | |
117 | grn_hash * |
118 | grn_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 | |
148 | grn_rc |
149 | grn_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 | |
168 | grn_obj * |
169 | grn_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 | |
187 | grn_obj * |
188 | grn_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 | |
199 | grn_obj * |
200 | grn_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 | |
206 | grn_obj * |
207 | grn_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 | |
213 | grn_obj * |
214 | grn_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 | |
221 | grn_obj * |
222 | grn_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 | |
228 | grn_proc_type |
229 | grn_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 | |
235 | grn_rc |
236 | grn_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 | |
246 | grn_rc |
247 | grn_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 | |
257 | grn_operator |
258 | grn_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 | |
267 | grn_rc |
268 | grn_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 | |
278 | grn_bool |
279 | grn_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 | |
290 | grn_obj * |
291 | grn_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 | |
299 | grn_rc |
300 | grn_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 | |
309 | grn_obj * |
310 | grn_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 | |
335 | void |
336 | grn_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 | |
350 | const uint8_t * |
351 | grn_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 | |
366 | typedef 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 | |
372 | void |
373 | grn_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 | |
408 | const uint8_t * |
409 | grn_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 | |
472 | grn_obj * |
473 | grn_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 | } |
510 | exit : |
511 | return (grn_obj *)expr; |
512 | } |
513 | |
514 | /* Pass ownership of `obj` to `expr`. */ |
515 | void |
516 | grn_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 */ |
523 | typedef struct { |
524 | grn_expr_code *code; |
525 | grn_id domain; |
526 | unsigned char type; |
527 | } grn_expr_dfi; |
528 | |
529 | static grn_expr_dfi * |
530 | grn_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 | |
544 | static void |
545 | grn_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 | |
559 | grn_obj * |
560 | grn_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 | } |
619 | exit : |
620 | GRN_API_RETURN((grn_obj *)expr); |
621 | } |
622 | |
623 | grn_rc |
624 | grn_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 | |
691 | grn_obj * |
692 | grn_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 | |
730 | grn_obj * |
731 | grn_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 | |
740 | grn_obj * |
741 | grn_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 | |
762 | grn_obj * |
763 | grn_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 | |
852 | static void |
853 | grn_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 | |
867 | grn_obj * |
868 | grn_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 | } |
1311 | exit : |
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 | |
1318 | grn_obj * |
1319 | grn_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 */ |
1348 | exit : |
1349 | GRN_API_RETURN(res); |
1350 | } |
1351 | |
1352 | static grn_obj * |
1353 | grn_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 | |
1364 | grn_obj * |
1365 | grn_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 | |
1375 | grn_obj * |
1376 | grn_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 | |
1390 | grn_rc |
1391 | grn_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 | |
1397 | grn_rc |
1398 | grn_expr_compile(grn_ctx *ctx, grn_obj *expr) |
1399 | { |
1400 | grn_obj_spec_save(ctx, DB_OBJ(expr)); |
1401 | return ctx->rc; |
1402 | } |
1403 | |
1404 | grn_obj * |
1405 | grn_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 | |
1456 | grn_rc |
1457 | grn_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 | |
2462 | inline static void |
2463 | grn_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 | |
2562 | inline static void |
2563 | grn_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 | |
2590 | static inline grn_bool |
2591 | grn_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 | |
2611 | static inline grn_obj * |
2612 | grn_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 | |
2619 | grn_obj * |
2620 | grn_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 | } |
3827 | exit : |
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 | |
3838 | grn_obj * |
3839 | grn_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 0 |
3855 | #define DEFAULT_WEIGHT_VECTOR_SIZE 4096 |
3856 | |
3857 | #define GRN_SCAN_INFO_MAX_N_ARGS 128 |
3858 | |
3859 | struct _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 | |
3919 | static scan_info ** |
3920 | put_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 |
3985 | static 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 | |
4064 | static void |
4065 | put_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 | |
4076 | static grn_rc |
4077 | grn_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 | |
4141 | static void |
4142 | scan_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 | |
4173 | static int32_t |
4174 | get_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 | |
4202 | scan_info * |
4203 | grn_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 | |
4228 | void |
4229 | grn_scan_info_close(grn_ctx *ctx, scan_info *si) |
4230 | { |
4231 | SI_FREE(si); |
4232 | } |
4233 | |
4234 | void |
4235 | grn_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 | |
4247 | scan_info ** |
4248 | grn_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 | |
4254 | int32_t |
4255 | grn_expr_code_get_weight(grn_ctx *ctx, grn_expr_code *ec, uint32_t *offset) |
4256 | { |
4257 | return get_weight(ctx, ec, offset); |
4258 | } |
4259 | |
4260 | int |
4261 | grn_scan_info_get_flags(scan_info *si) |
4262 | { |
4263 | return si->flags; |
4264 | } |
4265 | |
4266 | void |
4267 | grn_scan_info_set_flags(scan_info *si, int flags) |
4268 | { |
4269 | si->flags = flags; |
4270 | } |
4271 | |
4272 | grn_operator |
4273 | grn_scan_info_get_logical_op(scan_info *si) |
4274 | { |
4275 | return si->logical_op; |
4276 | } |
4277 | |
4278 | void |
4279 | grn_scan_info_set_logical_op(scan_info *si, grn_operator logical_op) |
4280 | { |
4281 | si->logical_op = logical_op; |
4282 | } |
4283 | |
4284 | grn_operator |
4285 | grn_scan_info_get_op(scan_info *si) |
4286 | { |
4287 | return si->op; |
4288 | } |
4289 | |
4290 | void |
4291 | grn_scan_info_set_op(scan_info *si, grn_operator op) |
4292 | { |
4293 | si->op = op; |
4294 | } |
4295 | |
4296 | void |
4297 | grn_scan_info_set_end(scan_info *si, uint32_t end) |
4298 | { |
4299 | si->end = end; |
4300 | } |
4301 | |
4302 | void |
4303 | grn_scan_info_set_query(scan_info *si, grn_obj *query) |
4304 | { |
4305 | si->query = query; |
4306 | } |
4307 | |
4308 | int |
4309 | grn_scan_info_get_max_interval(scan_info *si) |
4310 | { |
4311 | return si->max_interval; |
4312 | } |
4313 | |
4314 | void |
4315 | grn_scan_info_set_max_interval(scan_info *si, int max_interval) |
4316 | { |
4317 | si->max_interval = max_interval; |
4318 | } |
4319 | |
4320 | int |
4321 | grn_scan_info_get_similarity_threshold(scan_info *si) |
4322 | { |
4323 | return si->similarity_threshold; |
4324 | } |
4325 | |
4326 | void |
4327 | grn_scan_info_set_similarity_threshold(scan_info *si, int similarity_threshold) |
4328 | { |
4329 | si->similarity_threshold = similarity_threshold; |
4330 | } |
4331 | |
4332 | grn_bool |
4333 | grn_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 | |
4343 | grn_obj * |
4344 | grn_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 | |
4352 | int |
4353 | grn_scan_info_get_start_position(scan_info *si) |
4354 | { |
4355 | return si->position.start; |
4356 | } |
4357 | |
4358 | void |
4359 | grn_scan_info_set_start_position(scan_info *si, int start) |
4360 | { |
4361 | si->position.specified = GRN_TRUE; |
4362 | si->position.start = start; |
4363 | } |
4364 | |
4365 | void |
4366 | grn_scan_info_reset_position(scan_info *si) |
4367 | { |
4368 | si->position.specified = GRN_FALSE; |
4369 | } |
4370 | |
4371 | static uint32_t |
4372 | scan_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 | |
4434 | static uint32_t |
4435 | scan_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 | |
4517 | static void |
4518 | scan_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 | |
4530 | static grn_bool |
4531 | is_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 | |
4643 | static void |
4644 | scan_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 | |
4724 | static grn_bool |
4725 | grn_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 | |
4825 | static scan_info ** |
4826 | grn_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 | |
5233 | static scan_info ** |
5234 | grn_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 | |
5263 | static scan_info ** |
5264 | grn_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 | |
5295 | static scan_info ** |
5296 | grn_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 | |
5376 | static scan_info ** |
5377 | grn_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 | |
5493 | exit : |
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 | |
5507 | static scan_info ** |
5508 | grn_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 | |
5536 | scan_info ** |
5537 | grn_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 | |
5560 | void |
5561 | grn_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 | |
5598 | void |
5599 | grn_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 | |
5610 | inline static int32_t |
5611 | exec_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 | |
5642 | static void |
5643 | grn_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 | |
5740 | static inline void |
5741 | grn_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 | |
5746 | static inline void |
5747 | grn_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 | |
5755 | static inline grn_bool |
5756 | grn_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 | |
5806 | static inline grn_bool |
5807 | grn_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 | |
5950 | static inline grn_bool |
5951 | grn_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 | |
6063 | static grn_bool |
6064 | grn_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 | |
6149 | static grn_bool |
6150 | grn_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 | |
6171 | static inline grn_bool |
6172 | grn_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 | |
6272 | static inline grn_bool |
6273 | grn_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 | |
6391 | static inline grn_bool |
6392 | grn_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 | |
6475 | static inline grn_bool |
6476 | grn_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 | |
6593 | static inline grn_bool |
6594 | grn_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 | |
6674 | static inline grn_bool |
6675 | grn_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 | |
6697 | static inline grn_bool |
6698 | grn_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 | |
6814 | grn_obj * |
6815 | grn_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 | |
6927 | grn_obj * |
6928 | grn_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 | |
6937 | int32_t |
6938 | grn_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 | |
6951 | typedef 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 | |
6988 | typedef struct { |
6989 | grn_operator op; |
6990 | int weight; |
6991 | } efs_op; |
6992 | |
6993 | inline static void |
6994 | skip_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 | |
7007 | static grn_bool |
7008 | parse_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 |
7057 | static const char * |
7058 | get_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 | |
7107 | static void |
7108 | get_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 | |
7156 | static int |
7157 | section_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 | |
7172 | static grn_rc |
7173 | grn_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 | |
7183 | static void |
7184 | parse_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 | |
7247 | static void |
7248 | parse_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 | |
7275 | static void |
7276 | parse_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 | |
7299 | static void |
7300 | parse_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 | |
7326 | static grn_rc |
7327 | parse_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 | |
7443 | static grn_rc |
7444 | parse_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 | } |
7640 | exit : |
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 | |
7668 | static grn_rc |
7669 | get_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 | |
7694 | static grn_obj * |
7695 | resolve_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 | |
7729 | static grn_rc |
7730 | get_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 | } |
7754 | done : |
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 | } |
7847 | exit : |
7848 | q->cur = s; |
7849 | return rc; |
7850 | } |
7851 | |
7852 | static void |
7853 | set_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 | |
7860 | static grn_obj * |
7861 | (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 | |
7905 | static grn_rc |
7906 | parse_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 | } |
8358 | exit : |
8359 | PARSE(0); |
8360 | return rc; |
8361 | } |
8362 | |
8363 | grn_rc |
8364 | grn_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 | |
8456 | grn_rc |
8457 | grn_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 | |
8467 | typedef 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); |
8472 | static grn_rc |
8473 | grn_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 | |
8502 | typedef struct { |
8503 | grn_obj *table; |
8504 | grn_obj *column; |
8505 | } grn_expr_syntax_expand_term_by_column_data; |
8506 | |
8507 | static grn_rc |
8508 | grn_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 | |
8550 | typedef 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 | |
8556 | static grn_rc |
8557 | grn_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 | |
8667 | static grn_rc |
8668 | grn_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 | } |
8779 | exit : |
8780 | GRN_OBJ_FIN(ctx, &buf); |
8781 | return GRN_SUCCESS; |
8782 | } |
8783 | |
8784 | grn_rc |
8785 | grn_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 | |
8868 | grn_rc |
8869 | grn_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 | |
8970 | grn_rc |
8971 | grn_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 | |
9068 | grn_rc |
9069 | grn_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 | |
9112 | grn_obj * |
9113 | grn_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 | */ |
9142 | grn_rc |
9143 | grn_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 | |
9164 | grn_rc |
9165 | grn_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 | |
9209 | grn_rc |
9210 | grn_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 | |
9232 | grn_rc |
9233 | grn_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 | |
9253 | static unsigned int |
9254 | grn_expr_estimate_size_raw(grn_ctx *ctx, grn_obj *expr, grn_obj *table) |
9255 | { |
9256 | return grn_table_size(ctx, table); |
9257 | } |
9258 | |
9259 | unsigned int |
9260 | grn_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 | |