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
}