Kouhei Sutou
null+****@clear*****
Wed Oct 7 18:30:45 JST 2015
Kouhei Sutou 2015-10-07 18:30:45 +0900 (Wed, 07 Oct 2015) New Revision: 66e87a9ca527dfb3caae8e01e0d5ebab3f191ed0 https://github.com/groonga/groonga/commit/66e87a9ca527dfb3caae8e01e0d5ebab3f191ed0 Message: Add query rewrite system TODO: * Support customizing rewriter registration table * Support ordering rewriters Added files: lib/mrb/scripts/expression_rewriter.rb lib/mrb/scripts/expression_rewriters.rb Modified files: include/groonga/expr.h lib/expr.c lib/grn_scanner.h lib/mrb/mrb_expr.c lib/mrb/mrb_expr.h lib/mrb/scripts/expression.rb lib/scanner.c Modified: include/groonga/expr.h (+2 -1) =================================================================== --- include/groonga/expr.h 2015-10-07 18:08:16 +0900 (63cbb6e) +++ include/groonga/expr.h 2015-10-07 18:30:45 +0900 (c4668f2) @@ -1,5 +1,5 @@ /* - Copyright(C) 2009-2014 Brazil + Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -55,6 +55,7 @@ GRN_API grn_rc grn_expr_syntax_escape_query(grn_ctx *ctx, grn_obj *escaped_query); GRN_API grn_rc grn_expr_compile(grn_ctx *ctx, grn_obj *expr); +GRN_API grn_obj *grn_expr_rewrite(grn_ctx *ctx, grn_obj *expr); GRN_API grn_rc grn_expr_dump_plan(grn_ctx *ctx, grn_obj *expr, grn_obj *buffer); GRN_API grn_obj *grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs); Modified: lib/expr.c (+17 -1) =================================================================== --- lib/expr.c 2015-10-07 18:08:16 +0900 (4171bd4) +++ lib/expr.c 2015-10-07 18:30:45 +0900 (3150125) @@ -1224,6 +1224,22 @@ grn_expr_compile(grn_ctx *ctx, grn_obj *expr) return ctx->rc; } +grn_obj * +grn_expr_rewrite(grn_ctx *ctx, grn_obj *expr) +{ + grn_obj *rewritten = NULL; + + GRN_API_ENTER; + +#ifdef GRN_WITH_MRUBY + if (ctx->impl->mrb.state) { + rewritten = grn_mrb_expr_rewrite(ctx, expr); + } +#endif + + GRN_API_RETURN(rewritten); +} + #define WITH_SPSAVE(block) do {\ ctx->impl->stack_curr = sp - ctx->impl->stack;\ e->values_curr = vp - e->values;\ @@ -5471,7 +5487,7 @@ grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr, scanner = grn_scanner_open(ctx, expr, op, res_size > 0); if (scanner) { grn_obj res_stack; - grn_expr *e = (grn_expr *)expr; + grn_expr *e = (grn_expr *)scanner->expr; grn_expr_code *codes = e->codes; uint32_t codes_curr = e->codes_curr; GRN_PTR_INIT(&res_stack, GRN_OBJ_VECTOR, GRN_ID_NIL); Modified: lib/grn_scanner.h (+1 -1) =================================================================== --- lib/grn_scanner.h 2015-10-07 18:08:16 +0900 (5c86ecb) +++ lib/grn_scanner.h 2015-10-07 18:30:45 +0900 (c511f48) @@ -27,7 +27,7 @@ extern "C" { typedef struct _grn_scaner { grn_obj *expr; - grn_obj *rewritten_expr; + grn_obj *source_expr; scan_info **sis; unsigned int n_sis; } grn_scanner; Modified: lib/mrb/mrb_expr.c (+32 -0) =================================================================== --- lib/mrb/mrb_expr.c 2015-10-07 18:08:16 +0900 (285f047) +++ lib/mrb/mrb_expr.c 2015-10-07 18:30:45 +0900 (73a7bb8) @@ -809,6 +809,38 @@ grn_mrb_expr_init(grn_ctx *ctx) mrb_grn_expression_append_operator, MRB_ARGS_REQ(2)); } +grn_obj * +grn_mrb_expr_rewrite(grn_ctx *ctx, grn_obj *expr) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + mrb_value mrb_expression; + mrb_value mrb_rewritten_expression; + grn_obj *rewritten_expression = NULL; + int arena_index; + + arena_index = mrb_gc_arena_save(mrb); + + mrb_expression = grn_mrb_value_from_grn_obj(mrb, expr); + mrb_rewritten_expression = mrb_funcall(mrb, mrb_expression, "rewrite", 0); + if (mrb_nil_p(mrb_rewritten_expression)) { + goto exit; + } + + if (mrb_type(mrb_rewritten_expression) == MRB_TT_EXCEPTION) { + mrb->exc = mrb_obj_ptr(mrb_rewritten_expression); + mrb_print_error(mrb); + goto exit; + } + + rewritten_expression = DATA_PTR(mrb_rewritten_expression); + +exit: + mrb_gc_arena_restore(mrb, arena_index); + + return rewritten_expression; +} + scan_info ** grn_mrb_scan_info_build(grn_ctx *ctx, grn_obj *expr, Modified: lib/mrb/mrb_expr.h (+2 -0) =================================================================== --- lib/mrb/mrb_expr.h 2015-10-07 18:08:16 +0900 (6838aeb) +++ lib/mrb/mrb_expr.h 2015-10-07 18:30:45 +0900 (85c65e3) @@ -27,6 +27,8 @@ extern "C" { #endif void grn_mrb_expr_init(grn_ctx *ctx); + +grn_obj *grn_mrb_expr_rewrite(grn_ctx *ctx, grn_obj *expr); scan_info **grn_mrb_scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n, Modified: lib/mrb/scripts/expression.rb (+28 -0) =================================================================== --- lib/mrb/scripts/expression.rb 2015-10-07 18:08:16 +0900 (41ccc73) +++ lib/mrb/scripts/expression.rb 2015-10-07 18:30:45 +0900 (69a0fee) @@ -1,3 +1,6 @@ +require "expression_rewriter" +require "expression_rewriters" + require "scan_info" require "scan_info_builder" @@ -5,6 +8,31 @@ require "expression_size_estimator" module Groonga class Expression + def rewrite + rewritten = nil + begin + source = self + ExpressionRewriters.classes.each do |rewriter_class| + rewriter = rewriter_class.new(source) + new_rewritten = rewriter.rewrite + if new_rewritten + rewritten.close if rewritten + rewritten = new_rewritten + source = rewritten + end + end + rescue GroongaError => groonga_error + context.set_groonga_error(groonga_error) + rewritten.close if rewritten + rewritten = nil + rescue => error + context.record_error(:invalid_argument, error) + rewritten.close if rewritten + rewritten = nil + end + rewritten + end + def build_scan_info(op, record_exist) begin builder = ScanInfoBuilder.new(self, op, record_exist) Added: lib/mrb/scripts/expression_rewriter.rb (+22 -0) 100644 =================================================================== --- /dev/null +++ lib/mrb/scripts/expression_rewriter.rb 2015-10-07 18:30:45 +0900 (8f56ca7) @@ -0,0 +1,22 @@ +module Groonga + class ExpressionRewriter + class << self + def register(name) + ExpressionRewriters.register(name, self) + end + end + + def initialize(expression) + @expression = expression + end + + def rewrite + nil + end + + private + def context + @context ||= Context.instance + end + end +end Added: lib/mrb/scripts/expression_rewriters.rb (+29 -0) 100644 =================================================================== --- /dev/null +++ lib/mrb/scripts/expression_rewriters.rb 2015-10-07 18:30:45 +0900 (48a969c) @@ -0,0 +1,29 @@ +module Groonga + module ExpressionRewriters + @@rewriters = {} + + class << self + def register(name, rewriter_class) + @@rewriters[name] = rewriter_class + end + + def classes + rewriters_table = Context.instance["rewriters"] + return [] if rewriters_table.nil? + + rewriters_table.collect do |id| + record = Record.new(rewriters_table, id) + name = record.key + rewriter = @@rewriters[name] + if rewriter.nil? + plugin_name = record.plugin_name.value + require plugin_name + rewriter = @@rewriters[name] + raise "unknown rewriter: <#{name}>:<#{plugin_name}>" if rewriter.nil? + end + rewriter + end + end + end + end +end Modified: lib/scanner.c (+23 -26) =================================================================== --- lib/scanner.c 2015-10-07 18:08:16 +0900 (62bdf7c) +++ lib/scanner.c 2015-10-07 18:30:45 +0900 (c7d86ff) @@ -18,16 +18,6 @@ #include "grn_scanner.h" -static void -sis_free(grn_ctx *ctx, scan_info **sis, unsigned int n_sis) -{ - int i; - for (i = 0; i < n_sis; i++) { - grn_scan_info_close(ctx, sis[i]); - } - GRN_FREE(sis); -} - grn_scanner * grn_scanner_open(grn_ctx *ctx, grn_obj *expr, @@ -35,24 +25,27 @@ grn_scanner_open(grn_ctx *ctx, grn_bool record_exist) { grn_scanner *scanner; - scan_info **sis; - unsigned int n_sis; - - sis = grn_scan_info_build(ctx, expr, &n_sis, op, record_exist); - if (!sis) { - return NULL; - } scanner = GRN_MALLOC(sizeof(grn_scanner)); if (!scanner) { - sis_free(ctx, sis, n_sis); return NULL; } - scanner->expr = expr; - scanner->rewritten_expr = NULL; - scanner->sis = sis; - scanner->n_sis = n_sis; + scanner->source_expr = expr; + scanner->expr = grn_expr_rewrite(ctx, expr); + if (!scanner->expr) { + scanner->expr = expr; + } + + scanner->sis = grn_scan_info_build(ctx, + scanner->expr, + &(scanner->n_sis), + op, + record_exist); + if (!scanner->sis) { + grn_scanner_close(ctx, scanner); + return NULL; + } return scanner; } @@ -64,12 +57,16 @@ grn_scanner_close(grn_ctx *ctx, grn_scanner *scanner) return; } - if (scanner->rewritten_expr) { - grn_obj_close(ctx, scanner->rewritten_expr); + if (scanner->sis) { + int i; + for (i = 0; i < scanner->n_sis; i++) { + grn_scan_info_close(ctx, scanner->sis[i]); + } + GRN_FREE(scanner->sis); } - if (scanner->sis) { - sis_free(ctx, scanner->sis, scanner->n_sis); + if (scanner->expr != scanner->source_expr) { + grn_obj_close(ctx, scanner->expr); } GRN_FREE(scanner); -------------- next part -------------- HTML����������������������������...Download