[Groonga-commit] groonga/groonga [master] Added output.c and output.h

Back to archive index

null+****@clear***** null+****@clear*****
2010年 6月 16日 (水) 22:53:21 JST


Daijiro MORI	2010-06-16 13:53:21 +0000 (Wed, 16 Jun 2010)

  New Revision: 5f7782f1cd589d2df0206648cbc3b1c7c683f969

  Log:
    Added output.c and output.h

  Added files:
    lib/output.c
    lib/output.h
  Modified files:
    groonga.h
    lib/Makefile.am
    lib/ctx.c
    lib/expr.c
    lib/proc.c
    lib/ql.h
    lib/str.h

  Modified: groonga.h (+1 -2)
===================================================================
--- groonga.h    2010-06-16 07:34:48 +0000 (b280268)
+++ groonga.h    2010-06-16 13:53:21 +0000 (381fe6f)
@@ -2062,8 +2062,7 @@ GRN_API grn_table_sort_key *grn_table_sort_key_from_str(grn_ctx *ctx,
 GRN_API grn_rc grn_table_sort_key_close(grn_ctx *ctx,
                                         grn_table_sort_key *keys, unsigned nkeys);
 
-GRN_API grn_rc grn_select(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
-                          const char *table, unsigned table_len,
+GRN_API grn_rc grn_select(grn_ctx *ctx, const char *table, unsigned table_len,
                           const char *match_columns, unsigned match_columns_len,
                           const char *query, unsigned query_len,
                           const char *filter, unsigned filter_len,

  Modified: lib/Makefile.am (+2 -2)
===================================================================
--- lib/Makefile.am    2010-06-16 07:34:48 +0000 (e1a9038)
+++ lib/Makefile.am    2010-06-16 13:53:21 +0000 (9649e66)
@@ -5,14 +5,14 @@ AM_CFLAGS = -fno-strict-aliasing $(COVERAGE_CFLAGS)
 DEFAULT_INCLUDES = -I$(top_builddir) -I$(srcdir) -I$(top_srcdir)
 DEFS += -D_REENTRANT -DGROONGA_VERSION=\"$(GROONGA_VERSION)\"
 
-libgroonga_la_SOURCES = io.c str.c nfkc.c snip.c query.c store.c com.c ql.c scm.c ctx.c hash.c db.c pat.c ii.c token.c proc.c expr.c util.c module.c
+libgroonga_la_SOURCES = io.c str.c nfkc.c snip.c query.c store.c com.c ql.c scm.c ctx.c hash.c db.c pat.c ii.c token.c proc.c expr.c util.c module.c output.c
 
 libgroonga_la_LDFLAGS =				\
 	-version-info 0:0:0			\
 	-no-undefined				\
 	$(WINDOWS_LDFLAGS)
 
-noinst_HEADERS = com.h io.h ql.h nfkc.h groonga_in.h snip.h store.h str.h ctx.h hash.h db.h pat.h ii.h token.h proc.h util.h module.h
+noinst_HEADERS = com.h io.h ql.h nfkc.h groonga_in.h snip.h store.h str.h ctx.h hash.h db.h pat.h ii.h token.h proc.h util.h module.h output.h
 
 EXTRA_DIST = ecmascript.c ecmascript.h ecmascript.y
 

  Modified: lib/ctx.c (+6 -0)
===================================================================
--- lib/ctx.c    2010-06-16 07:34:48 +0000 (fcdb9f4)
+++ lib/ctx.c    2010-06-16 13:53:21 +0000 (c6dc83c)
@@ -257,6 +257,9 @@ grn_ctx_impl_init(grn_ctx *ctx)
   ctx->impl->qe_next = NULL;
   ctx->impl->parser = NULL;
 
+  GRN_TEXT_INIT(&ctx->impl->names, 0);
+  GRN_TEXT_INIT(&ctx->impl->levels, 0);
+
   ctx->impl->phs = NIL;
   ctx->impl->code = NIL;
   ctx->impl->dump = NIL;
@@ -425,6 +428,8 @@ grn_ctx_fin(grn_ctx *ctx)
       grn_ctx_send(ctx, "ACK", 3, GRN_CTX_HEAD);
       rc = grn_com_close(ctx, ctx->impl->com);
     }
+    GRN_OBJ_FIN(ctx, &ctx->impl->names);
+    GRN_OBJ_FIN(ctx, &ctx->impl->levels);
     rc = grn_obj_close(ctx, ctx->impl->outbuf);
     rc = grn_bulk_fin(ctx, &ctx->impl->subbuf);
     {
@@ -999,6 +1004,7 @@ grn_ctx_send(grn_ctx *ctx, const char *str, unsigned int str_len, int flags)
       } else {
         ctx->impl->mime_type = "application/json";
         ctx->impl->output_type = GRN_CONTENT_JSON;
+        ctx->impl->opened = 1;
         grn_timeval_now(ctx, &ctx->impl->tv);
         GRN_LOG(ctx, GRN_LOG_NONE, "%08x|>%.*s", (intptr_t)ctx, str_len, str);
         if (str_len && *str == '/') {

  Modified: lib/expr.c (+0 -311)
===================================================================
--- lib/expr.c    2010-06-16 07:34:48 +0000 (81a2643)
+++ lib/expr.c    2010-06-16 13:53:21 +0000 (f9c4de8)
@@ -20,7 +20,6 @@
 #include <string.h>
 #include <float.h>
 #include "ii.h"
-#include "util.h"
 
 grn_obj *
 grn_expr_alloc(grn_ctx *ctx, grn_obj *expr, grn_id domain, grn_obj_flags flags)
@@ -5494,313 +5493,3 @@ grn_expr_snip(grn_ctx *ctx, grn_obj *expr, int flags,
   }
   GRN_API_RETURN(res);
 }
-
-grn_rc
-grn_select(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
-           const char *table, unsigned table_len,
-           const char *match_columns, unsigned match_columns_len,
-           const char *query, unsigned query_len,
-           const char *filter, unsigned filter_len,
-           const char *scorer, unsigned scorer_len,
-           const char *sortby, unsigned sortby_len,
-           const char *output_columns, unsigned output_columns_len,
-           int offset, int limit,
-           const char *drilldown, unsigned drilldown_len,
-           const char *drilldown_sortby, unsigned drilldown_sortby_len,
-           const char *drilldown_output_columns, unsigned drilldown_output_columns_len,
-           int drilldown_offset, int drilldown_limit,
-           const char *cache, unsigned cache_len)
-{
-  uint32_t nkeys, nhits;
-  uint16_t cacheable = 1, taintable = 0;
-  grn_obj_format format;
-  grn_table_sort_key *keys;
-  grn_obj *table_, *match_columns_ = NULL, *cond, *scorer_, *res = NULL, *sorted;
-  char cache_key[GRN_TABLE_MAX_KEY_SIZE];
-  uint32_t cache_key_size = table_len + 1 + match_columns_len + 1 + query_len + 1 +
-    filter_len + 1 + scorer_len + 1 + sortby_len + 1 + output_columns_len + 1 +
-    drilldown_len + 1 + drilldown_sortby_len + 1 + drilldown_output_columns_len +
-    sizeof(grn_content_type) + sizeof(int) * 4;
-  if (cache_key_size <= GRN_TABLE_MAX_KEY_SIZE) {
-    grn_obj *cache;
-    char *cp = cache_key;
-    memcpy(cp, table, table_len);
-    cp += table_len; *cp++ = '\0';
-    memcpy(cp, match_columns, match_columns_len);
-    cp += match_columns_len; *cp++ = '\0';
-    memcpy(cp, query, query_len);
-    cp += query_len; *cp++ = '\0';
-    memcpy(cp, filter, filter_len);
-    cp += filter_len; *cp++ = '\0';
-    memcpy(cp, scorer, scorer_len);
-    cp += scorer_len; *cp++ = '\0';
-    memcpy(cp, sortby, sortby_len);
-    cp += sortby_len; *cp++ = '\0';
-    memcpy(cp, output_columns, output_columns_len);
-    cp += output_columns_len; *cp++ = '\0';
-    memcpy(cp, drilldown, drilldown_len);
-    cp += drilldown_len; *cp++ = '\0';
-    memcpy(cp, drilldown_sortby, drilldown_sortby_len);
-    cp += drilldown_sortby_len; *cp++ = '\0';
-    memcpy(cp, drilldown_output_columns, drilldown_output_columns_len);
-    cp += drilldown_output_columns_len; *cp++ = '\0';
-    memcpy(cp, &output_type, sizeof(grn_content_type)); cp += sizeof(grn_content_type);
-    memcpy(cp, &offset, sizeof(int)); cp += sizeof(int);
-    memcpy(cp, &limit, sizeof(int)); cp += sizeof(int);
-    memcpy(cp, &drilldown_offset, sizeof(int)); cp += sizeof(int);
-    memcpy(cp, &drilldown_limit, sizeof(int)); cp += sizeof(int);
-    if ((cache = grn_cache_fetch(ctx, cache_key, cache_key_size))) {
-      GRN_TEXT_PUT(ctx, outbuf, GRN_TEXT_VALUE(cache), GRN_TEXT_LEN(cache));
-      grn_cache_unref(cache_key, cache_key_size);
-      LAP("cache");
-      return ctx->rc;
-    }
-  }
-  if ((table_ = grn_ctx_get(ctx, table, table_len))) {
-    // match_columns_ = grn_obj_column(ctx, table_, match_columns, match_columns_len);
-    if (query_len || filter_len) {
-      grn_obj *v;
-      GRN_EXPR_CREATE_FOR_QUERY(ctx, table_, cond, v);
-      if (cond) {
-        if (match_columns_len) {
-          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);
-          } else {
-            /* todo */
-          }
-        }
-        if (query_len) {
-          grn_expr_parse(ctx, cond, query, query_len,
-                         match_columns_, GRN_OP_MATCH, GRN_OP_AND,
-                         GRN_EXPR_SYNTAX_QUERY|GRN_EXPR_ALLOW_PRAGMA|GRN_EXPR_ALLOW_COLUMN);
-          if (!ctx->rc && filter_len) {
-            grn_expr_parse(ctx, cond, filter, filter_len,
-                           match_columns_, GRN_OP_MATCH, GRN_OP_AND,
-                           GRN_EXPR_SYNTAX_SCRIPT);
-            if (!ctx->rc) { grn_expr_append_op(ctx, cond, GRN_OP_AND, 2); }
-          }
-        } else {
-          grn_expr_parse(ctx, cond, filter, filter_len,
-                         match_columns_, GRN_OP_MATCH, GRN_OP_AND,
-                         GRN_EXPR_SYNTAX_SCRIPT);
-        }
-        cacheable *= ((grn_expr *)cond)->cacheable;
-        taintable += ((grn_expr *)cond)->taintable;
-        /*
-        grn_obj strbuf;
-        GRN_TEXT_INIT(&strbuf, 0);
-        grn_expr_inspect(ctx, &strbuf, cond);
-        GRN_TEXT_PUTC(ctx, &strbuf, '\0');
-        GRN_LOG(ctx, GRN_LOG_NOTICE, "query=(%s)", GRN_TEXT_VALUE(&strbuf));
-        GRN_OBJ_FIN(ctx, &strbuf);
-        */
-        if (!ctx->rc) { res = grn_table_select(ctx, table_, cond, NULL, GRN_OP_OR); }
-        if (match_columns_) { grn_obj_unlink(ctx, match_columns_); }
-        grn_obj_unlink(ctx, cond);
-      } else {
-        /* todo */
-        ERRCLR(ctx);
-      }
-    } else {
-      res = table_;
-    }
-    LAP("select");
-    switch (output_type) {
-    case GRN_CONTENT_JSON:
-      GRN_TEXT_PUTS(ctx, outbuf, "[");
-      break;
-    case GRN_CONTENT_XML:
-      GRN_TEXT_PUTS(ctx, outbuf, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
-                    "<SEGMENTS>\n<SEGMENT>\n<RESULTPAGE>\n");
-      break;
-    case GRN_CONTENT_TSV:
-      grn_text_itoa(ctx, outbuf, ctx->rc);
-    case GRN_CONTENT_NONE:
-      break;
-    }
-    if (res) {
-      if (scorer && scorer_len) {
-        grn_obj *v;
-        GRN_EXPR_CREATE_FOR_QUERY(ctx, res, scorer_, v);
-        if (scorer_ && v) {
-          grn_table_cursor *tc;
-          grn_expr_parse(ctx, scorer_, scorer, scorer_len, NULL, GRN_OP_MATCH, GRN_OP_AND,
-                         GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE);
-          cacheable *= ((grn_expr *)scorer_)->cacheable;
-          taintable += ((grn_expr *)scorer_)->taintable;
-          if ((tc = grn_table_cursor_open(ctx, res, NULL, 0, NULL, 0, 0, -1, 0))) {
-            while (!grn_table_cursor_next_o(ctx, tc, v)) {
-              grn_expr_exec(ctx, scorer_, 0);
-            }
-            grn_table_cursor_close(ctx, tc);
-          }
-          grn_obj_unlink(ctx, scorer_);
-        }
-        LAP("score");
-      }
-      nhits = grn_table_size(ctx, res);
-
-      grn_normalize_offset_and_limit(ctx, nhits, &offset, &limit);
-      ERRCLR(ctx);
-
-      if (sortby_len) {
-        if ((sorted = grn_table_create(ctx, NULL, 0, NULL,
-                                       GRN_OBJ_TABLE_NO_KEY, NULL, res))) {
-          if ((keys = grn_table_sort_key_from_str(ctx, sortby, sortby_len, res, &nkeys))) {
-            grn_table_sort(ctx, res, offset, limit, sorted, keys, nkeys);
-            LAP("sort");
-            GRN_OBJ_FORMAT_INIT(&format, nhits, 0, limit, offset);
-            grn_obj_columns(ctx, sorted, output_columns, output_columns_len, &format.columns);
-            switch (output_type) {
-            case GRN_CONTENT_JSON:
-              format.flags = GRN_OBJ_FORMAT_WITH_COLUMN_NAMES;
-              grn_text_otoj(ctx, outbuf, sorted, &format);
-              break;
-            case GRN_CONTENT_TSV:
-              GRN_TEXT_PUTC(ctx, outbuf, '\n');
-              /* TODO: implement grn_text_ototsv */
-              break;
-            case GRN_CONTENT_XML:
-              format.flags = GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET;
-              grn_text_otoxml(ctx, outbuf, sorted, &format);
-              break;
-            case GRN_CONTENT_NONE:
-              break;
-            }
-            GRN_OBJ_FORMAT_FIN(ctx, &format);
-            grn_table_sort_key_close(ctx, keys, nkeys);
-          }
-          grn_obj_unlink(ctx, sorted);
-        }
-      } else {
-        GRN_OBJ_FORMAT_INIT(&format, nhits, offset, limit, offset);
-        grn_obj_columns(ctx, res, output_columns, output_columns_len, &format.columns);
-        switch (output_type) {
-        case GRN_CONTENT_JSON:
-          format.flags = GRN_OBJ_FORMAT_WITH_COLUMN_NAMES;
-          grn_text_otoj(ctx, outbuf, res, &format);
-          break;
-        case GRN_CONTENT_TSV:
-          GRN_TEXT_PUTC(ctx, outbuf, '\n');
-          /* TODO: implement */
-          break;
-        case GRN_CONTENT_XML:
-          format.flags = GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET;
-          grn_text_otoxml(ctx, outbuf, res, &format);
-          break;
-        case GRN_CONTENT_NONE:
-          break;
-        }
-        GRN_OBJ_FORMAT_FIN(ctx, &format);
-      }
-      LAP("output");
-      if (!ctx->rc && drilldown_len) {
-        uint32_t i, ngkeys;
-        grn_table_sort_key *gkeys;
-        grn_table_group_result g = {NULL, 0, 0, 1, GRN_TABLE_GROUP_CALC_COUNT, 0};
-        if ((gkeys = grn_table_sort_key_from_str(ctx, drilldown,
-                                                 drilldown_len, res, &ngkeys))) {
-          for (i = 0; i < ngkeys; i++) {
-            if ((g.table = grn_table_create_for_group(ctx, NULL, 0, NULL,
-                                                      GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC,
-                                                      gkeys[i].key, NULL))) {
-              int n_drilldown_offset = drilldown_offset,
-                  n_drilldown_limit = drilldown_limit;
-
-              grn_table_group(ctx, res, &gkeys[i], 1, &g, 1);
-              nhits = grn_table_size(ctx, g.table);
-
-              grn_normalize_offset_and_limit(ctx, nhits,
-                                             &n_drilldown_offset, &n_drilldown_limit);
-              ERRCLR(ctx);
-
-              if (drilldown_sortby_len) {
-                if ((keys = grn_table_sort_key_from_str(ctx,
-                                                        drilldown_sortby, drilldown_sortby_len,
-                                                        g.table, &nkeys))) {
-                  if ((sorted = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY,
-                                                 NULL, g.table))) {
-                    grn_table_sort(ctx, g.table, n_drilldown_offset, n_drilldown_limit,
-                                   sorted, keys, nkeys);
-                    GRN_OBJ_FORMAT_INIT(&format, nhits, 0,
-                                        n_drilldown_limit, n_drilldown_offset);
-                    grn_obj_columns(ctx, sorted,
-                                    drilldown_output_columns, drilldown_output_columns_len,
-                                    &format.columns);
-                    switch (output_type) {
-                    case GRN_CONTENT_JSON:
-                      format.flags = GRN_OBJ_FORMAT_WITH_COLUMN_NAMES;
-                      GRN_TEXT_PUTC(ctx, outbuf, ',');
-                      grn_text_otoj(ctx, outbuf, sorted, &format);
-                      break;
-                    case GRN_CONTENT_XML:
-                      format.flags = GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY;
-                      grn_text_otoxml(ctx, outbuf, sorted, &format);
-                      break;
-                    case GRN_CONTENT_NONE:
-                    case GRN_CONTENT_TSV:
-                      /* TODO: implement */
-                      break;
-                    }
-                    GRN_OBJ_FORMAT_FIN(ctx, &format);
-                    grn_obj_unlink(ctx, sorted);
-                  }
-                  grn_table_sort_key_close(ctx, keys, nkeys);
-                }
-              } else {
-                GRN_OBJ_FORMAT_INIT(&format, nhits, n_drilldown_offset,
-                                    n_drilldown_limit, n_drilldown_offset);
-                grn_obj_columns(ctx, g.table, drilldown_output_columns,
-                                drilldown_output_columns_len, &format.columns);
-                switch (output_type) {
-                case GRN_CONTENT_JSON:
-                  format.flags = GRN_OBJ_FORMAT_WITH_COLUMN_NAMES;
-                  GRN_TEXT_PUTC(ctx, outbuf, ',');
-                  grn_text_otoj(ctx, outbuf, g.table, &format);
-                  break;
-                case GRN_CONTENT_XML:
-                  format.flags = GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY;
-                  grn_text_otoxml(ctx, outbuf, g.table, &format);
-                  break;
-                case GRN_CONTENT_NONE:
-                case GRN_CONTENT_TSV:
-                  /* TODO: implement */
-                  break;
-                }
-                GRN_OBJ_FORMAT_FIN(ctx, &format);
-              }
-              grn_obj_unlink(ctx, g.table);
-            }
-            LAP("drilldown");
-          }
-          grn_table_sort_key_close(ctx, gkeys, ngkeys);
-        }
-      }
-      if (res != table_) { grn_obj_unlink(ctx, res); }
-    }
-    switch (output_type) {
-    case GRN_CONTENT_JSON:
-      GRN_TEXT_PUTS(ctx, outbuf, "]");
-      break;
-    case GRN_CONTENT_TSV:
-      GRN_TEXT_PUTC(ctx, outbuf, '\n');
-      break;
-    case GRN_CONTENT_XML:
-      GRN_TEXT_PUTS(ctx, outbuf, "</RESULTPAGE>\n</SEGMENT>\n</SEGMENTS>\n");
-      break;
-    case GRN_CONTENT_NONE:
-      break;
-    }
-    if (!ctx->rc && cacheable && cache_key_size <= GRN_TABLE_MAX_KEY_SIZE
-        && (!cache || cache_len != 2 || *cache != 'n' || *(cache + 1) != 'o')) {
-      grn_cache_update(ctx, cache_key, cache_key_size, outbuf);
-    }
-    if (taintable) { grn_db_touch(ctx, DB_OBJ(table_)->db); }
-    grn_obj_unlink(ctx, table_);
-  }
-  /* GRN_LOG(ctx, GRN_LOG_NONE, "%d", ctx->seqno); */
-  return ctx->rc;
-}

  Added: lib/output.c (+151 -0) 100644
===================================================================
--- /dev/null
+++ lib/output.c    2010-06-16 13:53:21 +0000 (038a661)
@@ -0,0 +1,151 @@
+/* -*- c-basic-offset: 2 -*- */
+/* Copyright(C) 2009-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 <string.h>
+#include "output.h"
+#include "ql.h"
+
+void
+grn_output_array_open(grn_ctx *ctx, const char *name, int nelements)
+{
+  grn_obj *outbuf = ctx->impl->outbuf;
+  grn_content_type output_type = ctx->impl->output_type;
+  switch (output_type) {
+  case GRN_CONTENT_JSON:
+    if (!ctx->impl->opened) { GRN_TEXT_PUTC(ctx, outbuf, ','); }
+    GRN_TEXT_PUTC(ctx, outbuf, '[');
+    break;
+  case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, outbuf, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+                  "<SEGMENTS>\n<SEGMENT>\n<RESULTPAGE>\n");
+    break;
+  case GRN_CONTENT_TSV:
+    grn_text_itoa(ctx, outbuf, ctx->rc);
+  case GRN_CONTENT_NONE:
+    break;
+  }
+  ctx->impl->opened = 1;
+}
+
+void
+grn_output_array_close(grn_ctx *ctx)
+{
+  grn_obj *outbuf = ctx->impl->outbuf;
+  grn_content_type output_type = ctx->impl->output_type;
+  switch (output_type) {
+  case GRN_CONTENT_JSON:
+    GRN_TEXT_PUTC(ctx, outbuf, ']');
+    break;
+  case GRN_CONTENT_TSV:
+    GRN_TEXT_PUTC(ctx, outbuf, '\n');
+    break;
+  case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, outbuf, "</RESULTPAGE>\n</SEGMENT>\n</SEGMENTS>\n");
+    break;
+  case GRN_CONTENT_NONE:
+    break;
+  }
+  ctx->impl->opened = 0;
+}
+
+void
+grn_output_map_open(grn_ctx *ctx, int nelements)
+{
+  grn_obj *outbuf = ctx->impl->outbuf;
+  grn_content_type output_type = ctx->impl->output_type;
+  switch (output_type) {
+  case GRN_CONTENT_JSON:
+    if (!ctx->impl->opened) { GRN_TEXT_PUTC(ctx, outbuf, ','); }
+    GRN_TEXT_PUTS(ctx, outbuf, "{");
+    break;
+  case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, outbuf, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+                  "<SEGMENTS>\n<SEGMENT>\n<RESULTPAGE>\n");
+    break;
+  case GRN_CONTENT_TSV:
+    grn_text_itoa(ctx, outbuf, ctx->rc);
+  case GRN_CONTENT_NONE:
+    break;
+  }
+  ctx->impl->opened = 1;
+}
+
+void
+grn_output_map_close(grn_ctx *ctx)
+{
+  grn_obj *outbuf = ctx->impl->outbuf;
+  grn_content_type output_type = ctx->impl->output_type;
+  switch (output_type) {
+  case GRN_CONTENT_JSON:
+    GRN_TEXT_PUTS(ctx, outbuf, "}");
+    break;
+  case GRN_CONTENT_TSV:
+    GRN_TEXT_PUTC(ctx, outbuf, '\n');
+    break;
+  case GRN_CONTENT_XML:
+    GRN_TEXT_PUTS(ctx, outbuf, "</RESULTPAGE>\n</SEGMENT>\n</SEGMENTS>\n");
+    break;
+  case GRN_CONTENT_NONE:
+    break;
+  }
+  ctx->impl->opened = 0;
+}
+
+void
+grn_output_int(grn_ctx *ctx, int value)
+{
+  grn_obj *outbuf = ctx->impl->outbuf;
+  grn_content_type output_type = ctx->impl->output_type;
+  switch (output_type) {
+  case GRN_CONTENT_JSON:
+    if (!ctx->impl->opened) { GRN_TEXT_PUTC(ctx, outbuf, ','); }
+    grn_text_itoa(ctx, outbuf, value);
+    break;
+  case GRN_CONTENT_TSV:
+    grn_text_itoa(ctx, outbuf, value);
+    break;
+  case GRN_CONTENT_XML:
+    grn_text_itoa(ctx, outbuf, value);
+    break;
+  case GRN_CONTENT_NONE:
+    break;
+  }
+  ctx->impl->opened = 0;
+}
+
+void
+grn_output_obj(grn_ctx *ctx, grn_obj *obj, grn_obj_format *format)
+{
+  grn_obj *outbuf = ctx->impl->outbuf;
+  grn_content_type output_type = ctx->impl->output_type;
+  switch (output_type) {
+  case GRN_CONTENT_JSON:
+    if (!ctx->impl->opened) { GRN_TEXT_PUTC(ctx, outbuf, ','); }
+    grn_text_otoj(ctx, outbuf, obj, format);
+    break;
+  case GRN_CONTENT_TSV:
+    GRN_TEXT_PUTC(ctx, outbuf, '\n');
+    /* TODO: implement grn_text_ototsv */
+    break;
+  case GRN_CONTENT_XML:
+    grn_text_otoxml(ctx, outbuf, obj, format);
+    break;
+  case GRN_CONTENT_NONE:
+    break;
+  }
+  ctx->impl->opened = 0;
+}

  Added: lib/output.h (+47 -0) 100644
===================================================================
--- /dev/null
+++ lib/output.h    2010-06-16 13:53:21 +0000 (2a547bf)
@@ -0,0 +1,47 @@
+/* -*- c-basic-offset: 2 -*- */
+/* 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
+*/
+#ifndef GRN_OUTPUT_H
+#define GRN_OUTPUT_H
+
+#ifndef GROONGA_IN_H
+#include "groonga_in.h"
+#endif /* GROONGA_IN_H */
+
+#ifndef GRN_CTX_H
+#include "ctx.h"
+#endif /* GRN_CTX_H */
+
+#ifndef GRN_STORE_H
+#include "store.h"
+#endif /* GRN_STORE_H */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grn_output_array_open(grn_ctx *ctx, const char *name, int nelements);
+void grn_output_array_close(grn_ctx *ctx);
+void grn_output_map_open(grn_ctx *ctx, int nelements);
+void grn_output_map_close(grn_ctx *ctx);
+void grn_output_int(grn_ctx *ctx, int value);
+void grn_output_obj(grn_ctx *ctx, grn_obj *obj, grn_obj_format *format);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_OUTPUT_H */

  Modified: lib/proc.c (+253 -4)
===================================================================
--- lib/proc.c    2010-06-16 07:34:48 +0000 (ff8bb5d)
+++ lib/proc.c    2010-06-16 13:53:21 +0000 (07aa1cb)
@@ -23,6 +23,8 @@
 #include "proc.h"
 #include "ql.h"
 #include "db.h"
+#include "util.h"
+#include "output.h"
 
 #ifndef O_NOFOLLOW
 #define O_NOFOLLOW 0
@@ -40,11 +42,259 @@ const char *grn_admin_html_path = NULL;
 #define DEFAULT_DRILLDOWN_LIMIT           10
 #define DEFAULT_DRILLDOWN_OUTPUT_COLUMNS  "_key _nsubrecs"
 
+#define LAP(msg) {\
+  uint64_t et;\
+  grn_timeval tv;\
+  grn_timeval_now(ctx, &tv);\
+  et = (tv.tv_sec - ctx->impl->tv.tv_sec) * GRN_TIME_USEC_PER_SEC\
+    + (tv.tv_usec - ctx->impl->tv.tv_usec);\
+  GRN_LOG(ctx, GRN_LOG_NONE, "%08x|:%012llu %s", (intptr_t)ctx, et, msg);\
+}
+
+grn_rc
+grn_select(grn_ctx *ctx, const char *table, unsigned table_len,
+           const char *match_columns, unsigned match_columns_len,
+           const char *query, unsigned query_len,
+           const char *filter, unsigned filter_len,
+           const char *scorer, unsigned scorer_len,
+           const char *sortby, unsigned sortby_len,
+           const char *output_columns, unsigned output_columns_len,
+           int offset, int limit,
+           const char *drilldown, unsigned drilldown_len,
+           const char *drilldown_sortby, unsigned drilldown_sortby_len,
+           const char *drilldown_output_columns, unsigned drilldown_output_columns_len,
+           int drilldown_offset, int drilldown_limit,
+           const char *cache, unsigned cache_len)
+{
+  uint32_t nkeys, nhits;
+  uint16_t cacheable = 1, taintable = 0;
+  grn_obj_format format;
+  grn_table_sort_key *keys;
+  grn_obj *outbuf = ctx->impl->outbuf;
+  grn_content_type output_type = ctx->impl->output_type;
+  grn_obj *table_, *match_columns_ = NULL, *cond, *scorer_, *res = NULL, *sorted;
+  char cache_key[GRN_TABLE_MAX_KEY_SIZE];
+  uint32_t cache_key_size = table_len + 1 + match_columns_len + 1 + query_len + 1 +
+    filter_len + 1 + scorer_len + 1 + sortby_len + 1 + output_columns_len + 1 +
+    drilldown_len + 1 + drilldown_sortby_len + 1 + drilldown_output_columns_len +
+    sizeof(grn_content_type) + sizeof(int) * 4;
+  if (cache_key_size <= GRN_TABLE_MAX_KEY_SIZE) {
+    grn_obj *cache;
+    char *cp = cache_key;
+    memcpy(cp, table, table_len);
+    cp += table_len; *cp++ = '\0';
+    memcpy(cp, match_columns, match_columns_len);
+    cp += match_columns_len; *cp++ = '\0';
+    memcpy(cp, query, query_len);
+    cp += query_len; *cp++ = '\0';
+    memcpy(cp, filter, filter_len);
+    cp += filter_len; *cp++ = '\0';
+    memcpy(cp, scorer, scorer_len);
+    cp += scorer_len; *cp++ = '\0';
+    memcpy(cp, sortby, sortby_len);
+    cp += sortby_len; *cp++ = '\0';
+    memcpy(cp, output_columns, output_columns_len);
+    cp += output_columns_len; *cp++ = '\0';
+    memcpy(cp, drilldown, drilldown_len);
+    cp += drilldown_len; *cp++ = '\0';
+    memcpy(cp, drilldown_sortby, drilldown_sortby_len);
+    cp += drilldown_sortby_len; *cp++ = '\0';
+    memcpy(cp, drilldown_output_columns, drilldown_output_columns_len);
+    cp += drilldown_output_columns_len; *cp++ = '\0';
+    memcpy(cp, &output_type, sizeof(grn_content_type)); cp += sizeof(grn_content_type);
+    memcpy(cp, &offset, sizeof(int)); cp += sizeof(int);
+    memcpy(cp, &limit, sizeof(int)); cp += sizeof(int);
+    memcpy(cp, &drilldown_offset, sizeof(int)); cp += sizeof(int);
+    memcpy(cp, &drilldown_limit, sizeof(int)); cp += sizeof(int);
+    if ((cache = grn_cache_fetch(ctx, cache_key, cache_key_size))) {
+      GRN_TEXT_PUT(ctx, outbuf, GRN_TEXT_VALUE(cache), GRN_TEXT_LEN(cache));
+      grn_cache_unref(cache_key, cache_key_size);
+      LAP("cache");
+      return ctx->rc;
+    }
+  }
+  if ((table_ = grn_ctx_get(ctx, table, table_len))) {
+    // match_columns_ = grn_obj_column(ctx, table_, match_columns, match_columns_len);
+    if (query_len || filter_len) {
+      grn_obj *v;
+      GRN_EXPR_CREATE_FOR_QUERY(ctx, table_, cond, v);
+      if (cond) {
+        if (match_columns_len) {
+          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);
+          } else {
+            /* todo */
+          }
+        }
+        if (query_len) {
+          grn_expr_parse(ctx, cond, query, query_len,
+                         match_columns_, GRN_OP_MATCH, GRN_OP_AND,
+                         GRN_EXPR_SYNTAX_QUERY|GRN_EXPR_ALLOW_PRAGMA|GRN_EXPR_ALLOW_COLUMN);
+          if (!ctx->rc && filter_len) {
+            grn_expr_parse(ctx, cond, filter, filter_len,
+                           match_columns_, GRN_OP_MATCH, GRN_OP_AND,
+                           GRN_EXPR_SYNTAX_SCRIPT);
+            if (!ctx->rc) { grn_expr_append_op(ctx, cond, GRN_OP_AND, 2); }
+          }
+        } else {
+          grn_expr_parse(ctx, cond, filter, filter_len,
+                         match_columns_, GRN_OP_MATCH, GRN_OP_AND,
+                         GRN_EXPR_SYNTAX_SCRIPT);
+        }
+        cacheable *= ((grn_expr *)cond)->cacheable;
+        taintable += ((grn_expr *)cond)->taintable;
+        /*
+        grn_obj strbuf;
+        GRN_TEXT_INIT(&strbuf, 0);
+        grn_expr_inspect(ctx, &strbuf, cond);
+        GRN_TEXT_PUTC(ctx, &strbuf, '\0');
+        GRN_LOG(ctx, GRN_LOG_NOTICE, "query=(%s)", GRN_TEXT_VALUE(&strbuf));
+        GRN_OBJ_FIN(ctx, &strbuf);
+        */
+        if (!ctx->rc) { res = grn_table_select(ctx, table_, cond, NULL, GRN_OP_OR); }
+        if (match_columns_) { grn_obj_unlink(ctx, match_columns_); }
+        grn_obj_unlink(ctx, cond);
+      } else {
+        /* todo */
+        ERRCLR(ctx);
+      }
+    } else {
+      res = table_;
+    }
+    LAP("select");
+    grn_output_array_open(ctx, "RESULTPAGE", -1);
+    if (res) {
+      if (scorer && scorer_len) {
+        grn_obj *v;
+        GRN_EXPR_CREATE_FOR_QUERY(ctx, res, scorer_, v);
+        if (scorer_ && v) {
+          grn_table_cursor *tc;
+          grn_expr_parse(ctx, scorer_, scorer, scorer_len, NULL, GRN_OP_MATCH, GRN_OP_AND,
+                         GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE);
+          cacheable *= ((grn_expr *)scorer_)->cacheable;
+          taintable += ((grn_expr *)scorer_)->taintable;
+          if ((tc = grn_table_cursor_open(ctx, res, NULL, 0, NULL, 0, 0, -1, 0))) {
+            while (!grn_table_cursor_next_o(ctx, tc, v)) {
+              grn_expr_exec(ctx, scorer_, 0);
+            }
+            grn_table_cursor_close(ctx, tc);
+          }
+          grn_obj_unlink(ctx, scorer_);
+        }
+        LAP("score");
+      }
+      nhits = grn_table_size(ctx, res);
+
+      grn_normalize_offset_and_limit(ctx, nhits, &offset, &limit);
+      ERRCLR(ctx);
+
+      if (sortby_len) {
+        if ((sorted = grn_table_create(ctx, NULL, 0, NULL,
+                                       GRN_OBJ_TABLE_NO_KEY, NULL, res))) {
+          if ((keys = grn_table_sort_key_from_str(ctx, sortby, sortby_len, res, &nkeys))) {
+            grn_table_sort(ctx, res, offset, limit, sorted, keys, nkeys);
+            LAP("sort");
+            GRN_OBJ_FORMAT_INIT(&format, nhits, 0, limit, offset);
+            format.flags =
+              GRN_OBJ_FORMAT_WITH_COLUMN_NAMES|
+              GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET;
+            grn_obj_columns(ctx, sorted, output_columns, output_columns_len, &format.columns);
+            grn_output_obj(ctx, sorted, &format);
+            GRN_OBJ_FORMAT_FIN(ctx, &format);
+            grn_table_sort_key_close(ctx, keys, nkeys);
+          }
+          grn_obj_unlink(ctx, sorted);
+        }
+      } else {
+        GRN_OBJ_FORMAT_INIT(&format, nhits, offset, limit, offset);
+        format.flags =
+          GRN_OBJ_FORMAT_WITH_COLUMN_NAMES|
+          GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET;
+        grn_obj_columns(ctx, res, output_columns, output_columns_len, &format.columns);
+        grn_output_obj(ctx, res, &format);
+        GRN_OBJ_FORMAT_FIN(ctx, &format);
+      }
+      LAP("output");
+      if (!ctx->rc && drilldown_len) {
+        uint32_t i, ngkeys;
+        grn_table_sort_key *gkeys;
+        grn_table_group_result g = {NULL, 0, 0, 1, GRN_TABLE_GROUP_CALC_COUNT, 0};
+        if ((gkeys = grn_table_sort_key_from_str(ctx, drilldown,
+                                                 drilldown_len, res, &ngkeys))) {
+          for (i = 0; i < ngkeys; i++) {
+            if ((g.table = grn_table_create_for_group(ctx, NULL, 0, NULL,
+                                                      GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC,
+                                                      gkeys[i].key, NULL))) {
+              int n_drilldown_offset = drilldown_offset,
+                  n_drilldown_limit = drilldown_limit;
+
+              grn_table_group(ctx, res, &gkeys[i], 1, &g, 1);
+              nhits = grn_table_size(ctx, g.table);
+
+              grn_normalize_offset_and_limit(ctx, nhits,
+                                             &n_drilldown_offset, &n_drilldown_limit);
+              ERRCLR(ctx);
+
+              if (drilldown_sortby_len) {
+                if ((keys = grn_table_sort_key_from_str(ctx,
+                                                        drilldown_sortby, drilldown_sortby_len,
+                                                        g.table, &nkeys))) {
+                  if ((sorted = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY,
+                                                 NULL, g.table))) {
+                    grn_table_sort(ctx, g.table, n_drilldown_offset, n_drilldown_limit,
+                                   sorted, keys, nkeys);
+                    GRN_OBJ_FORMAT_INIT(&format, nhits, 0,
+                                        n_drilldown_limit, n_drilldown_offset);
+                    format.flags =
+                      GRN_OBJ_FORMAT_WITH_COLUMN_NAMES|
+                      GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY;
+                    grn_obj_columns(ctx, sorted,
+                                    drilldown_output_columns, drilldown_output_columns_len,
+                                    &format.columns);
+                    grn_output_obj(ctx, sorted, &format);
+                    GRN_OBJ_FORMAT_FIN(ctx, &format);
+                    grn_obj_unlink(ctx, sorted);
+                  }
+                  grn_table_sort_key_close(ctx, keys, nkeys);
+                }
+              } else {
+                GRN_OBJ_FORMAT_INIT(&format, nhits, n_drilldown_offset,
+                                    n_drilldown_limit, n_drilldown_offset);
+                format.flags =
+                  GRN_OBJ_FORMAT_WITH_COLUMN_NAMES|
+                  GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY;
+                grn_obj_columns(ctx, g.table, drilldown_output_columns,
+                                drilldown_output_columns_len, &format.columns);
+                grn_output_obj(ctx, g.table, &format);
+                GRN_OBJ_FORMAT_FIN(ctx, &format);
+              }
+              grn_obj_unlink(ctx, g.table);
+            }
+            LAP("drilldown");
+          }
+          grn_table_sort_key_close(ctx, gkeys, ngkeys);
+        }
+      }
+      if (res != table_) { grn_obj_unlink(ctx, res); }
+    }
+    grn_output_array_close(ctx);
+    if (!ctx->rc && cacheable && cache_key_size <= GRN_TABLE_MAX_KEY_SIZE
+        && (!cache || cache_len != 2 || *cache != 'n' || *(cache + 1) != 'o')) {
+      grn_cache_update(ctx, cache_key, cache_key_size, outbuf);
+    }
+    if (taintable) { grn_db_touch(ctx, DB_OBJ(table_)->db); }
+    grn_obj_unlink(ctx, table_);
+  }
+  /* GRN_LOG(ctx, GRN_LOG_NONE, "%d", ctx->seqno); */
+  return ctx->rc;
+}
+
 static grn_obj *
 proc_select(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
 {
-  grn_content_type ct = ctx->impl->output_type;
-  grn_obj *outbuf = ctx->impl->outbuf;
   int offset = GRN_TEXT_LEN(VAR(7))
     ? grn_atoi(GRN_TEXT_VALUE(VAR(7)), GRN_BULK_CURR(VAR(7)), NULL)
     : 0;
@@ -69,8 +319,7 @@ proc_select(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
     drilldown_output_columns = DEFAULT_DRILLDOWN_OUTPUT_COLUMNS;
     drilldown_output_columns_len = strlen(DEFAULT_DRILLDOWN_OUTPUT_COLUMNS);
   }
-  if (grn_select(ctx, outbuf, ct,
-                 GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0)),
+  if (grn_select(ctx, GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0)),
                  GRN_TEXT_VALUE(VAR(1)), GRN_TEXT_LEN(VAR(1)),
                  GRN_TEXT_VALUE(VAR(2)), GRN_TEXT_LEN(VAR(2)),
                  GRN_TEXT_VALUE(VAR(3)), GRN_TEXT_LEN(VAR(3)),

  Modified: lib/ql.h (+3 -0)
===================================================================
--- lib/ql.h    2010-06-16 07:34:48 +0000 (1fe6bee)
+++ lib/ql.h    2010-06-16 13:53:21 +0000 (dbbcc3a)
@@ -196,6 +196,9 @@ struct _grn_ctx_impl {
   /* output portion */
   grn_content_type output_type;
   const char *mime_type;
+  uint32_t opened;
+  grn_obj names;
+  grn_obj levels;
 
   /* ql portion */
   uint32_t ncells;

  Modified: lib/str.h (+3 -3)
===================================================================
--- lib/str.h    2010-06-16 07:34:48 +0000 (0218d2e)
+++ lib/str.h    2010-06-16 13:53:21 +0000 (2030e46)
@@ -113,9 +113,9 @@ void grn_str_url_path_normalize(grn_ctx *ctx, const char *path, size_t path_len,
 
 GRN_API grn_rc grn_text_otoxml(grn_ctx *ctx, grn_obj *bulk, grn_obj *obj,
                                 grn_obj_format *format);
-#define GRN_OBJ_FORMAT_XML_ELEMENT_MASK             (0x01<<0)
-#define GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET        (0x00<<0)
-#define GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY  (0x01<<0)
+#define GRN_OBJ_FORMAT_XML_ELEMENT_MASK             (0x01<<1)
+#define GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET        (0x00<<1)
+#define GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY  (0x01<<1)
 
 #ifdef __cplusplus
 }




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