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 }