[Groonga-commit] groonga/groonga at 66e87a9 [master] Add query rewrite system

Back to archive index

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 



More information about the Groonga-commit mailing list
Back to archive index