[Groonga-commit] groonga/groonga [master] Added suggest function module.

Back to archive index

null+****@clear***** null+****@clear*****
2010年 8月 19日 (木) 18:46:21 JST


Tasuku SUENAGA a.k.a. gunyarakun	2010-08-19 09:46:21 +0000 (Thu, 19 Aug 2010)

  New Revision: 218c887b7db8dfd038d6452964a92858ede95488

  Log:
    Added suggest function module.

  Added files:
    modules/functions/suggest.c
  Modified files:
    modules/functions/Makefile.am

  Modified: modules/functions/Makefile.am (+2 -1)
===================================================================
--- modules/functions/Makefile.am    2010-08-19 06:11:35 +0000 (ddbae23)
+++ modules/functions/Makefile.am    2010-08-19 09:46:21 +0000 (fa8b1dd)
@@ -11,6 +11,7 @@ AM_LDFLAGS =					\
 LIBS =						\
 	$(top_builddir)/lib/libgroonga.la
 
-function_modules_LTLIBRARIES = cast.la
+function_modules_LTLIBRARIES = cast.la suggest.la
 
 cast_la_SOURCES = cast.c
+suggest_la_SOURCES = suggest.c

  Added: modules/functions/suggest.c (+147 -0) 100644
===================================================================
--- /dev/null
+++ modules/functions/suggest.c    2010-08-19 09:46:21 +0000 (f67a7a4)
@@ -0,0 +1,147 @@
+/* Copyright(C) 2010 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "db.h"
+#include "ii.h"
+#include "output.h"
+#include <string.h>
+
+#define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0
+#define VAR GRN_PROC_GET_VAR_BY_OFFSET
+
+static grn_obj *
+func_suggest(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
+{
+  grn_obj *table;
+  if ((table = grn_ctx_get(ctx, GRN_TEXT_VALUE(VAR(0)),
+                           GRN_TEXT_LEN(VAR(0))))) {
+    grn_obj *col;
+    if ((col = grn_obj_column(ctx, table, GRN_TEXT_VALUE(VAR(1)),
+                              GRN_TEXT_LEN(VAR(1))))) {
+      grn_obj *index;
+      /* FIXME: support index selection */
+      if (grn_column_index(ctx, col, GRN_OP_PREFIX,
+                           &index, 1, NULL)) {
+        grn_table_cursor *cur;
+        if ((cur = grn_table_cursor_open(ctx, grn_ctx_at(ctx, index->header.domain),
+                                         GRN_TEXT_VALUE(VAR(2)), GRN_TEXT_LEN(VAR(2)),
+                                         NULL, 0,
+                                         0, -1,
+                                         GRN_CURSOR_PREFIX | GRN_CURSOR_RK))) {
+          grn_obj *res;
+          if ((res = grn_table_create(ctx, NULL, 0, NULL,
+                                       GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, table, NULL))) {
+            /* RK search */
+            grn_id id;
+            while ((id = grn_table_cursor_next(ctx, cur))) {
+              grn_ii_cursor *icur;
+              if ((icur = grn_ii_cursor_open(ctx, (grn_ii *)index, id,
+                                             GRN_ID_NIL, GRN_ID_MAX, 1, 0))) {
+                grn_ii_posting *p;
+                while ((p = grn_ii_cursor_next(ctx, icur))) {
+                  grn_hash_add(ctx, (grn_hash *)res, &p->rid, sizeof(grn_id), NULL, NULL);
+                }
+                grn_ii_cursor_close(ctx, icur);
+              } else {
+                ERR(GRN_UNKNOWN_ERROR, "cannot open cursor for index.");
+                break;
+              }
+            }
+            /* sort */
+            {
+              grn_obj *sorted;
+              if ((sorted = grn_table_create(ctx, NULL, 0, NULL,
+                                             GRN_OBJ_TABLE_NO_KEY, NULL, res))) {
+                uint32_t nkeys;
+                grn_table_sort_key *keys;
+                if ((keys = grn_table_sort_key_from_str(ctx, CONST_STR_LEN("-score"), res, &nkeys))) {
+                  grn_table_cursor *scur;
+                  /* TODO: support offset limit */
+                  grn_table_sort(ctx, res, 0, grn_table_size(ctx, res), sorted, keys, nkeys);
+                  GRN_OUTPUT_ARRAY_OPEN("RESULT", -1);
+                  if ((scur = grn_table_cursor_open(ctx, sorted, NULL, 0, NULL, 0, 0, -1, 0))) {
+                    grn_id sid;
+                    while ((sid = grn_table_cursor_next(ctx, scur))) {
+                      grn_id stid;
+                      unsigned int key_len;
+                      char key[GRN_TABLE_MAX_KEY_SIZE];
+                      grn_table_get_key(ctx, sorted, sid, &stid, sizeof(grn_id));
+                      key_len = grn_table_get_key(ctx, table, stid, key, GRN_TABLE_MAX_KEY_SIZE);
+                      GRN_OUTPUT_STR(key, key_len);
+                    }
+                    grn_table_cursor_close(ctx, scur);
+                  } else {
+                    ERR(GRN_UNKNOWN_ERROR, "cannot open sorted cursor.");
+                  }
+                  GRN_OUTPUT_ARRAY_CLOSE();
+                  grn_table_sort_key_close(ctx, keys, nkeys);
+                } else {
+                  ERR(GRN_UNKNOWN_ERROR, "cannot sort.");
+                }
+                grn_obj_close(ctx, sorted);
+              } else {
+                ERR(GRN_UNKNOWN_ERROR, "cannot create temporary sort table.");
+              }
+            }
+            grn_obj_close(ctx, res);
+          } else {
+            ERR(GRN_UNKNOWN_ERROR, "cannot create temporary table.");
+          }
+          grn_table_cursor_close(ctx, cur);
+        } else {
+          ERR(GRN_UNKNOWN_ERROR, "cannot open cursor for pk.");
+        }
+      } else {
+        ERR(GRN_UNKNOWN_ERROR, "cannot find index for prefix search.");
+      }
+    } else {
+      ERR(GRN_INVALID_ARGUMENT, "invalid column.");
+    }
+  } else {
+    ERR(GRN_INVALID_ARGUMENT, "invalid table.");
+  }
+  return NULL;
+}
+
+grn_rc
+grn_module_init_suggest(grn_ctx *ctx)
+{
+  return GRN_SUCCESS;
+}
+
+grn_rc
+grn_module_register_suggest(grn_ctx *ctx)
+{
+  /* TODO: offset/limit */
+  grn_expr_var vars[] = {
+    {CONST_STR_LEN("table")},
+    {CONST_STR_LEN("column")},
+    {CONST_STR_LEN("query")}
+  };
+  GRN_TEXT_INIT(&vars[0].value, 0);
+  GRN_TEXT_INIT(&vars[1].value, 0);
+  GRN_TEXT_INIT(&vars[2].value, 0);
+
+  grn_proc_create(ctx, CONST_STR_LEN("suggest"), GRN_PROC_FUNCTION, func_suggest, NULL, NULL, 3, vars);
+
+  return ctx->rc;
+}
+
+grn_rc
+grn_module_fin_suggest(grn_ctx *ctx)
+{
+  return GRN_SUCCESS;
+}




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