1 | /* -*- c-basic-offset: 2 -*- */ |
2 | /* |
3 | Copyright(C) 2013-2017 Brazil |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License version 2.1 as published by the Free Software Foundation. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with this library; if not, write to the Free Software |
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ |
18 | |
19 | #include "../grn_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 | #include <mruby/string.h> |
27 | #include <mruby/array.h> |
28 | #include <mruby/hash.h> |
29 | |
30 | #include "../grn_expr.h" |
31 | #include "../grn_proc.h" |
32 | #include "../grn_util.h" |
33 | #include "../grn_mrb.h" |
34 | #include "mrb_accessor.h" |
35 | #include "mrb_ctx.h" |
36 | #include "mrb_expr.h" |
37 | #include "mrb_operator.h" |
38 | #include "mrb_converter.h" |
39 | #include "mrb_options.h" |
40 | |
41 | static struct mrb_data_type mrb_grn_scan_info_type = { |
42 | "Groonga::ScanInfo" , |
43 | NULL |
44 | }; |
45 | static struct mrb_data_type mrb_grn_expr_code_type = { |
46 | "Groonga::ExpressionCode" , |
47 | NULL |
48 | }; |
49 | static struct mrb_data_type mrb_grn_expression_type = { |
50 | "Groonga::Expression" , |
51 | NULL |
52 | }; |
53 | |
54 | static mrb_value |
55 | mrb_grn_scan_info_new(mrb_state *mrb, scan_info *scan_info) |
56 | { |
57 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
58 | struct RClass *module = ctx->impl->mrb.module; |
59 | struct RClass *klass; |
60 | mrb_value mrb_scan_info; |
61 | |
62 | mrb_scan_info = mrb_cptr_value(mrb, scan_info); |
63 | klass = mrb_class_get_under(mrb, module, "ScanInfo" ); |
64 | return mrb_obj_new(mrb, klass, 1, &mrb_scan_info); |
65 | } |
66 | |
67 | static mrb_value |
68 | mrb_grn_expr_code_new(mrb_state *mrb, grn_expr_code *code) |
69 | { |
70 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
71 | struct RClass *module = ctx->impl->mrb.module; |
72 | struct RClass *klass; |
73 | mrb_value mrb_code; |
74 | |
75 | mrb_code = mrb_cptr_value(mrb, code); |
76 | klass = mrb_class_get_under(mrb, module, "ExpressionCode" ); |
77 | return mrb_obj_new(mrb, klass, 1, &mrb_code); |
78 | } |
79 | |
80 | static mrb_value |
81 | mrb_grn_scan_info_initialize(mrb_state *mrb, mrb_value self) |
82 | { |
83 | mrb_value mrb_ptr; |
84 | |
85 | mrb_get_args(mrb, "o" , &mrb_ptr); |
86 | DATA_TYPE(self) = &mrb_grn_scan_info_type; |
87 | DATA_PTR(self) = mrb_cptr(mrb_ptr); |
88 | return self; |
89 | } |
90 | |
91 | static mrb_value |
92 | mrb_grn_expr_code_initialize(mrb_state *mrb, mrb_value self) |
93 | { |
94 | mrb_value mrb_code; |
95 | |
96 | mrb_get_args(mrb, "o" , &mrb_code); |
97 | DATA_TYPE(self) = &mrb_grn_expr_code_type; |
98 | DATA_PTR(self) = mrb_cptr(mrb_code); |
99 | return self; |
100 | } |
101 | |
102 | static mrb_value |
103 | mrb_grn_scan_info_put_index(mrb_state *mrb, mrb_value self) |
104 | { |
105 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
106 | scan_info *si; |
107 | mrb_value mrb_index; |
108 | mrb_int sid; |
109 | mrb_int weight; |
110 | mrb_value mrb_scorer; |
111 | mrb_value mrb_scorer_args_expr; |
112 | mrb_int scorer_args_expr_offset; |
113 | grn_obj *index; |
114 | grn_obj *scorer = NULL; |
115 | grn_obj *scorer_args_expr = NULL; |
116 | |
117 | mrb_get_args(mrb, "oiiooi" , |
118 | &mrb_index, &sid, &weight, |
119 | &mrb_scorer, |
120 | &mrb_scorer_args_expr, |
121 | &scorer_args_expr_offset); |
122 | si = DATA_PTR(self); |
123 | index = DATA_PTR(mrb_index); |
124 | if (!mrb_nil_p(mrb_scorer)) { |
125 | scorer = DATA_PTR(mrb_scorer); |
126 | } |
127 | if (!mrb_nil_p(mrb_scorer_args_expr)) { |
128 | scorer_args_expr = DATA_PTR(mrb_scorer_args_expr); |
129 | } |
130 | grn_scan_info_put_index(ctx, si, index, sid, weight, |
131 | scorer, |
132 | scorer_args_expr, |
133 | scorer_args_expr_offset); |
134 | return self; |
135 | } |
136 | |
137 | static mrb_value |
138 | mrb_grn_scan_info_get_op(mrb_state *mrb, mrb_value self) |
139 | { |
140 | scan_info *si; |
141 | grn_operator op; |
142 | |
143 | si = DATA_PTR(self); |
144 | op = grn_scan_info_get_op(si); |
145 | return grn_mrb_value_from_operator(mrb, op); |
146 | } |
147 | |
148 | static mrb_value |
149 | mrb_grn_scan_info_set_op(mrb_state *mrb, mrb_value self) |
150 | { |
151 | scan_info *si; |
152 | mrb_value mrb_op; |
153 | grn_operator op; |
154 | |
155 | mrb_get_args(mrb, "o" , &mrb_op); |
156 | si = DATA_PTR(self); |
157 | op = grn_mrb_value_to_operator(mrb, mrb_op); |
158 | grn_scan_info_set_op(si, op); |
159 | return self; |
160 | } |
161 | |
162 | static mrb_value |
163 | mrb_grn_scan_info_set_end(mrb_state *mrb, mrb_value self) |
164 | { |
165 | scan_info *si; |
166 | mrb_int end; |
167 | |
168 | mrb_get_args(mrb, "i" , &end); |
169 | si = DATA_PTR(self); |
170 | grn_scan_info_set_end(si, end); |
171 | return self; |
172 | } |
173 | |
174 | static mrb_value |
175 | mrb_grn_scan_info_set_query(mrb_state *mrb, mrb_value self) |
176 | { |
177 | scan_info *si; |
178 | mrb_value mrb_query; |
179 | |
180 | mrb_get_args(mrb, "o" , &mrb_query); |
181 | si = DATA_PTR(self); |
182 | if (mrb_nil_p(mrb_query)) { |
183 | grn_scan_info_set_query(si, NULL); |
184 | } else { |
185 | grn_scan_info_set_query(si, DATA_PTR(mrb_query)); |
186 | } |
187 | return self; |
188 | } |
189 | |
190 | static mrb_value |
191 | mrb_grn_scan_info_set_flags(mrb_state *mrb, mrb_value self) |
192 | { |
193 | scan_info *si; |
194 | mrb_int flags; |
195 | |
196 | mrb_get_args(mrb, "i" , &flags); |
197 | si = DATA_PTR(self); |
198 | grn_scan_info_set_flags(si, flags); |
199 | return self; |
200 | } |
201 | |
202 | static mrb_value |
203 | mrb_grn_scan_info_get_flags(mrb_state *mrb, mrb_value self) |
204 | { |
205 | scan_info *si; |
206 | int flags; |
207 | |
208 | si = DATA_PTR(self); |
209 | flags = grn_scan_info_get_flags(si); |
210 | return mrb_fixnum_value(flags); |
211 | } |
212 | |
213 | static mrb_value |
214 | mrb_grn_scan_info_set_logical_op(mrb_state *mrb, mrb_value self) |
215 | { |
216 | scan_info *si; |
217 | mrb_value mrb_logical_op; |
218 | grn_operator logical_op; |
219 | |
220 | mrb_get_args(mrb, "o" , &mrb_logical_op); |
221 | si = DATA_PTR(self); |
222 | logical_op = grn_mrb_value_to_operator(mrb, mrb_logical_op); |
223 | grn_scan_info_set_logical_op(si, logical_op); |
224 | return self; |
225 | } |
226 | |
227 | static mrb_value |
228 | mrb_grn_scan_info_get_logical_op(mrb_state *mrb, mrb_value self) |
229 | { |
230 | scan_info *si; |
231 | grn_operator logical_op; |
232 | |
233 | si = DATA_PTR(self); |
234 | logical_op = grn_scan_info_get_logical_op(si); |
235 | return grn_mrb_value_from_operator(mrb, logical_op); |
236 | } |
237 | |
238 | static mrb_value |
239 | mrb_grn_scan_info_set_max_interval(mrb_state *mrb, mrb_value self) |
240 | { |
241 | scan_info *si; |
242 | mrb_int max_interval; |
243 | |
244 | mrb_get_args(mrb, "i" , &max_interval); |
245 | si = DATA_PTR(self); |
246 | grn_scan_info_set_max_interval(si, max_interval); |
247 | return self; |
248 | } |
249 | |
250 | static mrb_value |
251 | mrb_grn_scan_info_get_max_interval(mrb_state *mrb, mrb_value self) |
252 | { |
253 | scan_info *si; |
254 | int max_interval; |
255 | |
256 | si = DATA_PTR(self); |
257 | max_interval = grn_scan_info_get_max_interval(si); |
258 | return mrb_fixnum_value(max_interval); |
259 | } |
260 | |
261 | static mrb_value |
262 | mrb_grn_scan_info_set_similarity_threshold(mrb_state *mrb, mrb_value self) |
263 | { |
264 | scan_info *si; |
265 | mrb_int similarity_threshold; |
266 | |
267 | mrb_get_args(mrb, "i" , &similarity_threshold); |
268 | si = DATA_PTR(self); |
269 | grn_scan_info_set_similarity_threshold(si, similarity_threshold); |
270 | return self; |
271 | } |
272 | |
273 | static mrb_value |
274 | mrb_grn_scan_info_get_similarity_threshold(mrb_state *mrb, mrb_value self) |
275 | { |
276 | scan_info *si; |
277 | int similarity_threshold; |
278 | |
279 | si = DATA_PTR(self); |
280 | similarity_threshold = grn_scan_info_get_similarity_threshold(si); |
281 | return mrb_fixnum_value(similarity_threshold); |
282 | } |
283 | |
284 | static mrb_value |
285 | mrb_grn_scan_info_get_arg(mrb_state *mrb, mrb_value self) |
286 | { |
287 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
288 | scan_info *si; |
289 | mrb_int index; |
290 | grn_obj *arg; |
291 | |
292 | mrb_get_args(mrb, "i" , &index); |
293 | |
294 | si = DATA_PTR(self); |
295 | arg = grn_scan_info_get_arg(ctx, si, index); |
296 | |
297 | return grn_mrb_value_from_grn_obj(mrb, arg); |
298 | } |
299 | |
300 | static mrb_value |
301 | mrb_grn_scan_info_push_arg(mrb_state *mrb, mrb_value self) |
302 | { |
303 | scan_info *si; |
304 | mrb_value mrb_arg; |
305 | grn_bool success; |
306 | |
307 | mrb_get_args(mrb, "o" , &mrb_arg); |
308 | |
309 | si = DATA_PTR(self); |
310 | success = grn_scan_info_push_arg(si, DATA_PTR(mrb_arg)); |
311 | |
312 | return mrb_bool_value(success); |
313 | } |
314 | |
315 | static mrb_value |
316 | mrb_grn_scan_info_get_start_position(mrb_state *mrb, mrb_value self) |
317 | { |
318 | scan_info *si; |
319 | int start_position; |
320 | |
321 | si = DATA_PTR(self); |
322 | start_position = grn_scan_info_get_start_position(si); |
323 | return mrb_fixnum_value(start_position); |
324 | } |
325 | |
326 | static mrb_value |
327 | mrb_grn_scan_info_set_start_position(mrb_state *mrb, mrb_value self) |
328 | { |
329 | scan_info *si; |
330 | mrb_int start_position; |
331 | |
332 | mrb_get_args(mrb, "i" , &start_position); |
333 | si = DATA_PTR(self); |
334 | grn_scan_info_set_start_position(si, start_position); |
335 | return self; |
336 | } |
337 | |
338 | static mrb_value |
339 | mrb_grn_scan_info_reset_position(mrb_state *mrb, mrb_value self) |
340 | { |
341 | scan_info *si; |
342 | |
343 | si = DATA_PTR(self); |
344 | grn_scan_info_reset_position(si); |
345 | return self; |
346 | } |
347 | |
348 | static mrb_value |
349 | mrb_grn_expr_code_inspect(mrb_state *mrb, mrb_value self) |
350 | { |
351 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
352 | grn_expr_code *code; |
353 | mrb_value inspected; |
354 | |
355 | code = DATA_PTR(self); |
356 | |
357 | inspected = mrb_str_buf_new(mrb, 48); |
358 | |
359 | mrb_str_cat_lit(mrb, inspected, "#<" ); |
360 | mrb_str_cat_cstr(mrb, inspected, mrb_obj_classname(mrb, self)); |
361 | mrb_str_cat_lit(mrb, inspected, ":" ); |
362 | mrb_str_concat(mrb, inspected, mrb_ptr_to_str(mrb, mrb_cptr(self))); |
363 | |
364 | { |
365 | int32_t weight; |
366 | uint32_t offset; |
367 | |
368 | weight = grn_expr_code_get_weight(ctx, DATA_PTR(self), &offset); |
369 | |
370 | mrb_str_cat_lit(mrb, inspected, " weight=" ); |
371 | mrb_str_concat(mrb, inspected, |
372 | mrb_funcall(mrb, |
373 | mrb_fixnum_value(weight), |
374 | "inspect" , |
375 | 0)); |
376 | mrb_str_cat_lit(mrb, inspected, ", offset=" ); |
377 | mrb_str_concat(mrb, inspected, |
378 | mrb_funcall(mrb, |
379 | mrb_fixnum_value(offset), |
380 | "inspect" , |
381 | 0)); |
382 | } |
383 | |
384 | mrb_str_cat_lit(mrb, inspected, ", n_args=" ); |
385 | mrb_str_concat(mrb, inspected, |
386 | mrb_funcall(mrb, |
387 | mrb_fixnum_value(code->nargs), |
388 | "inspect" , |
389 | 0)); |
390 | |
391 | mrb_str_cat_lit(mrb, inspected, ", modify=" ); |
392 | mrb_str_concat(mrb, inspected, |
393 | mrb_funcall(mrb, |
394 | mrb_fixnum_value(code->modify), |
395 | "inspect" , |
396 | 0)); |
397 | |
398 | mrb_str_cat_lit(mrb, inspected, ", op=" ); |
399 | mrb_str_concat(mrb, inspected, |
400 | mrb_funcall(mrb, |
401 | grn_mrb_value_from_operator(mrb, code->op), |
402 | "inspect" , |
403 | 0)); |
404 | |
405 | mrb_str_cat_lit(mrb, inspected, ", flags=" ); |
406 | mrb_str_concat(mrb, inspected, |
407 | mrb_funcall(mrb, |
408 | mrb_fixnum_value(code->flags), |
409 | "inspect" , |
410 | 0)); |
411 | |
412 | mrb_str_cat_lit(mrb, inspected, ", value=" ); |
413 | mrb_str_concat(mrb, inspected, |
414 | mrb_funcall(mrb, |
415 | grn_mrb_value_from_grn_obj(mrb, code->value), |
416 | "inspect" , |
417 | 0)); |
418 | |
419 | mrb_str_cat_lit(mrb, inspected, ">" ); |
420 | |
421 | return inspected; |
422 | } |
423 | |
424 | static mrb_value |
425 | mrb_grn_expr_code_get_weight(mrb_state *mrb, mrb_value self) |
426 | { |
427 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
428 | int32_t weight; |
429 | uint32_t offset; |
430 | mrb_value mrb_values[2]; |
431 | |
432 | weight = grn_expr_code_get_weight(ctx, DATA_PTR(self), &offset); |
433 | mrb_values[0] = mrb_fixnum_value(weight); |
434 | mrb_values[1] = mrb_fixnum_value(offset); |
435 | return mrb_ary_new_from_values(mrb, 2, mrb_values); |
436 | } |
437 | |
438 | static mrb_value |
439 | mrb_grn_expr_code_get_value(mrb_state *mrb, mrb_value self) |
440 | { |
441 | grn_expr_code *expr_code; |
442 | |
443 | expr_code = DATA_PTR(self); |
444 | return grn_mrb_value_from_grn_obj(mrb, expr_code->value); |
445 | } |
446 | |
447 | static mrb_value |
448 | mrb_grn_expr_code_get_n_args(mrb_state *mrb, mrb_value self) |
449 | { |
450 | grn_expr_code *expr_code; |
451 | |
452 | expr_code = DATA_PTR(self); |
453 | return mrb_fixnum_value(expr_code->nargs); |
454 | } |
455 | |
456 | static mrb_value |
457 | mrb_grn_expr_code_get_op(mrb_state *mrb, mrb_value self) |
458 | { |
459 | grn_expr_code *expr_code; |
460 | |
461 | expr_code = DATA_PTR(self); |
462 | return grn_mrb_value_from_operator(mrb, expr_code->op); |
463 | } |
464 | |
465 | static mrb_value |
466 | mrb_grn_expr_code_get_flags(mrb_state *mrb, mrb_value self) |
467 | { |
468 | grn_expr_code *expr_code; |
469 | |
470 | expr_code = DATA_PTR(self); |
471 | return mrb_fixnum_value(expr_code->flags); |
472 | } |
473 | |
474 | static mrb_value |
475 | mrb_grn_expr_code_get_modify(mrb_state *mrb, mrb_value self) |
476 | { |
477 | grn_expr_code *expr_code; |
478 | |
479 | expr_code = DATA_PTR(self); |
480 | return mrb_fixnum_value(expr_code->modify); |
481 | } |
482 | |
483 | static mrb_value |
484 | mrb_grn_expression_class_create(mrb_state *mrb, mrb_value klass) |
485 | { |
486 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
487 | mrb_value mrb_expr; |
488 | mrb_value mrb_table; |
489 | mrb_value mrb_new_arguments[1]; |
490 | grn_obj *expr, *variable = NULL; |
491 | |
492 | mrb_get_args(mrb, "o" , &mrb_table); |
493 | if (mrb_nil_p(mrb_table)) { |
494 | expr = grn_expr_create(ctx, NULL, 0); |
495 | } else { |
496 | grn_obj *table = DATA_PTR(mrb_table); |
497 | GRN_EXPR_CREATE_FOR_QUERY(ctx, table, expr, variable); |
498 | } |
499 | |
500 | if (!expr) { |
501 | grn_mrb_ctx_check(mrb); |
502 | return mrb_nil_value(); |
503 | } |
504 | |
505 | mrb_new_arguments[0] = mrb_cptr_value(mrb, expr); |
506 | mrb_expr = mrb_obj_new(mrb, mrb_class_ptr(klass), 1, mrb_new_arguments); |
507 | { |
508 | mrb_value mrb_variable = mrb_nil_value(); |
509 | if (variable) { |
510 | mrb_variable = grn_mrb_value_from_grn_obj(mrb, variable); |
511 | } |
512 | mrb_iv_set(mrb, mrb_expr, mrb_intern_lit(mrb, "@variable" ), mrb_variable); |
513 | } |
514 | |
515 | return mrb_expr; |
516 | } |
517 | |
518 | static mrb_value |
519 | mrb_grn_expression_initialize(mrb_state *mrb, mrb_value self) |
520 | { |
521 | mrb_value mrb_expression_ptr; |
522 | |
523 | mrb_get_args(mrb, "o" , &mrb_expression_ptr); |
524 | DATA_TYPE(self) = &mrb_grn_expression_type; |
525 | DATA_PTR(self) = mrb_cptr(mrb_expression_ptr); |
526 | return self; |
527 | } |
528 | |
529 | static mrb_value |
530 | mrb_grn_expression_is_empty(mrb_state *mrb, mrb_value self) |
531 | { |
532 | grn_expr *expr; |
533 | |
534 | expr = DATA_PTR(self); |
535 | return mrb_bool_value(expr->codes_curr == 0); |
536 | } |
537 | |
538 | static mrb_value |
539 | mrb_grn_expression_codes(mrb_state *mrb, mrb_value self) |
540 | { |
541 | grn_expr *expr; |
542 | mrb_value mrb_codes; |
543 | int i; |
544 | |
545 | expr = DATA_PTR(self); |
546 | mrb_codes = mrb_ary_new_capa(mrb, expr->codes_curr); |
547 | for (i = 0; i < expr->codes_curr; i++) { |
548 | grn_expr_code *code = expr->codes + i; |
549 | mrb_ary_push(mrb, mrb_codes, mrb_grn_expr_code_new(mrb, code)); |
550 | } |
551 | |
552 | return mrb_codes; |
553 | } |
554 | |
555 | static mrb_value |
556 | mrb_grn_expression_array_reference(mrb_state *mrb, mrb_value self) |
557 | { |
558 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
559 | grn_obj *expr; |
560 | mrb_value mrb_key; |
561 | grn_obj *var; |
562 | |
563 | mrb_get_args(mrb, "o" , &mrb_key); |
564 | |
565 | expr = DATA_PTR(self); |
566 | switch (mrb_type(mrb_key)) { |
567 | case MRB_TT_SYMBOL : |
568 | { |
569 | const char *name; |
570 | mrb_int name_length; |
571 | |
572 | name = mrb_sym2name_len(mrb, mrb_symbol(mrb_key), &name_length); |
573 | var = grn_expr_get_var(ctx, expr, name, name_length); |
574 | } |
575 | break; |
576 | case MRB_TT_STRING : |
577 | var = grn_expr_get_var(ctx, expr, |
578 | RSTRING_PTR(mrb_key), RSTRING_LEN(mrb_key)); |
579 | break; |
580 | case MRB_TT_FIXNUM : |
581 | var = grn_expr_get_var_by_offset(ctx, expr, mrb_fixnum(mrb_key)); |
582 | break; |
583 | default : |
584 | mrb_raisef(mrb, E_ARGUMENT_ERROR, |
585 | "key must be Symbol, String or Fixnum: %S" , |
586 | mrb_key); |
587 | break; |
588 | } |
589 | |
590 | return grn_mrb_value_from_grn_obj(mrb, var); |
591 | } |
592 | |
593 | static mrb_value |
594 | mrb_grn_expression_set_condition(mrb_state *mrb, mrb_value self) |
595 | { |
596 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
597 | grn_obj *expr; |
598 | mrb_value mrb_condition; |
599 | grn_obj *condition_ptr; |
600 | |
601 | mrb_get_args(mrb, "o" , &mrb_condition); |
602 | |
603 | expr = DATA_PTR(self); |
604 | condition_ptr = grn_expr_get_or_add_var(ctx, |
605 | expr, |
606 | GRN_SELECT_INTERNAL_VAR_CONDITION, |
607 | GRN_SELECT_INTERNAL_VAR_CONDITION_LEN); |
608 | GRN_OBJ_FIN(ctx, condition_ptr); |
609 | GRN_PTR_INIT(condition_ptr, 0, GRN_DB_OBJECT); |
610 | GRN_PTR_SET(ctx, condition_ptr, GRN_MRB_DATA_PTR(mrb_condition)); |
611 | |
612 | return mrb_nil_value(); |
613 | } |
614 | |
615 | static mrb_value |
616 | mrb_grn_expression_take_object(mrb_state *mrb, mrb_value self) |
617 | { |
618 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
619 | grn_obj *expr; |
620 | mrb_value mrb_object; |
621 | grn_obj *grn_object; |
622 | |
623 | mrb_get_args(mrb, "o" , &mrb_object); |
624 | expr = DATA_PTR(self); |
625 | grn_object = DATA_PTR(mrb_object); |
626 | grn_expr_take_obj(ctx, expr, grn_object); |
627 | |
628 | return mrb_object; |
629 | } |
630 | |
631 | static mrb_value |
632 | mrb_grn_expression_allocate_constant(mrb_state *mrb, mrb_value self) |
633 | { |
634 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
635 | grn_obj *expr; |
636 | mrb_value mrb_object; |
637 | grn_obj *grn_object; |
638 | |
639 | mrb_get_args(mrb, "o" , &mrb_object); |
640 | expr = DATA_PTR(self); |
641 | |
642 | switch (mrb_type(mrb_object)) { |
643 | case MRB_TT_STRING: |
644 | grn_object = grn_expr_alloc_const(ctx, expr); |
645 | if (!grn_object) { |
646 | grn_mrb_ctx_check(mrb); |
647 | } |
648 | GRN_TEXT_INIT(grn_object, 0); |
649 | GRN_TEXT_SET(ctx, grn_object, |
650 | RSTRING_PTR(mrb_object), RSTRING_LEN(mrb_object)); |
651 | break; |
652 | case MRB_TT_TRUE: |
653 | grn_object = grn_expr_alloc_const(ctx, expr); |
654 | if (!grn_object) { |
655 | grn_mrb_ctx_check(mrb); |
656 | } |
657 | GRN_BOOL_INIT(grn_object, 0); |
658 | GRN_BOOL_SET(ctx, grn_object, GRN_TRUE); |
659 | break; |
660 | default: |
661 | mrb_raisef(mrb, E_ARGUMENT_ERROR, "unsupported type: %S" , mrb_object); |
662 | break; |
663 | } |
664 | |
665 | return grn_mrb_value_from_grn_obj(mrb, grn_object); |
666 | } |
667 | |
668 | static mrb_value |
669 | mrb_grn_expression_parse(mrb_state *mrb, mrb_value self) |
670 | { |
671 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
672 | grn_obj *expr; |
673 | char *query; |
674 | mrb_int query_size; |
675 | grn_obj *default_column = NULL; |
676 | grn_operator default_mode = GRN_OP_MATCH; |
677 | grn_operator default_operator = GRN_OP_AND; |
678 | grn_expr_flags flags = GRN_EXPR_SYNTAX_SCRIPT; |
679 | mrb_value mrb_options = mrb_nil_value(); |
680 | |
681 | expr = DATA_PTR(self); |
682 | mrb_get_args(mrb, "s|H" , &query, &query_size, &mrb_options); |
683 | |
684 | if (!mrb_nil_p(mrb_options)) { |
685 | mrb_value mrb_default_column; |
686 | mrb_value mrb_flags; |
687 | |
688 | mrb_default_column = |
689 | grn_mrb_options_get_lit(mrb, mrb_options, "default_column" ); |
690 | default_column = GRN_MRB_DATA_PTR(mrb_default_column); |
691 | |
692 | mrb_flags = grn_mrb_options_get_lit(mrb, mrb_options, "flags" ); |
693 | if (!mrb_nil_p(mrb_flags)) { |
694 | flags = mrb_fixnum(mrb_flags); |
695 | } |
696 | } |
697 | |
698 | grn_expr_parse(ctx, expr, query, query_size, default_column, |
699 | default_mode, default_operator, flags); |
700 | grn_mrb_ctx_check(mrb); |
701 | |
702 | return mrb_nil_value(); |
703 | } |
704 | |
705 | static mrb_value |
706 | mrb_grn_expression_append_object(mrb_state *mrb, mrb_value self) |
707 | { |
708 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
709 | grn_obj *expr; |
710 | mrb_value mrb_object; |
711 | grn_obj *object; |
712 | mrb_value mrb_op; |
713 | grn_operator op; |
714 | mrb_int n_args; |
715 | |
716 | expr = DATA_PTR(self); |
717 | mrb_get_args(mrb, "ooi" , &mrb_object, &mrb_op, &n_args); |
718 | |
719 | object = DATA_PTR(mrb_object); |
720 | op = grn_mrb_value_to_operator(mrb, mrb_op); |
721 | grn_expr_append_obj(ctx, expr, object, op, n_args); |
722 | grn_mrb_ctx_check(mrb); |
723 | |
724 | return mrb_nil_value(); |
725 | } |
726 | |
727 | static mrb_value |
728 | mrb_grn_expression_append_constant(mrb_state *mrb, mrb_value self) |
729 | { |
730 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
731 | grn_obj *expr; |
732 | mrb_value mrb_constant; |
733 | mrb_value mrb_op; |
734 | grn_operator op; |
735 | mrb_int n_args; |
736 | |
737 | expr = DATA_PTR(self); |
738 | mrb_get_args(mrb, "ooi" , &mrb_constant, &mrb_op, &n_args); |
739 | |
740 | op = grn_mrb_value_to_operator(mrb, mrb_op); |
741 | switch (mrb_type(mrb_constant)) { |
742 | case MRB_TT_FALSE : |
743 | if (mrb_nil_p(mrb_constant)) { |
744 | grn_obj constant; |
745 | GRN_VOID_INIT(&constant); |
746 | grn_expr_append_const(ctx, expr, &constant, op, n_args); |
747 | GRN_OBJ_FIN(ctx, &constant); |
748 | } else { |
749 | grn_obj constant; |
750 | GRN_BOOL_INIT(&constant, 0); |
751 | GRN_BOOL_SET(ctx, &constant, GRN_FALSE); |
752 | grn_expr_append_const(ctx, expr, &constant, op, n_args); |
753 | GRN_OBJ_FIN(ctx, &constant); |
754 | } |
755 | break; |
756 | case MRB_TT_TRUE : |
757 | { |
758 | grn_obj constant; |
759 | GRN_BOOL_INIT(&constant, 0); |
760 | GRN_BOOL_SET(ctx, &constant, GRN_TRUE); |
761 | grn_expr_append_const(ctx, expr, &constant, op, n_args); |
762 | GRN_OBJ_FIN(ctx, &constant); |
763 | } |
764 | break; |
765 | case MRB_TT_FIXNUM : |
766 | grn_expr_append_const_int(ctx, expr, mrb_fixnum(mrb_constant), op, n_args); |
767 | break; |
768 | case MRB_TT_SYMBOL : |
769 | { |
770 | const char *value; |
771 | mrb_int value_length; |
772 | |
773 | value = mrb_sym2name_len(mrb, mrb_symbol(mrb_constant), &value_length); |
774 | grn_expr_append_const_str(ctx, expr, value, value_length, op, n_args); |
775 | } |
776 | break; |
777 | case MRB_TT_FLOAT : |
778 | { |
779 | grn_obj constant; |
780 | GRN_FLOAT_INIT(&constant, 0); |
781 | GRN_FLOAT_SET(ctx, &constant, mrb_float(mrb_constant)); |
782 | grn_expr_append_const(ctx, expr, &constant, op, n_args); |
783 | GRN_OBJ_FIN(ctx, &constant); |
784 | } |
785 | break; |
786 | case MRB_TT_STRING : |
787 | grn_expr_append_const_str(ctx, expr, |
788 | RSTRING_PTR(mrb_constant), |
789 | RSTRING_LEN(mrb_constant), |
790 | op, n_args); |
791 | break; |
792 | default : |
793 | { |
794 | struct RClass *klass; |
795 | |
796 | klass = mrb_class(mrb, mrb_constant); |
797 | if (klass == ctx->impl->mrb.builtin.time_class) { |
798 | grn_obj constant; |
799 | mrb_value mrb_sec; |
800 | mrb_value mrb_usec; |
801 | |
802 | mrb_sec = mrb_funcall(mrb, mrb_constant, "to_i" , 0); |
803 | mrb_usec = mrb_funcall(mrb, mrb_constant, "usec" , 0); |
804 | GRN_TIME_INIT(&constant, 0); |
805 | GRN_TIME_SET(ctx, &constant, |
806 | GRN_TIME_PACK(mrb_fixnum(mrb_sec), mrb_fixnum(mrb_usec))); |
807 | grn_expr_append_const(ctx, expr, &constant, op, n_args); |
808 | GRN_OBJ_FIN(ctx, &constant); |
809 | } else { |
810 | mrb_raisef(mrb, E_ARGUMENT_ERROR, |
811 | "unsupported constant to append to expression: %S" , |
812 | mrb_constant); |
813 | } |
814 | } |
815 | break; |
816 | } |
817 | |
818 | grn_mrb_ctx_check(mrb); |
819 | |
820 | return mrb_nil_value(); |
821 | } |
822 | |
823 | static mrb_value |
824 | mrb_grn_expression_append_operator(mrb_state *mrb, mrb_value self) |
825 | { |
826 | grn_ctx *ctx = (grn_ctx *)mrb->ud; |
827 | grn_obj *expr; |
828 | mrb_value mrb_op; |
829 | mrb_int n_args; |
830 | grn_operator op; |
831 | |
832 | expr = DATA_PTR(self); |
833 | mrb_get_args(mrb, "oi" , &mrb_op, &n_args); |
834 | |
835 | op = grn_mrb_value_to_operator(mrb, mrb_op); |
836 | grn_expr_append_op(ctx, expr, op, n_args); |
837 | grn_mrb_ctx_check(mrb); |
838 | |
839 | return mrb_nil_value(); |
840 | } |
841 | |
842 | void |
843 | grn_mrb_expr_init(grn_ctx *ctx) |
844 | { |
845 | mrb_state *mrb = ctx->impl->mrb.state; |
846 | struct RClass *module = ctx->impl->mrb.module; |
847 | struct RClass *object_class = ctx->impl->mrb.object_class; |
848 | struct RClass *klass; |
849 | |
850 | klass = mrb_define_class_under(mrb, module, "ScanInfo" , mrb->object_class); |
851 | MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); |
852 | mrb_define_method(mrb, klass, "initialize" , |
853 | mrb_grn_scan_info_initialize, MRB_ARGS_REQ(1)); |
854 | mrb_define_method(mrb, klass, "put_index" , |
855 | mrb_grn_scan_info_put_index, MRB_ARGS_REQ(6)); |
856 | mrb_define_method(mrb, klass, "op" , |
857 | mrb_grn_scan_info_get_op, MRB_ARGS_NONE()); |
858 | mrb_define_method(mrb, klass, "op=" , |
859 | mrb_grn_scan_info_set_op, MRB_ARGS_REQ(1)); |
860 | mrb_define_method(mrb, klass, "end=" , |
861 | mrb_grn_scan_info_set_end, MRB_ARGS_REQ(1)); |
862 | mrb_define_method(mrb, klass, "query=" , |
863 | mrb_grn_scan_info_set_query, MRB_ARGS_REQ(1)); |
864 | mrb_define_method(mrb, klass, "flags" , |
865 | mrb_grn_scan_info_get_flags, MRB_ARGS_NONE()); |
866 | mrb_define_method(mrb, klass, "flags=" , |
867 | mrb_grn_scan_info_set_flags, MRB_ARGS_REQ(1)); |
868 | mrb_define_method(mrb, klass, "logical_op" , |
869 | mrb_grn_scan_info_get_logical_op, MRB_ARGS_NONE()); |
870 | mrb_define_method(mrb, klass, "logical_op=" , |
871 | mrb_grn_scan_info_set_logical_op, MRB_ARGS_REQ(1)); |
872 | mrb_define_method(mrb, klass, "max_interval" , |
873 | mrb_grn_scan_info_get_max_interval, MRB_ARGS_NONE()); |
874 | mrb_define_method(mrb, klass, "max_interval=" , |
875 | mrb_grn_scan_info_set_max_interval, MRB_ARGS_REQ(1)); |
876 | mrb_define_method(mrb, klass, "similarity_threshold" , |
877 | mrb_grn_scan_info_get_similarity_threshold, MRB_ARGS_NONE()); |
878 | mrb_define_method(mrb, klass, "similarity_threshold=" , |
879 | mrb_grn_scan_info_set_similarity_threshold, MRB_ARGS_REQ(1)); |
880 | mrb_define_method(mrb, klass, "get_arg" , |
881 | mrb_grn_scan_info_get_arg, MRB_ARGS_REQ(1)); |
882 | mrb_define_method(mrb, klass, "push_arg" , |
883 | mrb_grn_scan_info_push_arg, MRB_ARGS_REQ(1)); |
884 | mrb_define_method(mrb, klass, "start_position" , |
885 | mrb_grn_scan_info_get_start_position, MRB_ARGS_NONE()); |
886 | mrb_define_method(mrb, klass, "start_position=" , |
887 | mrb_grn_scan_info_set_start_position, MRB_ARGS_REQ(1)); |
888 | mrb_define_method(mrb, klass, "reset_position" , |
889 | mrb_grn_scan_info_reset_position, MRB_ARGS_NONE()); |
890 | |
891 | klass = mrb_define_class_under(mrb, module, |
892 | "ExpressionCode" , mrb->object_class); |
893 | MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); |
894 | mrb_define_method(mrb, klass, "initialize" , |
895 | mrb_grn_expr_code_initialize, MRB_ARGS_REQ(1)); |
896 | mrb_define_method(mrb, klass, "inspect" , |
897 | mrb_grn_expr_code_inspect, MRB_ARGS_NONE()); |
898 | mrb_define_method(mrb, klass, "weight" , |
899 | mrb_grn_expr_code_get_weight, MRB_ARGS_NONE()); |
900 | mrb_define_method(mrb, klass, "value" , |
901 | mrb_grn_expr_code_get_value, MRB_ARGS_NONE()); |
902 | mrb_define_method(mrb, klass, "n_args" , |
903 | mrb_grn_expr_code_get_n_args, MRB_ARGS_NONE()); |
904 | mrb_define_method(mrb, klass, "op" , |
905 | mrb_grn_expr_code_get_op, MRB_ARGS_NONE()); |
906 | mrb_define_method(mrb, klass, "flags" , |
907 | mrb_grn_expr_code_get_flags, MRB_ARGS_NONE()); |
908 | mrb_define_method(mrb, klass, "modify" , |
909 | mrb_grn_expr_code_get_modify, MRB_ARGS_NONE()); |
910 | |
911 | { |
912 | struct RClass *expression_code_class = klass; |
913 | struct RClass *flags_module; |
914 | flags_module = mrb_define_module_under(mrb, expression_code_class, "Flags" ); |
915 | mrb_define_const(mrb, flags_module, "RELATIONAL_EXPRESSION" , |
916 | mrb_fixnum_value(GRN_EXPR_CODE_RELATIONAL_EXPRESSION)); |
917 | } |
918 | |
919 | klass = mrb_define_class_under(mrb, module, "Expression" , object_class); |
920 | MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); |
921 | |
922 | #define DEFINE_FLAG(name) \ |
923 | mrb_define_const(mrb, klass, \ |
924 | #name, \ |
925 | mrb_fixnum_value(GRN_EXPR_ ## name)) |
926 | |
927 | DEFINE_FLAG(SYNTAX_QUERY); |
928 | DEFINE_FLAG(SYNTAX_SCRIPT); |
929 | DEFINE_FLAG(SYNTAX_OUTPUT_COLUMNS); |
930 | DEFINE_FLAG(ALLOW_PRAGMA); |
931 | DEFINE_FLAG(ALLOW_COLUMN); |
932 | DEFINE_FLAG(ALLOW_UPDATE); |
933 | DEFINE_FLAG(ALLOW_LEADING_NOT); |
934 | |
935 | #undef DEFINE_FLAG |
936 | |
937 | mrb_define_class_method(mrb, klass, "create" , |
938 | mrb_grn_expression_class_create, |
939 | MRB_ARGS_REQ(1)); |
940 | |
941 | mrb_define_method(mrb, klass, "initialize" , |
942 | mrb_grn_expression_initialize, MRB_ARGS_REQ(1)); |
943 | mrb_define_method(mrb, klass, "empty?" , |
944 | mrb_grn_expression_is_empty, MRB_ARGS_NONE()); |
945 | mrb_define_method(mrb, klass, "codes" , |
946 | mrb_grn_expression_codes, MRB_ARGS_NONE()); |
947 | mrb_define_method(mrb, klass, "[]" , |
948 | mrb_grn_expression_array_reference, MRB_ARGS_REQ(1)); |
949 | mrb_define_method(mrb, klass, "condition=" , |
950 | mrb_grn_expression_set_condition, MRB_ARGS_REQ(1)); |
951 | mrb_define_method(mrb, klass, "take_object" , |
952 | mrb_grn_expression_take_object, MRB_ARGS_REQ(1)); |
953 | mrb_define_method(mrb, klass, "allocate_constant" , |
954 | mrb_grn_expression_allocate_constant, MRB_ARGS_REQ(1)); |
955 | |
956 | mrb_define_method(mrb, klass, "parse" , |
957 | mrb_grn_expression_parse, MRB_ARGS_ARG(1, 1)); |
958 | |
959 | mrb_define_method(mrb, klass, "append_object" , |
960 | mrb_grn_expression_append_object, MRB_ARGS_REQ(2)); |
961 | mrb_define_method(mrb, klass, "append_constant" , |
962 | mrb_grn_expression_append_constant, MRB_ARGS_REQ(3)); |
963 | mrb_define_method(mrb, klass, "append_operator" , |
964 | mrb_grn_expression_append_operator, MRB_ARGS_REQ(2)); |
965 | } |
966 | |
967 | grn_obj * |
968 | grn_mrb_expr_rewrite(grn_ctx *ctx, grn_obj *expr) |
969 | { |
970 | grn_mrb_data *data = &(ctx->impl->mrb); |
971 | mrb_state *mrb = data->state; |
972 | mrb_value mrb_expression; |
973 | mrb_value mrb_rewritten_expression; |
974 | grn_obj *rewritten_expression = NULL; |
975 | int arena_index; |
976 | |
977 | arena_index = mrb_gc_arena_save(mrb); |
978 | |
979 | mrb_expression = grn_mrb_value_from_grn_obj(mrb, expr); |
980 | mrb_rewritten_expression = mrb_funcall(mrb, mrb_expression, "rewrite" , 0); |
981 | if (mrb_nil_p(mrb_rewritten_expression)) { |
982 | goto exit; |
983 | } |
984 | |
985 | if (mrb_type(mrb_rewritten_expression) == MRB_TT_EXCEPTION) { |
986 | mrb->exc = mrb_obj_ptr(mrb_rewritten_expression); |
987 | mrb_print_error(mrb); |
988 | goto exit; |
989 | } |
990 | |
991 | rewritten_expression = DATA_PTR(mrb_rewritten_expression); |
992 | |
993 | exit: |
994 | mrb_gc_arena_restore(mrb, arena_index); |
995 | |
996 | return rewritten_expression; |
997 | } |
998 | |
999 | scan_info ** |
1000 | grn_mrb_scan_info_build(grn_ctx *ctx, |
1001 | grn_obj *expr, |
1002 | int *n, |
1003 | grn_operator op, |
1004 | grn_bool record_exist) |
1005 | { |
1006 | grn_mrb_data *data = &(ctx->impl->mrb); |
1007 | mrb_state *mrb = data->state; |
1008 | mrb_value mrb_expression; |
1009 | mrb_value mrb_sis; |
1010 | scan_info **sis = NULL; |
1011 | int i; |
1012 | int arena_index; |
1013 | |
1014 | arena_index = mrb_gc_arena_save(mrb); |
1015 | |
1016 | mrb_expression = grn_mrb_value_from_grn_obj(mrb, expr); |
1017 | mrb_sis = mrb_funcall(mrb, mrb_expression, "build_scan_info" , 2, |
1018 | grn_mrb_value_from_operator(mrb, op), |
1019 | mrb_bool_value(record_exist)); |
1020 | |
1021 | if (mrb_nil_p(mrb_sis)) { |
1022 | goto exit; |
1023 | } |
1024 | |
1025 | if (mrb_type(mrb_sis) == MRB_TT_EXCEPTION) { |
1026 | mrb->exc = mrb_obj_ptr(mrb_sis); |
1027 | mrb_print_error(mrb); |
1028 | goto exit; |
1029 | } |
1030 | |
1031 | *n = RARRAY_LEN(mrb_sis); |
1032 | sis = GRN_MALLOCN(scan_info *, *n); |
1033 | for (i = 0; i < *n; i++) { |
1034 | mrb_value mrb_si; |
1035 | mrb_value mrb_si_data; |
1036 | scan_info *si; |
1037 | int start; |
1038 | |
1039 | mrb_si_data = RARRAY_PTR(mrb_sis)[i]; |
1040 | start = mrb_fixnum(mrb_funcall(mrb, mrb_si_data, "start" , 0)); |
1041 | si = grn_scan_info_open(ctx, start); |
1042 | mrb_si = mrb_grn_scan_info_new(mrb, si); |
1043 | mrb_funcall(mrb, mrb_si, "apply" , 1, mrb_si_data); |
1044 | sis[i] = si; |
1045 | } |
1046 | |
1047 | exit: |
1048 | mrb_gc_arena_restore(mrb, arena_index); |
1049 | |
1050 | return sis; |
1051 | } |
1052 | |
1053 | unsigned int |
1054 | grn_mrb_expr_estimate_size(grn_ctx *ctx, grn_obj *expr, grn_obj *table) |
1055 | { |
1056 | grn_mrb_data *data = &(ctx->impl->mrb); |
1057 | mrb_state *mrb = data->state; |
1058 | mrb_value mrb_expression; |
1059 | mrb_value mrb_table; |
1060 | mrb_value mrb_size; |
1061 | unsigned int size; |
1062 | int arena_index; |
1063 | |
1064 | arena_index = mrb_gc_arena_save(mrb); |
1065 | |
1066 | mrb_expression = grn_mrb_value_from_grn_obj(mrb, expr); |
1067 | mrb_table = grn_mrb_value_from_grn_obj(mrb, table); |
1068 | mrb_size = mrb_funcall(mrb, mrb_expression, "estimate_size" , 1, mrb_table); |
1069 | if (mrb->exc) { |
1070 | size = grn_table_size(ctx, table); |
1071 | } else { |
1072 | size = mrb_fixnum(mrb_size); |
1073 | } |
1074 | |
1075 | mrb_gc_arena_restore(mrb, arena_index); |
1076 | |
1077 | return size; |
1078 | } |
1079 | #endif |
1080 | |