[Groonga-commit] groonga/groonga at 9cdb44c [master] window function: add support for context tables

Back to archive index
Kouhei Sutou null+****@clear*****
Fri Apr 26 15:43:03 JST 2019


Kouhei Sutou	2019-04-26 15:43:03 +0900 (Fri, 26 Apr 2019)

  Revision: 9cdb44cb2f940d9eb68f78f6e081026e9ceeacdf
  https://github.com/groonga/groonga/commit/9cdb44cb2f940d9eb68f78f6e081026e9ceeacdf

  Message:
    window function: add support for context tables

  Modified files:
    include/groonga/window_function.h
    include/groonga/window_function_executor.h
    lib/grn_window_function.h
    lib/grn_window_function_executor.h
    lib/mrb/mrb_window_function_executor.c
    lib/window_function.c
    lib/window_function_executor.c
    lib/window_functions.c

  Modified: include/groonga/window_function.h (+3 -2)
===================================================================
--- include/groonga/window_function.h    2019-04-26 14:43:53 +0900 (fa8068557)
+++ include/groonga/window_function.h    2019-04-26 15:43:03 +0900 (ff6423b69)
@@ -4,8 +4,7 @@
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
+  License version 2.1 as published by the Free Software Foundation.
 
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -39,6 +38,8 @@ GRN_API grn_rc grn_window_set_direction(grn_ctx *ctx,
                                         grn_window_direction direction);
 GRN_API grn_obj *grn_window_get_table(grn_ctx *ctx,
                                       grn_window *window);
+GRN_API bool grn_window_is_context_table(grn_ctx *ctx,
+                                         grn_window *window);
 GRN_API grn_obj *grn_window_get_output_column(grn_ctx *ctx,
                                               grn_window *window);
 GRN_API size_t grn_window_get_n_arguments(grn_ctx *ctx,

  Modified: include/groonga/window_function_executor.h (+4 -0)
===================================================================
--- include/groonga/window_function_executor.h    2019-04-26 14:43:53 +0900 (2612b73ef)
+++ include/groonga/window_function_executor.h    2019-04-26 15:43:03 +0900 (f7c37c36f)
@@ -34,6 +34,10 @@ grn_window_function_executor_add_table(grn_ctx *ctx,
                                        grn_window_function_executor *executor,
                                        grn_obj *table);
 GRN_API grn_rc
+grn_window_function_executor_add_context_table(grn_ctx *ctx,
+                                               grn_window_function_executor *executor,
+                                               grn_obj *table);
+GRN_API grn_rc
 grn_window_function_executor_set_source(grn_ctx *ctx,
                                         grn_window_function_executor *executor,
                                         const char *source,

  Modified: lib/grn_window_function.h (+3 -2)
===================================================================
--- lib/grn_window_function.h    2019-04-26 14:43:53 +0900 (799202f1d)
+++ lib/grn_window_function.h    2019-04-26 15:43:03 +0900 (cea1e2abb)
@@ -5,8 +5,7 @@
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
+  License version 2.1 as published by the Free Software Foundation.
 
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -24,6 +23,7 @@
 
 typedef struct {
   grn_obj *table;
+  bool is_context_table;
   grn_obj *window_function_call;
   grn_proc *window_function;
   grn_obj *arguments;
@@ -47,6 +47,7 @@ grn_rc grn_window_reset(grn_ctx *ctx, grn_window *window);
 grn_rc grn_window_add_record(grn_ctx *ctx,
                              grn_window *window,
                              grn_obj *table,
+                             bool is_context_table,
                              grn_id record_id,
                              grn_obj *window_function_call,
                              grn_obj *output_column);

  Modified: lib/grn_window_function_executor.h (+1 -0)
===================================================================
--- lib/grn_window_function_executor.h    2019-04-26 14:43:53 +0900 (cf14f2fb8)
+++ lib/grn_window_function_executor.h    2019-04-26 15:43:03 +0900 (2f7782e02)
@@ -26,6 +26,7 @@ extern "C" {
 
 struct _grn_window_function_executor {
   grn_obj tables;
+  grn_obj is_context_tables;
   grn_obj source;
   grn_obj sort_keys;
   grn_obj group_keys;

  Modified: lib/mrb/mrb_window_function_executor.c (+18 -0)
===================================================================
--- lib/mrb/mrb_window_function_executor.c    2019-04-26 14:43:53 +0900 (44532e25a)
+++ lib/mrb/mrb_window_function_executor.c    2019-04-26 15:43:03 +0900 (6900f70d1)
@@ -102,6 +102,21 @@ mrb_grn_window_function_executor_add_table(mrb_state *mrb, mrb_value self)
 }
 
 static mrb_value
+mrb_grn_window_function_executor_add_context_table(mrb_state *mrb, mrb_value self)
+{
+  mrb_value mrb_table;
+  mrb_get_args(mrb, "o", &mrb_table);
+
+  grn_ctx *ctx = (grn_ctx *)mrb->ud;
+  grn_window_function_executor *executor = DATA_PTR(self);
+  grn_obj *table = GRN_MRB_DATA_PTR(mrb_table);
+  grn_window_function_executor_add_context_table(ctx, executor, table);
+  grn_mrb_ctx_check(mrb);
+
+  return mrb_nil_value();
+}
+
+static mrb_value
 mrb_grn_window_function_executor_set_sort_keys(mrb_state *mrb, mrb_value self)
 {
   char *keys;
@@ -183,6 +198,9 @@ grn_mrb_window_function_executor_init(grn_ctx *ctx)
   mrb_define_method(mrb, klass, "add_table",
                     mrb_grn_window_function_executor_add_table,
                     MRB_ARGS_REQ(1));
+  mrb_define_method(mrb, klass, "add_context_table",
+                    mrb_grn_window_function_executor_add_context_table,
+                    MRB_ARGS_REQ(1));
   mrb_define_method(mrb, klass, "source=",
                     mrb_grn_window_function_executor_set_source,
                     MRB_ARGS_REQ(1));

  Modified: lib/window_function.c (+30 -1)
===================================================================
--- lib/window_function.c    2019-04-26 14:43:53 +0900 (b291f1319)
+++ lib/window_function.c    2019-04-26 15:43:03 +0900 (211a4c729)
@@ -28,10 +28,12 @@ static void
 grn_window_shard_init(grn_ctx *ctx,
                       grn_window_shard *shard,
                       grn_obj *table,
+                      bool is_context_table,
                       grn_obj *window_function_call,
                       grn_obj *output_column)
 {
   shard->table = table;
+  shard->is_context_table = is_context_table;
   shard->window_function_call = window_function_call;
   grn_expr *expr = (grn_expr *)(window_function_call);
   shard->window_function = (grn_proc *)(expr->codes[0].value);
@@ -167,6 +169,24 @@ grn_window_get_table(grn_ctx *ctx, grn_window *window)
   GRN_API_RETURN(shard->table);
 }
 
+bool
+grn_window_is_context_table(grn_ctx *ctx, grn_window *window)
+{
+  GRN_API_ENTER;
+
+  if (!window) {
+    ERR(GRN_INVALID_ARGUMENT, "[window][is-context-table] window is NULL");
+    GRN_API_RETURN(false);
+  }
+
+  if (window->current_shard < 0) {
+    GRN_API_RETURN(false);
+  }
+
+  grn_window_shard *shard = &(window->shards[window->current_shard]);
+  GRN_API_RETURN(shard->is_context_table);
+}
+
 grn_obj *
 grn_window_get_output_column(grn_ctx *ctx, grn_window *window)
 {
@@ -182,7 +202,11 @@ grn_window_get_output_column(grn_ctx *ctx, grn_window *window)
   }
 
   grn_window_shard *shard = &(window->shards[window->current_shard]);
-  GRN_API_RETURN(shard->output_column);
+  if (shard->is_context_table) {
+    GRN_API_RETURN(NULL);
+  } else {
+    GRN_API_RETURN(shard->output_column);
+  }
 }
 
 size_t
@@ -346,6 +370,7 @@ grn_rc
 grn_window_add_record(grn_ctx *ctx,
                       grn_window *window,
                       grn_obj *table,
+                      bool is_context_table,
                       grn_id record_id,
                       grn_obj *window_function_call,
                       grn_obj *output_column)
@@ -365,6 +390,7 @@ grn_window_add_record(grn_ctx *ctx,
     grn_window_shard_init(ctx,
                           &(window->shards[0]),
                           table,
+                          is_context_table,
                           window_function_call,
                           output_column);
     window->current_shard = 0;
@@ -399,6 +425,7 @@ grn_window_add_record(grn_ctx *ctx,
     grn_window_shard_init(ctx,
                           &(window->shards[window->n_shards - 1]),
                           table,
+                          is_context_table,
                           window_function_call,
                           output_column);
   }
@@ -644,6 +671,7 @@ grn_table_apply_window_function(grn_ctx *ctx,
       grn_window_add_record(ctx,
                             &window,
                             table,
+                            false,
                             record_id,
                             window_function_call,
                             output_column);
@@ -665,6 +693,7 @@ grn_table_apply_window_function(grn_ctx *ctx,
       grn_window_add_record(ctx,
                             &window,
                             table,
+                            false,
                             record_id,
                             window_function_call,
                             output_column);

  Modified: lib/window_function_executor.c (+47 -3)
===================================================================
--- lib/window_function_executor.c    2019-04-26 14:43:53 +0900 (f4fba2221)
+++ lib/window_function_executor.c    2019-04-26 15:43:03 +0900 (bf3d44398)
@@ -26,6 +26,7 @@ grn_window_function_executor_init(grn_ctx *ctx,
   GRN_API_ENTER;
 
   GRN_PTR_INIT(&(executor->tables), GRN_OBJ_VECTOR, GRN_ID_NIL);
+  GRN_BOOL_INIT(&(executor->is_context_tables), 0);
   GRN_TEXT_INIT(&(executor->source), 0);
   GRN_TEXT_INIT(&(executor->sort_keys), 0);
   GRN_TEXT_INIT(&(executor->group_keys), 0);
@@ -118,6 +119,7 @@ grn_window_function_executor_fin(grn_ctx *ctx,
   GRN_OBJ_FIN(ctx, &(executor->group_keys));
   GRN_OBJ_FIN(ctx, &(executor->sort_keys));
   GRN_OBJ_FIN(ctx, &(executor->source));
+  GRN_OBJ_FIN(ctx, &(executor->is_context_tables));
   GRN_OBJ_FIN(ctx, &(executor->tables));
 
   GRN_API_RETURN(GRN_SUCCESS);
@@ -182,6 +184,28 @@ grn_window_function_executor_add_table(grn_ctx *ctx,
   grn_window_function_executor_rewind(ctx, executor);
 
   GRN_PTR_PUT(ctx, &(executor->tables), table);
+  GRN_BOOL_PUT(ctx, &(executor->is_context_tables), false);
+
+  GRN_API_RETURN(ctx->rc);
+}
+
+grn_rc
+grn_window_function_executor_add_context_table(grn_ctx *ctx,
+                                               grn_window_function_executor *executor,
+                                               grn_obj *table)
+{
+  GRN_API_ENTER;
+
+  if (!executor) {
+    ERR(GRN_INVALID_ARGUMENT,
+        "[window-function-executor][context-table][add] executor is NULL");
+    GRN_API_RETURN(ctx->rc);
+  }
+
+  grn_window_function_executor_rewind(ctx, executor);
+
+  GRN_PTR_PUT(ctx, &(executor->tables), table);
+  GRN_BOOL_PUT(ctx, &(executor->is_context_tables), true);
 
   GRN_API_RETURN(ctx->rc);
 }
@@ -326,9 +350,22 @@ grn_window_function_executor_execute(grn_ctx *ctx,
 
   const bool is_ascending =
     grn_window_function_executor_is_ascending(ctx, executor);
+  bool in_before_context = true;
+  bool in_after_context = false;
   for (size_t i = 0; i < n_tables; i++) {
     size_t nth_table = (is_ascending ? i : (n_tables - i - 1));
     grn_obj *table = GRN_PTR_VALUE_AT(&(executor->tables), nth_table);
+    const bool is_context_table =
+      GRN_BOOL_VALUE_AT(&(executor->is_context_tables), nth_table);
+    if (in_before_context) {
+      if (!is_context_table) {
+        in_before_context = false;
+      }
+    } else if (!in_after_context) {
+      if (is_context_table) {
+        in_after_context = true;
+      }
+    }
 
     grn_obj *output_column = grn_obj_column(ctx,
                                             table,
@@ -556,15 +593,21 @@ grn_window_function_executor_execute(grn_ctx *ctx,
 
         if (is_group_key_changed &&
             !grn_window_is_empty(ctx, &(executor->window))) {
-          grn_window_execute(ctx, &(executor->window));
-          if (ctx->rc != GRN_SUCCESS) {
-            break;
+          if (!in_before_context) {
+            grn_window_execute(ctx, &(executor->window));
+            if (ctx->rc != GRN_SUCCESS) {
+              break;
+            }
           }
           grn_window_reset(ctx, &(executor->window));
+          if (in_after_context) {
+            break;
+          }
         }
         grn_window_add_record(ctx,
                               &(executor->window),
                               table,
+                              is_context_table,
                               record_id,
                               window_function_call,
                               output_column);
@@ -582,6 +625,7 @@ grn_window_function_executor_execute(grn_ctx *ctx,
         grn_window_add_record(ctx,
                               &(executor->window),
                               table,
+                              is_context_table,
                               record_id,
                               window_function_call,
                               output_column);

  Modified: lib/window_functions.c (+15 -5)
===================================================================
--- lib/window_functions.c    2019-04-26 14:43:53 +0900 (9d23bde81)
+++ lib/window_functions.c    2019-04-26 15:43:03 +0900 (79ca24b94)
@@ -35,7 +35,9 @@ window_record_number(grn_ctx *ctx,
   while ((id = grn_window_next(ctx, window))) {
     GRN_UINT32_SET(ctx, &value, nth_record);
     grn_obj *output_column = grn_window_get_output_column(ctx, window);
-    grn_obj_set_value(ctx, output_column, id, &value, GRN_OBJ_SET);
+    if (output_column) {
+      grn_obj_set_value(ctx, output_column, id, &value, GRN_OBJ_SET);
+    }
     nth_record++;
   }
   GRN_OBJ_FIN(ctx, &value);
@@ -200,7 +202,9 @@ window_sum(grn_ctx *ctx,
         break;
       }
       grn_obj *output_column = grn_window_get_output_column(ctx, window);
-      grn_obj_set_value(ctx, output_column, id, &sum, GRN_OBJ_SET);
+      if (output_column) {
+        grn_obj_set_value(ctx, output_column, id, &sum, GRN_OBJ_SET);
+      }
     }
   } else {
     int64_t sum_raw_int64 = 0;
@@ -266,7 +270,9 @@ window_sum(grn_ctx *ctx,
     grn_window_rewind(ctx, window);
     while ((id = grn_window_next(ctx, window))) {
       grn_obj *output_column = grn_window_get_output_column(ctx, window);
-      grn_obj_set_value(ctx, output_column, id, &sum, GRN_OBJ_SET);
+      if (output_column) {
+        grn_obj_set_value(ctx, output_column, id, &sum, GRN_OBJ_SET);
+      }
     }
   }
 
@@ -352,7 +358,9 @@ window_count(grn_ctx *ctx,
         break;
       }
       grn_obj *output_column = grn_window_get_output_column(ctx, window);
-      grn_obj_set_value(ctx, output_column, id, &n_records, GRN_OBJ_SET);
+      if (output_column) {
+        grn_obj_set_value(ctx, output_column, id, &n_records, GRN_OBJ_SET);
+      }
     }
   } else {
     uint32_t n_records_raw = 0;
@@ -382,7 +390,9 @@ window_count(grn_ctx *ctx,
     grn_window_rewind(ctx, window);
     while ((id = grn_window_next(ctx, window))) {
       grn_obj *output_column = grn_window_get_output_column(ctx, window);
-      grn_obj_set_value(ctx, output_column, id, &n_records, GRN_OBJ_SET);
+      if (output_column) {
+        grn_obj_set_value(ctx, output_column, id, &n_records, GRN_OBJ_SET);
+      }
     }
   }
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.osdn.me/mailman/archives/groonga-commit/attachments/20190426/2f63b6c4/attachment-0001.html>


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