[Groonga-commit] groonga/groonga [master] table: add table plugin.

Back to archive index

null+****@clear***** null+****@clear*****
2012年 5月 7日 (月) 21:20:31 JST


Daijiro MORI	2012-05-07 21:20:31 +0900 (Mon, 07 May 2012)

  New Revision: dd062452834628fda9d15e4710caf275d500efde

  Log:
    table: add table plugin.

  Added files:
    plugins/table/Makefile.am
    plugins/table/sources.am
    plugins/table/table.c
  Copied files:
    plugins/table/CMakeLists.txt
      (from plugins/CMakeLists.txt)
  Modified files:
    configure.ac
    plugins/CMakeLists.txt
    plugins/Makefile.am

  Modified: configure.ac (+4 -0)
===================================================================
--- configure.ac    2012-05-07 18:32:37 +0900 (f324108)
+++ configure.ac    2012-05-07 21:20:31 +0900 (6e01116)
@@ -206,6 +206,7 @@ AC_CONFIG_FILES([
   plugins/Makefile
   plugins/tokenizers/Makefile
   plugins/suggest/Makefile
+  plugins/table/Makefile
   examples/Makefile
   examples/dictionary/Makefile
   examples/dictionary/edict/Makefile
@@ -1061,6 +1062,9 @@ AC_SUBST(tokenizer_pluginsdir)
 suggest_pluginsdir="\${pluginsdir}/suggest"
 AC_SUBST(suggest_pluginsdir)
 
+table_pluginsdir="\${pluginsdir}/table"
+AC_SUBST(table_pluginsdir)
+
 AC_MSG_CHECKING(for the suffix of plugin shared libraries)
 shrext_cmds=$(./libtool --config | grep '^shrext_cmds=')
 eval $shrext_cmds

  Modified: plugins/CMakeLists.txt (+1 -0)
===================================================================
--- plugins/CMakeLists.txt    2012-05-07 18:32:37 +0900 (c0646a4)
+++ plugins/CMakeLists.txt    2012-05-07 21:20:31 +0900 (0cf9205)
@@ -15,3 +15,4 @@
 
 add_subdirectory(suggest)
 add_subdirectory(tokenizers)
+add_subdirectory(table)

  Modified: plugins/Makefile.am (+2 -1)
===================================================================
--- plugins/Makefile.am    2012-05-07 18:32:37 +0900 (054db03)
+++ plugins/Makefile.am    2012-05-07 21:20:31 +0900 (8d6b1ef)
@@ -1,6 +1,7 @@
 SUBDIRS =		\
 	tokenizers	\
-	suggest
+	suggest \
+	table
 
 EXTRA_DIST =					\
 	CMakeLists.txt

  Copied: plugins/table/CMakeLists.txt (+9 -2) 68%
===================================================================
--- plugins/CMakeLists.txt    2012-05-07 18:32:37 +0900 (c0646a4)
+++ plugins/table/CMakeLists.txt    2012-05-07 21:20:31 +0900 (7a7faab)
@@ -13,5 +13,12 @@
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
-add_subdirectory(suggest)
-add_subdirectory(tokenizers)
+include_directories(
+  ${CMAKE_SOURCE_DIR}/lib
+  )
+
+read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/sources.am TABLE_SOURCES)
+add_library(table MODULE ${TABLE_SOURCES})
+set_target_properties(table PROPERTIES PREFIX "")
+target_link_libraries(table ${LIBGROONGA})
+install(TARGETS table DESTINATION "${GRN_PLUGINS_DIR}/table")

  Added: plugins/table/Makefile.am (+21 -0) 100644
===================================================================
--- /dev/null
+++ plugins/table/Makefile.am    2012-05-07 21:20:31 +0900 (37db668)
@@ -0,0 +1,21 @@
+EXTRA_DIST =					\
+	CMakeLists.txt
+
+INCLUDES =			\
+	-I$(top_builddir)	\
+	-I$(top_srcdir)/include	\
+	-I$(top_srcdir)/lib	\
+	$(MESSAGE_PACK_CFLAGS)
+
+AM_LDFLAGS =					\
+	-avoid-version				\
+	-module					\
+	-no-undefined
+
+LIBS =						\
+	$(top_builddir)/lib/libgroonga.la	\
+	$(MESSAGE_PACK_LIBS)
+
+table_plugins_LTLIBRARIES = table.la
+
+include sources.am

  Added: plugins/table/sources.am (+2 -0) 100644
===================================================================
--- /dev/null
+++ plugins/table/sources.am    2012-05-07 21:20:31 +0900 (943e79b)
@@ -0,0 +1,2 @@
+table_la_SOURCES =				\
+	table.c

  Added: plugins/table/table.c (+336 -0) 100644
===================================================================
--- /dev/null
+++ plugins/table/table.c    2012-05-07 21:20:31 +0900 (1caecc2)
@@ -0,0 +1,336 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* Copyright(C) 2012 Brazil
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  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
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "ctx.h"
+#include "db.h"
+#include "output.h"
+#include "util.h"
+#include <groonga/plugin.h>
+
+#define VAR GRN_PROC_GET_VAR_BY_OFFSET
+#define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0
+#define TEXT_VALUE_LEN(x) GRN_TEXT_VALUE(x), GRN_TEXT_LEN(x)
+
+static grn_obj *
+grn_ctx_get_table_by_name_or_id(grn_ctx *ctx,
+                                const char *name, unsigned int name_len)
+{
+  grn_obj *table;
+  const char *end = name + name_len;
+  const char *rest = NULL;
+  grn_id id = grn_atoui(name, end, &rest);
+  if (rest == end) {
+    table = grn_ctx_at(ctx, id);
+  } else {
+    table = grn_ctx_get(ctx, name, name_len);
+  }
+  if (!GRN_OBJ_TABLEP(table)) {
+    ERR(GRN_INVALID_ARGUMENT, "invalid table name: <%.*s>", name_len, name);
+    if (table) {
+      grn_obj_unlink(ctx, table);
+      table = NULL;
+    }
+  }
+  return table;
+}
+
+static void
+grn_output_table_name_or_id(grn_ctx *ctx, grn_obj *table)
+{
+  if (table) {
+    if (((grn_db_obj *)table)->id & GRN_OBJ_TMP_OBJECT) {
+      GRN_OUTPUT_INT64(((grn_db_obj *)table)->id);
+    } else {
+      int name_len;
+      char name_buf[GRN_TABLE_MAX_KEY_SIZE];
+      name_len = grn_obj_name(ctx, table, name_buf, GRN_TABLE_MAX_KEY_SIZE);
+      GRN_OUTPUT_STR(name_buf, name_len);
+    }
+  } else {
+    GRN_OUTPUT_INT64(0);
+  }
+}
+
+static grn_obj *
+command_find(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
+{
+  const char *table = GRN_TEXT_VALUE(VAR(0));
+  unsigned int table_len = GRN_TEXT_LEN(VAR(0));
+  const char *match_columns = GRN_TEXT_VALUE(VAR(1));
+  unsigned int match_columns_len = GRN_TEXT_LEN(VAR(1));
+  const char *match_op = GRN_TEXT_VALUE(VAR(2));
+  unsigned int match_op_len = GRN_TEXT_LEN(VAR(2));
+  const char *query = GRN_TEXT_VALUE(VAR(3));
+  unsigned int query_len = GRN_TEXT_LEN(VAR(3));
+  const char *set = GRN_TEXT_VALUE(VAR(4));
+  unsigned int set_len = GRN_TEXT_LEN(VAR(4));
+  /* TODO: support them.
+  const char *set_op = GRN_TEXT_VALUE(VAR(5));
+  unsigned int set_op_len = GRN_TEXT_LEN(VAR(5));
+  const char *expr = GRN_TEXT_VALUE(VAR(6));
+  unsigned int expr_len = GRN_TEXT_LEN(VAR(6));
+  */
+  grn_obj *set_;
+  grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len);
+  if (table_) {
+    if (match_columns_len) {
+      grn_obj *v, *cond, *match_columns_;
+      GRN_EXPR_CREATE_FOR_QUERY(ctx, table_, cond, v);
+      if (cond) {
+        GRN_EXPR_CREATE_FOR_QUERY(ctx, table_, match_columns_, v);
+        if (match_columns_) {
+          grn_expr_parse(ctx, match_columns_, match_columns, match_columns_len,
+                         NULL, GRN_OP_MATCH, GRN_OP_AND,
+                         GRN_EXPR_SYNTAX_SCRIPT);
+        }
+        {
+          grn_expr_flags flags;
+          flags = GRN_EXPR_SYNTAX_QUERY|GRN_EXPR_ALLOW_PRAGMA|GRN_EXPR_ALLOW_COLUMN;
+          grn_expr_parse(ctx, cond, query, query_len,
+                         match_columns_, GRN_OP_MATCH, GRN_OP_AND, flags);
+        }
+        if (set_len) {
+          set_ = grn_ctx_get_table_by_name_or_id(ctx, set, set_len);
+        } else {
+          set_ = grn_table_create(ctx, NULL, 0, NULL,
+                                  GRN_TABLE_HASH_KEY|
+                                  GRN_OBJ_WITH_SUBREC,
+                                  table_, NULL);
+        }
+        if (set_) {
+          grn_table_select(ctx, table_, cond, set_, GRN_OP_OR);
+        }
+      }
+    }
+  }
+  grn_output_table_name_or_id(ctx, set_);
+  return NULL;
+}
+
+static grn_obj *
+command_group(grn_ctx *ctx, int nargs, grn_obj **args,
+              grn_user_data *user_data)
+{
+  const char *table = GRN_TEXT_VALUE(VAR(0));
+  unsigned int table_len = GRN_TEXT_LEN(VAR(0));
+  const char *key = GRN_TEXT_VALUE(VAR(1));
+  unsigned int key_len = GRN_TEXT_LEN(VAR(1));
+  const char *set = GRN_TEXT_VALUE(VAR(2));
+  unsigned int set_len = GRN_TEXT_LEN(VAR(2));
+  grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len);
+  grn_obj *set_ = NULL;
+  if (table_) {
+    uint32_t ngkeys;
+    grn_table_sort_key *gkeys;
+    gkeys = grn_table_sort_key_from_str(ctx, key, key_len, table_, &ngkeys);
+    if (gkeys) {
+      if (set_len) {
+        set_ = grn_ctx_get_table_by_name_or_id(ctx, set, set_len);
+      } else {
+        set_ = grn_table_create_for_group(ctx, NULL, 0, NULL,
+                                          GRN_TABLE_HASH_KEY|
+                                          GRN_OBJ_WITH_SUBREC,
+                                          gkeys[0].key, NULL);
+      }
+      if (set_) {
+        grn_table_group_result g = {
+          set_, 0, 0, 1,
+          GRN_TABLE_GROUP_CALC_COUNT, 0
+        };
+        grn_table_group(ctx, table_, gkeys, 1, &g, 1);
+      }
+      grn_table_sort_key_close(ctx, gkeys, ngkeys);
+    }
+  }
+  grn_output_table_name_or_id(ctx, set_);
+  return NULL;
+}
+
+#define DEFAULT_LIMIT           10
+
+static grn_obj *
+command_sort(grn_ctx *ctx, int nargs, grn_obj **args,
+             grn_user_data *user_data)
+{
+  const char *table = GRN_TEXT_VALUE(VAR(0));
+  unsigned int table_len = GRN_TEXT_LEN(VAR(0));
+  const char *keys = GRN_TEXT_VALUE(VAR(1));
+  unsigned int keys_len = GRN_TEXT_LEN(VAR(1));
+  int offset = GRN_TEXT_LEN(VAR(2))
+    ? grn_atoi(GRN_TEXT_VALUE(VAR(2)), GRN_BULK_CURR(VAR(2)), NULL)
+    : 0;
+  int limit = GRN_TEXT_LEN(VAR(3))
+    ? grn_atoi(GRN_TEXT_VALUE(VAR(3)), GRN_BULK_CURR(VAR(3)), NULL)
+    : DEFAULT_LIMIT;
+  grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len);
+  grn_obj *sorted = NULL;
+  if (table_) {
+    uint32_t nkeys;
+    grn_table_sort_key *keys_;
+    if (keys_len &&
+        (keys_ = grn_table_sort_key_from_str(ctx, keys, keys_len,
+                                             table_, &nkeys))) {
+      if ((sorted = grn_table_create(ctx, NULL, 0, NULL,
+                                     GRN_OBJ_TABLE_NO_KEY, NULL, table_))) {
+        int table_size = (int)grn_table_size(ctx, table_);
+        grn_normalize_offset_and_limit(ctx, table_size, &offset, &limit);
+        grn_table_sort(ctx, table_, offset, limit, sorted, keys_, nkeys);
+        grn_table_sort_key_close(ctx, keys_, nkeys);
+      }
+    }
+  }
+  grn_output_table_name_or_id(ctx, sorted);
+  return NULL;
+}
+
+static grn_obj *
+command_output(grn_ctx *ctx, int nargs, grn_obj **args,
+               grn_user_data *user_data)
+{
+  const char *table = GRN_TEXT_VALUE(VAR(0));
+  unsigned int table_len = GRN_TEXT_LEN(VAR(0));
+  const char *columns = GRN_TEXT_VALUE(VAR(1));
+  unsigned int columns_len = GRN_TEXT_LEN(VAR(1));
+  int offset = GRN_TEXT_LEN(VAR(2))
+    ? grn_atoi(GRN_TEXT_VALUE(VAR(2)), GRN_BULK_CURR(VAR(2)), NULL)
+    : 0;
+  int limit = GRN_TEXT_LEN(VAR(3))
+    ? grn_atoi(GRN_TEXT_VALUE(VAR(3)), GRN_BULK_CURR(VAR(3)), NULL)
+    : DEFAULT_LIMIT;
+  grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len);
+  if (table_) {
+    grn_obj_format format;
+    int table_size = (int)grn_table_size(ctx, table_);
+    GRN_OBJ_FORMAT_INIT(&format, table_size, 0, limit, offset);
+    format.flags =
+      GRN_OBJ_FORMAT_WITH_COLUMN_NAMES|
+      GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET;
+    /* TODO: accept only comma separated expr as columns */
+    grn_obj_columns(ctx, table_, columns, columns_len, &format.columns);
+    GRN_OUTPUT_OBJ(table_, &format);
+    GRN_OBJ_FORMAT_FIN(ctx, &format);
+  }
+  return NULL;
+}
+
+static grn_obj *
+command_each(grn_ctx *ctx, int nargs, grn_obj **args,
+             grn_user_data *user_data)
+{
+  const char *table = GRN_TEXT_VALUE(VAR(0));
+  unsigned int table_len = GRN_TEXT_LEN(VAR(0));
+  const char *expr = GRN_TEXT_VALUE(VAR(1));
+  unsigned int expr_len = GRN_TEXT_LEN(VAR(1));
+  grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len);
+  if (table_) {
+    grn_obj *v, *expr_;
+    GRN_EXPR_CREATE_FOR_QUERY(ctx, table_, expr_, v);
+    if (expr_ && v) {
+      grn_table_cursor *tc;
+      grn_expr_parse(ctx, expr_, expr, expr_len,
+                     NULL, GRN_OP_MATCH, GRN_OP_AND,
+                     GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE);
+      if ((tc = grn_table_cursor_open(ctx, table_, NULL, 0,
+                                      NULL, 0, 0, -1, 0))) {
+        while (!grn_table_cursor_next_o(ctx, tc, v)) {
+          grn_expr_exec(ctx, expr_, 0);
+        }
+        grn_table_cursor_close(ctx, tc);
+      }
+      grn_obj_unlink(ctx, expr_);
+    }
+  }
+  GRN_OUTPUT_BOOL(!ctx->rc);
+  return NULL;
+}
+
+static grn_obj *
+command_unlink(grn_ctx *ctx, int nargs, grn_obj **args,
+               grn_user_data *user_data)
+{
+  const char *table = GRN_TEXT_VALUE(VAR(0));
+  unsigned int table_len = GRN_TEXT_LEN(VAR(0));
+  grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len);
+  if (table_) {
+    grn_obj_unlink(ctx, table_);
+  }
+  GRN_OUTPUT_BOOL(!ctx->rc);
+  return NULL;
+}
+
+grn_rc
+GRN_PLUGIN_INIT(grn_ctx *ctx)
+{
+  return GRN_SUCCESS;
+}
+
+#define DEF_VAR(v,x) do {\
+  (v).name = (x);\
+  (v).name_size = (x) ? sizeof(x) - 1 : 0;\
+  GRN_TEXT_INIT(&(v).value, 0);\
+} while (0)
+
+#define DEF_COMMAND(name,func,nvars,vars)\
+  (grn_proc_create(ctx, CONST_STR_LEN(name),\
+                   GRN_PROC_COMMAND, (func), NULL, NULL, (nvars), (vars)))
+
+grn_rc
+GRN_PLUGIN_REGISTER(grn_ctx *ctx)
+{
+  grn_expr_var vars[18];
+
+  DEF_VAR(vars[0], "table");
+  DEF_VAR(vars[1], "match_columns");
+  DEF_VAR(vars[2], "match_op");
+  DEF_VAR(vars[3], "match_value");
+  DEF_VAR(vars[4], "set");
+  DEF_VAR(vars[5], "set_op");
+  DEF_VAR(vars[6], "expr");
+  DEF_COMMAND("find", command_find, 7, vars);
+
+  DEF_VAR(vars[0], "table");
+  DEF_VAR(vars[1], "key");
+  DEF_VAR(vars[2], "set");
+  DEF_COMMAND("group", command_group, 3, vars);
+
+  DEF_VAR(vars[0], "table");
+  DEF_VAR(vars[1], "keys");
+  DEF_VAR(vars[2], "offset");
+  DEF_VAR(vars[3], "limit");
+  DEF_COMMAND("sort", command_sort, 4, vars);
+
+  DEF_VAR(vars[0], "table");
+  DEF_VAR(vars[1], "columns");
+  DEF_VAR(vars[2], "offset");
+  DEF_VAR(vars[3], "limit");
+  DEF_COMMAND("output", command_output, 4, vars);
+
+  DEF_VAR(vars[0], "table");
+  DEF_VAR(vars[1], "expr");
+  DEF_COMMAND("each", command_each, 2, vars);
+
+  DEF_VAR(vars[0], "table");
+  DEF_COMMAND("unlink", command_unlink, 1, vars);
+
+  return ctx->rc;
+}
+
+grn_rc
+GRN_PLUGIN_FIN(grn_ctx *ctx)
+{
+  return GRN_SUCCESS;
+}




Groonga-commit メーリングリストの案内
Back to archive index