Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
expr.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2 -*- */
2 /*
3  Copyright(C) 2010-2013 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 "groonga_in.h"
19 #include "db.h"
20 #include "ctx_impl.h"
21 #include <string.h>
22 #include <float.h>
23 #include "ii.h"
24 #include "geo.h"
25 #include "expr.h"
26 #include "util.h"
27 #include "normalizer_in.h"
28 #include "mrb.h"
29 #include "mrb/mrb_expr.h"
30 
31 static inline int
32 function_proc_p(grn_obj *obj)
33 {
34  return (obj &&
35  obj->header.type == GRN_PROC &&
36  ((grn_proc *)obj)->type == GRN_PROC_FUNCTION);
37 }
38 
39 static inline int
40 selector_proc_p(grn_obj *obj)
41 {
42  return (function_proc_p(obj) && ((grn_proc *)obj)->selector);
43 }
44 
45 grn_obj *
46 grn_expr_alloc(grn_ctx *ctx, grn_obj *expr, grn_id domain, grn_obj_flags flags)
47 {
48  grn_obj *res = NULL;
49  grn_expr *e = (grn_expr *)expr;
50  if (e) {
51  if (e->values_curr >= e->values_size) {
52  // todo : expand values.
53  ERR(GRN_NO_MEMORY_AVAILABLE, "no more e->values");
54  return NULL;
55  }
56  res = &e->values[e->values_curr++];
57  if (e->values_curr > e->values_tail) { e->values_tail = e->values_curr; }
58  grn_obj_reinit(ctx, res, domain, flags);
59  }
60  return res;
61 }
62 
63 static grn_hash *
64 grn_expr_get_vars(grn_ctx *ctx, grn_obj *expr, unsigned int *nvars)
65 {
66  grn_hash *vars = NULL;
67  if (expr->header.type == GRN_PROC || expr->header.type == GRN_EXPR) {
68  grn_id id = DB_OBJ(expr)->id;
69  grn_expr *e = (grn_expr *)expr;
70  int added = 0;
71  grn_hash **vp;
72  if (grn_hash_add(ctx, ctx->impl->expr_vars, &id, sizeof(grn_id), (void **)&vp, &added)) {
73  if (!*vp) {
74  *vp = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, sizeof(grn_obj),
76  if (*vp) {
77  uint32_t i;
78  grn_obj *value;
79  grn_expr_var *v;
80  for (v = e->vars, i = e->nvars; i; v++, i--) {
81  grn_hash_add(ctx, *vp, v->name, v->name_size, (void **)&value, &added);
82  GRN_OBJ_INIT(value, v->value.header.type, 0, v->value.header.domain);
83  GRN_TEXT_PUT(ctx, value, GRN_TEXT_VALUE(&v->value), GRN_TEXT_LEN(&v->value));
84  }
85  }
86  }
87  vars = *vp;
88  }
89  }
90  *nvars = vars ? GRN_HASH_SIZE(vars) : 0;
91  return vars;
92 }
93 
94 grn_rc
96 {
97  if (expr->header.type == GRN_PROC || expr->header.type == GRN_EXPR) {
98  grn_hash **vp;
99  grn_id eid, id = DB_OBJ(expr)->id;
100  if ((eid = grn_hash_get(ctx, ctx->impl->expr_vars, &id, sizeof(grn_id), (void **)&vp))) {
101  if (*vp) {
102  grn_obj *value;
103  GRN_HASH_EACH(ctx, *vp, i, NULL, NULL, (void **)&value, {
104  GRN_OBJ_FIN(ctx, value);
105  });
106  grn_hash_close(ctx, *vp);
107  }
108  grn_hash_delete_by_id(ctx, ctx->impl->expr_vars, eid, NULL);
109  }
110  }
111  return ctx->rc;
112 }
113 
114 grn_obj *
116  grn_expr_var **vars, unsigned int *nvars, grn_obj **caller)
117 {
118  grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
119  if (caller) { *caller = pctx->caller; }
120  if (pctx->proc) {
121  if (vars) {
122  *vars = pctx->proc->vars;
123  // *vars = grn_expr_get_vars(ctx, (grn_obj *)pctx->proc, nvars);
124  }
125  if (nvars) { *nvars = pctx->proc->nvars; }
126  } else {
127  if (vars) { *vars = NULL; }
128  if (nvars) { *nvars = 0; }
129  }
130  return (grn_obj *)pctx->proc;
131 }
132 
133 grn_obj *
134 grn_proc_get_var(grn_ctx *ctx, grn_user_data *user_data, const char *name, unsigned int name_size)
135 {
136  grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
137  return pctx->proc ? grn_expr_get_var(ctx, (grn_obj *)pctx->proc, name, name_size) : NULL;
138 }
139 
140 grn_obj *
141 grn_proc_get_var_by_offset(grn_ctx *ctx, grn_user_data *user_data, unsigned int offset)
142 {
143  grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
144  return pctx->proc ? grn_expr_get_var_by_offset(ctx, (grn_obj *)pctx->proc, offset) : NULL;
145 }
146 
147 grn_obj *
149  const char *name, unsigned int name_size)
150 {
151  grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
152  return pctx->proc ? grn_expr_get_or_add_var(ctx, (grn_obj *)pctx->proc, name, name_size) : NULL;
153 }
154 
155 grn_obj *
156 grn_proc_alloc(grn_ctx *ctx, grn_user_data *user_data, grn_id domain, grn_obj_flags flags)
157 {
158  grn_proc_ctx *pctx = (grn_proc_ctx *)user_data;
159  return pctx->caller ? grn_expr_alloc(ctx, (grn_obj *)pctx->caller, domain, flags) : NULL;
160 }
161 
162 grn_rc
164 {
165  grn_proc *proc_ = (grn_proc *)proc;
166  if (!function_proc_p(proc)) {
167  return GRN_INVALID_ARGUMENT;
168  }
169  proc_->selector = selector;
170  return GRN_SUCCESS;
171 }
172 
173 /* grn_expr */
174 
175 static const char *opstrs[] = {
176  "PUSH",
177  "POP",
178  "NOP",
179  "CALL",
180  "INTERN",
181  "GET_REF",
182  "GET_VALUE",
183  "AND",
184  "BUT",
185  "OR",
186  "ASSIGN",
187  "STAR_ASSIGN",
188  "SLASH_ASSIGN",
189  "MOD_ASSIGN",
190  "PLUS_ASSIGN",
191  "MINUS_ASSIGN",
192  "SHIFTL_ASSIGN",
193  "SHIFTR_ASSIGN",
194  "SHIFTRR_ASSIGN",
195  "AND_ASSIGN",
196  "XOR_ASSIGN",
197  "OR_ASSIGN",
198  "JUMP",
199  "CJUMP",
200  "COMMA",
201  "BITWISE_OR",
202  "BITWISE_XOR",
203  "BITWISE_AND",
204  "BITWISE_NOT",
205  "EQUAL",
206  "NOT_EQUAL",
207  "LESS",
208  "GREATER",
209  "LESS_EQUAL",
210  "GREATER_EQUAL",
211  "IN",
212  "MATCH",
213  "NEAR",
214  "NEAR2",
215  "SIMILAR",
216  "TERM_EXTRACT",
217  "SHIFTL",
218  "SHIFTR",
219  "SHIFTRR",
220  "PLUS",
221  "MINUS",
222  "STAR",
223  "SLASH",
224  "MOD",
225  "DELETE",
226  "INCR",
227  "DECR",
228  "INCR_POST",
229  "DECR_POST",
230  "NOT",
231  "ADJUST",
232  "EXACT",
233  "LCP",
234  "PARTIAL",
235  "UNSPLIT",
236  "PREFIX",
237  "SUFFIX",
238  "GEO_DISTANCE1",
239  "GEO_DISTANCE2",
240  "GEO_DISTANCE3",
241  "GEO_DISTANCE4",
242  "GEO_WITHINP5",
243  "GEO_WITHINP6",
244  "GEO_WITHINP8",
245  "OBJ_SEARCH",
246  "EXPR_GET_VAR",
247  "TABLE_CREATE",
248  "TABLE_SELECT",
249  "TABLE_SORT",
250  "TABLE_GROUP",
251  "JSON_PUT"
252 };
253 
254 static void
255 put_value(grn_ctx *ctx, grn_obj *buf, grn_obj *obj)
256 {
257  int len;
258  char namebuf[GRN_TABLE_MAX_KEY_SIZE];
259  if ((len = grn_column_name(ctx, obj, namebuf, GRN_TABLE_MAX_KEY_SIZE))) {
260  GRN_TEXT_PUT(ctx, buf, namebuf, len);
261  } else {
262  grn_text_otoj(ctx, buf, obj, NULL);
263  }
264 }
265 
266 grn_rc
268 {
269  uint32_t i, j;
270  grn_expr_var *var;
271  grn_expr_code *code;
272  grn_expr *e = (grn_expr *)expr;
273  grn_hash *vars = grn_expr_get_vars(ctx, expr, &i);
274  GRN_TEXT_PUTS(ctx, buf, "noname");
275  GRN_TEXT_PUTC(ctx, buf, '(');
276  {
277  int i = 0;
278  grn_obj *value;
279  const char *name;
280  uint32_t name_len;
281  GRN_HASH_EACH(ctx, vars, id, &name, &name_len, &value, {
282  if (i++) { GRN_TEXT_PUTC(ctx, buf, ','); }
283  GRN_TEXT_PUT(ctx, buf, name, name_len);
284  GRN_TEXT_PUTC(ctx, buf, ':');
285  put_value(ctx, buf, value);
286  });
287  }
288  GRN_TEXT_PUTC(ctx, buf, ')');
289  GRN_TEXT_PUTC(ctx, buf, '{');
290  for (j = 0, code = e->codes; j < e->codes_curr; j++, code++) {
291  if (j) { GRN_TEXT_PUTC(ctx, buf, ','); }
292  grn_text_itoa(ctx, buf, code->modify);
293  if (code->op == GRN_OP_PUSH) {
294  for (i = 0, var = e->vars; i < e->nvars; i++, var++) {
295  if (&var->value == code->value) {
296  GRN_TEXT_PUTC(ctx, buf, '?');
297  if (var->name_size) {
298  GRN_TEXT_PUT(ctx, buf, var->name, var->name_size);
299  } else {
300  grn_text_itoa(ctx, buf, (int)i);
301  }
302  break;
303  }
304  }
305  if (i == e->nvars) {
306  put_value(ctx, buf, code->value);
307  }
308  } else {
309  if (code->value) {
310  put_value(ctx, buf, code->value);
311  GRN_TEXT_PUTC(ctx, buf, ' ');
312  }
313  GRN_TEXT_PUTS(ctx, buf, opstrs[code->op]);
314  }
315  }
316  GRN_TEXT_PUTC(ctx, buf, '}');
317  return GRN_SUCCESS;
318 }
319 
320 grn_obj *
322 {
323  if (ctx && ctx->impl && ctx->impl->stack_curr) {
324  return ctx->impl->stack[--ctx->impl->stack_curr];
325  }
326  return NULL;
327 }
328 
329 grn_rc
331 {
332  if (ctx && ctx->impl && ctx->impl->stack_curr < GRN_STACK_SIZE) {
333  ctx->impl->stack[ctx->impl->stack_curr++] = obj;
334  return GRN_SUCCESS;
335  }
336  return GRN_STACK_OVER_FLOW;
337 }
338 
339 static grn_obj *
340 const_new(grn_ctx *ctx, grn_expr *e)
341 {
342  if (!e->consts) {
343  if (!(e->consts = GRN_MALLOCN(grn_obj, GRN_STACK_SIZE))) {
344  ERR(GRN_NO_MEMORY_AVAILABLE, "malloc failed");
345  return NULL;
346  }
347  }
348  if (e->nconsts < GRN_STACK_SIZE) {
349  return e->consts + e->nconsts++;
350  } else {
351  ERR(GRN_STACK_OVER_FLOW, "too many constants.");
352  return NULL;
353  }
354 }
355 
356 void
358 {
359  grn_text_benc(ctx, buf, obj->header.type);
360  if (GRN_DB_OBJP(obj)) {
361  grn_text_benc(ctx, buf, DB_OBJ(obj)->id);
362  } else {
363  // todo : support vector, query, accessor, snip..
364  uint32_t vs = GRN_BULK_VSIZE(obj);
365  grn_text_benc(ctx, buf, obj->header.domain);
366  grn_text_benc(ctx, buf, vs);
367  if (vs) { GRN_TEXT_PUT(ctx, buf, GRN_BULK_HEAD(obj), vs); }
368  }
369 }
370 
371 const uint8_t *
372 grn_obj_unpack(grn_ctx *ctx, const uint8_t *p, const uint8_t *pe, uint8_t type, uint8_t flags, grn_obj *obj)
373 {
374  grn_id domain;
375  uint32_t vs;
376  GRN_B_DEC(domain, p);
377  GRN_OBJ_INIT(obj, type, flags, domain);
378  GRN_B_DEC(vs, p);
379  if (pe < p + vs) {
380  ERR(GRN_INVALID_FORMAT, "benced image is corrupt");
381  return p;
382  }
383  grn_bulk_write(ctx, obj, (const char *)p, vs);
384  return p + vs;
385 }
386 
387 typedef enum {
392 
393 void
395 {
396  grn_expr_code *c;
397  grn_expr_var *v;
398  grn_expr *e = (grn_expr *)expr;
399  uint32_t i, j;
400  grn_text_benc(ctx, buf, e->nvars);
401  for (i = e->nvars, v = e->vars; i; i--, v++) {
402  grn_text_benc(ctx, buf, v->name_size);
403  if (v->name_size) { GRN_TEXT_PUT(ctx, buf, v->name, v->name_size); }
404  grn_obj_pack(ctx, buf, &v->value);
405  }
406  i = e->codes_curr;
407  grn_text_benc(ctx, buf, i);
408  for (c = e->codes; i; i--, c++) {
409  grn_text_benc(ctx, buf, c->op);
410  grn_text_benc(ctx, buf, c->nargs);
411  if (!c->value) {
413  } else {
414  for (j = 0, v = e->vars; j < e->nvars; j++, v++) {
415  if (&v->value == c->value) {
417  grn_text_benc(ctx, buf, j);
418  break;
419  }
420  }
421  if (j == e->nvars) {
423  grn_obj_pack(ctx, buf, c->value);
424  }
425  }
426  }
427 }
428 
429 const uint8_t *
430 grn_expr_unpack(grn_ctx *ctx, const uint8_t *p, const uint8_t *pe, grn_obj *expr)
431 {
432  grn_obj *v;
434  uint32_t i, n, ns;
435  grn_expr_code *code;
436  grn_expr *e = (grn_expr *)expr;
437  GRN_B_DEC(n, p);
438  for (i = 0; i < n; i++) {
439  uint32_t object_type;
440  GRN_B_DEC(ns, p);
441  v = grn_expr_add_var(ctx, expr, ns ? (const char *)p : NULL, ns);
442  p += ns;
443  GRN_B_DEC(object_type, p);
444  if (GRN_TYPE <= object_type && object_type <= GRN_COLUMN_INDEX) { /* error */ }
445  p = grn_obj_unpack(ctx, p, pe, object_type, 0, v);
446  if (pe < p) {
447  ERR(GRN_INVALID_FORMAT, "benced image is corrupt");
448  return p;
449  }
450  }
451  GRN_B_DEC(n, p);
452  /* confirm e->codes_size >= n */
453  e->codes_curr = n;
454  for (i = 0, code = e->codes; i < n; i++, code++) {
455  GRN_B_DEC(code->op, p);
456  GRN_B_DEC(code->nargs, p);
457  GRN_B_DEC(type, p);
458  switch (type) {
460  code->value = NULL;
461  break;
463  {
464  uint32_t offset;
465  GRN_B_DEC(offset, p);
466  code->value = &e->vars[i].value;
467  }
468  break;
470  {
471  uint32_t object_type;
472  GRN_B_DEC(object_type, p);
473  if (GRN_TYPE <= object_type && object_type <= GRN_COLUMN_INDEX) {
474  grn_id id;
475  GRN_B_DEC(id, p);
476  code->value = grn_ctx_at(ctx, id);
477  } else {
478  if (!(v = const_new(ctx, e))) { return NULL; }
479  p = grn_obj_unpack(ctx, p, pe, object_type, GRN_OBJ_EXPRCONST, v);
480  code->value = v;
481  }
482  }
483  break;
484  }
485  if (pe < p) {
486  ERR(GRN_INVALID_FORMAT, "benced image is corrupt");
487  return p;
488  }
489  }
490  return p;
491 }
492 
493 grn_obj *
494 grn_expr_open(grn_ctx *ctx, grn_obj_spec *spec, const uint8_t *p, const uint8_t *pe)
495 {
496  grn_expr *expr = NULL;
497  if ((expr = GRN_MALLOCN(grn_expr, 1))) {
498  int size = 256;
499  expr->consts = NULL;
500  expr->nconsts = 0;
501  GRN_TEXT_INIT(&expr->name_buf, 0);
502  GRN_TEXT_INIT(&expr->dfi, 0);
504  expr->vars = NULL;
505  expr->nvars = 0;
507  if ((expr->values = GRN_MALLOCN(grn_obj, size))) {
508  int i;
509  for (i = 0; i < size; i++) {
511  }
512  expr->values_curr = 0;
513  expr->values_tail = 0;
514  expr->values_size = size;
515  if ((expr->codes = GRN_MALLOCN(grn_expr_code, size))) {
516  expr->codes_curr = 0;
517  expr->codes_size = size;
518  expr->obj.header = spec->header;
519  if (grn_expr_unpack(ctx, p, pe, (grn_obj *)expr) == pe) {
520  goto exit;
521  } else {
522  ERR(GRN_INVALID_FORMAT, "benced image is corrupt");
523  }
524  GRN_FREE(expr->codes);
525  }
526  GRN_FREE(expr->values);
527  }
528  GRN_FREE(expr);
529  expr = NULL;
530  }
531 exit :
532  return (grn_obj *)expr;
533 }
534 
535 /* data flow info */
536 typedef struct {
539  unsigned char type;
540 } grn_expr_dfi;
541 
542 #define DFI_POP(e,d) do {\
543  if (GRN_BULK_VSIZE(&(e)->dfi) >= sizeof(grn_expr_dfi)) {\
544  GRN_BULK_INCR_LEN((&(e)->dfi), -(sizeof(grn_expr_dfi)));\
545  (d) = (grn_expr_dfi *)(GRN_BULK_CURR(&(e)->dfi));\
546  (e)->code0 = (d)->code;\
547  } else {\
548  (d) = NULL;\
549  (e)->code0 = NULL;\
550  }\
551 } while (0)
552 
553 #define DFI_PUT(e,t,d,c) do {\
554  grn_expr_dfi dfi;\
555  dfi.type = (t);\
556  dfi.domain = (d);\
557  dfi.code = (c);\
558  if ((e)->code0) { (e)->code0->modify = (c) ? ((c) - (e)->code0) : 0; }\
559  grn_bulk_write(ctx, &(e)->dfi, (char *)&dfi, sizeof(grn_expr_dfi));\
560  (e)->code0 = NULL;\
561 } while (0)
562 
563 grn_expr_dfi *
564 dfi_value_at(grn_expr *expr, int offset)
565 {
566  grn_obj *obj = &expr->dfi;
567  int size = GRN_BULK_VSIZE(obj) / sizeof(grn_expr_dfi);
568  if (offset < 0) { offset = size + offset; }
569  return (0 <= offset && offset < size)
570  ? &(((grn_expr_dfi *)GRN_BULK_HEAD(obj))[offset])
571  : NULL;
572 }
573 
574 grn_obj *
575 grn_expr_create(grn_ctx *ctx, const char *name, unsigned int name_size)
576 {
577  grn_id id;
578  grn_obj *db;
579  grn_expr *expr = NULL;
580  if (!ctx || !ctx->impl || !(db = ctx->impl->db)) {
581  ERR(GRN_INVALID_ARGUMENT, "db not initialized");
582  return NULL;
583  }
584  if (name_size) {
586  "[expr][create] anonymous expression isn't implemented yet");
587  return NULL;
588  }
590  if (grn_db_check_name(ctx, name, name_size)) {
591  GRN_DB_CHECK_NAME_ERR("[expr][create]", name, name_size);
592  GRN_API_RETURN(NULL);
593  }
594  if (!GRN_DB_P(db)) {
595  ERR(GRN_INVALID_ARGUMENT, "named expr is not supported");
596  GRN_API_RETURN(NULL);
597  }
598  id = grn_obj_register(ctx, db, name, name_size);
599  if (id && (expr = GRN_MALLOCN(grn_expr, 1))) {
600  int size = GRN_STACK_SIZE;
601  expr->consts = NULL;
602  expr->nconsts = 0;
603  GRN_TEXT_INIT(&expr->name_buf, 0);
604  GRN_TEXT_INIT(&expr->dfi, 0);
606  expr->code0 = NULL;
607  expr->vars = NULL;
608  expr->nvars = 0;
609  expr->cacheable = 1;
610  expr->taintable = 0;
611  expr->values_curr = 0;
612  expr->values_tail = 0;
613  expr->values_size = size;
614  expr->codes_curr = 0;
615  expr->codes_size = size;
617  expr->obj.header.domain = GRN_ID_NIL;
618  expr->obj.range = GRN_ID_NIL;
619  if (!grn_db_obj_init(ctx, db, id, DB_OBJ(expr))) {
620  if ((expr->values = GRN_MALLOCN(grn_obj, size))) {
621  int i;
622  for (i = 0; i < size; i++) {
624  }
625  if ((expr->codes = GRN_MALLOCN(grn_expr_code, size))) {
626  goto exit;
627  }
628  GRN_FREE(expr->values);
629  }
630  }
631  GRN_FREE(expr);
632  expr = NULL;
633  }
634 exit :
635  GRN_API_RETURN((grn_obj *)expr);
636 }
637 
638 #define GRN_PTR_POP(obj,value) do {\
639  if (GRN_BULK_VSIZE(obj) >= sizeof(grn_obj *)) {\
640  GRN_BULK_INCR_LEN((obj), -(sizeof(grn_obj *)));\
641  value = *(grn_obj **)(GRN_BULK_CURR(obj));\
642  } else {\
643  value = NULL;\
644  }\
645 } while (0)
646 
647 grn_rc
649 {
650  uint32_t i;
651  grn_expr *e = (grn_expr *)expr;
653  /*
654  if (e->obj.header.domain) {
655  grn_hash_delete(ctx, ctx->impl->qe, &e->obj.header.domain, sizeof(grn_id), NULL);
656  }
657  */
658  grn_expr_clear_vars(ctx, expr);
659  for (i = 0; i < e->nconsts; i++) {
660  grn_obj_close(ctx, &e->consts[i]);
661  }
662  if (e->consts) { GRN_FREE(e->consts); }
663  grn_obj_close(ctx, &e->name_buf);
664  grn_obj_close(ctx, &e->dfi);
665  for (;;) {
666  grn_obj *obj;
667  GRN_PTR_POP(&e->objs, obj);
668  if (obj) {
669 #ifdef USE_MEMORY_DEBUG
670  grn_obj_unlink(ctx, obj);
671 #else
672  if (obj->header.type) {
673  grn_obj_unlink(ctx, obj);
674  } else {
675  GRN_LOG(ctx, GRN_LOG_WARNING, "GRN_VOID object is tried to be unlinked");
676  }
677 #endif
678  } else { break; }
679  }
680  grn_obj_close(ctx, &e->objs);
681  for (i = 0; i < e->nvars; i++) {
682  grn_obj_close(ctx, &e->vars[i].value);
683  }
684  if (e->vars) { GRN_FREE(e->vars); }
685  for (i = 0; i < e->values_tail; i++) {
686  grn_obj_close(ctx, &e->values[i]);
687  }
688  GRN_FREE(e->values);
689  GRN_FREE(e->codes);
690  GRN_FREE(e);
691  GRN_API_RETURN(ctx->rc);
692 }
693 
694 grn_obj *
695 grn_expr_add_var(grn_ctx *ctx, grn_obj *expr, const char *name, unsigned int name_size)
696 {
697  uint32_t i;
698  char *p;
699  grn_expr_var *v;
700  grn_obj *res = NULL;
701  grn_expr *e = (grn_expr *)expr;
703  if (DB_OBJ(expr)->id & GRN_OBJ_TMP_OBJECT) {
704  res = grn_expr_get_or_add_var(ctx, expr, name, name_size);
705  } else {
706  if (!e->vars) {
708  ERR(GRN_NO_MEMORY_AVAILABLE, "malloc failed");
709  }
710  }
711  if (e->vars && e->nvars < GRN_STACK_SIZE) {
712  v = e->vars + e->nvars++;
713  if (name_size) {
714  GRN_TEXT_PUT(ctx, &e->name_buf, name, name_size);
715  } else {
716  uint32_t ol = GRN_TEXT_LEN(&e->name_buf);
717  GRN_TEXT_PUTC(ctx, &e->name_buf, '$');
718  grn_text_itoa(ctx, &e->name_buf, e->nvars);
719  name_size = GRN_TEXT_LEN(&e->name_buf) - ol;
720  }
721  v->name_size = name_size;
722  res = &v->value;
723  GRN_VOID_INIT(res);
724  for (i = e->nvars, p = GRN_TEXT_VALUE(&e->name_buf), v = e->vars; i; i--, v++) {
725  v->name = p;
726  p += v->name_size;
727  }
728  }
729  }
730  GRN_API_RETURN(res);
731 }
732 
733 grn_obj *
734 grn_expr_get_var(grn_ctx *ctx, grn_obj *expr, const char *name, unsigned int name_size)
735 {
736  uint32_t n;
737  grn_obj *res = NULL;
738  grn_hash *vars = grn_expr_get_vars(ctx, expr, &n);
739  if (vars) { grn_hash_get(ctx, vars, name, name_size, (void **)&res); }
740  return res;
741 }
742 
743 grn_obj *
744 grn_expr_get_or_add_var(grn_ctx *ctx, grn_obj *expr, const char *name, unsigned int name_size)
745 {
746  uint32_t n;
747  grn_obj *res = NULL;
748  grn_hash *vars = grn_expr_get_vars(ctx, expr, &n);
749  if (vars) {
750  int added = 0;
751  char name_buf[16];
752  if (!name_size) {
753  char *rest;
754  name_buf[0] = '$';
755  grn_itoa((int)GRN_HASH_SIZE(vars) + 1, name_buf + 1, name_buf + 16, &rest);
756  name_size = rest - name_buf;
757  name = name_buf;
758  }
759  grn_hash_add(ctx, vars, name, name_size, (void **)&res, &added);
760  if (added) { GRN_TEXT_INIT(res, 0); }
761  }
762  return res;
763 }
764 
765 grn_obj *
766 grn_expr_get_var_by_offset(grn_ctx *ctx, grn_obj *expr, unsigned int offset)
767 {
768  uint32_t n;
769  grn_obj *res = NULL;
770  grn_hash *vars = grn_expr_get_vars(ctx, expr, &n);
771  if (vars) { res = (grn_obj *)grn_hash_get_value_(ctx, vars, offset + 1, &n); }
772  return res;
773 }
774 
775 #define EXPRVP(x) ((x)->header.impl_flags & GRN_OBJ_EXPRVALUE)
776 
777 #define CONSTP(obj) ((obj) && ((obj)->header.impl_flags & GRN_OBJ_EXPRCONST))
778 
779 #define PUSH_CODE(e,o,v,n,c) do {\
780  (c) = &(e)->codes[e->codes_curr++];\
781  (c)->value = (v);\
782  (c)->nargs = (n);\
783  (c)->op = (o);\
784  (c)->flags = 0;\
785  (c)->modify = 0;\
786 } while (0)
787 
788 #define APPEND_UNARY_MINUS_OP(e) do { \
789  grn_expr_code *code_; \
790  grn_id domain; \
791  unsigned char type; \
792  grn_obj *x; \
793  DFI_POP(e, dfi); \
794  code_ = dfi->code; \
795  domain = dfi->domain; \
796  type = dfi->type; \
797  x = code_->value; \
798  if (CONSTP(x)) { \
799  switch (domain) { \
800  case GRN_DB_UINT32: \
801  { \
802  unsigned int value; \
803  value = GRN_UINT32_VALUE(x); \
804  if (value > (unsigned int)0x80000000) { \
805  domain = GRN_DB_INT64; \
806  x->header.domain = domain; \
807  GRN_INT64_SET(ctx, x, -((long long int)value)); \
808  } else { \
809  domain = GRN_DB_INT32; \
810  x->header.domain = domain; \
811  GRN_INT32_SET(ctx, x, -((int)value)); \
812  } \
813  } \
814  break; \
815  case GRN_DB_INT64: \
816  GRN_INT64_SET(ctx, x, -GRN_INT64_VALUE(x)); \
817  break; \
818  case GRN_DB_FLOAT: \
819  GRN_FLOAT_SET(ctx, x, -GRN_FLOAT_VALUE(x)); \
820  break; \
821  default: \
822  PUSH_CODE(e, op, obj, nargs, code); \
823  break; \
824  } \
825  } else { \
826  PUSH_CODE(e, op, obj, nargs, code); \
827  } \
828  DFI_PUT(e, type, domain, code_); \
829 } while (0)
830 
831 #define PUSH_N_ARGS_ARITHMETIC_OP(e, op, obj, nargs, code) do { \
832  PUSH_CODE(e, op, obj, nargs, code); \
833  { \
834  int i = nargs; \
835  while (i--) { \
836  DFI_POP(e, dfi); \
837  } \
838  } \
839  DFI_PUT(e, type, domain, code); \
840 } while (0)
841 
842 grn_obj *
843 grn_expr_append_obj(grn_ctx *ctx, grn_obj *expr, grn_obj *obj, grn_operator op, int nargs)
844 {
845  uint8_t type = GRN_VOID;
846  grn_id domain = GRN_ID_NIL;
847  grn_expr_dfi *dfi;
848  grn_expr_code *code;
849  grn_obj *res = NULL;
850  grn_expr *e = (grn_expr *)expr;
852  if (e->codes_curr >= e->codes_size) {
853  ERR(GRN_NO_MEMORY_AVAILABLE, "stack is full");
854  goto exit;
855  }
856  {
857  switch (op) {
858  case GRN_OP_PUSH :
859  if (obj) {
860  PUSH_CODE(e, op, obj, nargs, code);
861  DFI_PUT(e, obj->header.type, GRN_OBJ_GET_DOMAIN(obj), code);
862  } else {
863  ERR(GRN_INVALID_ARGUMENT, "obj not assigned for GRN_OP_PUSH");
864  goto exit;
865  }
866  break;
867  case GRN_OP_NOP :
868  /* nop */
869  break;
870  case GRN_OP_POP :
871  if (obj) {
872  ERR(GRN_INVALID_ARGUMENT, "obj assigned for GRN_OP_POP");
873  goto exit;
874  } else {
875  PUSH_CODE(e, op, obj, nargs, code);
876  DFI_POP(e, dfi);
877  }
878  break;
879  case GRN_OP_CALL :
880  {
881  grn_obj *proc = NULL;
882  if (e->codes_curr - nargs > 0) {
883  int i;
884  grn_expr_code *code;
885  code = &(e->codes[e->codes_curr - 1]);
886  for (i = 0; i < nargs; i++) {
887  int rest_n_codes = 1;
888  while (rest_n_codes > 0) {
889  if (!code->value) {
890  rest_n_codes += code->nargs;
891  }
892  rest_n_codes--;
893  code--;
894  }
895  }
896  proc = code->value;
897  }
898  if (!proc) {
899  ERR(GRN_INVALID_ARGUMENT, "invalid function call expression");
900  goto exit;
901  }
902  if (!function_proc_p(proc)) {
903  grn_obj buffer;
904 
905  GRN_TEXT_INIT(&buffer, 0);
906  switch (proc->header.type) {
907  case GRN_TABLE_HASH_KEY:
908  case GRN_TABLE_PAT_KEY:
909  case GRN_TABLE_NO_KEY:
910  case GRN_COLUMN_FIX_SIZE:
911  case GRN_COLUMN_VAR_SIZE:
912  case GRN_COLUMN_INDEX:
913  grn_inspect_name(ctx, &buffer, proc);
914  break;
915  default:
916  grn_inspect(ctx, &buffer, proc);
917  break;
918  }
919  ERR(GRN_INVALID_ARGUMENT, "invalid function: <%.*s>",
920  (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer));
921  GRN_OBJ_FIN(ctx, &buffer);
922  goto exit;
923  }
924  }
925  PUSH_CODE(e, op, obj, nargs, code);
926  {
927  int i = nargs;
928  while (i--) { DFI_POP(e, dfi); }
929  }
930  if (!obj) { DFI_POP(e, dfi); }
931  // todo : increment e->values_tail.
932  DFI_PUT(e, type, domain, code); /* cannot identify type of return value */
933  e->cacheable = 0;
934  break;
935  case GRN_OP_INTERN :
936  if (obj && CONSTP(obj)) {
937  grn_obj *value;
938  value = grn_expr_get_var(ctx, expr, GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj));
939  if (!value) { value = grn_ctx_get(ctx, GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj)); }
940  if (value) {
941  obj = value;
942  op = GRN_OP_PUSH;
943  type = obj->header.type;
944  domain = GRN_OBJ_GET_DOMAIN(obj);
945  }
946  }
947  PUSH_CODE(e, op, obj, nargs, code);
948  DFI_PUT(e, type, domain, code);
949  break;
950  case GRN_OP_EQUAL :
951  PUSH_CODE(e, op, obj, nargs, code);
952  if (nargs) {
953  grn_id xd, yd = GRN_ID_NIL;
954  grn_obj *x, *y = NULL;
955  int i = nargs - 1;
956  if (obj) {
957  xd = GRN_OBJ_GET_DOMAIN(obj);
958  x = obj;
959  } else {
960  DFI_POP(e, dfi);
961  x = dfi->code->value;
962  xd = dfi->domain;
963  }
964  while (i--) {
965  DFI_POP(e, dfi);
966  y = dfi->code->value;
967  yd = dfi->domain;
968  }
969  if (CONSTP(x)) {
970  if (CONSTP(y)) {
971  /* todo */
972  } else {
973  grn_obj dest;
974  if (xd != yd) {
975  GRN_OBJ_INIT(&dest, GRN_BULK, 0, yd);
976  if (!grn_obj_cast(ctx, x, &dest, GRN_FALSE)) {
977  grn_obj_reinit(ctx, x, yd, 0);
978  grn_bulk_write(ctx, x, GRN_BULK_HEAD(&dest), GRN_BULK_VSIZE(&dest));
979  }
980  GRN_OBJ_FIN(ctx, &dest);
981  }
982  }
983  } else {
984  if (CONSTP(y)) {
985  grn_obj dest;
986  if (xd != yd) {
987  GRN_OBJ_INIT(&dest, GRN_BULK, 0, xd);
988  if (!grn_obj_cast(ctx, y, &dest, GRN_FALSE)) {
989  grn_obj_reinit(ctx, y, xd, 0);
990  grn_bulk_write(ctx, y, GRN_BULK_HEAD(&dest), GRN_BULK_VSIZE(&dest));
991  }
992  GRN_OBJ_FIN(ctx, &dest);
993  }
994  }
995  }
996  }
997  DFI_PUT(e, type, domain, code);
998  break;
999  case GRN_OP_TABLE_CREATE :
1000  case GRN_OP_EXPR_GET_VAR :
1001  case GRN_OP_MATCH :
1002  case GRN_OP_NEAR :
1003  case GRN_OP_NEAR2 :
1004  case GRN_OP_SIMILAR :
1005  case GRN_OP_PREFIX :
1006  case GRN_OP_SUFFIX :
1007  case GRN_OP_NOT_EQUAL :
1008  case GRN_OP_LESS :
1009  case GRN_OP_GREATER :
1010  case GRN_OP_LESS_EQUAL :
1011  case GRN_OP_GREATER_EQUAL :
1012  case GRN_OP_GEO_DISTANCE1 :
1013  case GRN_OP_GEO_DISTANCE2 :
1014  case GRN_OP_GEO_DISTANCE3 :
1015  case GRN_OP_GEO_DISTANCE4 :
1016  case GRN_OP_GEO_WITHINP5 :
1017  case GRN_OP_GEO_WITHINP6 :
1018  case GRN_OP_GEO_WITHINP8 :
1019  case GRN_OP_OBJ_SEARCH :
1020  case GRN_OP_TABLE_SELECT :
1021  case GRN_OP_TABLE_SORT :
1022  case GRN_OP_TABLE_GROUP :
1023  case GRN_OP_JSON_PUT :
1024  case GRN_OP_GET_REF :
1025  case GRN_OP_ADJUST :
1026  case GRN_OP_TERM_EXTRACT :
1027  PUSH_CODE(e, op, obj, nargs, code);
1028  if (nargs) {
1029  int i = nargs - 1;
1030  if (!obj) { DFI_POP(e, dfi); }
1031  while (i--) { DFI_POP(e, dfi); }
1032  }
1033  DFI_PUT(e, type, domain, code);
1034  break;
1035  case GRN_OP_AND :
1036  case GRN_OP_OR :
1037  case GRN_OP_AND_NOT :
1038  PUSH_CODE(e, op, obj, nargs, code);
1039  if (nargs != 2) {
1040  GRN_LOG(ctx, GRN_LOG_WARNING, "nargs(%d) != 2 in relative op", nargs);
1041  }
1042  if (obj) {
1043  GRN_LOG(ctx, GRN_LOG_WARNING, "obj assigned to relative op");
1044  }
1045  {
1046  int i = nargs;
1047  while (i--) {
1048  DFI_POP(e, dfi);
1049  if (dfi) {
1051  } else {
1052  ERR(GRN_SYNTAX_ERROR, "stack under flow in relative op");
1053  }
1054  }
1055  }
1056  DFI_PUT(e, type, domain, code);
1057  break;
1058  case GRN_OP_NOT :
1059  if (nargs == 1) {
1060  PUSH_CODE(e, op, obj, nargs, code);
1061  }
1062  break;
1063  case GRN_OP_PLUS :
1064  if (nargs > 1) {
1065  PUSH_N_ARGS_ARITHMETIC_OP(e, op, obj, nargs, code);
1066  }
1067  break;
1068  case GRN_OP_MINUS :
1069  if (nargs == 1) {
1071  } else {
1072  PUSH_N_ARGS_ARITHMETIC_OP(e, op, obj, nargs, code);
1073  }
1074  break;
1075  case GRN_OP_BITWISE_NOT :
1076  PUSH_CODE(e, op, obj, nargs, code);
1077  break;
1078  case GRN_OP_STAR :
1079  case GRN_OP_SLASH :
1080  case GRN_OP_MOD :
1081  case GRN_OP_SHIFTL :
1082  case GRN_OP_SHIFTR :
1083  case GRN_OP_SHIFTRR :
1084  case GRN_OP_BITWISE_OR :
1085  case GRN_OP_BITWISE_XOR :
1086  case GRN_OP_BITWISE_AND :
1087  PUSH_N_ARGS_ARITHMETIC_OP(e, op, obj, nargs, code);
1088  break;
1089  case GRN_OP_INCR :
1090  case GRN_OP_DECR :
1091  case GRN_OP_INCR_POST :
1092  case GRN_OP_DECR_POST :
1093  {
1094  DFI_POP(e, dfi);
1095  if (dfi) {
1096  type = dfi->type;
1097  domain = dfi->domain;
1098  if (dfi->code) {
1099  if (dfi->code->op == GRN_OP_GET_VALUE) {
1100  dfi->code->op = GRN_OP_GET_REF;
1101  }
1102  if (dfi->code->value && grn_obj_is_persistent(ctx, dfi->code->value)) {
1103  e->cacheable = 0;
1104  e->taintable = 1;
1105  }
1106  }
1107  }
1108  PUSH_CODE(e, op, obj, nargs, code);
1109  }
1110  DFI_PUT(e, type, domain, code);
1111  break;
1112  case GRN_OP_GET_VALUE :
1113  {
1114  grn_id vdomain = GRN_ID_NIL;
1115  if (obj) {
1116  if (nargs == 1) {
1117  grn_obj *v = grn_expr_get_var_by_offset(ctx, expr, 0);
1118  if (v) { vdomain = GRN_OBJ_GET_DOMAIN(v); }
1119  } else {
1120  DFI_POP(e, dfi);
1121  vdomain = dfi->domain;
1122  }
1123  if (vdomain && CONSTP(obj) && obj->header.type == GRN_BULK) {
1124  grn_obj *table = grn_ctx_at(ctx, vdomain);
1125  grn_obj *col = grn_obj_column(ctx, table, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj));
1126  if (col) {
1127  obj = col;
1128  type = col->header.type;
1129  domain = grn_obj_get_range(ctx, col);
1130  grn_obj_unlink(ctx, col);
1131  }
1132  } else {
1133  domain = grn_obj_get_range(ctx, obj);
1134  }
1135  PUSH_CODE(e, op, obj, nargs, code);
1136  } else {
1137  grn_expr_dfi *dfi0;
1138  DFI_POP(e, dfi0);
1139  if (nargs == 1) {
1140  grn_obj *v = grn_expr_get_var_by_offset(ctx, expr, 0);
1141  if (v) { vdomain = GRN_OBJ_GET_DOMAIN(v); }
1142  } else {
1143  DFI_POP(e, dfi);
1144  vdomain = dfi->domain;
1145  }
1146  if (dfi0->code->op == GRN_OP_PUSH) {
1147  dfi0->code->op = op;
1148  dfi0->code->nargs = nargs;
1149  obj = dfi0->code->value;
1150  if (vdomain && obj && CONSTP(obj) && obj->header.type == GRN_BULK) {
1151  grn_obj *table = grn_ctx_at(ctx, vdomain);
1152  grn_obj *col = grn_obj_column(ctx, table, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj));
1153  if (col) {
1154  dfi0->code->value = col;
1155  type = col->header.type;
1156  domain = grn_obj_get_range(ctx, col);
1157  grn_obj_unlink(ctx, col);
1158  }
1159  } else {
1160  domain = grn_obj_get_range(ctx, obj);
1161  }
1162  code = dfi0->code;
1163  } else {
1164  PUSH_CODE(e, op, obj, nargs, code);
1165  }
1166  }
1167  }
1168  DFI_PUT(e, type, domain, code);
1169  break;
1170  case GRN_OP_ASSIGN :
1171  case GRN_OP_STAR_ASSIGN :
1172  case GRN_OP_SLASH_ASSIGN :
1173  case GRN_OP_MOD_ASSIGN :
1174  case GRN_OP_PLUS_ASSIGN :
1175  case GRN_OP_MINUS_ASSIGN :
1176  case GRN_OP_SHIFTL_ASSIGN :
1177  case GRN_OP_SHIFTR_ASSIGN :
1178  case GRN_OP_SHIFTRR_ASSIGN :
1179  case GRN_OP_AND_ASSIGN :
1180  case GRN_OP_OR_ASSIGN :
1181  case GRN_OP_XOR_ASSIGN :
1182  {
1183  if (obj) {
1184  type = obj->header.type;
1185  domain = GRN_OBJ_GET_DOMAIN(obj);
1186  } else {
1187  DFI_POP(e, dfi);
1188  if (dfi) {
1189  type = dfi->type;
1190  domain = dfi->domain;
1191  }
1192  }
1193  DFI_POP(e, dfi);
1194  if (dfi && (dfi->code)) {
1195  if (dfi->code->op == GRN_OP_GET_VALUE) {
1196  dfi->code->op = GRN_OP_GET_REF;
1197  }
1198  if (dfi->code->value && grn_obj_is_persistent(ctx, dfi->code->value)) {
1199  e->cacheable = 0;
1200  e->taintable = 1;
1201  }
1202  }
1203  PUSH_CODE(e, op, obj, nargs, code);
1204  }
1205  DFI_PUT(e, type, domain, code);
1206  break;
1207  case GRN_OP_JUMP :
1208  DFI_POP(e, dfi);
1209  PUSH_CODE(e, op, obj, nargs, code);
1210  break;
1211  case GRN_OP_CJUMP :
1212  DFI_POP(e, dfi);
1213  PUSH_CODE(e, op, obj, nargs, code);
1214  break;
1215  case GRN_OP_COMMA :
1216  PUSH_CODE(e, op, obj, nargs, code);
1217  break;
1218  case GRN_OP_GET_MEMBER :
1219  DFI_POP(e, dfi);
1220  DFI_POP(e, dfi);
1221  if (dfi) {
1222  type = dfi->type;
1223  domain = dfi->domain;
1224  if (dfi->code) {
1225  if (dfi->code->op == GRN_OP_GET_VALUE) {
1226  dfi->code->op = GRN_OP_GET_REF;
1227  }
1228  }
1229  }
1230  PUSH_CODE(e, op, obj, nargs, code);
1231  DFI_PUT(e, type, domain, code);
1232  break;
1233  default :
1234  break;
1235  }
1236  }
1237 exit :
1238  if (!ctx->rc) { res = obj; }
1239  GRN_API_RETURN(res);
1240 }
1241 #undef PUSH_N_ARGS_ARITHMETIC_OP
1242 #undef APPEND_UNARY_MINUS_OP
1243 
1244 grn_obj *
1246  grn_operator op, int nargs)
1247 {
1248  grn_obj *res = NULL;
1249  grn_expr *e = (grn_expr *)expr;
1250  GRN_API_ENTER;
1251  if (!obj) {
1252  ERR(GRN_SYNTAX_ERROR, "constant is null");
1253  goto exit;
1254  }
1255  if (GRN_DB_OBJP(obj) || GRN_ACCESSORP(obj)) {
1256  res = obj;
1257  } else {
1258  if ((res = const_new(ctx, e))) {
1259  switch (obj->header.type) {
1260  case GRN_VOID :
1261  case GRN_BULK :
1262  case GRN_UVECTOR :
1263  GRN_OBJ_INIT(res, obj->header.type, 0, obj->header.domain);
1264  grn_bulk_write(ctx, res, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj));
1265  break;
1266  default :
1267  res = NULL;
1268  ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "unsupported type");
1269  goto exit;
1270  }
1272  }
1273  }
1274  grn_expr_append_obj(ctx, expr, res, op, nargs); /* constant */
1275 exit :
1276  GRN_API_RETURN(res);
1277 }
1278 
1279 static grn_obj *
1280 grn_expr_add_str(grn_ctx *ctx, grn_obj *expr, const char *str, unsigned int str_size)
1281 {
1282  grn_obj *res = NULL;
1283  grn_expr *e = (grn_expr *)expr;
1284  if ((res = const_new(ctx, e))) {
1285  GRN_TEXT_INIT(res, 0);
1286  grn_bulk_write(ctx, res, str, str_size);
1288  }
1289  return res;
1290 }
1291 
1292 grn_obj *
1293 grn_expr_append_const_str(grn_ctx *ctx, grn_obj *expr, const char *str, unsigned int str_size,
1294  grn_operator op, int nargs)
1295 {
1296  grn_obj *res;
1297  GRN_API_ENTER;
1298  res = grn_expr_add_str(ctx, expr, str, str_size);
1299  grn_expr_append_obj(ctx, expr, res, op, nargs); /* constant */
1300  GRN_API_RETURN(res);
1301 }
1302 
1303 grn_obj *
1305  grn_operator op, int nargs)
1306 {
1307  grn_obj *res = NULL;
1308  grn_expr *e = (grn_expr *)expr;
1309  GRN_API_ENTER;
1310  if ((res = const_new(ctx, e))) {
1311  GRN_INT32_INIT(res, 0);
1312  GRN_INT32_SET(ctx, res, i);
1314  }
1315  grn_expr_append_obj(ctx, expr, res, op, nargs); /* constant */
1316  GRN_API_RETURN(res);
1317 }
1318 
1319 grn_rc
1320 grn_expr_append_op(grn_ctx *ctx, grn_obj *expr, grn_operator op, int nargs)
1321 {
1322  grn_expr_append_obj(ctx, expr, NULL, op, nargs);
1323  return ctx->rc;
1324 }
1325 
1326 grn_rc
1328 {
1329  grn_obj_spec_save(ctx, DB_OBJ(expr));
1330  return ctx->rc;
1331 }
1332 
1333 #define WITH_SPSAVE(block) do {\
1334  ctx->impl->stack_curr = sp - ctx->impl->stack;\
1335  e->values_curr = vp - e->values;\
1336  block\
1337  vp = e->values + e->values_curr;\
1338  sp = ctx->impl->stack + ctx->impl->stack_curr;\
1339  s0 = sp[-1];\
1340  s1 = sp[-2];\
1341 } while (0)
1342 
1343 #define DO_COMPARE_SUB_NUMERIC(y,op) do {\
1344  switch ((y)->header.domain) {\
1345  case GRN_DB_INT8 :\
1346  r = (x_ op GRN_INT8_VALUE(y));\
1347  break;\
1348  case GRN_DB_UINT8 :\
1349  r = (x_ op GRN_UINT8_VALUE(y));\
1350  break;\
1351  case GRN_DB_INT16 :\
1352  r = (x_ op GRN_INT16_VALUE(y));\
1353  break;\
1354  case GRN_DB_UINT16 :\
1355  r = (x_ op GRN_UINT16_VALUE(y));\
1356  break;\
1357  case GRN_DB_INT32 :\
1358  r = (x_ op GRN_INT32_VALUE(y));\
1359  break;\
1360  case GRN_DB_UINT32 :\
1361  r = (x_ op GRN_UINT32_VALUE(y));\
1362  break;\
1363  case GRN_DB_INT64 :\
1364  r = (x_ op GRN_INT64_VALUE(y));\
1365  break;\
1366  case GRN_DB_TIME :\
1367  r = (GRN_TIME_PACK(x_,0) op GRN_INT64_VALUE(y));\
1368  break;\
1369  case GRN_DB_UINT64 :\
1370  r = (x_ op GRN_UINT64_VALUE(y));\
1371  break;\
1372  case GRN_DB_FLOAT :\
1373  r = (x_ op GRN_FLOAT_VALUE(y));\
1374  break;\
1375  default :\
1376  r = 0;\
1377  break;\
1378  }\
1379 } while (0)
1380 
1381 #define DO_COMPARE_SUB(op) do {\
1382  switch (y->header.domain) {\
1383  case GRN_DB_SHORT_TEXT :\
1384  case GRN_DB_TEXT :\
1385  case GRN_DB_LONG_TEXT :\
1386  {\
1387  grn_obj y_;\
1388  GRN_OBJ_INIT(&y_, GRN_BULK, 0, x->header.domain);\
1389  if (grn_obj_cast(ctx, y, &y_, GRN_FALSE)) {\
1390  r = 0;\
1391  } else {\
1392  DO_COMPARE_SUB_NUMERIC(&y_, op);\
1393  }\
1394  GRN_OBJ_FIN(ctx, &y_);\
1395  }\
1396  break;\
1397  default :\
1398  DO_COMPARE_SUB_NUMERIC(y,op);\
1399  break;\
1400  }\
1401 } while (0)
1402 
1403 #define DO_COMPARE_BUILTIN(x,y,r,op) do {\
1404  switch (x->header.domain) {\
1405  case GRN_DB_INT8 :\
1406  {\
1407  int8_t x_ = GRN_INT8_VALUE(x);\
1408  DO_COMPARE_SUB(op);\
1409  }\
1410  break;\
1411  case GRN_DB_UINT8 :\
1412  {\
1413  uint8_t x_ = GRN_UINT8_VALUE(x);\
1414  DO_COMPARE_SUB(op);\
1415  }\
1416  break;\
1417  case GRN_DB_INT16 :\
1418  {\
1419  int16_t x_ = GRN_INT16_VALUE(x);\
1420  DO_COMPARE_SUB(op);\
1421  }\
1422  break;\
1423  case GRN_DB_UINT16 :\
1424  {\
1425  uint16_t x_ = GRN_UINT16_VALUE(x);\
1426  DO_COMPARE_SUB(op);\
1427  }\
1428  break;\
1429  case GRN_DB_INT32 :\
1430  {\
1431  int32_t x_ = GRN_INT32_VALUE(x);\
1432  DO_COMPARE_SUB(op);\
1433  }\
1434  break;\
1435  case GRN_DB_UINT32 :\
1436  {\
1437  uint32_t x_ = GRN_UINT32_VALUE(x);\
1438  DO_COMPARE_SUB(op);\
1439  }\
1440  break;\
1441  case GRN_DB_TIME :\
1442  {\
1443  int64_t x_ = GRN_INT64_VALUE(x);\
1444  switch (y->header.domain) {\
1445  case GRN_DB_INT32 :\
1446  r = (x_ op GRN_TIME_PACK(GRN_INT32_VALUE(y), 0));\
1447  break;\
1448  case GRN_DB_UINT32 :\
1449  r = (x_ op GRN_TIME_PACK(GRN_UINT32_VALUE(y), 0));\
1450  break;\
1451  case GRN_DB_INT64 :\
1452  case GRN_DB_TIME :\
1453  r = (x_ op GRN_INT64_VALUE(y));\
1454  break;\
1455  case GRN_DB_UINT64 :\
1456  r = (x_ op GRN_UINT64_VALUE(y));\
1457  break;\
1458  case GRN_DB_FLOAT :\
1459  r = (x_ op GRN_TIME_PACK(GRN_FLOAT_VALUE(y), 0));\
1460  break;\
1461  case GRN_DB_SHORT_TEXT :\
1462  case GRN_DB_TEXT :\
1463  case GRN_DB_LONG_TEXT :\
1464  {\
1465  const char *p_ = GRN_TEXT_VALUE(y);\
1466  int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\
1467  r = (x_ op GRN_TIME_PACK(i_, 0));\
1468  }\
1469  break;\
1470  default :\
1471  r = 0;\
1472  break;\
1473  }\
1474  }\
1475  break;\
1476  case GRN_DB_INT64 :\
1477  {\
1478  int64_t x_ = GRN_INT64_VALUE(x);\
1479  DO_COMPARE_SUB(op);\
1480  }\
1481  break;\
1482  case GRN_DB_UINT64 :\
1483  {\
1484  uint64_t x_ = GRN_UINT64_VALUE(x);\
1485  DO_COMPARE_SUB(op);\
1486  }\
1487  break;\
1488  case GRN_DB_FLOAT :\
1489  {\
1490  double x_ = GRN_FLOAT_VALUE(x);\
1491  DO_COMPARE_SUB(op);\
1492  }\
1493  break;\
1494  case GRN_DB_SHORT_TEXT :\
1495  case GRN_DB_TEXT :\
1496  case GRN_DB_LONG_TEXT :\
1497  if (GRN_DB_SHORT_TEXT <= y->header.domain && y->header.domain <= GRN_DB_LONG_TEXT) {\
1498  int r_;\
1499  uint32_t la = GRN_TEXT_LEN(x), lb = GRN_TEXT_LEN(y);\
1500  if (la > lb) {\
1501  if (!(r_ = memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), lb))) {\
1502  r_ = 1;\
1503  }\
1504  } else {\
1505  if (!(r_ = memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), la))) {\
1506  r_ = la == lb ? 0 : -1;\
1507  }\
1508  }\
1509  r = (r_ op 0);\
1510  } else {\
1511  const char *q_ = GRN_TEXT_VALUE(x);\
1512  int x_ = grn_atoi(q_, q_ + GRN_TEXT_LEN(x), NULL);\
1513  DO_COMPARE_SUB(op);\
1514  }\
1515  break;\
1516  default :\
1517  r = 0;\
1518  break;\
1519  }\
1520 } while (0)
1521 
1522 #define DO_COMPARE(x, y, r, op) do {\
1523  if (x->header.domain >= GRN_N_RESERVED_TYPES) {\
1524  grn_obj *table;\
1525  table = grn_ctx_at(ctx, x->header.domain);\
1526  switch (table->header.type) {\
1527  case GRN_TABLE_HASH_KEY :\
1528  case GRN_TABLE_PAT_KEY :\
1529  {\
1530  grn_obj key;\
1531  int length;\
1532  GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain);\
1533  length = grn_table_get_key2(ctx, table, GRN_RECORD_VALUE(x), &key);\
1534  if (length > 0) {\
1535  grn_obj *x_original = x;\
1536  x = &key;\
1537  DO_COMPARE_BUILTIN((&key), y, r, op);\
1538  x = x_original;\
1539  } else {\
1540  r = 0;\
1541  }\
1542  GRN_OBJ_FIN(ctx, &key);\
1543  }\
1544  break;\
1545  default :\
1546  r = 0;\
1547  break;\
1548  }\
1549  grn_obj_unlink(ctx, table);\
1550  } else {\
1551  DO_COMPARE_BUILTIN(x, y, r, op);\
1552  }\
1553 } while (0)
1554 
1555 #define DO_EQ_SUB do {\
1556  switch (y->header.domain) {\
1557  case GRN_DB_INT8 :\
1558  r = (x_ == GRN_INT8_VALUE(y));\
1559  break;\
1560  case GRN_DB_UINT8 :\
1561  r = (x_ == GRN_UINT8_VALUE(y));\
1562  break;\
1563  case GRN_DB_INT16 :\
1564  r = (x_ == GRN_INT16_VALUE(y));\
1565  break;\
1566  case GRN_DB_UINT16 :\
1567  r = (x_ == GRN_UINT16_VALUE(y));\
1568  break;\
1569  case GRN_DB_INT32 :\
1570  r = (x_ == GRN_INT32_VALUE(y));\
1571  break;\
1572  case GRN_DB_UINT32 :\
1573  r = (x_ == GRN_UINT32_VALUE(y));\
1574  break;\
1575  case GRN_DB_INT64 :\
1576  r = (x_ == GRN_INT64_VALUE(y));\
1577  break;\
1578  case GRN_DB_TIME :\
1579  r = (GRN_TIME_PACK(x_,0) == GRN_INT64_VALUE(y));\
1580  break;\
1581  case GRN_DB_UINT64 :\
1582  r = (x_ == GRN_UINT64_VALUE(y));\
1583  break;\
1584  case GRN_DB_FLOAT :\
1585  r = ((x_ <= GRN_FLOAT_VALUE(y)) && (x_ >= GRN_FLOAT_VALUE(y)));\
1586  break;\
1587  case GRN_DB_SHORT_TEXT :\
1588  case GRN_DB_TEXT :\
1589  case GRN_DB_LONG_TEXT :\
1590  {\
1591  const char *p_ = GRN_TEXT_VALUE(y);\
1592  int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\
1593  r = (x_ == i_);\
1594  }\
1595  break;\
1596  default :\
1597  r = 0;\
1598  break;\
1599  }\
1600 } while (0)
1601 
1602 #define DO_EQ(x,y,r) do {\
1603  switch (x->header.domain) {\
1604  case GRN_DB_VOID :\
1605  r = 0;\
1606  break;\
1607  case GRN_DB_INT8 :\
1608  {\
1609  int8_t x_ = GRN_INT8_VALUE(x);\
1610  DO_EQ_SUB;\
1611  }\
1612  break;\
1613  case GRN_DB_UINT8 :\
1614  {\
1615  uint8_t x_ = GRN_UINT8_VALUE(x);\
1616  DO_EQ_SUB;\
1617  }\
1618  break;\
1619  case GRN_DB_INT16 :\
1620  {\
1621  int16_t x_ = GRN_INT16_VALUE(x);\
1622  DO_EQ_SUB;\
1623  }\
1624  break;\
1625  case GRN_DB_UINT16 :\
1626  {\
1627  uint16_t x_ = GRN_UINT16_VALUE(x);\
1628  DO_EQ_SUB;\
1629  }\
1630  break;\
1631  case GRN_DB_INT32 :\
1632  {\
1633  int32_t x_ = GRN_INT32_VALUE(x);\
1634  DO_EQ_SUB;\
1635  }\
1636  break;\
1637  case GRN_DB_UINT32 :\
1638  {\
1639  uint32_t x_ = GRN_UINT32_VALUE(x);\
1640  DO_EQ_SUB;\
1641  }\
1642  break;\
1643  case GRN_DB_INT64 :\
1644  {\
1645  int64_t x_ = GRN_INT64_VALUE(x);\
1646  DO_EQ_SUB;\
1647  }\
1648  break;\
1649  case GRN_DB_TIME :\
1650  {\
1651  int64_t x_ = GRN_INT64_VALUE(x);\
1652  switch (y->header.domain) {\
1653  case GRN_DB_INT32 :\
1654  r = (x_ == GRN_TIME_PACK(GRN_INT32_VALUE(y), 0));\
1655  break;\
1656  case GRN_DB_UINT32 :\
1657  r = (x_ == GRN_TIME_PACK(GRN_UINT32_VALUE(y), 0));\
1658  break;\
1659  case GRN_DB_INT64 :\
1660  case GRN_DB_TIME :\
1661  r = (x_ == GRN_INT64_VALUE(y));\
1662  break;\
1663  case GRN_DB_UINT64 :\
1664  r = (x_ == GRN_UINT64_VALUE(y));\
1665  break;\
1666  case GRN_DB_FLOAT :\
1667  r = (x_ == GRN_TIME_PACK(GRN_FLOAT_VALUE(y), 0));\
1668  break;\
1669  case GRN_DB_SHORT_TEXT :\
1670  case GRN_DB_TEXT :\
1671  case GRN_DB_LONG_TEXT :\
1672  {\
1673  const char *p_ = GRN_TEXT_VALUE(y);\
1674  int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\
1675  r = (x_ == GRN_TIME_PACK(i_, 0));\
1676  }\
1677  break;\
1678  default :\
1679  r = 0;\
1680  break;\
1681  }\
1682  }\
1683  break;\
1684  case GRN_DB_UINT64 :\
1685  {\
1686  uint64_t x_ = GRN_UINT64_VALUE(x);\
1687  DO_EQ_SUB;\
1688  }\
1689  break;\
1690  case GRN_DB_FLOAT :\
1691  {\
1692  double x_ = GRN_FLOAT_VALUE(x);\
1693  switch (y->header.domain) {\
1694  case GRN_DB_INT32 :\
1695  r = ((x_ <= GRN_INT32_VALUE(y)) && (x_ >= GRN_INT32_VALUE(y)));\
1696  break;\
1697  case GRN_DB_UINT32 :\
1698  r = ((x_ <= GRN_UINT32_VALUE(y)) && (x_ >= GRN_UINT32_VALUE(y)));\
1699  break;\
1700  case GRN_DB_INT64 :\
1701  case GRN_DB_TIME :\
1702  r = ((x_ <= GRN_INT64_VALUE(y)) && (x_ >= GRN_INT64_VALUE(y)));\
1703  break;\
1704  case GRN_DB_UINT64 :\
1705  r = ((x_ <= GRN_UINT64_VALUE(y)) && (x_ >= GRN_UINT64_VALUE(y)));\
1706  break;\
1707  case GRN_DB_FLOAT :\
1708  r = ((x_ <= GRN_FLOAT_VALUE(y)) && (x_ >= GRN_FLOAT_VALUE(y)));\
1709  break;\
1710  case GRN_DB_SHORT_TEXT :\
1711  case GRN_DB_TEXT :\
1712  case GRN_DB_LONG_TEXT :\
1713  {\
1714  const char *p_ = GRN_TEXT_VALUE(y);\
1715  int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\
1716  r = (x_ <= i_ && x_ >= i_);\
1717  }\
1718  break;\
1719  default :\
1720  r = 0;\
1721  break;\
1722  }\
1723  }\
1724  break;\
1725  case GRN_DB_SHORT_TEXT :\
1726  case GRN_DB_TEXT :\
1727  case GRN_DB_LONG_TEXT :\
1728  if (GRN_DB_SHORT_TEXT <= y->header.domain && y->header.domain <= GRN_DB_LONG_TEXT) {\
1729  uint32_t la = GRN_TEXT_LEN(x), lb = GRN_TEXT_LEN(y);\
1730  r = (la == lb && !memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), lb));\
1731  } else {\
1732  const char *q_ = GRN_TEXT_VALUE(x);\
1733  int x_ = grn_atoi(q_, q_ + GRN_TEXT_LEN(x), NULL);\
1734  DO_EQ_SUB;\
1735  }\
1736  break;\
1737  default :\
1738  if ((x->header.domain == y->header.domain)) {\
1739  r = (GRN_BULK_VSIZE(x) == GRN_BULK_VSIZE(y) &&\
1740  !(memcmp(GRN_BULK_HEAD(x), GRN_BULK_HEAD(y), GRN_BULK_VSIZE(x))));\
1741  } else {\
1742  grn_obj dest;\
1743  if (x->header.domain < y->header.domain) {\
1744  GRN_OBJ_INIT(&dest, GRN_BULK, 0, y->header.domain);\
1745  if (!grn_obj_cast(ctx, x, &dest, GRN_FALSE)) {\
1746  r = (GRN_BULK_VSIZE(&dest) == GRN_BULK_VSIZE(y) &&\
1747  !memcmp(GRN_BULK_HEAD(&dest), GRN_BULK_HEAD(y), GRN_BULK_VSIZE(y))); \
1748  }\
1749  } else {\
1750  GRN_OBJ_INIT(&dest, GRN_BULK, 0, x->header.domain);\
1751  if (!grn_obj_cast(ctx, y, &dest, GRN_FALSE)) {\
1752  r = (GRN_BULK_VSIZE(&dest) == GRN_BULK_VSIZE(x) &&\
1753  !memcmp(GRN_BULK_HEAD(&dest), GRN_BULK_HEAD(x), GRN_BULK_VSIZE(x))); \
1754  }\
1755  }\
1756  GRN_OBJ_FIN(ctx, &dest);\
1757  }\
1758  break;\
1759  }\
1760 } while (0)
1761 
1762 #define GEO_RESOLUTION 3600000
1763 #define GEO_RADIOUS 6357303
1764 #define GEO_BES_C1 6334834
1765 #define GEO_BES_C2 6377397
1766 #define GEO_BES_C3 0.006674
1767 #define GEO_GRS_C1 6335439
1768 #define GEO_GRS_C2 6378137
1769 #define GEO_GRS_C3 0.006694
1770 #define GEO_INT2RAD(x) ((M_PI * x) / (GEO_RESOLUTION * 180))
1771 
1772 #define VAR_SET_VALUE(ctx,var,value) do {\
1773  if (GRN_DB_OBJP(value)) {\
1774  (var)->header.type = GRN_PTR;\
1775  (var)->header.domain = DB_OBJ(value)->id;\
1776  GRN_PTR_SET(ctx, (var), (value));\
1777  } else {\
1778  (var)->header.type = (value)->header.type;\
1779  (var)->header.domain = (value)->header.domain;\
1780  GRN_TEXT_SET(ctx, (var), GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value));\
1781  }\
1782 } while (0)
1783 
1784 grn_rc
1785 grn_proc_call(grn_ctx *ctx, grn_obj *proc, int nargs, grn_obj *caller)
1786 {
1787  grn_proc_ctx pctx;
1788  grn_obj *obj = NULL, **args;
1789  grn_proc *p = (grn_proc *)proc;
1790  if (nargs > ctx->impl->stack_curr) { return GRN_INVALID_ARGUMENT; }
1791  GRN_API_ENTER;
1792  args = ctx->impl->stack + ctx->impl->stack_curr - nargs;
1793  pctx.proc = p;
1794  pctx.caller = caller;
1795  pctx.user_data.ptr = NULL;
1796  if (p->funcs[PROC_INIT]) {
1797  obj = p->funcs[PROC_INIT](ctx, nargs, args, &pctx.user_data);
1798  }
1799  pctx.phase = PROC_NEXT;
1800  if (p->funcs[PROC_NEXT]) {
1801  obj = p->funcs[PROC_NEXT](ctx, nargs, args, &pctx.user_data);
1802  }
1803  pctx.phase = PROC_FIN;
1804  if (p->funcs[PROC_FIN]) {
1805  obj = p->funcs[PROC_FIN](ctx, nargs, args, &pctx.user_data);
1806  }
1807  ctx->impl->stack_curr -= nargs;
1808  grn_ctx_push(ctx, obj);
1809  GRN_API_RETURN(ctx->rc);
1810 }
1811 
1812 #define PUSH1(v) do {\
1813  if (EXPRVP(v)) { vp++; }\
1814  s1 = s0;\
1815  *sp++ = s0 = v;\
1816 } while (0)
1817 
1818 #define POP1(v) do {\
1819  if (EXPRVP(s0)) { vp--; }\
1820  v = s0;\
1821  s0 = s1;\
1822  sp--;\
1823  if (sp < s_) { ERR(GRN_INVALID_ARGUMENT, "stack underflow"); goto exit; }\
1824  s1 = sp[-2];\
1825 } while (0)
1826 
1827 #define ALLOC1(value) do {\
1828  s1 = s0;\
1829  *sp++ = s0 = value = vp++;\
1830  if (vp - e->values > e->values_tail) { e->values_tail = vp - e->values; }\
1831 } while (0)
1832 
1833 #define POP1ALLOC1(arg,value) do {\
1834  arg = s0;\
1835  if (EXPRVP(s0)) {\
1836  value = s0;\
1837  } else {\
1838  if (sp < s_ + 1) { ERR(GRN_INVALID_ARGUMENT, "stack underflow"); goto exit; }\
1839  sp[-1] = s0 = value = vp++;\
1840  s0->header.impl_flags |= GRN_OBJ_EXPRVALUE;\
1841  }\
1842 } while (0)
1843 
1844 #define POP2ALLOC1(arg1,arg2,value) do {\
1845  if (EXPRVP(s0)) { vp--; }\
1846  if (EXPRVP(s1)) { vp--; }\
1847  arg2 = s0;\
1848  arg1 = s1;\
1849  sp--;\
1850  if (sp < s_ + 1) { ERR(GRN_INVALID_ARGUMENT, "stack underflow"); goto exit; }\
1851  s1 = sp[-2];\
1852  sp[-1] = s0 = value = vp++;\
1853  s0->header.impl_flags |= GRN_OBJ_EXPRVALUE;\
1854 } while (0)
1855 
1856 #define INTEGER_ARITHMETIC_OPERATION_PLUS(x, y) ((x) + (y))
1857 #define FLOAT_ARITHMETIC_OPERATION_PLUS(x, y) ((double)(x) + (double)(y))
1858 #define INTEGER_ARITHMETIC_OPERATION_MINUS(x, y) ((x) - (y))
1859 #define FLOAT_ARITHMETIC_OPERATION_MINUS(x, y) ((double)(x) - (double)(y))
1860 #define INTEGER_ARITHMETIC_OPERATION_STAR(x, y) ((x) * (y))
1861 #define FLOAT_ARITHMETIC_OPERATION_STAR(x, y) ((double)(x) * (double)(y))
1862 #define INTEGER_ARITHMETIC_OPERATION_SLASH(x, y) ((x) / (y))
1863 #define FLOAT_ARITHMETIC_OPERATION_SLASH(x, y) ((double)(x) / (double)(y))
1864 #define INTEGER_ARITHMETIC_OPERATION_MOD(x, y) ((x) % (y))
1865 #define FLOAT_ARITHMETIC_OPERATION_MOD(x, y) (fmod((x), (y)))
1866 #define INTEGER_ARITHMETIC_OPERATION_SHIFTL(x, y) ((x) << (y))
1867 #define FLOAT_ARITHMETIC_OPERATION_SHIFTL(x, y) \
1868  ((long long int)(x) << (long long int)(y))
1869 #define INTEGER_ARITHMETIC_OPERATION_SHIFTR(x, y) ((x) >> (y))
1870 #define FLOAT_ARITHMETIC_OPERATION_SHIFTR(x, y) \
1871  ((long long int)(x) >> (long long int)(y))
1872 #define INTEGER8_ARITHMETIC_OPERATION_SHIFTRR(x, y) \
1873  ((uint8_t)(x) >> (y))
1874 #define INTEGER16_ARITHMETIC_OPERATION_SHIFTRR(x, y) \
1875  ((uint16_t)(x) >> (y))
1876 #define INTEGER32_ARITHMETIC_OPERATION_SHIFTRR(x, y) \
1877  ((unsigned int)(x) >> (y))
1878 #define INTEGER64_ARITHMETIC_OPERATION_SHIFTRR(x, y) \
1879  ((long long unsigned int)(x) >> (y))
1880 #define FLOAT_ARITHMETIC_OPERATION_SHIFTRR(x, y) \
1881  ((long long unsigned int)(x) >> (long long unsigned int)(y))
1882 
1883 #define INTEGER_ARITHMETIC_OPERATION_BITWISE_OR(x, y) ((x) | (y))
1884 #define FLOAT_ARITHMETIC_OPERATION_BITWISE_OR(x, y) \
1885  ((long long int)(x) | (long long int)(y))
1886 #define INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR(x, y) ((x) ^ (y))
1887 #define FLOAT_ARITHMETIC_OPERATION_BITWISE_XOR(x, y) \
1888  ((long long int)(x) ^ (long long int)(y))
1889 #define INTEGER_ARITHMETIC_OPERATION_BITWISE_AND(x, y) ((x) & (y))
1890 #define FLOAT_ARITHMETIC_OPERATION_BITWISE_AND(x, y) \
1891  ((long long int)(x) & (long long int)(y))
1892 
1893 #define INTEGER_UNARY_ARITHMETIC_OPERATION_MINUS(x) (-(x))
1894 #define FLOAT_UNARY_ARITHMETIC_OPERATION_MINUS(x) (-(x))
1895 #define INTEGER_UNARY_ARITHMETIC_OPERATION_BITWISE_NOT(x) (~(x))
1896 #define FLOAT_UNARY_ARITHMETIC_OPERATION_BITWISE_NOT(x) \
1897  (~((long long int)(x)))
1898 
1899 #define TEXT_ARITHMETIC_OPERATION(operator) do { \
1900  long long int x_; \
1901  long long int y_; \
1902  \
1903  res->header.domain = GRN_DB_INT64; \
1904  \
1905  GRN_INT64_SET(ctx, res, 0); \
1906  grn_obj_cast(ctx, x, res, GRN_FALSE); \
1907  x_ = GRN_INT64_VALUE(res); \
1908  \
1909  GRN_INT64_SET(ctx, res, 0); \
1910  grn_obj_cast(ctx, y, res, GRN_FALSE); \
1911  y_ = GRN_INT64_VALUE(res); \
1912  \
1913  GRN_INT64_SET(ctx, res, x_ operator y_); \
1914 } while (0)
1915 
1916 #define TEXT_UNARY_ARITHMETIC_OPERATION(unary_operator) do { \
1917  long long int x_; \
1918  \
1919  res->header.domain = GRN_DB_INT64; \
1920  \
1921  GRN_INT64_SET(ctx, res, 0); \
1922  grn_obj_cast(ctx, x, res, GRN_FALSE); \
1923  x_ = GRN_INT64_VALUE(res); \
1924  \
1925  GRN_INT64_SET(ctx, res, unary_operator x_); \
1926 } while (0)
1927 
1928 #define ARITHMETIC_OPERATION_NO_CHECK(y) do {} while (0)
1929 #define ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y) do { \
1930  if ((long long int)y == 0) { \
1931  ERR(GRN_INVALID_ARGUMENT, "dividend should not be 0"); \
1932  goto exit; \
1933  } \
1934 } while (0)
1935 
1936 
1937 #define NUMERIC_ARITHMETIC_OPERATION_DISPATCH(set, get, x_, y, res, \
1938  integer_operation, \
1939  float_operation, \
1940  right_expression_check, \
1941  invalid_type_error) do { \
1942  switch (y->header.domain) { \
1943  case GRN_DB_INT8 : \
1944  { \
1945  int8_t y_; \
1946  y_ = GRN_INT8_VALUE(y); \
1947  right_expression_check(y_); \
1948  set(ctx, res, integer_operation(x_, y_)); \
1949  } \
1950  break; \
1951  case GRN_DB_UINT8 : \
1952  { \
1953  uint8_t y_; \
1954  y_ = GRN_UINT8_VALUE(y); \
1955  right_expression_check(y_); \
1956  set(ctx, res, integer_operation(x_, y_)); \
1957  } \
1958  break; \
1959  case GRN_DB_INT16 : \
1960  { \
1961  int16_t y_; \
1962  y_ = GRN_INT16_VALUE(y); \
1963  right_expression_check(y_); \
1964  set(ctx, res, integer_operation(x_, y_)); \
1965  } \
1966  break; \
1967  case GRN_DB_UINT16 : \
1968  { \
1969  uint16_t y_; \
1970  y_ = GRN_UINT16_VALUE(y); \
1971  right_expression_check(y_); \
1972  set(ctx, res, integer_operation(x_, y_)); \
1973  } \
1974  break; \
1975  case GRN_DB_INT32 : \
1976  { \
1977  int y_; \
1978  y_ = GRN_INT32_VALUE(y); \
1979  right_expression_check(y_); \
1980  set(ctx, res, integer_operation(x_, y_)); \
1981  } \
1982  break; \
1983  case GRN_DB_UINT32 : \
1984  { \
1985  unsigned int y_; \
1986  y_ = GRN_UINT32_VALUE(y); \
1987  right_expression_check(y_); \
1988  set(ctx, res, integer_operation(x_, y_)); \
1989  } \
1990  break; \
1991  case GRN_DB_TIME : \
1992  { \
1993  long long int y_; \
1994  y_ = GRN_TIME_VALUE(y); \
1995  right_expression_check(y_); \
1996  set(ctx, res, integer_operation(x_, y_)); \
1997  } \
1998  break; \
1999  case GRN_DB_INT64 : \
2000  { \
2001  long long int y_; \
2002  y_ = GRN_INT64_VALUE(y); \
2003  right_expression_check(y_); \
2004  set(ctx, res, integer_operation(x_, y_)); \
2005  } \
2006  break; \
2007  case GRN_DB_UINT64 : \
2008  { \
2009  long long unsigned int y_; \
2010  y_ = GRN_UINT64_VALUE(y); \
2011  right_expression_check(y_); \
2012  set(ctx, res, integer_operation(x_, y_)); \
2013  } \
2014  break; \
2015  case GRN_DB_FLOAT : \
2016  { \
2017  double y_; \
2018  y_ = GRN_FLOAT_VALUE(y); \
2019  right_expression_check(y_); \
2020  res->header.domain = GRN_DB_FLOAT; \
2021  GRN_FLOAT_SET(ctx, res, float_operation(x_, y_)); \
2022  } \
2023  break; \
2024  case GRN_DB_SHORT_TEXT : \
2025  case GRN_DB_TEXT : \
2026  case GRN_DB_LONG_TEXT : \
2027  set(ctx, res, 0); \
2028  if (grn_obj_cast(ctx, y, res, GRN_FALSE)) { \
2029  ERR(GRN_INVALID_ARGUMENT, \
2030  "not a numerical format: <%.*s>", \
2031  (int)GRN_TEXT_LEN(y), GRN_TEXT_VALUE(y)); \
2032  goto exit; \
2033  } \
2034  set(ctx, res, integer_operation(x_, get(res))); \
2035  break; \
2036  default : \
2037  invalid_type_error; \
2038  break; \
2039  } \
2040 } while (0)
2041 
2042 
2043 #define ARITHMETIC_OPERATION_DISPATCH(x, y, res, \
2044  integer8_operation, \
2045  integer16_operation, \
2046  integer32_operation, \
2047  integer64_operation, \
2048  float_operation, \
2049  left_expression_check, \
2050  right_expression_check, \
2051  text_operation, \
2052  invalid_type_error) do { \
2053  switch (x->header.domain) { \
2054  case GRN_DB_INT8 : \
2055  { \
2056  int8_t x_; \
2057  x_ = GRN_INT8_VALUE(x); \
2058  left_expression_check(x_); \
2059  NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_INT8_SET, \
2060  GRN_INT8_VALUE, \
2061  x_, y, res, \
2062  integer8_operation, \
2063  float_operation, \
2064  right_expression_check, \
2065  invalid_type_error); \
2066  } \
2067  break; \
2068  case GRN_DB_UINT8 : \
2069  { \
2070  uint8_t x_; \
2071  x_ = GRN_UINT8_VALUE(x); \
2072  left_expression_check(x_); \
2073  NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT8_SET, \
2074  GRN_UINT8_VALUE, \
2075  x_, y, res, \
2076  integer8_operation, \
2077  float_operation, \
2078  right_expression_check, \
2079  invalid_type_error); \
2080  } \
2081  break; \
2082  case GRN_DB_INT16 : \
2083  { \
2084  int16_t x_; \
2085  x_ = GRN_INT16_VALUE(x); \
2086  left_expression_check(x_); \
2087  NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_INT16_SET, \
2088  GRN_INT16_VALUE, \
2089  x_, y, res, \
2090  integer16_operation, \
2091  float_operation, \
2092  right_expression_check, \
2093  invalid_type_error); \
2094  } \
2095  break; \
2096  case GRN_DB_UINT16 : \
2097  { \
2098  uint16_t x_; \
2099  x_ = GRN_UINT16_VALUE(x); \
2100  left_expression_check(x_); \
2101  NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT16_SET, \
2102  GRN_UINT16_VALUE, \
2103  x_, y, res, \
2104  integer16_operation, \
2105  float_operation, \
2106  right_expression_check, \
2107  invalid_type_error); \
2108  } \
2109  break; \
2110  case GRN_DB_INT32 : \
2111  { \
2112  int x_; \
2113  x_ = GRN_INT32_VALUE(x); \
2114  left_expression_check(x_); \
2115  NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_INT32_SET, \
2116  GRN_INT32_VALUE, \
2117  x_, y, res, \
2118  integer32_operation, \
2119  float_operation, \
2120  right_expression_check, \
2121  invalid_type_error); \
2122  } \
2123  break; \
2124  case GRN_DB_UINT32 : \
2125  { \
2126  unsigned int x_; \
2127  x_ = GRN_UINT32_VALUE(x); \
2128  left_expression_check(x_); \
2129  NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT32_SET, \
2130  GRN_UINT32_VALUE, \
2131  x_, y, res, \
2132  integer32_operation, \
2133  float_operation, \
2134  right_expression_check, \
2135  invalid_type_error); \
2136  } \
2137  break; \
2138  case GRN_DB_INT64 : \
2139  { \
2140  long long int x_; \
2141  x_ = GRN_INT64_VALUE(x); \
2142  left_expression_check(x_); \
2143  NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT64_SET, \
2144  GRN_UINT64_VALUE, \
2145  x_, y, res, \
2146  integer64_operation, \
2147  float_operation, \
2148  right_expression_check, \
2149  invalid_type_error); \
2150  } \
2151  break; \
2152  case GRN_DB_TIME : \
2153  { \
2154  long long int x_; \
2155  x_ = GRN_TIME_VALUE(x); \
2156  left_expression_check(x_); \
2157  NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_TIME_SET, \
2158  GRN_TIME_VALUE, \
2159  x_, y, res, \
2160  integer64_operation, \
2161  float_operation, \
2162  right_expression_check, \
2163  invalid_type_error); \
2164  } \
2165  break; \
2166  case GRN_DB_UINT64 : \
2167  { \
2168  long long unsigned int x_; \
2169  x_ = GRN_UINT64_VALUE(x); \
2170  left_expression_check(x_); \
2171  NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT64_SET, \
2172  GRN_UINT64_VALUE, \
2173  x_, y, res, \
2174  integer64_operation, \
2175  float_operation, \
2176  right_expression_check, \
2177  invalid_type_error); \
2178  } \
2179  break; \
2180  case GRN_DB_FLOAT : \
2181  { \
2182  double x_; \
2183  x_ = GRN_FLOAT_VALUE(x); \
2184  left_expression_check(x_); \
2185  NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_FLOAT_SET, \
2186  GRN_FLOAT_VALUE, \
2187  x_, y, res, \
2188  float_operation, \
2189  float_operation, \
2190  right_expression_check, \
2191  invalid_type_error); \
2192  } \
2193  break; \
2194  case GRN_DB_SHORT_TEXT : \
2195  case GRN_DB_TEXT : \
2196  case GRN_DB_LONG_TEXT : \
2197  text_operation; \
2198  break; \
2199  default: \
2200  invalid_type_error; \
2201  break; \
2202  } \
2203  code++; \
2204 } while (0)
2205 
2206 #define ARITHMETIC_BINARY_OPERATION_DISPATCH(integer8_operation, \
2207  integer16_operation, \
2208  integer32_operation, \
2209  integer64_operation, \
2210  float_operation, \
2211  left_expression_check, \
2212  right_expression_check, \
2213  text_operation, \
2214  invalid_type_error) do { \
2215  grn_obj *x, *y; \
2216  \
2217  POP2ALLOC1(x, y, res); \
2218  if (y != res) { \
2219  res->header.domain = x->header.domain; \
2220  } \
2221  ARITHMETIC_OPERATION_DISPATCH(x, y, res, \
2222  integer8_operation, \
2223  integer16_operation, \
2224  integer32_operation, \
2225  integer64_operation, \
2226  float_operation, \
2227  left_expression_check, \
2228  right_expression_check, \
2229  text_operation, \
2230  invalid_type_error); \
2231  if (y == res) { \
2232  res->header.domain = x->header.domain; \
2233  } \
2234 } while (0)
2235 
2236 #define ARITHMETIC_UNARY_OPERATION_DISPATCH(integer_operation, \
2237  float_operation, \
2238  left_expression_check, \
2239  right_expression_check, \
2240  text_operation, \
2241  invalid_type_error) do { \
2242  grn_obj *x; \
2243  POP1ALLOC1(x, res); \
2244  res->header.domain = x->header.domain; \
2245  switch (x->header.domain) { \
2246  case GRN_DB_INT8 : \
2247  { \
2248  int8_t x_; \
2249  x_ = GRN_INT8_VALUE(x); \
2250  left_expression_check(x_); \
2251  GRN_INT8_SET(ctx, res, integer_operation(x_)); \
2252  } \
2253  break; \
2254  case GRN_DB_UINT8 : \
2255  { \
2256  int16_t x_; \
2257  x_ = GRN_UINT8_VALUE(x); \
2258  left_expression_check(x_); \
2259  GRN_INT16_SET(ctx, res, integer_operation(x_)); \
2260  res->header.domain = GRN_DB_INT16; \
2261  } \
2262  break; \
2263  case GRN_DB_INT16 : \
2264  { \
2265  int16_t x_; \
2266  x_ = GRN_INT16_VALUE(x); \
2267  left_expression_check(x_); \
2268  GRN_INT16_SET(ctx, res, integer_operation(x_)); \
2269  } \
2270  break; \
2271  case GRN_DB_UINT16 : \
2272  { \
2273  int x_; \
2274  x_ = GRN_UINT16_VALUE(x); \
2275  left_expression_check(x_); \
2276  GRN_INT32_SET(ctx, res, integer_operation(x_)); \
2277  res->header.domain = GRN_DB_INT32; \
2278  } \
2279  break; \
2280  case GRN_DB_INT32 : \
2281  { \
2282  int x_; \
2283  x_ = GRN_INT32_VALUE(x); \
2284  left_expression_check(x_); \
2285  GRN_INT32_SET(ctx, res, integer_operation(x_)); \
2286  } \
2287  break; \
2288  case GRN_DB_UINT32 : \
2289  { \
2290  long long int x_; \
2291  x_ = GRN_UINT32_VALUE(x); \
2292  left_expression_check(x_); \
2293  GRN_INT64_SET(ctx, res, integer_operation(x_)); \
2294  res->header.domain = GRN_DB_INT64; \
2295  } \
2296  break; \
2297  case GRN_DB_INT64 : \
2298  { \
2299  long long int x_; \
2300  x_ = GRN_INT64_VALUE(x); \
2301  left_expression_check(x_); \
2302  GRN_INT64_SET(ctx, res, integer_operation(x_)); \
2303  } \
2304  break; \
2305  case GRN_DB_TIME : \
2306  { \
2307  long long int x_; \
2308  x_ = GRN_TIME_VALUE(x); \
2309  left_expression_check(x_); \
2310  GRN_TIME_SET(ctx, res, integer_operation(x_)); \
2311  } \
2312  break; \
2313  case GRN_DB_UINT64 : \
2314  { \
2315  long long unsigned int x_; \
2316  x_ = GRN_UINT64_VALUE(x); \
2317  left_expression_check(x_); \
2318  if (x_ > (long long unsigned int)INT64_MAX) { \
2319  ERR(GRN_INVALID_ARGUMENT, \
2320  "too large UInt64 value to inverse sign: " \
2321  "<%" GRN_FMT_LLU ">", \
2322  x_); \
2323  goto exit; \
2324  } else { \
2325  long long int signed_x_; \
2326  signed_x_ = x_; \
2327  GRN_INT64_SET(ctx, res, integer_operation(signed_x_)); \
2328  res->header.domain = GRN_DB_INT64; \
2329  } \
2330  } \
2331  break; \
2332  case GRN_DB_FLOAT : \
2333  { \
2334  double x_; \
2335  x_ = GRN_FLOAT_VALUE(x); \
2336  left_expression_check(x_); \
2337  GRN_FLOAT_SET(ctx, res, float_operation(x_)); \
2338  } \
2339  break; \
2340  case GRN_DB_SHORT_TEXT : \
2341  case GRN_DB_TEXT : \
2342  case GRN_DB_LONG_TEXT : \
2343  text_operation; \
2344  break; \
2345  default: \
2346  invalid_type_error; \
2347  break; \
2348  } \
2349  code++; \
2350 } while (0)
2351 
2352 #define EXEC_OPERATE(operate_sentence, assign_sentence) \
2353  operate_sentence \
2354  assign_sentence
2355 
2356 #define EXEC_OPERATE_POST(operate_sentence, assign_sentence) \
2357  assign_sentence \
2358  operate_sentence
2359 
2360 #define UNARY_OPERATE_AND_ASSIGN_DISPATCH(exec_operate, delta, \
2361  set_flags) do { \
2362  grn_obj *var, *col, value; \
2363  grn_id rid; \
2364  \
2365  POP1ALLOC1(var, res); \
2366  if (var->header.type != GRN_PTR) { \
2367  ERR(GRN_INVALID_ARGUMENT, "invalid variable type: 0x%0x", \
2368  var->header.type); \
2369  goto exit; \
2370  } \
2371  if (GRN_BULK_VSIZE(var) != (sizeof(grn_obj *) + sizeof(grn_id))) { \
2372  ERR(GRN_INVALID_ARGUMENT, \
2373  "invalid variable size: expected: %zu, actual: %zu", \
2374  (sizeof(grn_obj *) + sizeof(grn_id)), GRN_BULK_VSIZE(var)); \
2375  goto exit; \
2376  } \
2377  col = GRN_PTR_VALUE(var); \
2378  rid = *(grn_id *)(GRN_BULK_HEAD(var) + sizeof(grn_obj *)); \
2379  res->header.type = GRN_VOID; \
2380  res->header.domain = DB_OBJ(col)->range; \
2381  switch (DB_OBJ(col)->range) { \
2382  case GRN_DB_INT32 : \
2383  GRN_INT32_INIT(&value, 0); \
2384  GRN_INT32_SET(ctx, &value, delta); \
2385  break; \
2386  case GRN_DB_UINT32 : \
2387  GRN_UINT32_INIT(&value, 0); \
2388  GRN_UINT32_SET(ctx, &value, delta); \
2389  break; \
2390  case GRN_DB_INT64 : \
2391  GRN_INT64_INIT(&value, 0); \
2392  GRN_INT64_SET(ctx, &value, delta); \
2393  break; \
2394  case GRN_DB_UINT64 : \
2395  GRN_UINT64_INIT(&value, 0); \
2396  GRN_UINT64_SET(ctx, &value, delta); \
2397  break; \
2398  case GRN_DB_FLOAT : \
2399  GRN_FLOAT_INIT(&value, 0); \
2400  GRN_FLOAT_SET(ctx, &value, delta); \
2401  break; \
2402  case GRN_DB_TIME : \
2403  GRN_TIME_INIT(&value, 0); \
2404  GRN_TIME_SET(ctx, &value, GRN_TIME_PACK(delta, 0)); \
2405  break; \
2406  default: \
2407  ERR(GRN_INVALID_ARGUMENT, \
2408  "invalid increment target type: %d " \
2409  "(FIXME: type name is needed)", DB_OBJ(col)->range); \
2410  goto exit; \
2411  break; \
2412  } \
2413  exec_operate(grn_obj_set_value(ctx, col, rid, &value, set_flags);, \
2414  grn_obj_get_value(ctx, col, rid, res);); \
2415  code++; \
2416 } while (0)
2417 
2418 #define ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(integer8_operation, \
2419  integer16_operation, \
2420  integer32_operation, \
2421  integer64_operation, \
2422  float_operation, \
2423  left_expression_check, \
2424  right_expression_check,\
2425  text_operation) do { \
2426  grn_obj *value, *var, *res; \
2427  if (code->value) { \
2428  value = code->value; \
2429  POP1ALLOC1(var, res); \
2430  } else { \
2431  POP2ALLOC1(var, value, res); \
2432  } \
2433  if (var->header.type == GRN_PTR && \
2434  GRN_BULK_VSIZE(var) == (sizeof(grn_obj *) + sizeof(grn_id))) { \
2435  grn_obj *col = GRN_PTR_VALUE(var); \
2436  grn_id rid = *(grn_id *)(GRN_BULK_HEAD(var) + sizeof(grn_obj *)); \
2437  grn_obj variable_value, casted_value; \
2438  grn_id domain; \
2439  \
2440  value = GRN_OBJ_RESOLVE(ctx, value); \
2441  \
2442  domain = grn_obj_get_range(ctx, col); \
2443  GRN_OBJ_INIT(&variable_value, GRN_BULK, 0, domain); \
2444  grn_obj_get_value(ctx, col, rid, &variable_value); \
2445  \
2446  GRN_OBJ_INIT(&casted_value, GRN_BULK, 0, domain); \
2447  if (grn_obj_cast(ctx, value, &casted_value, GRN_FALSE)) { \
2448  ERR(GRN_INVALID_ARGUMENT, "invalid value: string"); \
2449  GRN_OBJ_FIN(ctx, &variable_value); \
2450  GRN_OBJ_FIN(ctx, &casted_value); \
2451  POP1(res); \
2452  goto exit; \
2453  } \
2454  grn_obj_reinit(ctx, res, domain, 0); \
2455  ARITHMETIC_OPERATION_DISPATCH((&variable_value), (&casted_value), \
2456  res, \
2457  integer8_operation, \
2458  integer16_operation, \
2459  integer32_operation, \
2460  integer64_operation, \
2461  float_operation, \
2462  left_expression_check, \
2463  right_expression_check, \
2464  text_operation,); \
2465  grn_obj_set_value(ctx, col, rid, res, GRN_OBJ_SET); \
2466  GRN_OBJ_FIN(ctx, (&variable_value)); \
2467  GRN_OBJ_FIN(ctx, (&casted_value)); \
2468  } else { \
2469  ERR(GRN_INVALID_ARGUMENT, "left hand expression isn't column."); \
2470  POP1(res); \
2471  } \
2472 } while (0)
2473 
2474 static grn_bool
2475 pseudo_query_scan(grn_ctx *ctx, grn_obj *x, grn_obj *y)
2476 {
2477  grn_obj *normalizer;
2478  grn_obj *a = NULL, *b = NULL;
2479  grn_bool matched = GRN_FALSE;
2480 
2481  normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1);
2482  switch (x->header.domain) {
2483  case GRN_DB_SHORT_TEXT:
2484  case GRN_DB_TEXT:
2485  case GRN_DB_LONG_TEXT:
2487  normalizer, 0);
2488  break;
2489  default:
2490  break;
2491  }
2492 
2493  switch (y->header.domain) {
2494  case GRN_DB_SHORT_TEXT:
2495  case GRN_DB_TEXT:
2496  case GRN_DB_LONG_TEXT:
2498  normalizer, 0);
2499  break;
2500  default:
2501  break;
2502  }
2503 
2504  /* normalized str doesn't contain '\0'. */
2505  if (a && b) {
2506  const char *a_norm, *b_norm;
2507  grn_string_get_normalized(ctx, a, &a_norm, NULL, NULL);
2508  grn_string_get_normalized(ctx, b, &b_norm, NULL, NULL);
2509  matched = (strstr(a_norm, b_norm) != NULL);
2510  }
2511 
2512  if (a) { grn_obj_close(ctx, a); }
2513  if (b) { grn_obj_close(ctx, b); }
2514 
2515  if (normalizer) { grn_obj_unlink(ctx, normalizer); }
2516 
2517  return matched;
2518 }
2519 
2520 inline static void
2521 grn_expr_exec_get_member(grn_ctx *ctx,
2522  grn_obj *expr,
2523  grn_obj *column_and_record_id,
2524  grn_obj *index,
2525  grn_obj *result)
2526 {
2527  grn_obj *column;
2528  grn_id record_id;
2529  grn_obj values;
2530  int i;
2531 
2532  column = GRN_PTR_VALUE(column_and_record_id);
2533  record_id = *((grn_id *)(&(GRN_PTR_VALUE_AT(column_and_record_id, 1))));
2534  GRN_TEXT_INIT(&values, 0);
2535  grn_obj_get_value(ctx, column, record_id, &values);
2536 
2537  grn_obj_reinit(ctx, result, DB_OBJ(column)->range, 0);
2538  i = GRN_UINT32_VALUE(index);
2539  if (values.header.type == GRN_UVECTOR) {
2540  int n_elements;
2541  n_elements = GRN_BULK_VSIZE(&values) / sizeof(grn_id);
2542  if (n_elements > i) {
2543  grn_id value;
2544  value = GRN_RECORD_VALUE_AT(&values, i);
2545  GRN_RECORD_SET(ctx, result, value);
2546  }
2547  } else {
2548  if (values.u.v.n_sections > i) {
2549  grn_section *section = &(values.u.v.sections[i]);
2550  grn_obj *body = values.u.v.body;
2551  const char *value;
2552  value = GRN_BULK_HEAD(body) + section->offset;
2553  grn_bulk_write(ctx, result, value, section->length);
2554  }
2555  }
2556 
2557  GRN_OBJ_FIN(ctx, &values);
2558 }
2559 
2560 grn_obj *
2561 grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs)
2562 {
2563  grn_obj *val = NULL;
2564  uint32_t stack_curr = ctx->impl->stack_curr;
2565  GRN_API_ENTER;
2566  if (expr->header.type == GRN_PROC) {
2567  grn_proc_call(ctx, expr, nargs, expr);
2568  } else {
2569  grn_expr *e = (grn_expr *)expr;
2570  register grn_obj **s_ = ctx->impl->stack, *s0 = NULL, *s1 = NULL, **sp, *vp = e->values;
2571  grn_obj *res = NULL, *v0 = grn_expr_get_var_by_offset(ctx, expr, 0);
2572  grn_expr_code *code = e->codes, *ce = &e->codes[e->codes_curr];
2573  sp = s_ + stack_curr;
2574  while (code < ce) {
2575  switch (code->op) {
2576  case GRN_OP_NOP :
2577  code++;
2578  break;
2579  case GRN_OP_PUSH :
2580  PUSH1(code->value);
2581  code++;
2582  break;
2583  case GRN_OP_POP :
2584  {
2585  grn_obj *obj;
2586  POP1(obj);
2587  code++;
2588  }
2589  break;
2590  case GRN_OP_GET_REF :
2591  {
2592  grn_obj *col, *rec;
2593  if (code->nargs == 1) {
2594  rec = v0;
2595  if (code->value) {
2596  col = code->value;
2597  ALLOC1(res);
2598  } else {
2599  POP1ALLOC1(col, res);
2600  }
2601  } else {
2602  if (code->value) {
2603  col = code->value;
2604  POP1ALLOC1(rec, res);
2605  } else {
2606  POP2ALLOC1(rec, col, res);
2607  }
2608  }
2609  if (col->header.type == GRN_BULK) {
2610  grn_obj *table = grn_ctx_at(ctx, GRN_OBJ_GET_DOMAIN(rec));
2611  col = grn_obj_column(ctx, table, GRN_BULK_HEAD(col), GRN_BULK_VSIZE(col));
2612  if (col) { GRN_PTR_PUT(ctx, &e->objs, col); }
2613  }
2614  if (col) {
2615  res->header.type = GRN_PTR;
2616  res->header.domain = GRN_ID_NIL;
2617  GRN_PTR_SET(ctx, res, col);
2618  GRN_UINT32_PUT(ctx, res, GRN_RECORD_VALUE(rec));
2619  } else {
2620  ERR(GRN_INVALID_ARGUMENT, "col resolve failed");
2621  goto exit;
2622  }
2623  code++;
2624  }
2625  break;
2626  case GRN_OP_CALL :
2627  {
2628  grn_obj *proc;
2629  if (code->value) {
2630  if (sp < s_ + code->nargs) {
2631  ERR(GRN_INVALID_ARGUMENT, "stack error");
2632  goto exit;
2633  }
2634  proc = code->value;
2635  WITH_SPSAVE({
2636  grn_proc_call(ctx, proc, code->nargs, expr);
2637  });
2638  } else {
2639  int offset = code->nargs + 1;
2640  if (sp < s_ + offset) {
2641  ERR(GRN_INVALID_ARGUMENT, "stack error");
2642  goto exit;
2643  }
2644  proc = sp[-offset];
2645  WITH_SPSAVE({
2646  grn_proc_call(ctx, proc, code->nargs, expr);
2647  });
2648  if (ctx->rc) {
2649  goto exit;
2650  }
2651  POP1(res);
2652  {
2653  grn_obj *proc_;
2654  POP1(proc_);
2655  if (proc != proc_) {
2656  GRN_LOG(ctx, GRN_LOG_WARNING, "stack may be corrupt");
2657  }
2658  }
2659  PUSH1(res);
2660  }
2661  }
2662  code++;
2663  break;
2664  case GRN_OP_INTERN :
2665  {
2666  grn_obj *obj;
2667  POP1(obj);
2668  obj = GRN_OBJ_RESOLVE(ctx, obj);
2669  res = grn_expr_get_var(ctx, expr, GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj));
2670  if (!res) { res = grn_ctx_get(ctx, GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj)); }
2671  if (!res) {
2672  ERR(GRN_INVALID_ARGUMENT, "intern failed");
2673  goto exit;
2674  }
2675  PUSH1(res);
2676  }
2677  code++;
2678  break;
2679  case GRN_OP_TABLE_CREATE :
2680  {
2681  grn_obj *value_type, *key_type, *flags, *name;
2682  POP1(value_type);
2683  value_type = GRN_OBJ_RESOLVE(ctx, value_type);
2684  POP1(key_type);
2685  key_type = GRN_OBJ_RESOLVE(ctx, key_type);
2686  POP1(flags);
2687  flags = GRN_OBJ_RESOLVE(ctx, flags);
2688  POP1(name);
2689  name = GRN_OBJ_RESOLVE(ctx, name);
2690  res = grn_table_create(ctx, GRN_TEXT_VALUE(name), GRN_TEXT_LEN(name),
2691  NULL, GRN_UINT32_VALUE(flags),
2692  key_type, value_type);
2693  PUSH1(res);
2694  }
2695  code++;
2696  break;
2697  case GRN_OP_EXPR_GET_VAR :
2698  {
2699  grn_obj *name, *expr;
2700  POP1(name);
2701  name = GRN_OBJ_RESOLVE(ctx, name);
2702  POP1(expr);
2703  expr = GRN_OBJ_RESOLVE(ctx, expr);
2704  switch (name->header.domain) {
2705  case GRN_DB_INT32 :
2706  res = grn_expr_get_var_by_offset(ctx, expr, (unsigned int) GRN_INT32_VALUE(name));
2707  break;
2708  case GRN_DB_UINT32 :
2709  res = grn_expr_get_var_by_offset(ctx, expr, (unsigned int) GRN_UINT32_VALUE(name));
2710  break;
2711  case GRN_DB_INT64 :
2712  res = grn_expr_get_var_by_offset(ctx, expr, (unsigned int) GRN_INT64_VALUE(name));
2713  break;
2714  case GRN_DB_UINT64 :
2715  res = grn_expr_get_var_by_offset(ctx, expr, (unsigned int) GRN_UINT64_VALUE(name));
2716  break;
2717  case GRN_DB_SHORT_TEXT :
2718  case GRN_DB_TEXT :
2719  case GRN_DB_LONG_TEXT :
2720  res = grn_expr_get_var(ctx, expr, GRN_TEXT_VALUE(name), GRN_TEXT_LEN(name));
2721  break;
2722  default :
2723  ERR(GRN_INVALID_ARGUMENT, "invalid type");
2724  goto exit;
2725  }
2726  PUSH1(res);
2727  }
2728  code++;
2729  break;
2730  case GRN_OP_ASSIGN :
2731  {
2732  grn_obj *value, *var;
2733  if (code->value) {
2734  value = code->value;
2735  } else {
2736  POP1(value);
2737  }
2738  value = GRN_OBJ_RESOLVE(ctx, value);
2739  POP1(var);
2740  // var = GRN_OBJ_RESOLVE(ctx, var);
2741  if (var->header.type == GRN_PTR &&
2742  GRN_BULK_VSIZE(var) == (sizeof(grn_obj *) + sizeof(grn_id))) {
2743  grn_obj *col = GRN_PTR_VALUE(var);
2744  grn_id rid = *(grn_id *)(GRN_BULK_HEAD(var) + sizeof(grn_obj *));
2745  grn_obj_set_value(ctx, col, rid, value, GRN_OBJ_SET);
2746  } else {
2747  VAR_SET_VALUE(ctx, var, value);
2748  }
2749  PUSH1(value);
2750  }
2751  code++;
2752  break;
2753  case GRN_OP_STAR_ASSIGN :
2762  {
2763  ERR(GRN_INVALID_ARGUMENT, "variable *= \"string\" isn't supported");
2764  goto exit;
2765  });
2766  break;
2767  case GRN_OP_SLASH_ASSIGN :
2776  {
2777  ERR(GRN_INVALID_ARGUMENT, "variable /= \"string\" isn't supported");
2778  goto exit;
2779  });
2780  break;
2781  case GRN_OP_MOD_ASSIGN :
2790  {
2791  ERR(GRN_INVALID_ARGUMENT, "variable %%= \"string\" isn't supported");
2792  goto exit;
2793  });
2794  break;
2795  case GRN_OP_PLUS_ASSIGN :
2804  {
2805  ERR(GRN_INVALID_ARGUMENT, "variable += \"string\" isn't supported");
2806  goto exit;
2807  });
2808  break;
2809  case GRN_OP_MINUS_ASSIGN :
2818  {
2819  ERR(GRN_INVALID_ARGUMENT, "variable -= \"string\" isn't supported");
2820  goto exit;
2821  });
2822  break;
2823  case GRN_OP_SHIFTL_ASSIGN :
2832  {
2833  ERR(GRN_INVALID_ARGUMENT, "variable <<= \"string\" isn't supported");
2834  goto exit;
2835  });
2836  break;
2837  case GRN_OP_SHIFTR_ASSIGN :
2846  {
2847  ERR(GRN_INVALID_ARGUMENT, "variable >>= \"string\" isn't supported");
2848  goto exit;
2849  });
2850  break;
2851  case GRN_OP_SHIFTRR_ASSIGN :
2860  {
2862  "variable >>>= \"string\" isn't supported");
2863  goto exit;
2864  });
2865  break;
2866  case GRN_OP_AND_ASSIGN :
2875  {
2876  ERR(GRN_INVALID_ARGUMENT, "variable &= \"string\" isn't supported");
2877  goto exit;
2878  });
2879  break;
2880  case GRN_OP_OR_ASSIGN :
2889  {
2890  ERR(GRN_INVALID_ARGUMENT, "variable |= \"string\" isn't supported");
2891  goto exit;
2892  });
2893  break;
2894  case GRN_OP_XOR_ASSIGN :
2903  {
2904  ERR(GRN_INVALID_ARGUMENT, "variable ^= \"string\" isn't supported");
2905  goto exit;
2906  });
2907  break;
2908  case GRN_OP_JUMP :
2909  code += code->nargs + 1;
2910  break;
2911  case GRN_OP_CJUMP :
2912  {
2913  grn_obj *v;
2914  unsigned int v_boolean;
2915  POP1(v);
2916  GRN_TRUEP(ctx, v, v_boolean);
2917  if (!v_boolean) { code += code->nargs; }
2918  }
2919  code++;
2920  break;
2921  case GRN_OP_GET_VALUE :
2922  {
2923  grn_obj *col, *rec;
2924  grn_obj pat_value;
2925  GRN_TEXT_INIT(&pat_value, 0);
2926  do {
2927  uint32_t size;
2928  const char *value;
2929  grn_bool is_pat_key_accessor = GRN_FALSE;
2930  if (code->nargs == 1) {
2931  rec = v0;
2932  if (code->value) {
2933  col = code->value;
2934  ALLOC1(res);
2935  } else {
2936  POP1ALLOC1(col, res);
2937  }
2938  } else {
2939  if (code->value) {
2940  col = code->value;
2941  POP1ALLOC1(rec, res);
2942  } else {
2943  POP2ALLOC1(rec, col, res);
2944  }
2945  }
2946  if (col->header.type == GRN_BULK) {
2947  grn_obj *table = grn_ctx_at(ctx, GRN_OBJ_GET_DOMAIN(rec));
2948  col = grn_obj_column(ctx, table, GRN_BULK_HEAD(col), GRN_BULK_VSIZE(col));
2949  if (col) { GRN_PTR_PUT(ctx, &e->objs, col); }
2950  }
2951  if (col) {
2952  grn_obj_reinit_for(ctx, res, col);
2953  if (col->header.type == GRN_ACCESSOR &&
2954  ((grn_accessor *)col)->action == GRN_ACCESSOR_GET_KEY &&
2955  ((grn_accessor *)col)->obj->header.type == GRN_TABLE_PAT_KEY) {
2956  is_pat_key_accessor = GRN_TRUE;
2957  GRN_BULK_REWIND(&pat_value);
2958  grn_obj_get_value(ctx, col, GRN_RECORD_VALUE(rec), &pat_value);
2959  value = GRN_BULK_HEAD(&pat_value);
2960  size = GRN_BULK_VSIZE(&pat_value);
2961  } else {
2962  value = grn_obj_get_value_(ctx, col, GRN_RECORD_VALUE(rec),
2963  &size);
2964  }
2965  } else {
2966  ERR(GRN_INVALID_ARGUMENT, "col resolve failed");
2967  GRN_OBJ_FIN(ctx, &pat_value);
2968  goto exit;
2969  }
2970  if (!is_pat_key_accessor && size == GRN_OBJ_GET_VALUE_IMD) {
2971  GRN_RECORD_SET(ctx, res, (uintptr_t)value);
2972  } else {
2973  if (value) {
2974  if (res->header.type == GRN_VECTOR) {
2975  grn_vector_decode(ctx, res, value, size);
2976  } else {
2977  grn_bulk_write_from(ctx, res, value, 0, size);
2978  }
2979  }
2980  }
2981  code++;
2982  } while (code < ce && code->op == GRN_OP_GET_VALUE);
2983  GRN_OBJ_FIN(ctx, &pat_value);
2984  }
2985  break;
2986  case GRN_OP_OBJ_SEARCH :
2987  {
2988  grn_obj *op, *query, *index;
2989  // todo : grn_search_optarg optarg;
2990  POP1(op);
2991  op = GRN_OBJ_RESOLVE(ctx, op);
2992  POP1(res);
2993  res = GRN_OBJ_RESOLVE(ctx, res);
2994  POP1(query);
2995  query = GRN_OBJ_RESOLVE(ctx, query);
2996  POP1(index);
2997  index = GRN_OBJ_RESOLVE(ctx, index);
2998  grn_obj_search(ctx, index, query, res,
2999  (grn_operator)GRN_UINT32_VALUE(op), NULL);
3000  }
3001  code++;
3002  break;
3003  case GRN_OP_TABLE_SELECT :
3004  {
3005  grn_obj *op, *res, *expr, *table;
3006  POP1(op);
3007  op = GRN_OBJ_RESOLVE(ctx, op);
3008  POP1(res);
3009  res = GRN_OBJ_RESOLVE(ctx, res);
3010  POP1(expr);
3011  expr = GRN_OBJ_RESOLVE(ctx, expr);
3012  POP1(table);
3013  table = GRN_OBJ_RESOLVE(ctx, table);
3014  WITH_SPSAVE({
3015  grn_table_select(ctx, table, expr, res, (grn_operator)GRN_UINT32_VALUE(op));
3016  });
3017  PUSH1(res);
3018  }
3019  code++;
3020  break;
3021  case GRN_OP_TABLE_SORT :
3022  {
3023  grn_obj *keys_, *res, *limit, *table;
3024  POP1(keys_);
3025  keys_ = GRN_OBJ_RESOLVE(ctx, keys_);
3026  POP1(res);
3027  res = GRN_OBJ_RESOLVE(ctx, res);
3028  POP1(limit);
3029  limit = GRN_OBJ_RESOLVE(ctx, limit);
3030  POP1(table);
3031  table = GRN_OBJ_RESOLVE(ctx, table);
3032  {
3033  grn_table_sort_key *keys;
3034  const char *p = GRN_BULK_HEAD(keys_), *tokbuf[256];
3035  int n = grn_str_tok(p, GRN_BULK_VSIZE(keys_), ' ', tokbuf, 256, NULL);
3036  if ((keys = GRN_MALLOCN(grn_table_sort_key, n))) {
3037  int i, n_keys = 0;
3038  for (i = 0; i < n; i++) {
3039  uint32_t len = (uint32_t) (tokbuf[i] - p);
3040  grn_obj *col = grn_obj_column(ctx, table, p, len);
3041  if (col) {
3042  keys[n_keys].key = col;
3043  keys[n_keys].flags = GRN_TABLE_SORT_ASC;
3044  keys[n_keys].offset = 0;
3045  n_keys++;
3046  } else {
3047  if (p[0] == ':' && p[1] == 'd' && len == 2 && n_keys) {
3048  keys[n_keys - 1].flags |= GRN_TABLE_SORT_DESC;
3049  }
3050  }
3051  p = tokbuf[i] + 1;
3052  }
3053  WITH_SPSAVE({
3054  grn_table_sort(ctx, table, 0, GRN_INT32_VALUE(limit), res, keys, n_keys);
3055  });
3056  for (i = 0; i < n_keys; i++) {
3057  grn_obj_unlink(ctx, keys[i].key);
3058  }
3059  GRN_FREE(keys);
3060  }
3061  }
3062  }
3063  code++;
3064  break;
3065  case GRN_OP_TABLE_GROUP :
3066  {
3067  grn_obj *res, *keys_, *table;
3068  POP1(res);
3069  res = GRN_OBJ_RESOLVE(ctx, res);
3070  POP1(keys_);
3071  keys_ = GRN_OBJ_RESOLVE(ctx, keys_);
3072  POP1(table);
3073  table = GRN_OBJ_RESOLVE(ctx, table);
3074  {
3075  grn_table_sort_key *keys;
3076  grn_table_group_result results;
3077  const char *p = GRN_BULK_HEAD(keys_), *tokbuf[256];
3078  int n = grn_str_tok(p, GRN_BULK_VSIZE(keys_), ' ', tokbuf, 256, NULL);
3079  if ((keys = GRN_MALLOCN(grn_table_sort_key, n))) {
3080  int i, n_keys = 0;
3081  for (i = 0; i < n; i++) {
3082  uint32_t len = (uint32_t) (tokbuf[i] - p);
3083  grn_obj *col = grn_obj_column(ctx, table, p, len);
3084  if (col) {
3085  keys[n_keys].key = col;
3086  keys[n_keys].flags = GRN_TABLE_SORT_ASC;
3087  keys[n_keys].offset = 0;
3088  n_keys++;
3089  } else if (n_keys) {
3090  if (p[0] == ':' && p[1] == 'd' && len == 2) {
3091  keys[n_keys - 1].flags |= GRN_TABLE_SORT_DESC;
3092  } else {
3093  keys[n_keys - 1].offset = grn_atoi(p, p + len, NULL);
3094  }
3095  }
3096  p = tokbuf[i] + 1;
3097  }
3098  /* todo : support multi-results */
3099  results.table = res;
3100  results.key_begin = 0;
3101  results.key_end = 0;
3102  results.limit = 0;
3103  results.flags = 0;
3104  results.op = GRN_OP_OR;
3105  WITH_SPSAVE({
3106  grn_table_group(ctx, table, keys, n_keys, &results, 1);
3107  });
3108  for (i = 0; i < n_keys; i++) {
3109  grn_obj_unlink(ctx, keys[i].key);
3110  }
3111  GRN_FREE(keys);
3112  }
3113  }
3114  }
3115  code++;
3116  break;
3117  case GRN_OP_JSON_PUT :
3118  {
3119  grn_obj_format format;
3120  grn_obj *str, *table, *res;
3121  POP1(res);
3122  res = GRN_OBJ_RESOLVE(ctx, res);
3123  POP1(str);
3124  str = GRN_OBJ_RESOLVE(ctx, str);
3125  POP1(table);
3126  table = GRN_OBJ_RESOLVE(ctx, table);
3127  GRN_OBJ_FORMAT_INIT(&format, grn_table_size(ctx, table), 0, -1, 0);
3128  format.flags = 0;
3129  grn_obj_columns(ctx, table,
3130  GRN_TEXT_VALUE(str), GRN_TEXT_LEN(str), &format.columns);
3131  grn_text_otoj(ctx, res, table, &format);
3132  GRN_OBJ_FORMAT_FIN(ctx, &format);
3133  }
3134  code++;
3135  break;
3136  case GRN_OP_AND :
3137  {
3138  grn_obj *x, *y;
3139  unsigned int x_boolean, y_boolean;
3140  int result;
3141  POP2ALLOC1(x, y, res);
3142  GRN_TRUEP(ctx, x, x_boolean);
3143  GRN_TRUEP(ctx, y, y_boolean);
3144  if (x_boolean && y_boolean) {
3145  result = 1;
3146  } else {
3147  result = 0;
3148  }
3149  grn_obj_reinit(ctx, res, GRN_DB_INT32, 0);
3150  GRN_INT32_SET(ctx, res, result);
3151  }
3152  code++;
3153  break;
3154  case GRN_OP_OR :
3155  {
3156  grn_obj *x, *y;
3157  unsigned int x_boolean, y_boolean;
3158  int result;
3159  POP2ALLOC1(x, y, res);
3160  GRN_TRUEP(ctx, x, x_boolean);
3161  GRN_TRUEP(ctx, y, y_boolean);
3162  if (x_boolean || y_boolean) {
3163  result = 1;
3164  } else {
3165  result = 0;
3166  }
3167  grn_obj_reinit(ctx, res, GRN_DB_INT32, 0);
3168  GRN_INT32_SET(ctx, res, result);
3169  }
3170  code++;
3171  break;
3172  case GRN_OP_AND_NOT :
3173  {
3174  grn_obj *x, *y;
3175  POP2ALLOC1(x, y, res);
3176  if (GRN_INT32_VALUE(x) == 0 || GRN_INT32_VALUE(y) == 1) {
3177  GRN_INT32_SET(ctx, res, 0);
3178  } else {
3179  GRN_INT32_SET(ctx, res, 1);
3180  }
3181  res->header.type = GRN_BULK;
3182  res->header.domain = GRN_DB_INT32;
3183  }
3184  code++;
3185  break;
3186  case GRN_OP_ADJUST :
3187  {
3188  /* todo */
3189  }
3190  code++;
3191  break;
3192  case GRN_OP_MATCH :
3193  {
3194  grn_obj *x, *y;
3195  grn_bool matched;
3196  POP1(y);
3197  POP1(x);
3198  WITH_SPSAVE({
3199  matched = pseudo_query_scan(ctx, x, y);
3200  });
3201  ALLOC1(res);
3202  grn_obj_reinit(ctx, res, GRN_DB_INT32, 0);
3203  GRN_INT32_SET(ctx, res, matched ? 1 : 0);
3204  }
3205  code++;
3206  break;
3207  case GRN_OP_EQUAL :
3208  {
3209  int r = GRN_FALSE;
3210  grn_obj *x, *y;
3211  POP2ALLOC1(x, y, res);
3212  DO_EQ(x, y, r);
3213  grn_obj_reinit(ctx, res, GRN_DB_INT32, 0);
3214  GRN_INT32_SET(ctx, res, r);
3215  }
3216  code++;
3217  break;
3218  case GRN_OP_NOT_EQUAL :
3219  {
3220  int r = GRN_FALSE;
3221  grn_obj *x, *y;
3222  POP2ALLOC1(x, y, res);
3223  DO_EQ(x, y, r);
3224  grn_obj_reinit(ctx, res, GRN_DB_INT32, 0);
3225  GRN_INT32_SET(ctx, res, 1 - r);
3226  }
3227  code++;
3228  break;
3229  case GRN_OP_PREFIX :
3230  {
3231  grn_obj *x, *y;
3232  POP2ALLOC1(x, y, res);
3233  GRN_INT32_SET(ctx, res,
3234  (GRN_TEXT_LEN(x) >= GRN_TEXT_LEN(y) &&
3235  !memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), GRN_TEXT_LEN(y))));
3236  res->header.type = GRN_BULK;
3237  res->header.domain = GRN_DB_INT32;
3238  }
3239  code++;
3240  break;
3241  case GRN_OP_SUFFIX :
3242  {
3243  grn_obj *x, *y;
3244  POP2ALLOC1(x, y, res);
3245  GRN_INT32_SET(ctx, res,
3246  (GRN_TEXT_LEN(x) >= GRN_TEXT_LEN(y) &&
3247  !memcmp(GRN_TEXT_VALUE(x) + GRN_TEXT_LEN(x) - GRN_TEXT_LEN(y),
3248  GRN_TEXT_VALUE(y), GRN_TEXT_LEN(y))));
3249  res->header.type = GRN_BULK;
3250  res->header.domain = GRN_DB_INT32;
3251  }
3252  code++;
3253  break;
3254  case GRN_OP_LESS :
3255  {
3256  int r;
3257  grn_obj *x, *y;
3258  POP2ALLOC1(x, y, res);
3259  DO_COMPARE(x, y, r, <);
3260  GRN_INT32_SET(ctx, res, r);
3261  res->header.type = GRN_BULK;
3262  res->header.domain = GRN_DB_INT32;
3263  }
3264  code++;
3265  break;
3266  case GRN_OP_GREATER :
3267  {
3268  int r;
3269  grn_obj *x, *y;
3270  POP2ALLOC1(x, y, res);
3271  DO_COMPARE(x, y, r, >);
3272  GRN_INT32_SET(ctx, res, r);
3273  res->header.type = GRN_BULK;
3274  res->header.domain = GRN_DB_INT32;
3275  }
3276  code++;
3277  break;
3278  case GRN_OP_LESS_EQUAL :
3279  {
3280  int r;
3281  grn_obj *x, *y;
3282  POP2ALLOC1(x, y, res);
3283  DO_COMPARE(x, y, r, <=);
3284  GRN_INT32_SET(ctx, res, r);
3285  res->header.type = GRN_BULK;
3286  res->header.domain = GRN_DB_INT32;
3287  }
3288  code++;
3289  break;
3290  case GRN_OP_GREATER_EQUAL :
3291  {
3292  int r;
3293  grn_obj *x, *y;
3294  POP2ALLOC1(x, y, res);
3295  DO_COMPARE(x, y, r, >=);
3296  GRN_INT32_SET(ctx, res, r);
3297  res->header.type = GRN_BULK;
3298  res->header.domain = GRN_DB_INT32;
3299  }
3300  code++;
3301  break;
3302  case GRN_OP_GEO_DISTANCE1 :
3303  {
3304  grn_obj *e;
3305  double lng1, lat1, lng2, lat2, x, y, d;
3306  POP1(e);
3307  lng1 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3308  POP1(e);
3309  lat1 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3310  POP1(e);
3311  lng2 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3312  POP1ALLOC1(e, res);
3313  lat2 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3314  x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5);
3315  y = (lat2 - lat1);
3316  d = sqrt((x * x) + (y * y)) * GEO_RADIOUS;
3317  res->header.type = GRN_BULK;
3318  res->header.domain = GRN_DB_FLOAT;
3319  GRN_FLOAT_SET(ctx, res, d);
3320  }
3321  code++;
3322  break;
3323  case GRN_OP_GEO_DISTANCE2 :
3324  {
3325  grn_obj *e;
3326  double lng1, lat1, lng2, lat2, x, y, d;
3327  POP1(e);
3328  lng1 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3329  POP1(e);
3330  lat1 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3331  POP1(e);
3332  lng2 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3333  POP1ALLOC1(e, res);
3334  lat2 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3335  x = sin(fabs(lng2 - lng1) * 0.5);
3336  y = sin(fabs(lat2 - lat1) * 0.5);
3337  d = asin(sqrt((y * y) + cos(lat1) * cos(lat2) * x * x)) * 2 * GEO_RADIOUS;
3338  res->header.type = GRN_BULK;
3339  res->header.domain = GRN_DB_FLOAT;
3340  GRN_FLOAT_SET(ctx, res, d);
3341  }
3342  code++;
3343  break;
3344  case GRN_OP_GEO_DISTANCE3 :
3345  {
3346  grn_obj *e;
3347  double lng1, lat1, lng2, lat2, p, q, m, n, x, y, d;
3348  POP1(e);
3349  lng1 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3350  POP1(e);
3351  lat1 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3352  POP1(e);
3353  lng2 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3354  POP1ALLOC1(e, res);
3355  lat2 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3356  p = (lat1 + lat2) * 0.5;
3357  q = (1 - GEO_BES_C3 * sin(p) * sin(p));
3358  m = GEO_BES_C1 / sqrt(q * q * q);
3359  n = GEO_BES_C2 / sqrt(q);
3360  x = n * cos(p) * fabs(lng1 - lng2);
3361  y = m * fabs(lat1 - lat2);
3362  d = sqrt((x * x) + (y * y));
3363  res->header.type = GRN_BULK;
3364  res->header.domain = GRN_DB_FLOAT;
3365  GRN_FLOAT_SET(ctx, res, d);
3366  }
3367  code++;
3368  break;
3369  case GRN_OP_GEO_DISTANCE4 :
3370  {
3371  grn_obj *e;
3372  double lng1, lat1, lng2, lat2, p, q, m, n, x, y, d;
3373  POP1(e);
3374  lng1 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3375  POP1(e);
3376  lat1 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3377  POP1(e);
3378  lng2 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3379  POP1ALLOC1(e, res);
3380  lat2 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3381  p = (lat1 + lat2) * 0.5;
3382  q = (1 - GEO_GRS_C3 * sin(p) * sin(p));
3383  m = GEO_GRS_C1 / sqrt(q * q * q);
3384  n = GEO_GRS_C2 / sqrt(q);
3385  x = n * cos(p) * fabs(lng1 - lng2);
3386  y = m * fabs(lat1 - lat2);
3387  d = sqrt((x * x) + (y * y));
3388  res->header.type = GRN_BULK;
3389  res->header.domain = GRN_DB_FLOAT;
3390  GRN_FLOAT_SET(ctx, res, d);
3391  }
3392  code++;
3393  break;
3394  case GRN_OP_GEO_WITHINP5 :
3395  {
3396  int r;
3397  grn_obj *e;
3398  double lng0, lat0, lng1, lat1, x, y, d;
3399  POP1(e);
3400  lng0 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3401  POP1(e);
3402  lat0 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3403  POP1(e);
3404  lng1 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3405  POP1(e);
3406  lat1 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3407  POP1ALLOC1(e, res);
3408  x = (lng1 - lng0) * cos((lat0 + lat1) * 0.5);
3409  y = (lat1 - lat0);
3410  d = sqrt((x * x) + (y * y)) * GEO_RADIOUS;
3411  switch (e->header.domain) {
3412  case GRN_DB_INT32 :
3413  r = d <= GRN_INT32_VALUE(e);
3414  break;
3415  case GRN_DB_FLOAT :
3416  r = d <= GRN_FLOAT_VALUE(e);
3417  break;
3418  default :
3419  r = 0;
3420  break;
3421  }
3422  GRN_INT32_SET(ctx, res, r);
3423  res->header.type = GRN_BULK;
3424  res->header.domain = GRN_DB_INT32;
3425  }
3426  code++;
3427  break;
3428  case GRN_OP_GEO_WITHINP6 :
3429  {
3430  int r;
3431  grn_obj *e;
3432  double lng0, lat0, lng1, lat1, lng2, lat2, x, y, d;
3433  POP1(e);
3434  lng0 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3435  POP1(e);
3436  lat0 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3437  POP1(e);
3438  lng1 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3439  POP1(e);
3440  lat1 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3441  POP1(e);
3442  lng2 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3443  POP1ALLOC1(e, res);
3444  lat2 = GEO_INT2RAD(GRN_INT32_VALUE(e));
3445  x = (lng1 - lng0) * cos((lat0 + lat1) * 0.5);
3446  y = (lat1 - lat0);
3447  d = (x * x) + (y * y);
3448  x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5);
3449  y = (lat2 - lat1);
3450  r = d <= (x * x) + (y * y);
3451  GRN_INT32_SET(ctx, res, r);
3452  res->header.type = GRN_BULK;
3453  res->header.domain = GRN_DB_INT32;
3454  }
3455  code++;
3456  break;
3457  case GRN_OP_GEO_WITHINP8 :
3458  {
3459  int r;
3460  grn_obj *e;
3461  int64_t ln0, la0, ln1, la1, ln2, la2, ln3, la3;
3462  POP1(e);
3463  ln0 = GRN_INT32_VALUE(e);
3464  POP1(e);
3465  la0 = GRN_INT32_VALUE(e);
3466  POP1(e);
3467  ln1 = GRN_INT32_VALUE(e);
3468  POP1(e);
3469  la1 = GRN_INT32_VALUE(e);
3470  POP1(e);
3471  ln2 = GRN_INT32_VALUE(e);
3472  POP1(e);
3473  la2 = GRN_INT32_VALUE(e);
3474  POP1(e);
3475  ln3 = GRN_INT32_VALUE(e);
3476  POP1ALLOC1(e, res);
3477  la3 = GRN_INT32_VALUE(e);
3478  r = ((ln2 <= ln0) && (ln0 <= ln3) && (la2 <= la0) && (la0 <= la3));
3479  GRN_INT32_SET(ctx, res, r);
3480  res->header.type = GRN_BULK;
3481  res->header.domain = GRN_DB_INT32;
3482  }
3483  code++;
3484  break;
3485  case GRN_OP_PLUS :
3494  {
3495  if (x == res) {
3496  grn_obj_cast(ctx, y, res, GRN_FALSE);
3497  } else if (y == res) {
3498  grn_obj buffer;
3499  GRN_TEXT_INIT(&buffer, 0);
3500  grn_obj_cast(ctx, x, &buffer, GRN_FALSE);
3501  grn_obj_cast(ctx, y, &buffer, GRN_FALSE);
3502  GRN_BULK_REWIND(res);
3503  grn_obj_cast(ctx, &buffer, res, GRN_FALSE);
3504  GRN_OBJ_FIN(ctx, &buffer);
3505  } else {
3506  GRN_BULK_REWIND(res);
3507  grn_obj_cast(ctx, x, res, GRN_FALSE);
3508  grn_obj_cast(ctx, y, res, GRN_FALSE);
3509  }
3510  }
3511  ,);
3512  break;
3513  case GRN_OP_MINUS :
3514  if (code->nargs == 1) {
3520  {
3521  long long int x_;
3522 
3523  res->header.type = GRN_BULK;
3524  res->header.domain = GRN_DB_INT64;
3525 
3526  GRN_INT64_SET(ctx, res, 0);
3527  grn_obj_cast(ctx, x, res, GRN_FALSE);
3528  x_ = GRN_INT64_VALUE(res);
3529 
3530  GRN_INT64_SET(ctx, res, -x_);
3531  }
3532  ,);
3533  } else {
3542  {
3544  "\"string\" - \"string\" "
3545  "isn't supported");
3546  goto exit;
3547  }
3548  ,);
3549  }
3550  break;
3551  case GRN_OP_STAR :
3560  {
3562  "\"string\" * \"string\" "
3563  "isn't supported");
3564  goto exit;
3565  }
3566  ,);
3567  break;
3568  case GRN_OP_SLASH :
3577  {
3579  "\"string\" / \"string\" "
3580  "isn't supported");
3581  goto exit;
3582  }
3583  ,);
3584  break;
3585  case GRN_OP_MOD :
3594  {
3596  "\"string\" %% \"string\" "
3597  "isn't supported");
3598  goto exit;
3599  }
3600  ,);
3601  break;
3602  case GRN_OP_BITWISE_NOT :
3609  break;
3610  case GRN_OP_BITWISE_OR :
3620  break;
3621  case GRN_OP_BITWISE_XOR :
3631  break;
3632  case GRN_OP_BITWISE_AND :
3642  break;
3643  case GRN_OP_SHIFTL :
3653  break;
3654  case GRN_OP_SHIFTR :
3664  break;
3665  case GRN_OP_SHIFTRR :
3674  {
3675  long long unsigned int x_;
3676  long long unsigned int y_;
3677 
3678  res->header.type = GRN_BULK;
3679  res->header.domain = GRN_DB_INT64;
3680 
3681  GRN_INT64_SET(ctx, res, 0);
3682  grn_obj_cast(ctx, x, res, GRN_FALSE);
3683  x_ = GRN_INT64_VALUE(res);
3684 
3685  GRN_INT64_SET(ctx, res, 0);
3686  grn_obj_cast(ctx, y, res, GRN_FALSE);
3687  y_ = GRN_INT64_VALUE(res);
3688 
3689  GRN_INT64_SET(ctx, res, x_ >> y_);
3690  }
3691  ,);
3692  break;
3693  case GRN_OP_INCR :
3695  break;
3696  case GRN_OP_DECR :
3698  break;
3699  case GRN_OP_INCR_POST :
3701  break;
3702  case GRN_OP_DECR_POST :
3704  break;
3705  case GRN_OP_NOT :
3706  {
3707  grn_obj *value;
3708  POP1ALLOC1(value, res);
3709  grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0);
3710  grn_obj_cast(ctx, value, res, GRN_FALSE);
3711  GRN_BOOL_SET(ctx, res, !GRN_BOOL_VALUE(res));
3712  }
3713  code++;
3714  break;
3715  case GRN_OP_GET_MEMBER :
3716  {
3717  grn_obj *column_and_record_id, *index;
3718  POP2ALLOC1(column_and_record_id, index, res);
3719  grn_expr_exec_get_member(ctx, expr, column_and_record_id, index, res);
3720  code++;
3721  }
3722  break;
3723  default :
3724  ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "not implemented operator assigned");
3725  goto exit;
3726  break;
3727  }
3728  }
3729  ctx->impl->stack_curr = sp - s_;
3730  }
3731  if (ctx->impl->stack_curr + nargs > stack_curr) {
3732  val = grn_ctx_pop(ctx);
3733  }
3734 exit :
3735  if (ctx->impl->stack_curr + nargs > stack_curr) {
3736  /*
3737  GRN_LOG(ctx, GRN_LOG_WARNING, "nargs=%d stack balance=%d",
3738  nargs, stack_curr - ctx->impl->stack_curr);
3739  */
3740  ctx->impl->stack_curr = stack_curr - nargs;
3741  }
3742  GRN_API_RETURN(val);
3743 }
3744 
3745 grn_obj *
3746 grn_expr_get_value(grn_ctx *ctx, grn_obj *expr, int offset)
3747 {
3748  grn_obj *res = NULL;
3749  grn_expr *e = (grn_expr *)expr;
3750  GRN_API_ENTER;
3751  if (0 <= offset && offset < e->values_size) {
3752  res = &e->values[offset];
3753  }
3754  GRN_API_RETURN(res);
3755 }
3756 
3757 inline static void
3758 res_add(grn_ctx *ctx, grn_hash *s, grn_rset_posinfo *pi, uint32_t score,
3759  grn_operator op)
3760 {
3761  grn_rset_recinfo *ri;
3762  switch (op) {
3763  case GRN_OP_OR :
3764  if (grn_hash_add(ctx, s, pi, s->key_size, (void **)&ri, NULL)) {
3765  grn_table_add_subrec((grn_obj *)s, ri, score, pi, 1);
3766  }
3767  break;
3768  case GRN_OP_AND :
3769  if (grn_hash_get(ctx, s, pi, s->key_size, (void **)&ri)) {
3771  grn_table_add_subrec((grn_obj *)s, ri, score, pi, 1);
3772  }
3773  break;
3774  case GRN_OP_AND_NOT :
3775  {
3776  grn_id id;
3777  if ((id = grn_hash_get(ctx, s, pi, s->key_size, (void **)&ri))) {
3778  grn_hash_delete_by_id(ctx, s, id, NULL);
3779  }
3780  }
3781  break;
3782  case GRN_OP_ADJUST :
3783  if (grn_hash_get(ctx, s, pi, s->key_size, (void **)&ri)) {
3784  ri->score += score;
3785  }
3786  break;
3787  default :
3788  break;
3789  }
3790 }
3791 
3793  uint32_t start;
3794  uint32_t end;
3795  int32_t nargs;
3796  int flags;
3803 };
3804 
3805 #define SI_FREE(si) do {\
3806  GRN_OBJ_FIN(ctx, &(si)->wv);\
3807  GRN_OBJ_FIN(ctx, &(si)->index);\
3808  GRN_FREE(si);\
3809 } while (0)
3810 
3811 #define SI_ALLOC(si, i, st) do {\
3812  if (!((si) = GRN_MALLOCN(scan_info, 1))) {\
3813  int j;\
3814  for (j = 0; j < i; j++) { SI_FREE(sis[j]); }\
3815  GRN_FREE(sis);\
3816  return NULL;\
3817  }\
3818  GRN_INT32_INIT(&(si)->wv, GRN_OBJ_VECTOR);\
3819  GRN_PTR_INIT(&(si)->index, GRN_OBJ_VECTOR, GRN_ID_NIL);\
3820  (si)->logical_op = GRN_OP_OR;\
3821  (si)->flags = SCAN_PUSH;\
3822  (si)->nargs = 0;\
3823  (si)->start = (st);\
3824 } while (0)
3825 
3826 static scan_info **
3827 put_logical_op(grn_ctx *ctx, scan_info **sis, int *ip, grn_operator op, int start)
3828 {
3829  int nparens = 1, ndifops = 0, i = *ip, j = i, r = 0;
3830  while (j--) {
3831  scan_info *s_ = sis[j];
3832  if (s_->flags & SCAN_POP) {
3833  ndifops++;
3834  nparens++;
3835  } else {
3836  if (s_->flags & SCAN_PUSH) {
3837  if (!(--nparens)) {
3838  if (!r) {
3839  if (ndifops) {
3840  if (j && op != GRN_OP_AND_NOT) {
3841  nparens = 1;
3842  ndifops = 0;
3843  r = j;
3844  } else {
3845  SI_ALLOC(s_, i, start);
3846  s_->flags = SCAN_POP;
3847  s_->logical_op = op;
3848  sis[i++] = s_;
3849  *ip = i;
3850  break;
3851  }
3852  } else {
3853  s_->flags &= ~SCAN_PUSH;
3854  s_->logical_op = op;
3855  break;
3856  }
3857  } else {
3858  if (ndifops) {
3859  SI_ALLOC(s_, i, start);
3860  s_->flags = SCAN_POP;
3861  s_->logical_op = op;
3862  sis[i++] = s_;
3863  *ip = i;
3864  } else {
3865  s_->flags &= ~SCAN_PUSH;
3866  s_->logical_op = op;
3867  memcpy(&sis[i], &sis[j], sizeof(scan_info *) * (r - j));
3868  memmove(&sis[j], &sis[r], sizeof(scan_info *) * (i - r));
3869  memcpy(&sis[i + j - r], &sis[i], sizeof(scan_info *) * (r - j));
3870  }
3871  break;
3872  }
3873  }
3874  } else {
3875  if ((op == GRN_OP_AND_NOT) || (op != s_->logical_op)) {
3876  ndifops++;
3877  }
3878  }
3879  }
3880  }
3881  if (j < 0) {
3882  ERR(GRN_INVALID_ARGUMENT, "unmatched nesting level");
3883  for (j = 0; j < i; j++) { SI_FREE(sis[j]); }
3884  GRN_FREE(sis);
3885  return NULL;
3886  }
3887  return sis;
3888 }
3889 
3890 
3891 #define EXPRLOG(name,expr) do {\
3892  grn_obj strbuf;\
3893  GRN_TEXT_INIT(&strbuf, 0);\
3894  grn_expr_inspect(ctx, &strbuf, (expr));\
3895  GRN_TEXT_PUTC(ctx, &strbuf, '\0');\
3896  GRN_LOG(ctx, GRN_LOG_NOTICE, "%s=(%s)", (name), GRN_TEXT_VALUE(&strbuf));\
3897  GRN_OBJ_FIN(ctx, &strbuf);\
3898 } while (0)
3899 
3900 static void
3901 scan_info_put_index(grn_ctx *ctx, scan_info *si, grn_obj *index, uint32_t sid, int32_t weight)
3902 {
3903  GRN_PTR_PUT(ctx, &si->index, index);
3904  GRN_UINT32_PUT(ctx, &si->wv, sid);
3905  GRN_INT32_PUT(ctx, &si->wv, weight);
3906  {
3907  int i, ni = (GRN_BULK_VSIZE(&si->index) / sizeof(grn_obj *)) - 1;
3908  grn_obj **pi = &GRN_PTR_VALUE_AT(&si->index, ni);
3909  for (i = 0; i < ni; i++, pi--) {
3910  if (index == pi[-1]) {
3911  if (i) {
3912  int32_t *pw = &GRN_INT32_VALUE_AT(&si->wv, (ni - i) * 2);
3913  memmove(pw + 2, pw, sizeof(int32_t) * 2 * i);
3914  pw[0] = (int32_t) sid;
3915  pw[1] = weight;
3916  memmove(pi + 1, pi, sizeof(grn_obj *) * i);
3917  pi[0] = index;
3918  }
3919  return;
3920  }
3921  }
3922  }
3923 }
3924 
3925 static int32_t
3926 get_weight(grn_ctx *ctx, grn_expr_code *ec)
3927 {
3928  if (ec->modify == 2 && ec[2].op == GRN_OP_STAR &&
3929  ec[1].value && ec[1].value->header.type == GRN_BULK) {
3930  if (ec[1].value->header.domain == GRN_DB_INT32 ||
3931  ec[1].value->header.domain == GRN_DB_UINT32) {
3932  return GRN_INT32_VALUE(ec[1].value);
3933  } else {
3934  int32_t weight = 1;
3935  grn_obj weight_buffer;
3936  GRN_INT32_INIT(&weight_buffer, 0);
3937  if (!grn_obj_cast(ctx, ec[1].value, &weight_buffer, GRN_FALSE)) {
3938  weight = GRN_INT32_VALUE(&weight_buffer);
3939  }
3940  grn_obj_unlink(ctx, &weight_buffer);
3941  return weight;
3942  }
3943  } else {
3944  return 1;
3945  }
3946 }
3947 
3948 scan_info *
3949 grn_scan_info_open(grn_ctx *ctx, int start)
3950 {
3951  scan_info *si = GRN_MALLOCN(scan_info, 1);
3952 
3953  if (!si) {
3954  return NULL;
3955  }
3956 
3959  si->logical_op = GRN_OP_OR;
3960  si->flags = SCAN_PUSH;
3961  si->nargs = 0;
3962  si->start = start;
3963 
3964  return si;
3965 }
3966 
3967 void
3969 {
3970  SI_FREE(si);
3971 }
3972 
3973 void
3974 grn_scan_info_put_index(grn_ctx *ctx, scan_info *si, grn_obj *index, uint32_t sid, int32_t weight)
3975 {
3976  scan_info_put_index(ctx, si, index, sid, weight);
3977 }
3978 
3979 scan_info **
3981  grn_operator op, int start)
3982 {
3983  return put_logical_op(ctx, sis, ip, op, start);
3984 }
3985 
3986 int32_t
3988 {
3989  return get_weight(ctx, ec);
3990 }
3991 
3992 int
3994 {
3995  return si->flags;
3996 }
3997 
3998 void
4000 {
4001  si->flags = flags;
4002 }
4003 
4006 {
4007  return si->logical_op;
4008 }
4009 
4010 void
4012 {
4013  si->logical_op = logical_op;
4014 }
4015 
4016 void
4018 {
4019  si->op = op;
4020 }
4021 
4022 void
4024 {
4025  si->end = end;
4026 }
4027 
4028 void
4030 {
4031  si->query = query;
4032 }
4033 
4034 grn_bool
4036 {
4037  if (si->nargs >= 8) {
4038  return GRN_FALSE;
4039  }
4040 
4041  si->args[si->nargs++] = arg;
4042  return GRN_TRUE;
4043 }
4044 
4045 grn_obj *
4047 {
4048  if (i >= si->nargs) {
4049  return NULL;
4050  }
4051  return si->args[i];
4052 }
4053 
4054 static scan_info **
4055 scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n,
4056  grn_operator op, uint32_t size)
4057 {
4058  grn_obj *var;
4059  scan_stat stat;
4060  int i, m = 0, o = 0;
4061  scan_info **sis, *si = NULL;
4062  grn_expr_code *c, *ce;
4063  grn_expr *e = (grn_expr *)expr;
4064 #ifdef GRN_WITH_MRUBY
4065  if (ctx->impl->mrb.state) {
4066  return grn_mrb_scan_info_build(ctx, expr, n, op, size);
4067  }
4068 #endif
4069  if (!(var = grn_expr_get_var_by_offset(ctx, expr, 0))) { return NULL; }
4070  for (stat = SCAN_START, c = e->codes, ce = &e->codes[e->codes_curr]; c < ce; c++) {
4071  switch (c->op) {
4072  case GRN_OP_MATCH :
4073  case GRN_OP_NEAR :
4074  case GRN_OP_NEAR2 :
4075  case GRN_OP_SIMILAR :
4076  case GRN_OP_PREFIX :
4077  case GRN_OP_SUFFIX :
4078  case GRN_OP_EQUAL :
4079  case GRN_OP_NOT_EQUAL :
4080  case GRN_OP_LESS :
4081  case GRN_OP_GREATER :
4082  case GRN_OP_LESS_EQUAL :
4083  case GRN_OP_GREATER_EQUAL :
4084  case GRN_OP_GEO_WITHINP5 :
4085  case GRN_OP_GEO_WITHINP6 :
4086  case GRN_OP_GEO_WITHINP8 :
4087  case GRN_OP_TERM_EXTRACT :
4088  if (stat < SCAN_COL1 || SCAN_CONST < stat) { return NULL; }
4089  stat = SCAN_START;
4090  m++;
4091  break;
4092  case GRN_OP_AND :
4093  case GRN_OP_OR :
4094  case GRN_OP_AND_NOT :
4095  case GRN_OP_ADJUST :
4096  if (stat != SCAN_START) { return NULL; }
4097  o++;
4098  if (o >= m) { return NULL; }
4099  break;
4100  case GRN_OP_PUSH :
4101  stat = (c->value == var) ? SCAN_VAR : SCAN_CONST;
4102  break;
4103  case GRN_OP_GET_VALUE :
4104  switch (stat) {
4105  case SCAN_START :
4106  case SCAN_CONST :
4107  case SCAN_VAR :
4108  stat = SCAN_COL1;
4109  break;
4110  case SCAN_COL1 :
4111  stat = SCAN_COL2;
4112  break;
4113  case SCAN_COL2 :
4114  break;
4115  default :
4116  return NULL;
4117  break;
4118  }
4119  break;
4120  case GRN_OP_CALL :
4121  if ((c->flags & GRN_EXPR_CODE_RELATIONAL_EXPRESSION) || c + 1 == ce) {
4122  stat = SCAN_START;
4123  m++;
4124  } else {
4125  stat = SCAN_COL2;
4126  }
4127  break;
4128  default :
4129  return NULL;
4130  break;
4131  }
4132  }
4133  if (stat || m != o + 1) { return NULL; }
4134  if (!(sis = GRN_MALLOCN(scan_info *, m + m + o))) { return NULL; }
4135  for (i = 0, stat = SCAN_START, c = e->codes, ce = &e->codes[e->codes_curr]; c < ce; c++) {
4136  switch (c->op) {
4137  case GRN_OP_MATCH :
4138  case GRN_OP_NEAR :
4139  case GRN_OP_NEAR2 :
4140  case GRN_OP_SIMILAR :
4141  case GRN_OP_PREFIX :
4142  case GRN_OP_SUFFIX :
4143  case GRN_OP_EQUAL :
4144  case GRN_OP_NOT_EQUAL :
4145  case GRN_OP_LESS :
4146  case GRN_OP_GREATER :
4147  case GRN_OP_LESS_EQUAL :
4148  case GRN_OP_GREATER_EQUAL :
4149  case GRN_OP_GEO_WITHINP5 :
4150  case GRN_OP_GEO_WITHINP6 :
4151  case GRN_OP_GEO_WITHINP8 :
4152  case GRN_OP_TERM_EXTRACT :
4153  stat = SCAN_START;
4154  si->op = c->op;
4155  si->end = c - e->codes;
4156  sis[i++] = si;
4157  {
4158  int sid;
4159  grn_obj *index, **p = si->args, **pe = si->args + si->nargs;
4160  for (; p < pe; p++) {
4161  if ((*p)->header.type == GRN_EXPR) {
4162  uint32_t j;
4163  grn_expr_code *ec;
4164  grn_expr *e = (grn_expr *)(*p);
4165  for (j = e->codes_curr, ec = e->codes; j--; ec++) {
4166  if (ec->value) {
4167  switch (ec->value->header.type) {
4168  case GRN_ACCESSOR :
4169  if (grn_column_index(ctx, ec->value, c->op, &index, 1, &sid)) {
4170  int32_t weight = get_weight(ctx, ec);
4171  si->flags |= SCAN_ACCESSOR;
4172  if (((grn_accessor *)ec->value)->next) {
4173  scan_info_put_index(ctx, si, ec->value, sid, weight);
4174  } else {
4175  scan_info_put_index(ctx, si, index, sid, weight);
4176  }
4177  }
4178  break;
4179  case GRN_COLUMN_FIX_SIZE :
4180  case GRN_COLUMN_VAR_SIZE :
4181  if (grn_column_index(ctx, ec->value, c->op, &index, 1, &sid)) {
4182  scan_info_put_index(ctx, si, index, sid, get_weight(ctx, ec));
4183  }
4184  break;
4185  case GRN_COLUMN_INDEX :
4186  sid = 0;
4187  index = ec->value;
4188  if (j > 2 &&
4189  ec[1].value &&
4190  ec[1].value->header.domain == GRN_DB_UINT32 &&
4191  ec[2].op == GRN_OP_GET_MEMBER) {
4192  sid = GRN_UINT32_VALUE(ec[1].value) + 1;
4193  j -= 2;
4194  ec += 2;
4195  }
4196  scan_info_put_index(ctx, si, index, sid, get_weight(ctx, ec));
4197  break;
4198  }
4199  }
4200  }
4201  } else if (GRN_DB_OBJP(*p)) {
4202  if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) {
4203  scan_info_put_index(ctx, si, index, sid, 1);
4204  }
4205  } else if (GRN_ACCESSORP(*p)) {
4206  si->flags |= SCAN_ACCESSOR;
4207  if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) {
4208  if (((grn_accessor *)(*p))->next) {
4209  scan_info_put_index(ctx, si, *p, sid, 1);
4210  } else {
4211  scan_info_put_index(ctx, si, index, sid, 1);
4212  }
4213  }
4214  } else {
4215  si->query = *p;
4216  }
4217  }
4218  }
4219  si = NULL;
4220  break;
4221  case GRN_OP_AND :
4222  case GRN_OP_OR :
4223  case GRN_OP_AND_NOT :
4224  case GRN_OP_ADJUST :
4225  if (!put_logical_op(ctx, sis, &i, c->op, c - e->codes)) { return NULL; }
4226  stat = SCAN_START;
4227  break;
4228  case GRN_OP_PUSH :
4229  if (!si) { SI_ALLOC(si, i, c - e->codes); }
4230  if (c->value == var) {
4231  stat = SCAN_VAR;
4232  } else {
4233  if (si->nargs < 8) {
4234  si->args[si->nargs++] = c->value;
4235  }
4236  if (stat == SCAN_START) { si->flags |= SCAN_PRE_CONST; }
4237  stat = SCAN_CONST;
4238  }
4239  break;
4240  case GRN_OP_GET_VALUE :
4241  switch (stat) {
4242  case SCAN_START :
4243  if (!si) { SI_ALLOC(si, i, c - e->codes); }
4244  // fallthru
4245  case SCAN_CONST :
4246  case SCAN_VAR :
4247  stat = SCAN_COL1;
4248  if (si->nargs < 8) {
4249  si->args[si->nargs++] = c->value;
4250  }
4251  break;
4252  case SCAN_COL1 :
4253  {
4254  int j;
4255  grn_obj inspected;
4256  GRN_TEXT_INIT(&inspected, 0);
4257  GRN_TEXT_PUTS(ctx, &inspected, "<");
4258  grn_inspect_name(ctx, &inspected, c->value);
4259  GRN_TEXT_PUTS(ctx, &inspected, ">: <");
4260  grn_inspect(ctx, &inspected, expr);
4261  GRN_TEXT_PUTS(ctx, &inspected, ">");
4263  "invalid expression: can't use column as a value: %.*s",
4264  (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected));
4265  GRN_OBJ_FIN(ctx, &inspected);
4266  for (j = 0; j < i; j++) { SI_FREE(sis[j]); }
4267  GRN_FREE(sis);
4268  return NULL;
4269  }
4270  stat = SCAN_COL2;
4271  break;
4272  case SCAN_COL2 :
4273  break;
4274  default :
4275  break;
4276  }
4277  break;
4278  case GRN_OP_CALL :
4279  if (!si) { SI_ALLOC(si, i, c - e->codes); }
4280  if ((c->flags & GRN_EXPR_CODE_RELATIONAL_EXPRESSION) || c + 1 == ce) {
4281  stat = SCAN_START;
4282  si->op = c->op;
4283  si->end = c - e->codes;
4284  sis[i++] = si;
4285  /* better index resolving framework for functions should be implemented */
4286  {
4287  int sid;
4288  grn_obj *index, **p = si->args, **pe = si->args + si->nargs;
4289  for (; p < pe; p++) {
4290  if (GRN_DB_OBJP(*p)) {
4291  if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) {
4292  scan_info_put_index(ctx, si, index, sid, 1);
4293  }
4294  } else if (GRN_ACCESSORP(*p)) {
4295  si->flags |= SCAN_ACCESSOR;
4296  if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) {
4297  scan_info_put_index(ctx, si, index, sid, 1);
4298  }
4299  } else {
4300  si->query = *p;
4301  }
4302  }
4303  }
4304  si = NULL;
4305  } else {
4306  stat = SCAN_COL2;
4307  }
4308  break;
4309  default :
4310  break;
4311  }
4312  }
4313  if (op == GRN_OP_OR && !size) {
4314  // for debug
4315  if (!(sis[0]->flags & SCAN_PUSH) || (sis[0]->logical_op != op)) {
4316  int j;
4317  ERR(GRN_INVALID_ARGUMENT, "invalid expr");
4318  for (j = 0; j < i; j++) { SI_FREE(sis[j]); }
4319  GRN_FREE(sis);
4320  return NULL;
4321  } else {
4322  sis[0]->flags &= ~SCAN_PUSH;
4323  sis[0]->logical_op = op;
4324  }
4325  } else {
4326  if (!put_logical_op(ctx, sis, &i, op, c - e->codes)) { return NULL; }
4327  }
4328  *n = i;
4329  return sis;
4330 }
4331 
4332 static void
4333 grn_table_select_(grn_ctx *ctx, grn_obj *table, grn_obj *expr, grn_obj *v,
4334  grn_obj *res, grn_operator op)
4335 {
4336  int32_t score;
4337  grn_id id, *idp;
4338  grn_table_cursor *tc;
4339  grn_hash_cursor *hc;
4340  grn_hash *s = (grn_hash *)res;
4341  grn_obj *r;
4342  GRN_RECORD_INIT(v, 0, grn_obj_id(ctx, table));
4343  switch (op) {
4344  case GRN_OP_OR :
4345  if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) {
4346  while ((id = grn_table_cursor_next(ctx, tc))) {
4347  GRN_RECORD_SET(ctx, v, id);
4348  r = grn_expr_exec(ctx, expr, 0);
4349  if (r && (score = GRN_UINT32_VALUE(r))) {
4350  grn_rset_recinfo *ri;
4351  if (grn_hash_add(ctx, s, &id, s->key_size, (void **)&ri, NULL)) {
4352  grn_table_add_subrec(res, ri, score, (grn_rset_posinfo *)&id, 1);
4353  }
4354  }
4355  }
4356  grn_table_cursor_close(ctx, tc);
4357  }
4358  break;
4359  case GRN_OP_AND :
4360  if ((hc = grn_hash_cursor_open(ctx, s, NULL, 0, NULL, 0, 0, -1, 0))) {
4361  while (grn_hash_cursor_next(ctx, hc)) {
4362  grn_hash_cursor_get_key(ctx, hc, (void **) &idp);
4363  GRN_RECORD_SET(ctx, v, *idp);
4364  r = grn_expr_exec(ctx, expr, 0);
4365  if (r && (score = GRN_UINT32_VALUE(r))) {
4366  grn_rset_recinfo *ri;
4367  grn_hash_cursor_get_value(ctx, hc, (void **) &ri);
4368  grn_table_add_subrec(res, ri, score, (grn_rset_posinfo *)idp, 1);
4369  } else {
4370  grn_hash_cursor_delete(ctx, hc, NULL);
4371  }
4372  }
4373  grn_hash_cursor_close(ctx, hc);
4374  }
4375  break;
4376  case GRN_OP_AND_NOT :
4377  if ((hc = grn_hash_cursor_open(ctx, s, NULL, 0, NULL, 0, 0, -1, 0))) {
4378  while (grn_hash_cursor_next(ctx, hc)) {
4379  grn_hash_cursor_get_key(ctx, hc, (void **) &idp);
4380  GRN_RECORD_SET(ctx, v, *idp);
4381  r = grn_expr_exec(ctx, expr, 0);
4382  if (r && (score = GRN_UINT32_VALUE(r))) {
4383  grn_hash_cursor_delete(ctx, hc, NULL);
4384  }
4385  }
4386  grn_hash_cursor_close(ctx, hc);
4387  }
4388  break;
4389  case GRN_OP_ADJUST :
4390  if ((hc = grn_hash_cursor_open(ctx, s, NULL, 0, NULL, 0, 0, -1, 0))) {
4391  while (grn_hash_cursor_next(ctx, hc)) {
4392  grn_hash_cursor_get_key(ctx, hc, (void **) &idp);
4393  GRN_RECORD_SET(ctx, v, *idp);
4394  r = grn_expr_exec(ctx, expr, 0);
4395  if (r && (score = GRN_UINT32_VALUE(r))) {
4396  grn_rset_recinfo *ri;
4397  grn_hash_cursor_get_value(ctx, hc, (void **) &ri);
4398  grn_table_add_subrec(res, ri, score, (grn_rset_posinfo *)idp, 1);
4399  }
4400  }
4401  grn_hash_cursor_close(ctx, hc);
4402  }
4403  break;
4404  default :
4405  break;
4406  }
4407 }
4408 
4409 static inline grn_bool
4410 grn_table_select_index_range_column(grn_ctx *ctx, grn_obj *table,
4411  grn_obj *index,
4412  scan_info *si, grn_operator logical_op,
4413  grn_obj *res)
4414 {
4415  grn_bool processed = GRN_FALSE;
4416  grn_obj *index_table;
4417  grn_obj range;
4418 
4419  index_table = grn_ctx_at(ctx, index->header.domain);
4420  if (!index_table) {
4421  return GRN_FALSE;
4422  }
4423 
4424  GRN_OBJ_INIT(&range, GRN_BULK, 0, index_table->header.domain);
4425  if (grn_obj_cast(ctx, si->query, &range, GRN_FALSE) == GRN_SUCCESS) {
4426  grn_table_cursor *cursor;
4427  const void *min = NULL, *max = NULL;
4428  unsigned int min_size = 0, max_size = 0;
4429  int offset = 0;
4430  int limit = -1;
4431  int flags = GRN_CURSOR_ASCENDING;
4432 
4433  switch (si->op) {
4434  case GRN_OP_LESS :
4435  flags |= GRN_CURSOR_LT;
4436  max = GRN_BULK_HEAD(&range);
4437  max_size = GRN_BULK_VSIZE(&range);
4438  break;
4439  case GRN_OP_GREATER :
4440  flags |= GRN_CURSOR_GT;
4441  min = GRN_BULK_HEAD(&range);
4442  min_size = GRN_BULK_VSIZE(&range);
4443  break;
4444  case GRN_OP_LESS_EQUAL :
4445  flags |= GRN_CURSOR_LE;
4446  max = GRN_BULK_HEAD(&range);
4447  max_size = GRN_BULK_VSIZE(&range);
4448  break;
4449  case GRN_OP_GREATER_EQUAL :
4450  flags |= GRN_CURSOR_GE;
4451  min = GRN_BULK_HEAD(&range);
4452  min_size = GRN_BULK_VSIZE(&range);
4453  break;
4454  default :
4455  break;
4456  }
4457  cursor = grn_table_cursor_open(ctx, index_table,
4458  min, min_size, max, max_size,
4459  offset, limit, flags);
4460  if (cursor) {
4461  grn_id index_id;
4462  while ((index_id = grn_table_cursor_next(ctx, cursor))) {
4463  grn_ii_at(ctx, (grn_ii *)index, index_id,
4464  (grn_hash *)res, logical_op);
4465  }
4466  grn_table_cursor_close(ctx, cursor);
4467  processed = GRN_TRUE;
4468  }
4469 
4470  grn_ii_resolve_sel_and(ctx, (grn_hash *)res, logical_op);
4471  }
4472  GRN_OBJ_FIN(ctx, &range);
4473 
4474  grn_obj_unlink(ctx, index_table);
4475 
4476  return processed;
4477 }
4478 
4479 static inline grn_bool
4480 grn_table_select_index_range_accessor(grn_ctx *ctx, grn_obj *table,
4481  grn_obj *accessor_stack,
4482  scan_info *si, grn_obj *res)
4483 {
4484  int n_accessors;
4485  grn_obj *current_res = NULL;
4486 
4487  n_accessors = GRN_BULK_VSIZE(accessor_stack) / sizeof(grn_obj *);
4488 
4489  {
4490  grn_accessor *last_accessor;
4491  grn_obj *target;
4492  grn_obj *index;
4493  grn_obj *range;
4494 
4495  last_accessor = (grn_accessor *)GRN_PTR_VALUE_AT(accessor_stack,
4496  n_accessors - 1);
4497  target = last_accessor->obj;
4498  if (grn_column_index(ctx, target, si->op, &index, 1, NULL) == 0) {
4499  return GRN_FALSE;
4500  }
4501 
4502  range = grn_ctx_at(ctx, DB_OBJ(index)->range);
4503  current_res = grn_table_create(ctx, NULL, 0, NULL,
4505  range,
4506  NULL);
4507  grn_obj_unlink(ctx, range);
4508  if (!current_res) {
4509  return GRN_FALSE;
4510  }
4511  if (!grn_table_select_index_range_column(ctx, table, index, si, GRN_OP_OR,
4512  current_res)) {
4513  grn_obj_unlink(ctx, current_res);
4514  return GRN_FALSE;
4515  }
4516  }
4517 
4518  {
4519  int i;
4520 
4521  for (i = n_accessors - 1; i > 0; i--) {
4522  grn_rc rc = GRN_SUCCESS;
4523  grn_accessor *accessor;
4524  grn_obj *index;
4525  grn_obj *domain;
4526  grn_obj *target;
4527  grn_obj *next_res;
4528  grn_operator next_op;
4529  grn_id *next_record_id = NULL;
4530 
4531  accessor = (grn_accessor *)GRN_PTR_VALUE_AT(accessor_stack, i - 1);
4532  target = accessor->obj;
4533  if (grn_column_index(ctx, target, GRN_OP_EQUAL, &index, 1, NULL) == 0) {
4534  grn_obj_unlink(ctx, current_res);
4535  current_res = NULL;
4536  break;
4537  }
4538 
4539  {
4540  grn_obj *range;
4541  range = grn_ctx_at(ctx, DB_OBJ(index)->range);
4542  next_res = grn_table_create(ctx, NULL, 0, NULL,
4544  range,
4545  NULL);
4546  grn_obj_unlink(ctx, range);
4547  if (!next_res) {
4548  grn_obj_unlink(ctx, current_res);
4549  current_res = NULL;
4550  break;
4551  }
4552  next_op = GRN_OP_OR;
4553  }
4554 
4555  domain = grn_ctx_at(ctx, index->header.domain);
4556  GRN_HASH_EACH(ctx, (grn_hash *)current_res, id, &next_record_id,
4557  NULL, NULL, {
4558  if (domain->header.type == GRN_TABLE_NO_KEY) {
4559  rc = grn_ii_sel(ctx, (grn_ii *)index,
4560  (const char *)next_record_id, sizeof(grn_id),
4561  (grn_hash *)next_res, next_op, NULL);
4562  } else {
4563  char key[GRN_TABLE_MAX_KEY_SIZE];
4564  int key_len;
4565  key_len = grn_table_get_key(ctx, domain, *next_record_id,
4566  key, GRN_TABLE_MAX_KEY_SIZE);
4567  rc = grn_ii_sel(ctx, (grn_ii *)index, key, key_len,
4568  (grn_hash *)next_res, next_op, NULL);
4569  }
4570  if (rc != GRN_SUCCESS) {
4571  break;
4572  }
4573  });
4574  grn_obj_unlink(ctx, domain);
4575  grn_obj_unlink(ctx, current_res);
4576 
4577  if (rc == GRN_SUCCESS) {
4578  if (i == 1) {
4579  grn_table_setoperation(ctx, res, next_res, res, si->logical_op);
4580  grn_obj_unlink(ctx, next_res);
4581  current_res = res;
4582  } else {
4583  current_res = next_res;
4584  }
4585  } else {
4586  if (res != next_res) {
4587  grn_obj_unlink(ctx, next_res);
4588  }
4589  current_res = NULL;
4590  break;
4591  }
4592  }
4593  }
4594 
4595  return current_res == res;
4596 }
4597 
4598 static inline grn_bool
4599 grn_table_select_index_range(grn_ctx *ctx, grn_obj *table, grn_obj *index,
4600  scan_info *si, grn_obj *res)
4601 {
4602  if (si->flags & SCAN_ACCESSOR) {
4603  grn_bool processed;
4604  grn_accessor *accessor = (grn_accessor *)index;
4605  grn_accessor *a;
4606  grn_obj accessor_stack;
4607 
4608  if (index->header.type != GRN_ACCESSOR) {
4609  return GRN_FALSE;
4610  }
4611 
4612  GRN_PTR_INIT(&accessor_stack, GRN_OBJ_VECTOR, GRN_ID_NIL);
4613  for (a = accessor; a; a = a->next) {
4614  GRN_PTR_PUT(ctx, &accessor_stack, a);
4615  }
4616  processed = grn_table_select_index_range_accessor(ctx, table,
4617  &accessor_stack,
4618  si, res);
4619  GRN_OBJ_FIN(ctx, &accessor_stack);
4620  return processed;
4621  } else {
4622  return grn_table_select_index_range_column(ctx, table, index, si,
4623  si->logical_op, res);
4624  }
4625 }
4626 
4627 static inline grn_bool
4628 grn_table_select_index(grn_ctx *ctx, grn_obj *table, scan_info *si,
4629  grn_obj *res)
4630 {
4631  grn_bool processed = GRN_FALSE;
4632  if (GRN_BULK_VSIZE(&si->index)) {
4633  grn_obj *index = GRN_PTR_VALUE(&si->index);
4634  switch (si->op) {
4635  case GRN_OP_EQUAL :
4636  if (si->flags & SCAN_ACCESSOR) {
4637  if (index->header.type == GRN_ACCESSOR &&
4638  !((grn_accessor *)index)->next) {
4639  grn_obj dest;
4640  grn_accessor *a = (grn_accessor *)index;
4641  grn_rset_posinfo pi;
4642  switch (a->action) {
4643  case GRN_ACCESSOR_GET_ID :
4644  GRN_UINT32_INIT(&dest, 0);
4645  if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) {
4646  memcpy(&pi, GRN_BULK_HEAD(&dest), GRN_BULK_VSIZE(&dest));
4647  if (pi.rid) {
4648  if (pi.rid == grn_table_at(ctx, table, pi.rid)) {
4649  res_add(ctx, (grn_hash *)res, &pi, 1, si->logical_op);
4650  }
4651  }
4652  processed = GRN_TRUE;
4653  }
4654  grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op);
4655  GRN_OBJ_FIN(ctx, &dest);
4656  break;
4657  case GRN_ACCESSOR_GET_KEY :
4658  GRN_OBJ_INIT(&dest, GRN_BULK, 0, table->header.domain);
4659  if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) {
4660  if ((pi.rid = grn_table_get(ctx, table,
4661  GRN_BULK_HEAD(&dest),
4662  GRN_BULK_VSIZE(&dest)))) {
4663  res_add(ctx, (grn_hash *)res, &pi, 1, si->logical_op);
4664  }
4665  processed = GRN_TRUE;
4666  }
4667  grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op);
4668  GRN_OBJ_FIN(ctx, &dest);
4669  break;
4670  }
4671  }
4672  } else {
4673  grn_obj *domain = grn_ctx_at(ctx, index->header.domain);
4674  if (domain) {
4675  grn_id tid;
4676  if (GRN_OBJ_GET_DOMAIN(si->query) == DB_OBJ(domain)->id) {
4677  tid = GRN_RECORD_VALUE(si->query);
4678  } else {
4679  tid = grn_table_get(ctx, domain,
4680  GRN_BULK_HEAD(si->query),
4681  GRN_BULK_VSIZE(si->query));
4682  }
4683  grn_ii_at(ctx, (grn_ii *)index, tid, (grn_hash *)res, si->logical_op);
4684  }
4685  grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op);
4686  processed = GRN_TRUE;
4687  }
4688  break;
4689  case GRN_OP_SUFFIX :
4690  {
4691  grn_obj *domain;
4692  if (si->flags & SCAN_ACCESSOR) {
4693  domain = table;
4694  } else {
4695  domain = grn_ctx_at(ctx, index->header.domain);
4696  }
4697  if (domain->header.type != GRN_TABLE_PAT_KEY) {
4698  break;
4699  }
4700  if (!(domain->header.flags & GRN_OBJ_KEY_WITH_SIS)) {
4701  break;
4702  }
4703  }
4704  /* fallthru */
4705  case GRN_OP_PREFIX :
4706  if (si->flags & SCAN_ACCESSOR) {
4707  if (index->header.type == GRN_ACCESSOR &&
4708  !((grn_accessor *)index)->next) {
4709  grn_obj dest;
4710  grn_accessor *a = (grn_accessor *)index;
4711  grn_rset_posinfo pi;
4712  switch (a->action) {
4713  case GRN_ACCESSOR_GET_ID :
4714  /* todo */
4715  break;
4716  case GRN_ACCESSOR_GET_KEY :
4717  GRN_OBJ_INIT(&dest, GRN_BULK, 0, table->header.domain);
4718  if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) {
4719  grn_hash *pres;
4720  if ((pres = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
4722  grn_id *key;
4723  grn_table_search(ctx, table,
4724  GRN_BULK_HEAD(&dest), GRN_BULK_VSIZE(&dest),
4725  si->op, (grn_obj *)pres, GRN_OP_OR);
4726  GRN_HASH_EACH(ctx, pres, id, &key, NULL, NULL, {
4727  pi.rid = *key;
4728  res_add(ctx, (grn_hash *)res, &pi, 1, si->logical_op);
4729  });
4730  grn_hash_close(ctx, pres);
4731  }
4732  processed = GRN_TRUE;
4733  }
4734  grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op);
4735  GRN_OBJ_FIN(ctx, &dest);
4736  break;
4737  }
4738  }
4739  } else {
4740  grn_obj *i = GRN_PTR_VALUE(&si->index);
4741  grn_obj *domain = grn_ctx_at(ctx, i->header.domain);
4742  if (domain) {
4743  grn_hash *pres;
4744  if ((pres = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
4746  grn_id *key;
4747  grn_table_search(ctx, domain,
4748  GRN_BULK_HEAD(si->query),
4749  GRN_BULK_VSIZE(si->query),
4750  si->op, (grn_obj *)pres, GRN_OP_OR);
4751  grn_obj_unlink(ctx, domain);
4752  GRN_HASH_EACH(ctx, pres, id, &key, NULL, NULL, {
4753  grn_ii_at(ctx, (grn_ii *)index, *key, (grn_hash *)res, si->logical_op);
4754  });
4755  grn_hash_close(ctx, pres);
4756  }
4757  grn_obj_unlink(ctx, domain);
4758  }
4759  grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op);
4760  processed = GRN_TRUE;
4761  }
4762  break;
4763  case GRN_OP_MATCH :
4764  case GRN_OP_NEAR :
4765  case GRN_OP_NEAR2 :
4766  case GRN_OP_SIMILAR :
4767  {
4768  grn_obj wv, **ip = &GRN_PTR_VALUE(&si->index);
4769  int j = GRN_BULK_VSIZE(&si->index)/sizeof(grn_obj *);
4770  int32_t *wp = &GRN_INT32_VALUE(&si->wv);
4771  grn_search_optarg optarg;
4773  if (si->op == GRN_OP_MATCH) {
4774  optarg.mode = GRN_OP_EXACT;
4775  } else {
4776  optarg.mode = si->op;
4777  }
4778  optarg.similarity_threshold = 0;
4779  switch (si->op) {
4780  case GRN_OP_NEAR :
4781  case GRN_OP_NEAR2 :
4782 #define DEFAULT_NEAR_MAX_INTERVAL 10
4784 #undef DEFAULT_NEAR_MAX_INTERVAL
4785  break;
4786  default :
4787  optarg.max_interval = 0;
4788  break;
4789  }
4790  optarg.weight_vector = (int *)GRN_BULK_HEAD(&wv);
4791  /* optarg.vector_size = GRN_BULK_VSIZE(&si->wv); */
4792  optarg.vector_size = 1;
4793  optarg.proc = NULL;
4794  optarg.max_size = 0;
4796  for (; j--; ip++, wp += 2) {
4797  uint32_t sid = (uint32_t) wp[0];
4798  int32_t weight = wp[1];
4799  if (sid) {
4800  int weight_index = sid - 1;
4801  GRN_INT32_SET_AT(ctx, &wv, weight_index, weight);
4802  optarg.weight_vector = &GRN_INT32_VALUE(&wv);
4803  optarg.vector_size = GRN_BULK_VSIZE(&wv)/sizeof(int32_t);
4804  } else {
4805  optarg.weight_vector = NULL;
4806  optarg.vector_size = weight;
4807  }
4808  if (j) {
4809  if (sid && ip[0] == ip[1]) { continue; }
4810  } else {
4812  }
4813  grn_obj_search(ctx, ip[0], si->query, res, si->logical_op, &optarg);
4814  if (optarg.weight_vector) {
4815  int i;
4816  for (i = 0; i < optarg.vector_size; i++) {
4817  optarg.weight_vector[i] = 0;
4818  }
4819  }
4820  GRN_BULK_REWIND(&wv);
4821  }
4822  GRN_OBJ_FIN(ctx, &wv);
4823  }
4824  processed = GRN_TRUE;
4825  break;
4826  case GRN_OP_TERM_EXTRACT :
4827  if (si->flags & SCAN_ACCESSOR) {
4828  if (index->header.type == GRN_ACCESSOR &&
4829  !((grn_accessor *)index)->next) {
4830  grn_accessor *a = (grn_accessor *)index;
4831  switch (a->action) {
4832  case GRN_ACCESSOR_GET_KEY :
4833  grn_table_search(ctx, table,
4835  GRN_OP_TERM_EXTRACT, res, si->logical_op);
4836  processed = GRN_TRUE;
4837  break;
4838  }
4839  }
4840  }
4841  break;
4842  case GRN_OP_CALL :
4843  if (selector_proc_p(si->args[0])) {
4844  grn_rc rc;
4845  grn_proc *proc = (grn_proc *)(si->args[0]);
4846  rc = proc->selector(ctx, table, index, si->nargs, si->args,
4847  res, si->logical_op);
4848  if (rc) {
4849  /* TODO: report error */
4850  } else {
4851  processed = GRN_TRUE;
4852  }
4853  }
4854  break;
4855  case GRN_OP_LESS :
4856  case GRN_OP_GREATER :
4857  case GRN_OP_LESS_EQUAL :
4858  case GRN_OP_GREATER_EQUAL :
4859  processed = grn_table_select_index_range(ctx, table, index, si, res);
4860  break;
4861  default :
4862  /* todo : implement */
4863  /* todo : handle SCAN_PRE_CONST */
4864  break;
4865  }
4866  } else {
4867  switch (si->op) {
4868  case GRN_OP_CALL :
4869  if (selector_proc_p(si->args[0])) {
4870  grn_rc rc;
4871  grn_proc *proc = (grn_proc *)(si->args[0]);
4872  rc = proc->selector(ctx, table, NULL, si->nargs, si->args,
4873  res, si->logical_op);
4874  if (rc) {
4875  /* TODO: report error */
4876  } else {
4877  processed = GRN_TRUE;
4878  }
4879  }
4880  default :
4881  break;
4882  }
4883  }
4884  return processed;
4885 }
4886 
4887 grn_obj *
4889  grn_obj *res, grn_operator op)
4890 {
4891  grn_obj *v;
4892  unsigned int res_size;
4893  grn_bool res_created = GRN_FALSE;
4894  if (res) {
4895  if (res->header.type != GRN_TABLE_HASH_KEY ||
4896  (res->header.domain != DB_OBJ(table)->id)) {
4897  ERR(GRN_INVALID_ARGUMENT, "hash table required");
4898  return NULL;
4899  }
4900  } else {
4901  if (!(res = grn_table_create(ctx, NULL, 0, NULL,
4902  GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, table, NULL))) {
4903  return NULL;
4904  }
4905  res_created = GRN_TRUE;
4906  }
4907  if (!(v = grn_expr_get_var_by_offset(ctx, expr, 0))) {
4908  ERR(GRN_INVALID_ARGUMENT, "at least one variable must be defined");
4909  return NULL;
4910  }
4911  GRN_API_ENTER;
4912  res_size = GRN_HASH_SIZE((grn_hash *)res);
4913  if (op == GRN_OP_OR || res_size) {
4914  int i, n;
4915  scan_info **sis;
4916  if ((sis = scan_info_build(ctx, expr, &n, op, res_size))) {
4917  grn_obj res_stack;
4918  grn_expr *e = (grn_expr *)expr;
4919  grn_expr_code *codes = e->codes;
4920  uint32_t codes_curr = e->codes_curr;
4921  GRN_PTR_INIT(&res_stack, GRN_OBJ_VECTOR, GRN_ID_NIL);
4922  for (i = 0; i < n; i++) {
4923  scan_info *si = sis[i];
4924  if (si->flags & SCAN_POP) {
4925  grn_obj *res_;
4926  GRN_PTR_POP(&res_stack, res_);
4927  grn_table_setoperation(ctx, res_, res, res_, si->logical_op);
4928  grn_obj_close(ctx, res);
4929  res = res_;
4930  } else {
4931  grn_bool processed = GRN_FALSE;
4932  if (si->flags & SCAN_PUSH) {
4933  grn_obj *res_ = NULL;
4934  res_ = grn_table_create(ctx, NULL, 0, NULL,
4936  if (!res_) {
4937  int i = 0;
4938  if (!res_created) { i++; }
4939  for (; i < GRN_BULK_VSIZE(&res_stack) / sizeof(grn_obj *); i++) {
4940  grn_obj *stacked_res;
4941  stacked_res = *((grn_obj **)GRN_BULK_HEAD(&res_stack) + i);
4942  grn_obj_close(ctx, stacked_res);
4943  }
4944  break;
4945  }
4946  GRN_PTR_PUT(ctx, &res_stack, res);
4947  res = res_;
4948  }
4949  processed = grn_table_select_index(ctx, table, si, res);
4950  if (!processed) {
4951  if (ctx->rc) { break; }
4952  e->codes = codes + si->start;
4953  e->codes_curr = si->end - si->start + 1;
4954  grn_table_select_(ctx, table, expr, v, res, si->logical_op);
4955  }
4956  }
4958  ":", "filter(%d)", grn_table_size(ctx, res));
4959  }
4960  for (i = 0; i < n; i++) {
4961  scan_info *si = sis[i];
4962  SI_FREE(si);
4963  }
4964  GRN_OBJ_FIN(ctx, &res_stack);
4965  GRN_FREE(sis);
4966  e->codes = codes;
4967  e->codes_curr = codes_curr;
4968  } else {
4969  if (!ctx->rc) {
4970  grn_table_select_(ctx, table, expr, v, res, op);
4971  }
4972  }
4973  }
4974  GRN_API_RETURN(res);
4975 }
4976 
4977 /* grn_expr_parse */
4978 
4979 grn_obj *
4980 grn_ptr_value_at(grn_obj *obj, int offset)
4981 {
4982  int size = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *);
4983  if (offset < 0) { offset = size + offset; }
4984  return (0 <= offset && offset < size)
4985  ? (((grn_obj **)GRN_BULK_HEAD(obj))[offset])
4986  : NULL;
4987 }
4988 
4989 int32_t
4990 grn_int32_value_at(grn_obj *obj, int offset)
4991 {
4992  int size = GRN_BULK_VSIZE(obj) / sizeof(int32_t);
4993  if (offset < 0) { offset = size + offset; }
4994  return (0 <= offset && offset < size)
4995  ? (((int32_t *)GRN_BULK_HEAD(obj))[offset])
4996  : 0;
4997 }
4998 
4999 /* grn_expr_create_from_str */
5000 
5001 #include "snip.h"
5002 
5003 #define DEFAULT_WEIGHT 5
5004 #define DEFAULT_DECAYSTEP 2
5005 #define DEFAULT_MAX_INTERVAL 10
5006 #define DEFAULT_SIMILARITY_THRESHOLD 10
5007 #define DEFAULT_TERM_EXTRACT_POLICY 0
5008 #define DEFAULT_WEIGHT_VECTOR_SIZE 4096
5009 
5010 typedef struct {
5014  const char *str;
5015  const char *cur;
5016  const char *str_end;
5034 } efs_info;
5035 
5036 typedef struct {
5038  int weight;
5039 } efs_op;
5040 
5041 inline static void
5042 skip_space(grn_ctx *ctx, efs_info *q)
5043 {
5044  unsigned int len;
5045  while (q->cur < q->str_end && grn_isspace(q->cur, ctx->encoding)) {
5046  /* null check and length check */
5047  if (!(len = grn_charlen(ctx, q->cur, q->str_end))) {
5048  q->cur = q->str_end;
5049  break;
5050  }
5051  q->cur += len;
5052  }
5053 }
5054 
5055 static grn_rc get_expr(grn_ctx *ctx, efs_info *q, grn_obj *column, grn_operator mode);
5056 static grn_rc get_token(grn_ctx *ctx, efs_info *q, efs_op *op, grn_obj *column, grn_operator mode);
5057 
5058 static grn_rc
5059 get_phrase(grn_ctx *ctx, efs_info *q, grn_obj *column, int mode, int option)
5060 {
5061  const char *start, *s;
5062  start = s = q->cur;
5063  GRN_BULK_REWIND(&q->buf);
5064  while (1) {
5065  unsigned int len;
5066  if (s >= q->str_end) {
5067  q->cur = s;
5068  break;
5069  }
5070  len = grn_charlen(ctx, s, q->str_end);
5071  if (len == 0) {
5072  /* invalid string containing malformed multibyte char */
5073  return GRN_END_OF_DATA;
5074  } else if (len == 1) {
5075  if (*s == GRN_QUERY_QUOTER) {
5076  q->cur = s + 1;
5077  break;
5078  } else if (*s == GRN_QUERY_ESCAPE && s + 1 < q->str_end) {
5079  s++;
5080  len = grn_charlen(ctx, s, q->str_end);
5081  }
5082  }
5083  GRN_TEXT_PUT(ctx, &q->buf, s, len);
5084  s += len;
5085  }
5086  grn_expr_append_obj(ctx, q->e, q->v, GRN_OP_PUSH, 1);
5087  grn_expr_append_const(ctx, q->e, column, GRN_OP_PUSH, 1);
5088  grn_expr_append_op(ctx, q->e, GRN_OP_GET_VALUE, 2);
5089  grn_expr_append_const(ctx, q->e, &q->buf, GRN_OP_PUSH, 1);
5090  if (mode == GRN_OP_MATCH || mode == GRN_OP_EXACT) {
5091  grn_expr_append_op(ctx, q->e, mode, 2);
5092  } else {
5093  grn_expr_append_const_int(ctx, q->e, option, GRN_OP_PUSH, 1);
5094  grn_expr_append_op(ctx, q->e, mode, 3);
5095  }
5096  return GRN_SUCCESS;
5097 }
5098 
5099 static grn_rc
5100 get_geocond(grn_ctx *ctx, efs_info *q, grn_obj *longitude, grn_obj *latitude)
5101 {
5102  unsigned int len;
5103  const char *start = q->cur, *end;
5104  for (end = q->cur;; ) {
5105  /* null check and length check */
5106  if (!(len = grn_charlen(ctx, end, q->str_end))) {
5107  q->cur = q->str_end;
5108  break;
5109  }
5110  if (grn_isspace(end, ctx->encoding) ||
5111  *end == GRN_QUERY_PARENR) {
5112  q->cur = end;
5113  break;
5114  }
5115  }
5116  {
5117  const char *tokbuf[8];
5118  int32_t lng0, lat0, lng1, lat1, lng2, lat2, r;
5119  int32_t n = grn_str_tok((char *)start, end - start, ',', tokbuf, 8, NULL);
5120  switch (n) {
5121  case 3 :
5122  lng0 = grn_atoi(start, tokbuf[0], NULL);
5123  lat0 = grn_atoi(tokbuf[0] + 1, tokbuf[1], NULL);
5124  r = grn_atoi(tokbuf[1] + 1, tokbuf[2], NULL);
5125  grn_expr_append_obj(ctx, q->e, q->v, GRN_OP_PUSH, 1);
5126  grn_expr_append_const(ctx, q->e, longitude, GRN_OP_PUSH, 1);
5127  grn_expr_append_op(ctx, q->e, GRN_OP_GET_VALUE, 2);
5128  grn_expr_append_obj(ctx, q->e, q->v, GRN_OP_PUSH, 1);
5129  grn_expr_append_const(ctx, q->e, latitude, GRN_OP_PUSH, 1);
5130  grn_expr_append_op(ctx, q->e, GRN_OP_GET_VALUE, 2);
5131  grn_expr_append_const_int(ctx, q->e, lng0, GRN_OP_PUSH, 1);
5132  grn_expr_append_const_int(ctx, q->e, lat0, GRN_OP_PUSH, 1);
5133  grn_expr_append_const_int(ctx, q->e, r, GRN_OP_PUSH, 1);
5135  break;
5136  case 4 :
5137  lng0 = grn_atoi(start, tokbuf[0], NULL);
5138  lat0 = grn_atoi(tokbuf[0] + 1, tokbuf[1], NULL);
5139  lng1 = grn_atoi(tokbuf[1] + 1, tokbuf[2], NULL);
5140  lat1 = grn_atoi(tokbuf[2] + 1, tokbuf[3], NULL);
5141  grn_expr_append_obj(ctx, q->e, q->v, GRN_OP_PUSH, 1);
5142  grn_expr_append_const(ctx, q->e, longitude, GRN_OP_PUSH, 1);
5143  grn_expr_append_op(ctx, q->e, GRN_OP_GET_VALUE, 2);
5144  grn_expr_append_obj(ctx, q->e, q->v, GRN_OP_PUSH, 1);
5145  grn_expr_append_const(ctx, q->e, latitude, GRN_OP_PUSH, 1);
5146  grn_expr_append_op(ctx, q->e, GRN_OP_GET_VALUE, 2);
5147  grn_expr_append_const_int(ctx, q->e, lng0, GRN_OP_PUSH, 1);
5148  grn_expr_append_const_int(ctx, q->e, lat0, GRN_OP_PUSH, 1);
5149  grn_expr_append_const_int(ctx, q->e, lng1, GRN_OP_PUSH, 1);
5150  grn_expr_append_const_int(ctx, q->e, lat1, GRN_OP_PUSH, 1);
5152  break;
5153  case 6 :
5154  lng0 = grn_atoi(start, tokbuf[0], NULL);
5155  lat0 = grn_atoi(tokbuf[0] + 1, tokbuf[1], NULL);
5156  lng1 = grn_atoi(tokbuf[1] + 1, tokbuf[2], NULL);
5157  lat1 = grn_atoi(tokbuf[2] + 1, tokbuf[3], NULL);
5158  lng2 = grn_atoi(tokbuf[3] + 1, tokbuf[4], NULL);
5159  lat2 = grn_atoi(tokbuf[4] + 1, tokbuf[5], NULL);
5160  grn_expr_append_obj(ctx, q->e, q->v, GRN_OP_PUSH, 1);
5161  grn_expr_append_const(ctx, q->e, longitude, GRN_OP_PUSH, 1);
5162  grn_expr_append_op(ctx, q->e, GRN_OP_GET_VALUE, 2);
5163  grn_expr_append_obj(ctx, q->e, q->v, GRN_OP_PUSH, 1);
5164  grn_expr_append_const(ctx, q->e, latitude, GRN_OP_PUSH, 1);
5165  grn_expr_append_op(ctx, q->e, GRN_OP_GET_VALUE, 2);
5166  grn_expr_append_const_int(ctx, q->e, lng0, GRN_OP_PUSH, 1);
5167  grn_expr_append_const_int(ctx, q->e, lat0, GRN_OP_PUSH, 1);
5168  grn_expr_append_const_int(ctx, q->e, lng1, GRN_OP_PUSH, 1);
5169  grn_expr_append_const_int(ctx, q->e, lat1, GRN_OP_PUSH, 1);
5170  grn_expr_append_const_int(ctx, q->e, lng2, GRN_OP_PUSH, 1);
5171  grn_expr_append_const_int(ctx, q->e, lat2, GRN_OP_PUSH, 1);
5173  break;
5174  default :
5175  ERR(GRN_INVALID_ARGUMENT, "invalid geocond");
5176  break;
5177  }
5178  }
5179  return ctx->rc;
5180 }
5181 
5182 static grn_rc
5183 get_word(grn_ctx *ctx, efs_info *q, grn_obj *column, int mode, int option)
5184 {
5185  const char *start = q->cur, *end;
5186  unsigned int len;
5187  for (end = q->cur;; ) {
5188  /* null check and length check */
5189  if (!(len = grn_charlen(ctx, end, q->str_end))) {
5190  q->cur = q->str_end;
5191  break;
5192  }
5193  if (grn_isspace(end, ctx->encoding) ||
5194  *end == GRN_QUERY_PARENR) {
5195  q->cur = end;
5196  break;
5197  }
5198  if (*end == GRN_QUERY_COLUMN) {
5199  grn_obj *c = grn_obj_column(ctx, q->table, start, end - start);
5200  if (c && end + 1 < q->str_end) {
5201  efs_op op;
5202  switch (end[1]) {
5203  case '!' :
5204  mode = GRN_OP_NOT_EQUAL;
5205  q->cur = end + 2;
5206  break;
5207  case '=' :
5208  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
5209  mode = GRN_OP_ASSIGN;
5210  q->cur = end + 2;
5211  } else {
5212  get_token(ctx, q, &op, c, mode);
5213  }
5214  break;
5215  case '<' :
5216  if (end + 2 < q->str_end && end[2] == '=') {
5217  mode = GRN_OP_LESS_EQUAL;
5218  q->cur = end + 3;
5219  } else {
5220  mode = GRN_OP_LESS;
5221  q->cur = end + 2;
5222  }
5223  break;
5224  case '>' :
5225  if (end + 2 < q->str_end && end[2] == '=') {
5226  mode = GRN_OP_GREATER_EQUAL;
5227  q->cur = end + 3;
5228  } else {
5229  mode = GRN_OP_GREATER;
5230  q->cur = end + 2;
5231  }
5232  break;
5233  case '%' :
5234  mode = GRN_OP_MATCH;
5235  q->cur = end + 2;
5236  break;
5237  case '@' :
5238  q->cur = end + 2;
5239  return get_geocond(ctx, q, column, c);
5240  break;
5241  default :
5242  mode = GRN_OP_EQUAL;
5243  q->cur = end + 1;
5244  break;
5245  }
5246  return get_token(ctx, q, &op, c, mode);
5247  } else {
5248  ERR(GRN_INVALID_ARGUMENT, "column lookup failed");
5249  return ctx->rc;
5250  }
5251  } else if (*end == GRN_QUERY_PREFIX) {
5252  mode = GRN_OP_PREFIX;
5253  q->cur = end + 1;
5254  break;
5255  }
5256  end += len;
5257  }
5258  if (!column) {
5259  ERR(GRN_INVALID_ARGUMENT, "column missing");
5260  return ctx->rc;
5261  }
5262  if (mode == GRN_OP_ASSIGN) {
5263  grn_expr_append_obj(ctx, q->e, q->v, GRN_OP_PUSH, 1);
5264  grn_expr_append_const(ctx, q->e, column, GRN_OP_PUSH, 1);
5265  grn_expr_append_const_str(ctx, q->e, start, end - start, GRN_OP_PUSH, 1);
5266  grn_expr_append_op(ctx, q->e, GRN_OP_ASSIGN, 2);
5267  } else {
5268  grn_expr_append_obj(ctx, q->e, q->v, GRN_OP_PUSH, 1);
5269  grn_expr_append_const(ctx, q->e, column, GRN_OP_PUSH, 1);
5270  grn_expr_append_op(ctx, q->e, GRN_OP_GET_VALUE, 2);
5271  grn_expr_append_const_str(ctx, q->e, start, end - start, GRN_OP_PUSH, 1);
5272  switch (mode) {
5273  case GRN_OP_NEAR :
5274  case GRN_OP_NEAR2 :
5275  case GRN_OP_SIMILAR :
5276  case GRN_OP_TERM_EXTRACT :
5277  grn_expr_append_const_int(ctx, q->e, option, GRN_OP_PUSH, 1);
5278  grn_expr_append_op(ctx, q->e, mode, 3);
5279  break;
5280  default :
5281  grn_expr_append_op(ctx, q->e, mode, 2);
5282  break;
5283  }
5284  }
5285  return GRN_SUCCESS;
5286 }
5287 
5288 static void
5289 get_op(efs_info *q, efs_op *op, grn_operator *mode, int *option)
5290 {
5291  const char *start, *end = q->cur;
5292  switch (*end) {
5293  case 'S' :
5294  *mode = GRN_OP_SIMILAR;
5295  start = ++end;
5296  *option = grn_atoi(start, q->str_end, (const char **)&end);
5297  if (start == end) { *option = DEFAULT_SIMILARITY_THRESHOLD; }
5298  q->cur = end;
5299  break;
5300  case 'N' :
5301  *mode = GRN_OP_NEAR;
5302  start = ++end;
5303  *option = grn_atoi(start, q->str_end, (const char **)&end);
5304  if (start == end) { *option = DEFAULT_MAX_INTERVAL; }
5305  q->cur = end;
5306  break;
5307  case 'n' :
5308  *mode = GRN_OP_NEAR2;
5309  start = ++end;
5310  *option = grn_atoi(start, q->str_end, (const char **)&end);
5311  if (start == end) { *option = DEFAULT_MAX_INTERVAL; }
5312  q->cur = end;
5313  break;
5314  case 'T' :
5315  *mode = GRN_OP_TERM_EXTRACT;
5316  start = ++end;
5317  *option = grn_atoi(start, q->str_end, (const char **)&end);
5318  if (start == end) { *option = DEFAULT_TERM_EXTRACT_POLICY; }
5319  q->cur = end;
5320  break;
5321  case 'X' : /* force exact mode */
5322  op->op = GRN_OP_AND;
5323  *mode = GRN_OP_EXACT;
5324  *option = 0;
5325  start = ++end;
5326  q->cur = end;
5327  break;
5328  default :
5329  break;
5330  }
5331 }
5332 
5333 static grn_rc
5334 get_token(grn_ctx *ctx, efs_info *q, efs_op *op, grn_obj *column, grn_operator mode)
5335 {
5336  int option = 0;
5337  op->op = q->default_op;
5338  op->weight = DEFAULT_WEIGHT;
5339  for (;;) {
5340  skip_space(ctx, q);
5341  if (q->cur >= q->str_end) { return GRN_END_OF_DATA; }
5342  switch (*q->cur) {
5343  case '\0' :
5344  return GRN_END_OF_DATA;
5345  break;
5346  case GRN_QUERY_PARENR :
5347  q->cur++;
5348  return GRN_END_OF_DATA;
5349  break;
5350  case GRN_QUERY_QUOTEL :
5351  q->cur++;
5352  return get_phrase(ctx, q, column, mode, option);
5353  break;
5354  case GRN_QUERY_PREFIX :
5355  q->cur++;
5356  get_op(q, op, &mode, &option);
5357  break;
5358  case GRN_QUERY_AND :
5359  q->cur++;
5360  op->op = GRN_OP_AND;
5361  break;
5362  case GRN_QUERY_AND_NOT :
5363  q->cur++;
5364  op->op = GRN_OP_AND_NOT;
5365  break;
5366  case GRN_QUERY_ADJ_INC :
5367  q->cur++;
5368  if (op->weight < 127) { op->weight++; }
5369  op->op = GRN_OP_ADJUST;
5370  break;
5371  case GRN_QUERY_ADJ_DEC :
5372  q->cur++;
5373  if (op->weight > -128) { op->weight--; }
5374  op->op = GRN_OP_ADJUST;
5375  break;
5376  case GRN_QUERY_ADJ_NEG :
5377  q->cur++;
5378  op->op = GRN_OP_ADJUST;
5379  op->weight = -1;
5380  break;
5381  case GRN_QUERY_PARENL :
5382  q->cur++;
5383  return get_expr(ctx, q, column, mode);
5384  break;
5385  case 'O' :
5386  if (q->cur[1] == 'R' && q->cur[2] == ' ') {
5387  q->cur += 2;
5388  op->op = GRN_OP_OR;
5389  break;
5390  }
5391  /* fallthru */
5392  default :
5393  return get_word(ctx, q, column, mode, option);
5394  break;
5395  }
5396  }
5397  return GRN_SUCCESS;
5398 }
5399 
5400 static grn_rc
5401 get_expr(grn_ctx *ctx, efs_info *q, grn_obj *column, grn_operator mode)
5402 {
5403  efs_op op;
5404  grn_rc rc = get_token(ctx, q, &op, column, mode);
5405  if (rc) { return rc; }
5406  while (!(rc = get_token(ctx, q, &op, column, mode))) {
5407  if (op.op == GRN_OP_ADJUST) {
5408  grn_expr_append_const_int(ctx, q->e, op.weight, GRN_OP_PUSH, 1);
5409  grn_expr_append_op(ctx, q->e, op.op, 3);
5410  } else {
5411  grn_expr_append_op(ctx, q->e, op.op, 2);
5412  }
5413  }
5414  return rc;
5415 }
5416 
5417 #define DISABLE_UNUSED_CODE 1
5418 #ifndef DISABLE_UNUSED_CODE
5419 static const char *
5420 get_weight_vector(grn_ctx *ctx, efs_info *query, const char *source)
5421 {
5422  const char *p;
5423 
5424  if (!query->opt.weight_vector &&
5425  !query->weight_set &&
5426  !(query->opt.weight_vector = GRN_CALLOC(sizeof(int) * DEFAULT_WEIGHT_VECTOR_SIZE))) {
5427  GRN_LOG(ctx, GRN_LOG_ALERT, "get_weight_vector malloc fail");
5428  return source;
5429  }
5430  for (p = source; p < query->str_end; ) {
5431  unsigned int key;
5432  int value;
5433 
5434  /* key, key is not zero */
5435  key = grn_atoui(p, query->str_end, &p);
5436  if (!key || key > GRN_ID_MAX) { break; }
5437 
5438  /* value */
5439  if (*p == ':') {
5440  p++;
5441  value = grn_atoi(p, query->str_end, &p);
5442  } else {
5443  value = 1;
5444  }
5445 
5446  if (query->weight_set) {
5447  int *pval;
5448  if (grn_hash_add(ctx, query->weight_set, &key, sizeof(unsigned int), (void **)&pval, NULL)) {
5449  *pval = value;
5450  }
5451  } else if (key < DEFAULT_WEIGHT_VECTOR_SIZE) {
5452  query->opt.weight_vector[key - 1] = value;
5453  } else {
5454  GRN_FREE(query->opt.weight_vector);
5455  query->opt.weight_vector = NULL;
5456  if (!(query->weight_set = grn_hash_create(ctx, NULL, sizeof(unsigned int), sizeof(int),
5457  0))) {
5458  return source;
5459  }
5460  p = source; /* reparse */
5461  continue;
5462  }
5463  if (*p != ',') { break; }
5464  p++;
5465  }
5466  return p;
5467 }
5468 
5469 static void
5470 get_pragma(grn_ctx *ctx, efs_info *q)
5471 {
5472  const char *start, *end = q->cur;
5473  while (end < q->str_end && *end == GRN_QUERY_PREFIX) {
5474  if (++end >= q->str_end) { break; }
5475  switch (*end) {
5476  case 'E' :
5477  start = ++end;
5478  q->escalation_threshold = grn_atoi(start, q->str_end, (const char **)&end);
5479  while (end < q->str_end && (('0' <= *end && *end <= '9') || *end == '-')) { end++; }
5480  if (*end == ',') {
5481  start = ++end;
5482  q->escalation_decaystep = grn_atoi(start, q->str_end, (const char **)&end);
5483  }
5484  q->cur = end;
5485  break;
5486  case 'D' :
5487  start = ++end;
5488  while (end < q->str_end && *end != GRN_QUERY_PREFIX && !grn_isspace(end, ctx->encoding)) {
5489  end++;
5490  }
5491  if (end > start) {
5492  switch (*start) {
5493  case 'O' :
5494  q->default_op = GRN_OP_OR;
5495  break;
5496  case GRN_QUERY_AND :
5497  q->default_op = GRN_OP_AND;
5498  break;
5499  case GRN_QUERY_AND_NOT :
5501  break;
5502  case GRN_QUERY_ADJ_INC :
5504  break;
5505  }
5506  }
5507  q->cur = end;
5508  break;
5509  case 'W' :
5510  start = ++end;
5511  end = (char *)get_weight_vector(ctx, q, start);
5512  q->cur = end;
5513  break;
5514  }
5515  }
5516 }
5517 
5518 static int
5519 section_weight_cb(grn_ctx *ctx, grn_hash *r, const void *rid, int sid, void *arg)
5520 {
5521  int *w;
5522  grn_hash *s = (grn_hash *)arg;
5523  if (s && grn_hash_get(ctx, s, &sid, sizeof(grn_id), (void **)&w)) {
5524  return *w;
5525  } else {
5526  return 0;
5527  }
5528 }
5529 #endif
5530 
5531 #include "ecmascript.h"
5532 #include "ecmascript.c"
5533 
5534 static grn_rc
5535 grn_expr_parser_open(grn_ctx *ctx)
5536 {
5537  if (!ctx->impl->parser) {
5538  yyParser *pParser = GRN_MALLOCN(yyParser, 1);
5539  if (pParser) {
5540  pParser->yyidx = -1;
5541 #if YYSTACKDEPTH<=0
5542  yyGrowStack(pParser);
5543 #endif
5544  ctx->impl->parser = pParser;
5545  }
5546  }
5547  return ctx->rc;
5548 }
5549 
5550 #define PARSE(token) grn_expr_parser(ctx->impl->parser, (token), 0, q)
5551 
5552 static void
5553 accept_query_string(grn_ctx *ctx, efs_info *efsi,
5554  const char *str, unsigned int str_size)
5555 {
5556  grn_obj *column, *token;
5557 
5558  GRN_PTR_PUT(ctx, &efsi->token_stack,
5559  grn_expr_add_str(ctx, efsi->e, str, str_size));
5560  {
5561  efs_info *q = efsi;
5563  }
5564 
5565  GRN_PTR_POP(&efsi->token_stack, token);
5566  column = grn_ptr_value_at(&efsi->column_stack, -1);
5567  grn_expr_append_const(efsi->ctx, efsi->e, column, GRN_OP_GET_VALUE, 1);
5568  grn_expr_append_obj(efsi->ctx, efsi->e, token, GRN_OP_PUSH, 1);
5569  grn_expr_append_op(efsi->ctx, efsi->e,
5570  grn_int32_value_at(&efsi->mode_stack, -1), 2);
5571 }
5572 
5573 static grn_rc
5574 get_word_(grn_ctx *ctx, efs_info *q)
5575 {
5576  const char *end;
5577  unsigned int len;
5578  GRN_BULK_REWIND(&q->buf);
5579  for (end = q->cur;; ) {
5580  /* null check and length check */
5581  if (!(len = grn_charlen(ctx, end, q->str_end))) {
5582  q->cur = q->str_end;
5583  break;
5584  }
5585  if (grn_isspace(end, ctx->encoding) ||
5586  *end == GRN_QUERY_PARENL || *end == GRN_QUERY_PARENR) {
5587  q->cur = end;
5588  break;
5589  }
5590  if (q->flags & GRN_EXPR_ALLOW_COLUMN && *end == GRN_QUERY_COLUMN) {
5591  grn_operator mode;
5592  grn_obj *c = grn_obj_column(ctx, q->table,
5593  GRN_TEXT_VALUE(&q->buf),
5594  GRN_TEXT_LEN(&q->buf));
5595  if (c && end + 1 < q->str_end) {
5596  // efs_op op;
5597  switch (end[1]) {
5598  case '!' :
5599  mode = GRN_OP_NOT_EQUAL;
5600  q->cur = end + 2;
5601  break;
5602  case '=' :
5603  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
5604  mode = GRN_OP_ASSIGN;
5605  q->cur = end + 2;
5606  } else {
5607  mode = GRN_OP_EQUAL;
5608  q->cur = end + 1;
5609  }
5610  break;
5611  case '<' :
5612  if (end + 2 < q->str_end && end[2] == '=') {
5613  mode = GRN_OP_LESS_EQUAL;
5614  q->cur = end + 3;
5615  } else {
5616  mode = GRN_OP_LESS;
5617  q->cur = end + 2;
5618  }
5619  break;
5620  case '>' :
5621  if (end + 2 < q->str_end && end[2] == '=') {
5622  mode = GRN_OP_GREATER_EQUAL;
5623  q->cur = end + 3;
5624  } else {
5625  mode = GRN_OP_GREATER;
5626  q->cur = end + 2;
5627  }
5628  break;
5629  case '@' :
5630  mode = GRN_OP_MATCH;
5631  q->cur = end + 2;
5632  break;
5633  case '^' :
5634  mode = GRN_OP_PREFIX;
5635  q->cur = end + 2;
5636  break;
5637  case '$' :
5638  mode = GRN_OP_SUFFIX;
5639  q->cur = end + 2;
5640  break;
5641  default :
5642  mode = GRN_OP_EQUAL;
5643  q->cur = end + 1;
5644  break;
5645  }
5646  } else {
5647  ERR(GRN_INVALID_ARGUMENT, "column lookup failed");
5648  q->cur = q->str_end;
5649  return ctx->rc;
5650  }
5653 
5654  GRN_PTR_PUT(ctx, &((grn_expr *)(q->e))->objs, c);
5655  GRN_PTR_PUT(ctx, &q->column_stack, c);
5656  GRN_INT32_PUT(ctx, &q->mode_stack, mode);
5657 
5658  return GRN_SUCCESS;
5659  } else if (*end == GRN_QUERY_PREFIX) {
5660  q->cur = end + 1;
5662  break;
5663  } else if (*end == GRN_QUERY_ESCAPE) {
5664  end += len;
5665  if (!(len = grn_charlen(ctx, end, q->str_end))) {
5666  q->cur = q->str_end;
5667  break;
5668  }
5669  }
5670  GRN_TEXT_PUT(ctx, &q->buf, end, len);
5671  end += len;
5672  }
5673  accept_query_string(ctx, q, GRN_TEXT_VALUE(&q->buf), GRN_TEXT_LEN(&q->buf));
5674 
5675  return GRN_SUCCESS;
5676 }
5677 
5678 static grn_rc
5679 parse_query(grn_ctx *ctx, efs_info *q)
5680 {
5681  int option = 0;
5682  grn_operator mode;
5683  efs_op op_, *op = &op_;
5684  grn_bool first_token = GRN_TRUE;
5685  grn_bool block_started = GRN_FALSE;
5686 
5687  op->op = q->default_op;
5688  op->weight = DEFAULT_WEIGHT;
5689  while (!ctx->rc) {
5690  skip_space(ctx, q);
5691  if (q->cur >= q->str_end) { goto exit; }
5692  switch (*q->cur) {
5693  case '\0' :
5694  goto exit;
5695  break;
5696  case GRN_QUERY_PARENR :
5697  q->cur++;
5699  break;
5700  case GRN_QUERY_QUOTEL :
5701  q->cur++;
5702 
5703  {
5704  const char *start, *s;
5705  start = s = q->cur;
5706  GRN_BULK_REWIND(&q->buf);
5707  while (1) {
5708  unsigned int len;
5709  if (s >= q->str_end) {
5710  q->cur = s;
5711  break;
5712  }
5713  len = grn_charlen(ctx, s, q->str_end);
5714  if (len == 0) {
5715  /* invalid string containing malformed multibyte char */
5716  goto exit;
5717  } else if (len == 1) {
5718  if (*s == GRN_QUERY_QUOTER) {
5719  q->cur = s + 1;
5720  break;
5721  } else if (*s == GRN_QUERY_ESCAPE && s + 1 < q->str_end) {
5722  s++;
5723  len = grn_charlen(ctx, s, q->str_end);
5724  }
5725  }
5726  GRN_TEXT_PUT(ctx, &q->buf, s, len);
5727  s += len;
5728 
5729  }
5730  accept_query_string(ctx, q,
5731  GRN_TEXT_VALUE(&q->buf), GRN_TEXT_LEN(&q->buf));
5732  }
5733 
5734  break;
5735  case GRN_QUERY_PREFIX :
5736  q->cur++;
5737  get_op(q, op, &mode, &option);
5739  break;
5740  case GRN_QUERY_AND :
5741  q->cur++;
5742  if (!first_token) {
5743  op->op = GRN_OP_AND;
5745  }
5746  break;
5747  case GRN_QUERY_AND_NOT :
5748  q->cur++;
5749  if (first_token && (q->flags & GRN_EXPR_ALLOW_LEADING_NOT)) {
5750  grn_obj *all_records = grn_ctx_get(ctx, "all_records", 11);
5751  if (all_records) {
5752  /* dummy token */
5754  grn_expr_append_obj(ctx, q->e, all_records, GRN_OP_PUSH, 1);
5755  grn_expr_append_op(ctx, q->e, GRN_OP_CALL, 0);
5756  }
5757  }
5758  op->op = GRN_OP_AND_NOT;
5760  break;
5761  case GRN_QUERY_ADJ_INC :
5762  q->cur++;
5763  if (op->weight < 127) { op->weight++; }
5764  op->op = GRN_OP_ADJUST;
5766  break;
5767  case GRN_QUERY_ADJ_DEC :
5768  q->cur++;
5769  if (op->weight > -128) { op->weight--; }
5770  op->op = GRN_OP_ADJUST;
5772  break;
5773  case GRN_QUERY_ADJ_NEG :
5774  q->cur++;
5775  op->op = GRN_OP_ADJUST;
5776  op->weight = -1;
5778  break;
5779  case GRN_QUERY_PARENL :
5780  q->cur++;
5782  block_started = GRN_TRUE;
5783  break;
5784  case 'O' :
5785  if (q->cur[1] == 'R' && q->cur[2] == ' ') {
5786  q->cur += 2;
5788  break;
5789  }
5790  /* fallthru */
5791  default :
5792  get_word_(ctx, q);
5793  break;
5794  }
5795  first_token = block_started;
5796  block_started = GRN_FALSE;
5797  }
5798 exit :
5799  PARSE(0);
5800  return GRN_SUCCESS;
5801 }
5802 
5803 static grn_rc
5804 get_string(grn_ctx *ctx, efs_info *q, char quote)
5805 {
5806  const char *s;
5807  unsigned int len;
5808  grn_rc rc = GRN_END_OF_DATA;
5809  GRN_BULK_REWIND(&q->buf);
5810  for (s = q->cur + 1; s < q->str_end; s += len) {
5811  if (!(len = grn_charlen(ctx, s, q->str_end))) { break; }
5812  if (len == 1) {
5813  if (*s == quote) {
5814  s++;
5815  rc = GRN_SUCCESS;
5816  break;
5817  }
5818  if (*s == GRN_QUERY_ESCAPE && s + 1 < q->str_end) {
5819  s++;
5820  if (!(len = grn_charlen(ctx, s, q->str_end))) { break; }
5821  }
5822  }
5823  GRN_TEXT_PUT(ctx, &q->buf, s, len);
5824  }
5825  q->cur = s;
5826  return rc;
5827 }
5828 
5829 static grn_obj *
5830 resolve_top_level_name(grn_ctx *ctx, const char *name, unsigned int name_size)
5831 {
5832  unsigned int i;
5833  unsigned int first_delimiter_position = 0;
5834  unsigned int n_delimiters = 0;
5835  grn_obj *top_level_object;
5836  grn_obj *object;
5837 
5838  for (i = 0; i < name_size; i++) {
5839  if (name[i] != GRN_DB_DELIMITER) {
5840  continue;
5841  }
5842 
5843  if (n_delimiters == 0) {
5844  first_delimiter_position = i;
5845  }
5846  n_delimiters++;
5847  }
5848 
5849  if (n_delimiters < 2) {
5850  return grn_ctx_get(ctx, name, name_size);
5851  }
5852 
5853  top_level_object = grn_ctx_get(ctx, name, first_delimiter_position);
5854  if (!top_level_object) {
5855  return NULL;
5856  }
5857  object = grn_obj_column(ctx, top_level_object,
5858  name + first_delimiter_position + 1,
5859  name_size - first_delimiter_position - 1);
5860  grn_obj_unlink(ctx, top_level_object);
5861  return object;
5862 }
5863 
5864 static grn_rc
5865 get_identifier(grn_ctx *ctx, efs_info *q)
5866 {
5867  const char *s;
5868  unsigned int len;
5869  grn_rc rc = GRN_SUCCESS;
5870  for (s = q->cur; s < q->str_end; s += len) {
5871  if (!(len = grn_charlen(ctx, s, q->str_end))) {
5872  rc = GRN_END_OF_DATA;
5873  goto exit;
5874  }
5875  if (grn_isspace(s, ctx->encoding)) { goto done; }
5876  if (len == 1) {
5877  switch (*s) {
5878  case '\0' : case '(' : case ')' : case '{' : case '}' :
5879  case '[' : case ']' : case ',' : case ':' : case '@' :
5880  case '?' : case '"' : case '*' : case '+' : case '-' :
5881  case '|' : case '/' : case '%' : case '!' : case '^' :
5882  case '&' : case '>' : case '<' : case '=' : case '~' :
5883  /* case '.' : */
5884  goto done;
5885  break;
5886  }
5887  }
5888  }
5889 done :
5890  len = s - q->cur;
5891  switch (*q->cur) {
5892  case 'd' :
5893  if (len == 6 && !memcmp(q->cur, "delete", 6)) {
5895  goto exit;
5896  }
5897  break;
5898  case 'f' :
5899  if (len == 5 && !memcmp(q->cur, "false", 5)) {
5900  grn_obj buf;
5902  GRN_BOOL_INIT(&buf, 0);
5903  GRN_BOOL_SET(ctx, &buf, 0);
5904  grn_expr_append_const(ctx, q->e, &buf, GRN_OP_PUSH, 1);
5905  GRN_OBJ_FIN(ctx, &buf);
5906  goto exit;
5907  }
5908  break;
5909  case 'i' :
5910  if (len == 2 && !memcmp(q->cur, "in", 2)) {
5912  goto exit;
5913  }
5914  break;
5915  case 'n' :
5916  if (len == 4 && !memcmp(q->cur, "null", 4)) {
5917  grn_obj buf;
5919  GRN_VOID_INIT(&buf);
5920  grn_expr_append_const(ctx, q->e, &buf, GRN_OP_PUSH, 1);
5921  GRN_OBJ_FIN(ctx, &buf);
5922  goto exit;
5923  }
5924  break;
5925  case 't' :
5926  if (len == 4 && !memcmp(q->cur, "true", 4)) {
5927  grn_obj buf;
5929  GRN_BOOL_INIT(&buf, 0);
5930  GRN_BOOL_SET(ctx, &buf, 1);
5931  grn_expr_append_const(ctx, q->e, &buf, GRN_OP_PUSH, 1);
5932  GRN_OBJ_FIN(ctx, &buf);
5933  goto exit;
5934  }
5935  break;
5936  }
5937  {
5938  grn_obj *obj;
5939  const char *name = q->cur;
5940  unsigned int name_size = s - q->cur;
5941  if ((obj = grn_expr_get_var(ctx, q->e, name, name_size))) {
5943  grn_expr_append_obj(ctx, q->e, obj, GRN_OP_PUSH, 1);
5944  goto exit;
5945  }
5946  if ((obj = grn_obj_column(ctx, q->table, name, name_size))) {
5947  GRN_PTR_PUT(ctx, &((grn_expr *)q->e)->objs, obj);
5949  grn_expr_append_obj(ctx, q->e, obj, GRN_OP_GET_VALUE, 1);
5950  goto exit;
5951  }
5952  if ((obj = resolve_top_level_name(ctx, name, name_size))) {
5953  GRN_PTR_PUT(ctx, &((grn_expr *)q->e)->objs, obj);
5955  grn_expr_append_obj(ctx, q->e, obj, GRN_OP_PUSH, 1);
5956  goto exit;
5957  }
5960  } else {
5961  rc = GRN_SYNTAX_ERROR;
5962  }
5963  }
5964 exit :
5965  q->cur = s;
5966  return rc;
5967 }
5968 
5969 static void
5970 set_tos_minor_to_curr(grn_ctx *ctx, efs_info *q)
5971 {
5972  yyParser *pParser = ctx->impl->parser;
5973  yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
5974  yytos->minor.yy0 = ((grn_expr *)(q->e))->codes_curr;
5975 }
5976 
5977 static grn_rc
5978 parse_script(grn_ctx *ctx, efs_info *q)
5979 {
5980  grn_rc rc = GRN_SUCCESS;
5981  for (;;) {
5982  skip_space(ctx, q);
5983  if (q->cur >= q->str_end) { rc = GRN_END_OF_DATA; goto exit; }
5984  switch (*q->cur) {
5985  case '\0' :
5986  rc = GRN_END_OF_DATA;
5987  goto exit;
5988  break;
5989  case '(' :
5990  q->cur++;
5992  break;
5993  case ')' :
5994  q->cur++;
5996  break;
5997  case '{' :
5998  q->cur++;
6000  break;
6001  case '}' :
6002  q->cur++;
6004  break;
6005  case '[' :
6006  q->cur++;
6008  break;
6009  case ']' :
6010  q->cur++;
6012  break;
6013  case ',' :
6014  q->cur++;
6016  break;
6017  case '.' :
6018  q->cur++;
6020  break;
6021  case ':' :
6022  q->cur++;
6024  set_tos_minor_to_curr(ctx, q);
6025  grn_expr_append_op(ctx, q->e, GRN_OP_JUMP, 0);
6026  break;
6027  case '@' :
6028  q->cur++;
6029  switch (*q->cur) {
6030  case '^' :
6031  q->cur++;
6033  break;
6034  case '$' :
6035  q->cur++;
6037  break;
6038  default :
6040  break;
6041  }
6042  break;
6043  case '~' :
6044  q->cur++;
6046  break;
6047  case '?' :
6048  q->cur++;
6050  set_tos_minor_to_curr(ctx, q);
6051  grn_expr_append_op(ctx, q->e, GRN_OP_CJUMP, 0);
6052  break;
6053  case '"' :
6054  if ((rc = get_string(ctx, q, '"'))) { goto exit; }
6056  grn_expr_append_const(ctx, q->e, &q->buf, GRN_OP_PUSH, 1);
6057  break;
6058  case '\'' :
6059  if ((rc = get_string(ctx, q, '\''))) { goto exit; }
6061  grn_expr_append_const(ctx, q->e, &q->buf, GRN_OP_PUSH, 1);
6062  break;
6063  case '*' :
6064  q->cur++;
6065  switch (*q->cur) {
6066  case 'N' :
6067  q->cur++;
6069  break;
6070  case 'S' :
6071  q->cur++;
6073  break;
6074  case 'T' :
6075  q->cur++;
6077  break;
6078  case '>' :
6079  q->cur++;
6081  break;
6082  case '<' :
6083  q->cur++;
6085  break;
6086  case '~' :
6087  q->cur++;
6089  break;
6090  case '=' :
6091  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6092  q->cur++;
6094  } else {
6096  "'*=' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6097  }
6098  break;
6099  default :
6101  break;
6102  }
6103  break;
6104  case '+' :
6105  q->cur++;
6106  switch (*q->cur) {
6107  case '+' :
6108  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6109  q->cur++;
6111  } else {
6113  "'++' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6114  }
6115  break;
6116  case '=' :
6117  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6118  q->cur++;
6120  } else {
6122  "'+=' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6123  goto exit;
6124  }
6125  break;
6126  default :
6128  break;
6129  }
6130  break;
6131  case '-' :
6132  q->cur++;
6133  switch (*q->cur) {
6134  case '-' :
6135  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6136  q->cur++;
6138  } else {
6140  "'--' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6141  }
6142  break;
6143  case '=' :
6144  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6145  q->cur++;
6147  } else {
6149  "'-=' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6150  }
6151  break;
6152  default :
6154  break;
6155  }
6156  break;
6157  case '|' :
6158  q->cur++;
6159  switch (*q->cur) {
6160  case '|' :
6161  q->cur++;
6163  break;
6164  case '=' :
6165  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6166  q->cur++;
6168  } else {
6170  "'|=' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6171  }
6172  break;
6173  default :
6175  break;
6176  }
6177  break;
6178  case '/' :
6179  q->cur++;
6180  switch (*q->cur) {
6181  case '=' :
6182  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6183  q->cur++;
6185  } else {
6187  "'/=' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6188  }
6189  break;
6190  default :
6192  break;
6193  }
6194  break;
6195  case '%' :
6196  q->cur++;
6197  switch (*q->cur) {
6198  case '=' :
6199  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6200  q->cur++;
6202  } else {
6204  "'%%=' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6205  }
6206  break;
6207  default :
6209  break;
6210  }
6211  break;
6212  case '!' :
6213  q->cur++;
6214  switch (*q->cur) {
6215  case '=' :
6216  q->cur++;
6218  break;
6219  default :
6221  break;
6222  }
6223  break;
6224  case '^' :
6225  q->cur++;
6226  switch (*q->cur) {
6227  case '=' :
6228  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6229  q->cur++;
6231  } else {
6233  "'^=' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6234  }
6235  break;
6236  default :
6238  break;
6239  }
6240  break;
6241  case '&' :
6242  q->cur++;
6243  switch (*q->cur) {
6244  case '&' :
6245  q->cur++;
6247  break;
6248  case '=' :
6249  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6250  q->cur++;
6252  } else {
6254  "'&=' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6255  }
6256  break;
6257  case '!' :
6258  q->cur++;
6260  break;
6261  default :
6263  break;
6264  }
6265  break;
6266  case '>' :
6267  q->cur++;
6268  switch (*q->cur) {
6269  case '>' :
6270  q->cur++;
6271  switch (*q->cur) {
6272  case '>' :
6273  q->cur++;
6274  switch (*q->cur) {
6275  case '=' :
6276  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6277  q->cur++;
6279  } else {
6281  "'>>>=' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6282  }
6283  break;
6284  default :
6286  break;
6287  }
6288  break;
6289  case '=' :
6290  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6291  q->cur++;
6293  } else {
6295  "'>>=' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6296  }
6297  break;
6298  default :
6300  break;
6301  }
6302  break;
6303  case '=' :
6304  q->cur++;
6306  break;
6307  default :
6309  break;
6310  }
6311  break;
6312  case '<' :
6313  q->cur++;
6314  switch (*q->cur) {
6315  case '<' :
6316  q->cur++;
6317  switch (*q->cur) {
6318  case '=' :
6319  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6320  q->cur++;
6322  } else {
6324  "'<<=' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6325  }
6326  break;
6327  default :
6329  break;
6330  }
6331  break;
6332  case '=' :
6333  q->cur++;
6335  break;
6336  default :
6338  break;
6339  }
6340  break;
6341  case '=' :
6342  q->cur++;
6343  switch (*q->cur) {
6344  case '=' :
6345  q->cur++;
6347  break;
6348  default :
6349  if (q->flags & GRN_EXPR_ALLOW_UPDATE) {
6351  } else {
6353  "'=' is not allowed (%.*s)", (int)(q->str_end - q->str), q->str);
6354  }
6355  break;
6356  }
6357  break;
6358  case '0' : case '1' : case '2' : case '3' : case '4' :
6359  case '5' : case '6' : case '7' : case '8' : case '9' :
6360  {
6361  const char *rest;
6362  int64_t int64 = grn_atoll(q->cur, q->str_end, &rest);
6363  // checks to see grn_atoll was appropriate
6364  // (NOTE: *q->cur begins with a digit. Thus, grn_atoll parses at leaset
6365  // one char.)
6366  if (q->str_end != rest &&
6367  (*rest == '.' || *rest == 'e' || *rest == 'E' ||
6368  (*rest >= '0' && *rest <= '9'))) {
6369  char *rest_float;
6370  double d = strtod(q->cur, &rest_float);
6371  grn_obj floatbuf;
6372  GRN_FLOAT_INIT(&floatbuf, 0);
6373  GRN_FLOAT_SET(ctx, &floatbuf, d);
6374  grn_expr_append_const(ctx, q->e, &floatbuf, GRN_OP_PUSH, 1);
6375  rest = rest_float;
6376  } else {
6377  const char *rest64 = rest;
6378  unsigned int uint32 = grn_atoui(q->cur, q->str_end, &rest);
6379  // checks to see grn_atoi failed (see above NOTE)
6380  if ((int64 > UINT32_MAX) ||
6381  (q->str_end != rest && *rest >= '0' && *rest <= '9')) {
6382  grn_obj int64buf;
6383  GRN_INT64_INIT(&int64buf, 0);
6384  GRN_INT64_SET(ctx, &int64buf, int64);
6385  grn_expr_append_const(ctx, q->e, &int64buf, GRN_OP_PUSH, 1);
6386  rest = rest64;
6387  } else {
6388  grn_obj uint32buf;
6389  GRN_UINT32_INIT(&uint32buf, 0);
6390  GRN_UINT32_SET(ctx, &uint32buf, uint32);
6391  grn_expr_append_const(ctx, q->e, &uint32buf, GRN_OP_PUSH, 1);
6392  }
6393  }
6394  q->cur = rest;
6396  }
6397  break;
6398  default :
6399  if ((rc = get_identifier(ctx, q))) { goto exit; }
6400  break;
6401  }
6402  if (ctx->rc) { rc = ctx->rc; break; }
6403  }
6404 exit :
6405  PARSE(0);
6406  return rc;
6407 }
6408 
6409 grn_rc
6411  const char *str, unsigned int str_size,
6412  grn_obj *default_column, grn_operator default_mode,
6413  grn_operator default_op, grn_expr_flags flags)
6414 {
6415  efs_info efsi;
6416  if (grn_expr_parser_open(ctx)) { return ctx->rc; }
6417  GRN_API_ENTER;
6418  efsi.ctx = ctx;
6419  efsi.str = str;
6420  if ((efsi.v = grn_expr_get_var_by_offset(ctx, expr, 0)) &&
6421  (efsi.table = grn_ctx_at(ctx, efsi.v->header.domain))) {
6422  GRN_TEXT_INIT(&efsi.buf, 0);
6427  efsi.e = expr;
6428  efsi.str = str;
6429  efsi.cur = str;
6430  efsi.str_end = str + str_size;
6431  efsi.default_column = default_column;
6432  GRN_PTR_PUT(ctx, &efsi.column_stack, default_column);
6433  GRN_INT32_PUT(ctx, &efsi.op_stack, default_op);
6434  GRN_INT32_PUT(ctx, &efsi.mode_stack, default_mode);
6435  efsi.default_flags = efsi.flags = flags;
6438  efsi.weight_offset = 0;
6439  efsi.opt.weight_vector = NULL;
6440  efsi.weight_set = NULL;
6441 
6443  if (flags & GRN_EXPR_SYNTAX_OUTPUT_COLUMNS) {
6444  efs_info *q = &efsi;
6446  }
6447  parse_script(ctx, &efsi);
6448  } else {
6449  parse_query(ctx, &efsi);
6450  }
6451 
6452  /*
6453  grn_obj strbuf;
6454  GRN_TEXT_INIT(&strbuf, 0);
6455  grn_expr_inspect(ctx, &strbuf, expr);
6456  GRN_TEXT_PUTC(ctx, &strbuf, '\0');
6457  GRN_LOG(ctx, GRN_LOG_NOTICE, "query=(%s)", GRN_TEXT_VALUE(&strbuf));
6458  GRN_OBJ_FIN(ctx, &strbuf);
6459  */
6460 
6461  /*
6462  efsi.opt.vector_size = DEFAULT_WEIGHT_VECTOR_SIZE;
6463  efsi.opt.func = efsi.weight_set ? section_weight_cb : NULL;
6464  efsi.opt.func_arg = efsi.weight_set;
6465  efsi.snip_conds = NULL;
6466  */
6467  GRN_OBJ_FIN(ctx, &efsi.op_stack);
6468  GRN_OBJ_FIN(ctx, &efsi.mode_stack);
6469  GRN_OBJ_FIN(ctx, &efsi.column_stack);
6470  GRN_OBJ_FIN(ctx, &efsi.token_stack);
6471  GRN_OBJ_FIN(ctx, &efsi.buf);
6472  } else {
6473  ERR(GRN_INVALID_ARGUMENT, "variable is not defined correctly");
6474  }
6475  GRN_API_RETURN(ctx->rc);
6476 }
6477 
6478 grn_rc
6480 {
6481  if (ctx->impl->parser) {
6482  yyParser *pParser = (yyParser*)ctx->impl->parser;
6483  while (pParser->yyidx >= 0) yy_pop_parser_stack(pParser);
6484 #if YYSTACKDEPTH<=0
6485  free(pParser->yystack);
6486 #endif
6487  GRN_FREE(pParser);
6488  ctx->impl->parser = NULL;
6489  }
6490  return ctx->rc;
6491 }
6492 
6493 grn_snip *
6494 grn_expr_snip(grn_ctx *ctx, grn_obj *expr, int flags,
6495  unsigned int width, unsigned int max_results,
6496  unsigned int n_tags,
6497  const char **opentags, unsigned int *opentag_lens,
6498  const char **closetags, unsigned int *closetag_lens,
6499  grn_snip_mapping *mapping)
6500 {
6501  int i, n;
6502  scan_info **sis, *si;
6503  grn_snip *res = NULL;
6504  GRN_API_ENTER;
6505  if ((sis = scan_info_build(ctx, expr, &n, GRN_OP_OR, 0))) {
6506  if ((res = grn_snip_open(ctx, flags, width, max_results,
6507  NULL, 0, NULL, 0, mapping))) {
6508  int butp = 0, nparens = 0, npbut = 0;
6509  grn_obj but_stack;
6510  grn_obj snip_stack;
6511  GRN_UINT32_INIT(&but_stack, GRN_OBJ_VECTOR);
6512  GRN_PTR_INIT(&snip_stack, GRN_OBJ_VECTOR, GRN_ID_NIL);
6513  for (i = n; i--;) {
6514  si = sis[i];
6515  if (si->flags & SCAN_POP) {
6516  nparens++;
6517  if (si->logical_op == GRN_OP_AND_NOT) {
6518  GRN_UINT32_PUT(ctx, &but_stack, npbut);
6519  npbut = nparens;
6520  butp = 1 - butp;
6521  }
6522  } else {
6523  if (si->op == GRN_OP_MATCH && si->query) {
6524  if (butp == (si->logical_op == GRN_OP_AND_NOT)) {
6525  GRN_PTR_PUT(ctx, &snip_stack, si->query);
6526  }
6527  }
6528  if (si->flags & SCAN_PUSH) {
6529  if (nparens == npbut) {
6530  butp = 1 - butp;
6531  GRN_UINT32_POP(&but_stack, npbut);
6532  }
6533  nparens--;
6534  }
6535  }
6536  }
6537  if (n_tags) {
6538  for (i = 0;; i = (i + 1) % n_tags) {
6539  grn_obj *q;
6540  GRN_PTR_POP(&snip_stack, q);
6541  if (!q) { break; }
6543  opentags[i], opentag_lens[i], closetags[i], closetag_lens[i]);
6544  }
6545  } else {
6546  for (;;) {
6547  grn_obj *q;
6548  GRN_PTR_POP(&snip_stack, q);
6549  if (!q) { break; }
6551  NULL, 0, NULL, 0);
6552  }
6553  }
6554  GRN_OBJ_FIN(ctx, &but_stack);
6555  GRN_OBJ_FIN(ctx, &snip_stack);
6556  }
6557  for (i = n; i--;) { SI_FREE(sis[i]); }
6558  GRN_FREE(sis);
6559  }
6560  GRN_API_RETURN(res);
6561 }
6562 
6563 /*
6564  So far, grn_column_filter() is nothing but a very rough prototype.
6565  Although GRN_COLUMN_EACH() can accelerate many range queries,
6566  the following stuff must be resolved one by one.
6567 
6568  * support accessors as column
6569  * support tables which have deleted records
6570  * support various operators
6571  * support various column types
6572 */
6573 grn_rc
6575  grn_operator operator,
6576  grn_obj *value, grn_obj *result_set,
6577  grn_operator set_operation)
6578 {
6579  uint32_t *vp;
6580  grn_rset_posinfo pi;
6581  uint32_t value_ = grn_atoui(GRN_TEXT_VALUE(value), GRN_BULK_CURR(value), NULL);
6582  GRN_COLUMN_EACH(ctx, column, id, vp, {
6583  if (*vp < value_) {
6584  pi.rid = id;
6585  res_add(ctx, (grn_hash *)result_set, &pi, 1, set_operation);
6586  }
6587  });
6588  grn_ii_resolve_sel_and(ctx, (grn_hash *)result_set, set_operation);
6589  return ctx->rc;
6590 }
6591 
6592 grn_rc
6593 grn_expr_syntax_escape(grn_ctx *ctx, const char *string, int string_size,
6594  const char *target_characters,
6595  char escape_character,
6596  grn_obj *escaped_string)
6597 {
6598  grn_rc rc = GRN_SUCCESS;
6599  const char *current, *string_end;
6600 
6601  if (!string) {
6602  return GRN_INVALID_ARGUMENT;
6603  }
6604 
6605  GRN_API_ENTER;
6606  if (string_size < 0) {
6607  string_size = strlen(string);
6608  }
6609  string_end = string + string_size;
6610 
6611  current = string;
6612  while (current < string_end) {
6613  unsigned int char_size;
6614  char_size = grn_charlen(ctx, current, string_end);
6615  switch (char_size) {
6616  case 0 :
6617  /* string includes malformed multibyte character. */
6618  return GRN_INVALID_ARGUMENT;
6619  break;
6620  case 1 :
6621  if (strchr(target_characters, *current)) {
6622  GRN_TEXT_PUTC(ctx, escaped_string, escape_character);
6623  }
6624  GRN_TEXT_PUT(ctx, escaped_string, current, char_size);
6625  current += char_size;
6626  break;
6627  default :
6628  GRN_TEXT_PUT(ctx, escaped_string, current, char_size);
6629  current += char_size;
6630  break;
6631  }
6632  }
6633 
6634  GRN_API_RETURN(rc);
6635 }
6636 
6637 grn_rc
6638 grn_expr_syntax_escape_query(grn_ctx *ctx, const char *query, int query_size,
6639  grn_obj *escaped_query)
6640 {
6641  const char target_characters[] = {
6642  GRN_QUERY_AND,
6653  '\0',
6654  };
6655  return grn_expr_syntax_escape(ctx, query, query_size,
6656  target_characters, GRN_QUERY_ESCAPE,
6657  escaped_query);
6658 }