Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
mrb_expr.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2 -*- */
2 /*
3  Copyright(C) 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 
19 #include "../ctx_impl.h"
20 
21 #ifdef GRN_WITH_MRUBY
22 #include <mruby.h>
23 #include <mruby/class.h>
24 #include <mruby/variable.h>
25 #include <mruby/data.h>
26 
27 #include "../expr.h"
28 #include "../util.h"
29 #include "../mrb.h"
30 #include "mrb_accessor.h"
31 #include "mrb_expr.h"
32 
33 static struct mrb_data_type mrb_grn_scan_info_type = {
34  "Groonga::ScanInfo",
35  NULL
36 };
37 static struct mrb_data_type mrb_grn_expr_code_type = {
38  "Groonga::ExpressionCode",
39  NULL
40 };
41 
42 static mrb_value
43 mrb_grn_scan_info_new(mrb_state *mrb, scan_info *scan_info)
44 {
45  grn_ctx *ctx = (grn_ctx *)mrb->ud;
46  struct RClass *module = ctx->impl->mrb.module;
47  struct RClass *klass;
48  mrb_value mrb_scan_info;
49 
50  mrb_scan_info = mrb_cptr_value(mrb, scan_info);
51  klass = mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(module),
52  mrb_intern(mrb, "ScanInfo")));
53  return mrb_obj_new(mrb, klass, 1, &mrb_scan_info);
54 }
55 
56 static mrb_value
57 mrb_grn_expr_code_new(mrb_state *mrb, grn_expr_code *code)
58 {
59  grn_ctx *ctx = (grn_ctx *)mrb->ud;
60  struct RClass *module = ctx->impl->mrb.module;
61  struct RClass *klass;
63 
64  mrb_code = mrb_cptr_value(mrb, code);
65  klass = mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(module),
66  mrb_intern(mrb, "ExpressionCode")));
67  return mrb_obj_new(mrb, klass, 1, &mrb_code);
68 }
69 
70 static scan_info **
71 scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n,
72  grn_operator op, uint32_t size)
73 {
74  grn_obj *var;
75  scan_stat stat;
76  int i, m = 0, o = 0;
77  scan_info **sis, *si = NULL;
78  grn_expr_code *c, *ce;
79  grn_expr *e = (grn_expr *)expr;
80  mrb_state *mrb = ctx->impl->mrb.state;
81  mrb_value mrb_si;
82 
83  if (!(var = grn_expr_get_var_by_offset(ctx, expr, 0))) { return NULL; }
84  for (stat = SCAN_START, c = e->codes, ce = &e->codes[e->codes_curr]; c < ce; c++) {
85  switch (c->op) {
86  case GRN_OP_MATCH :
87  case GRN_OP_NEAR :
88  case GRN_OP_NEAR2 :
89  case GRN_OP_SIMILAR :
90  case GRN_OP_PREFIX :
91  case GRN_OP_SUFFIX :
92  case GRN_OP_EQUAL :
93  case GRN_OP_NOT_EQUAL :
94  case GRN_OP_LESS :
95  case GRN_OP_GREATER :
96  case GRN_OP_LESS_EQUAL :
98  case GRN_OP_GEO_WITHINP5 :
99  case GRN_OP_GEO_WITHINP6 :
100  case GRN_OP_GEO_WITHINP8 :
101  case GRN_OP_TERM_EXTRACT :
102  if (stat < SCAN_COL1 || SCAN_CONST < stat) { return NULL; }
103  stat = SCAN_START;
104  m++;
105  break;
106  case GRN_OP_AND :
107  case GRN_OP_OR :
108  case GRN_OP_AND_NOT :
109  case GRN_OP_ADJUST :
110  if (stat != SCAN_START) { return NULL; }
111  o++;
112  if (o >= m) { return NULL; }
113  break;
114  case GRN_OP_PUSH :
115  stat = (c->value == var) ? SCAN_VAR : SCAN_CONST;
116  break;
117  case GRN_OP_GET_VALUE :
118  switch (stat) {
119  case SCAN_START :
120  case SCAN_CONST :
121  case SCAN_VAR :
122  stat = SCAN_COL1;
123  break;
124  case SCAN_COL1 :
125  stat = SCAN_COL2;
126  break;
127  case SCAN_COL2 :
128  break;
129  default :
130  return NULL;
131  break;
132  }
133  break;
134  case GRN_OP_CALL :
135  if ((c->flags & GRN_EXPR_CODE_RELATIONAL_EXPRESSION) || c + 1 == ce) {
136  stat = SCAN_START;
137  m++;
138  } else {
139  stat = SCAN_COL2;
140  }
141  break;
142  default :
143  return NULL;
144  break;
145  }
146  }
147  if (stat || m != o + 1) { return NULL; }
148  if (!(sis = GRN_MALLOCN(scan_info *, m + m + o))) { return NULL; }
149  for (i = 0, stat = SCAN_START, c = e->codes, ce = &e->codes[e->codes_curr]; c < ce; c++) {
150  switch (c->op) {
151  case GRN_OP_MATCH :
152  case GRN_OP_NEAR :
153  case GRN_OP_NEAR2 :
154  case GRN_OP_SIMILAR :
155  case GRN_OP_PREFIX :
156  case GRN_OP_SUFFIX :
157  case GRN_OP_EQUAL :
158  case GRN_OP_NOT_EQUAL :
159  case GRN_OP_LESS :
160  case GRN_OP_GREATER :
161  case GRN_OP_LESS_EQUAL :
162  case GRN_OP_GREATER_EQUAL :
163  case GRN_OP_GEO_WITHINP5 :
164  case GRN_OP_GEO_WITHINP6 :
165  case GRN_OP_GEO_WITHINP8 :
166  case GRN_OP_TERM_EXTRACT :
167  stat = SCAN_START;
168  mrb_si = mrb_grn_scan_info_new(mrb, si);
169  mrb_funcall(mrb, mrb_si, "op=", 1, mrb_fixnum_value(c->op));
170  mrb_funcall(mrb, mrb_si, "end=", 1, mrb_fixnum_value(c - e->codes));
171  sis[i++] = si;
172  {
173  int sid, k;
174  grn_obj *index, *arg, **p = &arg;
175  for (k = 0; (arg = grn_scan_info_get_arg(ctx, si, k)) ; k++) {
176  if ((*p)->header.type == GRN_EXPR) {
177  uint32_t j;
178  grn_expr_code *ec;
179  grn_expr *e = (grn_expr *)(*p);
180  for (j = e->codes_curr, ec = e->codes; j--; ec++) {
181  int32_t weight;
182  if (ec->value) {
183  switch (ec->value->header.type) {
184  case GRN_ACCESSOR :
185  if (grn_column_index(ctx, ec->value, c->op, &index, 1, &sid)) {
186  mrb_value mrb_ec = mrb_grn_expr_code_new(mrb, ec);
187  mrb_value mrb_accessor;
188  weight = mrb_fixnum(mrb_funcall(mrb, mrb_ec, "weight", 0));
190  mrb_si = mrb_grn_scan_info_new(mrb, si);
191  mrb_accessor = mrb_grn_accessor_new(mrb, (grn_accessor *)ec->value);
192  if (!mrb_nil_p(mrb_funcall(mrb, mrb_accessor, "next", 0))) {
193  mrb_funcall(mrb, mrb_si, "put_index", 3,
194  mrb_cptr_value(mrb, ec->value),
195  mrb_fixnum_value(sid),
196  mrb_fixnum_value(weight));
197  } else {
198  mrb_funcall(mrb, mrb_si, "put_index", 3,
199  mrb_cptr_value(mrb, index),
200  mrb_fixnum_value(sid),
201  mrb_fixnum_value(weight));
202  }
203  }
204  break;
205  case GRN_COLUMN_FIX_SIZE :
206  case GRN_COLUMN_VAR_SIZE :
207  if (grn_column_index(ctx, ec->value, c->op, &index, 1, &sid)) {
208  mrb_value mrb_ec = mrb_grn_expr_code_new(mrb, ec);
209  weight = mrb_fixnum(mrb_funcall(mrb, mrb_ec, "weight", 0));
210  mrb_si = mrb_grn_scan_info_new(mrb, si);
211  mrb_funcall(mrb, mrb_si, "put_index", 3,
212  mrb_cptr_value(mrb, index),
213  mrb_fixnum_value(sid),
214  mrb_fixnum_value(weight));
215  }
216  break;
217  case GRN_COLUMN_INDEX :
218  sid = 0;
219  index = ec->value;
220  if (j > 2 &&
221  ec[1].value &&
222  ec[1].value->header.domain == GRN_DB_UINT32 &&
223  ec[2].op == GRN_OP_GET_MEMBER) {
224  sid = GRN_UINT32_VALUE(ec[1].value) + 1;
225  j -= 2;
226  ec += 2;
227  }
228  {
229  mrb_value mrb_ec = mrb_grn_expr_code_new(mrb, ec);
230  weight = mrb_fixnum(mrb_funcall(mrb, mrb_ec, "weight", 0));
231  }
232  mrb_si = mrb_grn_scan_info_new(mrb, si);
233  mrb_funcall(mrb, mrb_si, "put_index", 3,
234  mrb_cptr_value(mrb, index),
235  mrb_fixnum_value(sid),
236  mrb_fixnum_value(weight));
237  break;
238  }
239  }
240  }
241  } else if (GRN_DB_OBJP(*p)) {
242  if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) {
243  mrb_si = mrb_grn_scan_info_new(mrb, si);
244  mrb_funcall(mrb, mrb_si, "put_index", 3,
245  mrb_cptr_value(mrb, index),
246  mrb_fixnum_value(sid),
247  mrb_fixnum_value(1));
248  }
249  } else if (GRN_ACCESSORP(*p)) {
251  if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) {
252  mrb_value mrb_accessor = mrb_grn_accessor_new(mrb, (grn_accessor *)*p);
253  if (!mrb_nil_p(mrb_funcall(mrb, mrb_accessor, "next", 0))) {
254  mrb_si = mrb_grn_scan_info_new(mrb, si);
255  mrb_funcall(mrb, mrb_si, "put_index", 3,
256  mrb_cptr_value(mrb, *p),
257  mrb_fixnum_value(sid),
258  mrb_fixnum_value(1));
259  } else {
260  mrb_si = mrb_grn_scan_info_new(mrb, si);
261  mrb_funcall(mrb, mrb_si, "put_index", 3,
262  mrb_cptr_value(mrb, index),
263  mrb_fixnum_value(sid),
264  mrb_fixnum_value(1));
265  }
266  }
267  } else {
268  grn_scan_info_set_query(si, *p);
269  }
270  }
271  }
272  si = NULL;
273  break;
274  case GRN_OP_AND :
275  case GRN_OP_OR :
276  case GRN_OP_AND_NOT :
277  case GRN_OP_ADJUST :
278  if (!grn_scan_info_put_logical_op(ctx, sis, &i, c->op, c - e->codes)) { return NULL; }
279  stat = SCAN_START;
280  break;
281  case GRN_OP_PUSH :
282  if (!si) {
283  si = grn_scan_info_open(ctx, c - e->codes);
284  if (!si) {
285  int j;
286  for (j = 0; j < i; j++) { grn_scan_info_close(ctx, sis[j]); }
287  GRN_FREE(sis);
288  return NULL;
289  }
290  }
291  if (c->value == var) {
292  stat = SCAN_VAR;
293  } else {
296  stat = SCAN_CONST;
297  }
298  break;
299  case GRN_OP_GET_VALUE :
300  switch (stat) {
301  case SCAN_START :
302  if (!si) {
303  si = grn_scan_info_open(ctx, c - e->codes);
304  if (!si) {
305  int j;
306  for (j = 0; j < i; j++) { grn_scan_info_close(ctx, sis[j]); }
307  GRN_FREE(sis);
308  return NULL;
309  }
310  }
311  // fallthru
312  case SCAN_CONST :
313  case SCAN_VAR :
314  stat = SCAN_COL1;
316  break;
317  case SCAN_COL1 :
318  {
319  int j;
320  grn_obj inspected;
321  GRN_TEXT_INIT(&inspected, 0);
322  GRN_TEXT_PUTS(ctx, &inspected, "<");
323  grn_inspect_name(ctx, &inspected, c->value);
324  GRN_TEXT_PUTS(ctx, &inspected, ">: <");
325  grn_inspect(ctx, &inspected, expr);
326  GRN_TEXT_PUTS(ctx, &inspected, ">");
328  "invalid expression: can't use column as a value: %.*s",
329  (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected));
330  GRN_OBJ_FIN(ctx, &inspected);
331  for (j = 0; j < i; j++) { grn_scan_info_close(ctx, sis[j]); }
332  GRN_FREE(sis);
333  return NULL;
334  }
335  stat = SCAN_COL2;
336  break;
337  case SCAN_COL2 :
338  break;
339  default :
340  break;
341  }
342  break;
343  case GRN_OP_CALL :
344  if (!si) {
345  si = grn_scan_info_open(ctx, c - e->codes);
346  if (!si) {
347  int j;
348  for (j = 0; j < i; j++) { grn_scan_info_close(ctx, sis[j]); }
349  GRN_FREE(sis);
350  return NULL;
351  }
352  }
353  if ((c->flags & GRN_EXPR_CODE_RELATIONAL_EXPRESSION) || c + 1 == ce) {
354  stat = SCAN_START;
355  mrb_si = mrb_grn_scan_info_new(mrb, si);
356  mrb_funcall(mrb, mrb_si, "op=", 1, mrb_fixnum_value(c->op));
357  mrb_funcall(mrb, mrb_si, "end=", 1, mrb_fixnum_value(c - e->codes));
358  sis[i++] = si;
359  /* better index resolving framework for functions should be implemented */
360  {
361  int sid, k;
362  grn_obj *index, *arg, **p = &arg;
363  for (k = 0; (arg = grn_scan_info_get_arg(ctx, si, k)) ; k++) {
364  if (GRN_DB_OBJP(*p)) {
365  if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) {
366  mrb_si = mrb_grn_scan_info_new(mrb, si);
367  mrb_funcall(mrb, mrb_si, "put_index", 3,
368  mrb_cptr_value(mrb, index),
369  mrb_fixnum_value(sid),
370  mrb_fixnum_value(1));
371  }
372  } else if (GRN_ACCESSORP(*p)) {
374  if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) {
375  mrb_si = mrb_grn_scan_info_new(mrb, si);
376  mrb_funcall(mrb, mrb_si, "put_index", 3,
377  mrb_cptr_value(mrb, index),
378  mrb_fixnum_value(sid),
379  mrb_fixnum_value(1));
380  }
381  } else {
382  grn_scan_info_set_query(si, *p);
383  }
384  }
385  }
386  si = NULL;
387  } else {
388  stat = SCAN_COL2;
389  }
390  break;
391  default :
392  break;
393  }
394  }
395  if (op == GRN_OP_OR && !size) {
396  // for debug
397  if (!(grn_scan_info_get_flags(sis[0]) & SCAN_PUSH) || (grn_scan_info_get_logical_op(sis[0]) != op)) {
398  int j;
399  ERR(GRN_INVALID_ARGUMENT, "invalid expr");
400  for (j = 0; j < i; j++) { grn_scan_info_close(ctx, sis[j]); }
401  GRN_FREE(sis);
402  return NULL;
403  } else {
404  grn_scan_info_set_flags(sis[0], grn_scan_info_get_flags(sis[0]) & ~SCAN_PUSH);
405  grn_scan_info_set_logical_op(sis[0], op);
406  }
407  } else {
408  if (!grn_scan_info_put_logical_op(ctx, sis, &i, op, c - e->codes)) { return NULL; }
409  }
410  *n = i;
411  return sis;
412 }
413 
414 static mrb_value
415 mrb_grn_expr_build(mrb_state *mrb, mrb_value self)
416 {
417  int *n;
418  uint32_t size;
419  scan_info **sis;
420  grn_operator op;
421  grn_obj *expr;
422  grn_ctx *ctx = (grn_ctx *)mrb->ud;
423  mrb_value mrb_expr, mrb_n;
424 
425  mrb_get_args(mrb, "ooii", &mrb_expr, &mrb_n, &op, &size);
426  expr = mrb_cptr(mrb_expr);
427  n = mrb_cptr(mrb_n);
428 
429  sis = scan_info_build(ctx, expr, n, op, size);
430  return mrb_cptr_value(mrb, sis);
431 }
432 
433 static mrb_value
434 mrb_grn_scan_info_initialize(mrb_state *mrb, mrb_value self)
435 {
437 
438  mrb_get_args(mrb, "o", &mrb_ptr);
439  DATA_TYPE(self) = &mrb_grn_scan_info_type;
440  DATA_PTR(self) = mrb_cptr(mrb_ptr);
441  return self;
442 }
443 
444 static mrb_value
445 mrb_grn_expr_code_initialize(mrb_state *mrb, mrb_value self)
446 {
448 
449  mrb_get_args(mrb, "o", &mrb_code);
450  DATA_TYPE(self) = &mrb_grn_expr_code_type;
451  DATA_PTR(self) = mrb_cptr(mrb_code);
452  return self;
453 }
454 
455 static mrb_value
456 mrb_grn_scan_info_put_index(mrb_state *mrb, mrb_value self)
457 {
458  int sid;
459  int32_t weight;
460  scan_info *si;
461  grn_ctx *ctx = (grn_ctx *)mrb->ud;
462  grn_obj *index;
463  mrb_value mrb_index;
464 
465  mrb_get_args(mrb, "oii", &mrb_index, &sid, &weight);
466  si = DATA_PTR(self);
467  index = mrb_cptr(mrb_index);
468  grn_scan_info_put_index(ctx, si, index, sid, weight);
469  return self;
470 }
471 
472 static mrb_value
473 mrb_grn_scan_info_set_op(mrb_state *mrb, mrb_value self)
474 {
475  scan_info *si;
476  grn_operator op;
477 
478  mrb_get_args(mrb, "i", &op);
479  si = DATA_PTR(self);
480  grn_scan_info_set_op(si, op);
481  return self;
482 }
483 
484 static mrb_value
485 mrb_grn_scan_info_set_end(mrb_state *mrb, mrb_value self)
486 {
487  scan_info *si;
488  int end;
489 
490  mrb_get_args(mrb, "i", &end);
491  si = DATA_PTR(self);
492  grn_scan_info_set_end(si, end);
493  return self;
494 }
495 
496 static mrb_value
497 mrb_grn_expr_code_get_weight(mrb_state *mrb, mrb_value self)
498 {
499  grn_ctx *ctx = (grn_ctx *)mrb->ud;
500 
501  return mrb_fixnum_value(grn_expr_code_get_weight(ctx, DATA_PTR(self)));
502 }
503 
504 void
506 {
507  mrb_state *mrb = ctx->impl->mrb.state;
508  struct RClass *module = ctx->impl->mrb.module;
509  struct RClass *klass;
510 
511  mrb_define_class_method(mrb, module,
512  "build", mrb_grn_expr_build, MRB_ARGS_REQ(4));
513 
514  klass = mrb_define_class_under(mrb, module, "ScanInfo", mrb->object_class);
516  mrb_define_method(mrb, klass, "initialize", mrb_grn_scan_info_initialize, MRB_ARGS_REQ(1));
517  mrb_define_method(mrb, klass, "put_index", mrb_grn_scan_info_put_index, MRB_ARGS_REQ(3));
518  mrb_define_method(mrb, klass, "op=", mrb_grn_scan_info_set_op, MRB_ARGS_REQ(1));
519  mrb_define_method(mrb, klass, "end=", mrb_grn_scan_info_set_end, MRB_ARGS_REQ(1));
520 
521  klass = mrb_define_class_under(mrb, module, "ExpressionCode", mrb->object_class);
523  mrb_define_method(mrb, klass, "initialize", mrb_grn_expr_code_initialize, MRB_ARGS_REQ(1));
524  mrb_define_method(mrb, klass, "weight", mrb_grn_expr_code_get_weight, MRB_ARGS_NONE());
525  grn_mrb_load(ctx, "expression.rb");
526 }
527 
528 scan_info **
529 grn_mrb_scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n,
530  grn_operator op, uint32_t size)
531 {
532  scan_info **sis;
533  mrb_state *mrb = ctx->impl->mrb.state;
534  mrb_value mrb_sis;
535 
536  mrb_sis = mrb_funcall(mrb, mrb_obj_value(ctx->impl->mrb.module), "build", 4,
537  mrb_cptr_value(mrb, expr),
538  mrb_cptr_value(mrb, n),
539  mrb_fixnum_value(op),
540  mrb_fixnum_value(size));
541  sis = mrb_cptr(mrb_sis);
542  return sis;
543 }
544 #endif