susumu.yata
null+****@clear*****
Mon Nov 16 15:17:14 JST 2015
susumu.yata 2015-11-16 15:17:14 +0900 (Mon, 16 Nov 2015) New Revision: c1d98ed0ab0b3890911275c6f92a8da96154ac51 https://github.com/groonga/groonga/commit/c1d98ed0ab0b3890911275c6f92a8da96154ac51 Message: grn_ts: add grn_ts_expr_builder to simplify grn_ts_expr Added files: lib/ts/ts_expr_builder.c lib/ts/ts_expr_builder.h Modified files: lib/ts.c lib/ts/sources.am lib/ts/ts_buf.h lib/ts/ts_expr.c lib/ts/ts_expr.h lib/ts/ts_expr_node.c lib/ts/ts_expr_node.h lib/ts/ts_expr_parser.c lib/ts/ts_expr_parser.h lib/ts/ts_str.h lib/ts/ts_util.c Modified: lib/ts.c (+4 -3) =================================================================== --- lib/ts.c 2015-11-16 14:59:23 +0900 (4a3c6f2) +++ lib/ts.c 2015-11-16 15:17:14 +0900 (cb7ab1c) @@ -429,7 +429,8 @@ grn_ts_writer_build(grn_ctx *ctx, grn_ts_writer *writer, grn_obj *table) const char *name_ptr; size_t name_size = grn_vector_get_element(ctx, &writer->name_buf, i, &name_ptr, NULL, NULL); - rc = grn_ts_expr_parse(ctx, table, name_ptr, name_size, &new_expr); + rc = grn_ts_expr_parse(ctx, table, (grn_ts_str){ name_ptr, name_size }, + &new_expr); if (rc != GRN_SUCCESS) { return rc; } @@ -667,7 +668,7 @@ grn_ts_select_filter(grn_ctx *ctx, grn_obj *table, grn_ts_str str, return (ctx->rc != GRN_SUCCESS) ? ctx->rc : GRN_UNKNOWN_ERROR; } - rc = grn_ts_expr_parse(ctx, table, str.ptr, str.size, &expr); + rc = grn_ts_expr_parse(ctx, table, str, &expr); if (rc == GRN_SUCCESS) { for ( ; ; ) { size_t i, batch_size; @@ -776,7 +777,7 @@ grn_ts_select_scorer(grn_ctx *ctx, grn_obj *table, grn_ts_str str, rest = str; } } - rc = grn_ts_expr_parse(ctx, table, rest.ptr, rest.size, &expr); + rc = grn_ts_expr_parse(ctx, table, rest, &expr); if (rc != GRN_SUCCESS) { return rc; } Modified: lib/ts/sources.am (+2 -0) =================================================================== --- lib/ts/sources.am 2015-11-16 14:59:23 +0900 (17fcc62) +++ lib/ts/sources.am 2015-11-16 15:17:14 +0900 (37732d6) @@ -3,6 +3,8 @@ libgrnts_la_SOURCES = \ ts_buf.h \ ts_expr.c \ ts_expr.h \ + ts_expr_builder.c \ + ts_expr_builder.h \ ts_expr_node.c \ ts_expr_node.h \ ts_expr_parser.c \ Modified: lib/ts/ts_buf.h (+2 -0) =================================================================== --- lib/ts/ts_buf.h 2015-11-16 14:59:23 +0900 (7a24b37) +++ lib/ts/ts_buf.h 2015-11-16 15:17:14 +0900 (4c66a00) @@ -19,6 +19,8 @@ #ifndef GRN_TS_BUF_H #define GRN_TS_BUF_H +#include "../grn.h" + #include "ts_types.h" #ifdef __cplusplus Modified: lib/ts/ts_expr.c (+64 -918) =================================================================== --- lib/ts/ts_expr.c 2015-11-16 14:59:23 +0900 (e987c40) +++ lib/ts/ts_expr.c 2015-11-16 15:17:14 +0900 (7eadc66) @@ -23,93 +23,74 @@ #include <string.h> #include "../grn_ctx.h" -#include "../grn_dat.h" -#include "../grn_db.h" -#include "../grn_geo.h" -#include "../grn_hash.h" -#include "../grn_pat.h" -#include "../grn_store.h" #include "ts_log.h" #include "ts_str.h" #include "ts_util.h" #include "ts_expr_parser.h" -/*------------------------------------------------------------- - * grn_ts_expr_bridge. - */ - -/* grn_ts_expr_bridge_init() initializes a bridge. */ -static void -grn_ts_expr_bridge_init(grn_ctx *ctx, grn_ts_expr_bridge *bridge) -{ - memset(bridge, 0, sizeof(*bridge)); - bridge->src_table = NULL; - bridge->dest_table = NULL; -} - -/* grn_ts_expr_bridge_fin() finalizes a bridge. */ -static void -grn_ts_expr_bridge_fin(grn_ctx *ctx, grn_ts_expr_bridge *bridge) -{ - if (bridge->dest_table) { - grn_obj_unlink(ctx, bridge->dest_table); - } - /* Note: bridge->src_table does not increment a reference count. */ -} - -/*------------------------------------------------------------- - * grn_ts_expr. - */ - /* grn_ts_expr_init() initializes an expression. */ static void grn_ts_expr_init(grn_ctx *ctx, grn_ts_expr *expr) { memset(expr, 0, sizeof(*expr)); expr->table = NULL; - expr->curr_table = NULL; expr->root = NULL; - expr->stack = NULL; - expr->bridges = NULL; } /* grn_ts_expr_fin() finalizes an expression. */ static void grn_ts_expr_fin(grn_ctx *ctx, grn_ts_expr *expr) { - size_t i; - if (expr->bridges) { - for (i = 0; i < expr->n_bridges; i++) { - grn_ts_expr_bridge_fin(ctx, &expr->bridges[i]); - } - GRN_FREE(expr->bridges); - } - if (expr->stack) { - for (i = 0; i < expr->stack_depth; i++) { - if (expr->stack[i]) { - grn_ts_expr_node_close(ctx, expr->stack[i]); - } - } - GRN_FREE(expr->stack); + if (expr->root) { + grn_ts_expr_node_close(ctx, expr->root); } - /* Note: expr->curr_table does not increment a reference count. */ if (expr->table) { grn_obj_unlink(ctx, expr->table); } } grn_rc -grn_ts_expr_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr **expr) +grn_ts_expr_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr_node *root, + grn_ts_expr **expr) { grn_rc rc; grn_ts_expr *new_expr; + grn_ts_expr_type type; if (!ctx) { return GRN_INVALID_ARGUMENT; } - if (!table || !grn_ts_obj_is_table(ctx, table) || !expr) { + if (!table || !grn_ts_obj_is_table(ctx, table) || !root || !expr) { GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); } + switch (root->type) { + case GRN_TS_EXPR_ID_NODE: { + type = GRN_TS_EXPR_ID; + break; + } + case GRN_TS_EXPR_SCORE_NODE: { + type = GRN_TS_EXPR_SCORE; + break; + } + case GRN_TS_EXPR_KEY_NODE: + case GRN_TS_EXPR_VALUE_NODE: { + type = GRN_TS_EXPR_VARIABLE; + break; + } + case GRN_TS_EXPR_CONST_NODE: { + type = GRN_TS_EXPR_CONST; + break; + } + case GRN_TS_EXPR_COLUMN_NODE: + case GRN_TS_EXPR_OP_NODE: + case GRN_TS_EXPR_BRIDGE_NODE: { + type = GRN_TS_EXPR_VARIABLE; + break; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + } new_expr = GRN_MALLOCN(grn_ts_expr, 1); if (!new_expr) { GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, @@ -123,34 +104,35 @@ grn_ts_expr_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr **expr) } grn_ts_expr_init(ctx, new_expr); new_expr->table = table; - new_expr->curr_table = table; + new_expr->type = type; + new_expr->data_kind = root->data_kind; + new_expr->data_type = root->data_type; + new_expr->root = root; *expr = new_expr; return GRN_SUCCESS; } grn_rc -grn_ts_expr_parse(grn_ctx *ctx, grn_obj *table, - const char *str_ptr, size_t str_size, grn_ts_expr **expr) +grn_ts_expr_parse(grn_ctx *ctx, grn_obj *table, grn_ts_str str, + grn_ts_expr **expr) { grn_rc rc; grn_ts_expr *new_expr; + grn_ts_expr_parser *parser; if (!ctx) { return GRN_INVALID_ARGUMENT; } if (!table || !grn_ts_obj_is_table(ctx, table) || - (!str_ptr && str_size) || !expr) { + (!str.ptr && str.size) || !expr) { GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); } - rc = grn_ts_expr_open(ctx, table, &new_expr); + rc = grn_ts_expr_parser_open(ctx, table, &parser); if (rc != GRN_SUCCESS) { return rc; } - rc = grn_ts_expr_push(ctx, new_expr, str_ptr, str_size); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_complete(ctx, new_expr); - } + rc = grn_ts_expr_parser_parse(ctx, parser, str, &new_expr); + grn_ts_expr_parser_close(ctx, parser); if (rc != GRN_SUCCESS) { - grn_ts_expr_close(ctx, new_expr); return rc; } *expr = new_expr; @@ -160,857 +142,14 @@ grn_ts_expr_parse(grn_ctx *ctx, grn_obj *table, grn_rc grn_ts_expr_close(grn_ctx *ctx, grn_ts_expr *expr) { - if (!ctx || !expr) { - return GRN_INVALID_ARGUMENT; - } - grn_ts_expr_fin(ctx, expr); - GRN_FREE(expr); - return GRN_SUCCESS; -} - -grn_obj * -grn_ts_expr_get_table(grn_ctx *ctx, grn_ts_expr *expr) -{ - if (!ctx || !expr) { - return NULL; - } - /* The reference counting will never fail in practice. */ - if (grn_ts_obj_increment_ref_count(ctx, expr->table) != GRN_SUCCESS) { - return NULL; - } - return expr->table; -} - -grn_ts_expr_type -grn_ts_expr_get_type(grn_ctx *ctx, grn_ts_expr *expr) -{ - return (!ctx || !expr) ? GRN_TS_EXPR_BROKEN : expr->type; -} - -grn_ts_data_kind -grn_ts_expr_get_data_kind(grn_ctx *ctx, grn_ts_expr *expr) -{ - return (!ctx || !expr) ? GRN_TS_VOID : expr->data_kind; -} - -grn_ts_data_type -grn_ts_expr_get_data_type(grn_ctx *ctx, grn_ts_expr *expr) -{ - return (!ctx || !expr) ? GRN_DB_VOID : expr->data_type; -} - -grn_ts_expr_node * -grn_ts_expr_get_root(grn_ctx *ctx, grn_ts_expr *expr) -{ - return (!ctx || !expr) ? NULL : expr->root; -} - -/* grn_ts_expr_reserve_stack() extends a stack. */ -static grn_rc -grn_ts_expr_reserve_stack(grn_ctx *ctx, grn_ts_expr *expr) -{ - size_t i, n_bytes, new_size; - grn_ts_expr_node **new_stack; - if (expr->stack_depth < expr->stack_size) { - return GRN_SUCCESS; - } - new_size = expr->stack_size ? (expr->stack_size * 2) : 1; - n_bytes = sizeof(grn_ts_expr_node *) * new_size; - new_stack = GRN_REALLOC(expr->stack, n_bytes); - if (!new_stack) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, - "GRN_REALLOC failed: %" GRN_FMT_SIZE, - n_bytes); - } - for (i = expr->stack_size; i < new_size; i++) { - new_stack[i] = NULL; - } - expr->stack = new_stack; - expr->stack_size = new_size; - return GRN_SUCCESS; -} - -/* grn_ts_expr_deref() dereferences a node. */ -static grn_rc -grn_ts_expr_deref(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_node **node_ptr) -{ - grn_ts_expr_node *node = *node_ptr; - while (node->data_kind == GRN_TS_REF) { - grn_rc rc; - grn_ts_expr_node *key_node, *bridge_node; - grn_id table_id = node->data_type; - grn_obj *table = grn_ctx_at(ctx, table_id); - if (!table) { - return GRN_OBJECT_CORRUPT; - } - if (!grn_ts_obj_is_table(ctx, table)) { - grn_obj_unlink(ctx, table); - return GRN_OBJECT_CORRUPT; - } - rc = grn_ts_expr_key_node_open(ctx, table, &key_node); - grn_obj_unlink(ctx, table); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_bridge_node_open(ctx, node, key_node, &bridge_node); - if (rc != GRN_SUCCESS) { - return rc; - } - node = bridge_node; - } - *node_ptr = node; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_push(grn_ctx *ctx, grn_ts_expr *expr, - const char *str_ptr, size_t str_size) -{ - grn_rc rc; - grn_ts_expr_parser *parser; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || - (!str_ptr && str_size)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_parser_open(ctx, expr, &parser); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_parser_parse(ctx, parser, str_ptr, str_size); - grn_ts_expr_parser_close(ctx, parser); - return rc; -} - -grn_rc -grn_ts_expr_push_name(grn_ctx *ctx, grn_ts_expr *expr, - const char *name_ptr, size_t name_size) -{ - grn_obj *column; - grn_ts_str name = { name_ptr, name_size }; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || - !grn_ts_str_is_name(name)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - if (grn_ts_str_is_id_name(name)) { - return grn_ts_expr_push_id(ctx, expr); - } - if (grn_ts_str_is_score_name(name)) { - return grn_ts_expr_push_score(ctx, expr); - } - if (grn_ts_str_is_key_name(name)) { - return grn_ts_expr_push_key(ctx, expr); - } - if (grn_ts_str_is_value_name(name)) { - return grn_ts_expr_push_value(ctx, expr); - } - /* grn_obj_column() returns a column or accessor. */ - column = grn_obj_column(ctx, expr->curr_table, name.ptr, name.size); - if (!column) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "object not found: \"%.*s\"", - (int)name.size, name.ptr); - } - return grn_ts_expr_push_obj(ctx, expr, column); -} - -#define GRN_TS_EXPR_PUSH_BULK_CASE(TYPE, kind)\ - case GRN_DB_ ## TYPE: {\ - return grn_ts_expr_push_ ## kind(ctx, expr, GRN_ ## TYPE ## _VALUE(obj));\ - } -/* grn_ts_expr_push_bulk() pushes a scalar. */ -static grn_rc -grn_ts_expr_push_bulk(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) -{ - switch (obj->header.domain) { - GRN_TS_EXPR_PUSH_BULK_CASE(BOOL, bool) - GRN_TS_EXPR_PUSH_BULK_CASE(INT8, int) - GRN_TS_EXPR_PUSH_BULK_CASE(INT16, int) - GRN_TS_EXPR_PUSH_BULK_CASE(INT32, int) - GRN_TS_EXPR_PUSH_BULK_CASE(INT64, int) - GRN_TS_EXPR_PUSH_BULK_CASE(UINT8, int) - GRN_TS_EXPR_PUSH_BULK_CASE(UINT16, int) - GRN_TS_EXPR_PUSH_BULK_CASE(UINT32, int) - /* The behavior is undefined if a value is greater than 2^63 - 1. */ - GRN_TS_EXPR_PUSH_BULK_CASE(UINT64, int) - GRN_TS_EXPR_PUSH_BULK_CASE(FLOAT, float) - GRN_TS_EXPR_PUSH_BULK_CASE(TIME, time) - case GRN_DB_SHORT_TEXT: - case GRN_DB_TEXT: - case GRN_DB_LONG_TEXT: { - grn_ts_text value = { GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj) }; - return grn_ts_expr_push_text(ctx, expr, value); - } - case GRN_DB_TOKYO_GEO_POINT: { - grn_ts_geo value; - GRN_GEO_POINT_VALUE(obj, value.latitude, value.longitude); - return grn_ts_expr_push_tokyo_geo(ctx, expr, value); - } - case GRN_DB_WGS84_GEO_POINT: { - grn_ts_geo value; - GRN_GEO_POINT_VALUE(obj, value.latitude, value.longitude); - return grn_ts_expr_push_wgs84_geo(ctx, expr, value); - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "not bulk"); - } - } -} -#undef GRN_TS_EXPR_PUSH_BULK_CASE - -#define GRN_TS_EXPR_PUSH_UVECTOR_CASE(TYPE, kind)\ - case GRN_DB_ ## TYPE: {\ - grn_ts_ ## kind ##_vector value = { (grn_ts_ ## kind *)GRN_BULK_HEAD(obj),\ - grn_uvector_size(ctx, obj) };\ - return grn_ts_expr_push_ ## kind ## _vector(ctx, expr, value);\ - } -#define GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(TYPE, kind)\ - case GRN_DB_ ## TYPE: {\ - size_t i;\ - grn_rc rc;\ - grn_ts_ ## kind *buf;\ - grn_ts_ ## kind ## _vector value = { NULL, grn_uvector_size(ctx, obj) };\ - if (!value.size) {\ - return grn_ts_expr_push_ ## kind ## _vector(ctx, expr, value);\ - }\ - buf = GRN_MALLOCN(grn_ts_ ## kind, value.size);\ - if (!buf) {\ - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE,\ - "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1",\ - sizeof(grn_ts_ ## kind));\ - }\ - for (i = 0; i < value.size; i++) {\ - buf[i] = GRN_ ## TYPE ##_VALUE_AT(obj, i);\ - }\ - value.ptr = buf;\ - rc = grn_ts_expr_push_ ## kind ## _vector(ctx, expr, value);\ - GRN_FREE(buf);\ - return rc;\ - } -/* grn_ts_expr_push_uvector() pushes an array of fixed-size values. */ -static grn_rc -grn_ts_expr_push_uvector(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) -{ - switch (obj->header.domain) { - GRN_TS_EXPR_PUSH_UVECTOR_CASE(BOOL, bool) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT8, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT16, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT32, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(INT64, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT8, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT16, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT32, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(UINT64, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(TIME, time) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(TOKYO_GEO_POINT, tokyo_geo) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(WGS84_GEO_POINT, wgs84_geo) - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data type: %d", - obj->header.domain); - } - } -} -#undef GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST -#undef GRN_TS_EXPR_PUSH_UVECTOR_CASE - -/* grn_ts_expr_push_vector() pushes an array of texts. */ -static grn_rc -grn_ts_expr_push_vector(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) -{ - switch (obj->header.domain) { - case GRN_DB_SHORT_TEXT: - case GRN_DB_TEXT: - case GRN_DB_LONG_TEXT: { - size_t i; - grn_rc rc; - grn_ts_text *buf; - grn_ts_text_vector value = { NULL, grn_vector_size(ctx, obj) }; - if (!value.size) { - return grn_ts_expr_push_text_vector(ctx, expr, value); - } - buf = GRN_MALLOCN(grn_ts_text, value.size); - if (!buf) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, - "GRN_MALLOCN failed: " - "%" GRN_FMT_SIZE " x %" GRN_FMT_SIZE, - sizeof(grn_ts_text), value.size); - } - for (i = 0; i < value.size; i++) { - buf[i].size = grn_vector_get_element(ctx, obj, i, &buf[i].ptr, - NULL, NULL); - } - value.ptr = buf; - rc = grn_ts_expr_push_text_vector(ctx, expr, value); - GRN_FREE(buf); - return rc; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data type: %d", - obj->header.domain); - } - } -} - -static grn_rc -grn_ts_expr_push_single_accessor(grn_ctx *ctx, grn_ts_expr *expr, - grn_accessor *accessor) -{ - switch (accessor->action) { - case GRN_ACCESSOR_GET_ID: { - return grn_ts_expr_push_id(ctx, expr); - } - case GRN_ACCESSOR_GET_SCORE: { - return grn_ts_expr_push_score(ctx, expr); - } - case GRN_ACCESSOR_GET_KEY: { - if (accessor->obj != expr->curr_table) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table conflict"); - } - return grn_ts_expr_push_key(ctx, expr); - } - case GRN_ACCESSOR_GET_VALUE: { - if (accessor->obj != expr->curr_table) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table conflict"); - } - return grn_ts_expr_push_value(ctx, expr); - } - case GRN_ACCESSOR_GET_COLUMN_VALUE: { - return grn_ts_expr_push_column(ctx, expr, accessor->obj); - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid accessor action: %d", - accessor->action); - } - } -} - -static grn_rc -grn_ts_expr_push_accessor(grn_ctx *ctx, grn_ts_expr *expr, - grn_accessor *accessor) -{ - grn_rc rc = grn_ts_expr_push_single_accessor(ctx, expr, accessor); - if (rc != GRN_SUCCESS) { - return rc; - } - for (accessor = accessor->next; accessor; accessor = accessor->next) { - rc = grn_ts_expr_begin_subexpr(ctx, expr); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_push_single_accessor(ctx, expr, accessor); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_end_subexpr(ctx, expr); - if (rc != GRN_SUCCESS) { - return rc; - } - } - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_push_obj(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) -{ - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || !obj) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - switch (obj->header.type) { - case GRN_BULK: { - return grn_ts_expr_push_bulk(ctx, expr, obj); - } - case GRN_UVECTOR: { - return grn_ts_expr_push_uvector(ctx, expr, obj); - } - case GRN_VECTOR: { - return grn_ts_expr_push_vector(ctx, expr, obj); - } - case GRN_ACCESSOR: { - return grn_ts_expr_push_accessor(ctx, expr, (grn_accessor *)obj); - } - case GRN_COLUMN_FIX_SIZE: - case GRN_COLUMN_VAR_SIZE: { - return grn_ts_expr_push_column(ctx, expr, obj); - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid object type: %d", - obj->header.type); - } - } -} - -grn_rc -grn_ts_expr_push_id(grn_ctx *ctx, grn_ts_expr *expr) -{ - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_id_node_open(ctx, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_score(grn_ctx *ctx, grn_ts_expr *expr) -{ - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_score_node_open(ctx, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_key(grn_ctx *ctx, grn_ts_expr *expr) -{ - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_key_node_open(ctx, expr->curr_table, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_value(grn_ctx *ctx, grn_ts_expr *expr) -{ - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_value_node_open(ctx, expr->curr_table, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_const(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_data_kind kind, const void *value) -{ - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || !value) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_const_node_open(ctx, kind, value, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_column(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *column) -{ - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || - !column || !grn_ts_obj_is_column(ctx, column) || - (DB_OBJ(expr->curr_table)->id != column->header.domain)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_column_node_open(ctx, column, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_op(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_op_type op_type) -{ - grn_rc rc; - grn_ts_expr_node **args, *node; - size_t i, n_args, max_n_args; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - n_args = grn_ts_op_get_n_args(op_type); - if (!n_args) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, - "invalid #arguments: %" GRN_FMT_SIZE, - n_args); - } - max_n_args = expr->stack_depth; - if (expr->n_bridges) { - max_n_args -= expr->bridges[expr->n_bridges - 1].stack_depth; - } - if (n_args > max_n_args) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, - "invalid #arguments: %" GRN_FMT_SIZE ", %" GRN_FMT_SIZE, - n_args, expr->stack_depth); - } - /* Arguments are the top n_args nodes in the stack. */ - args = &expr->stack[expr->stack_depth - n_args]; - for (i = 0; i < n_args; i++) { - /* - * FIXME: Operators "==" and "!=" should compare arguments as references - * if possible. - */ - rc = grn_ts_expr_deref(ctx, expr, &args[i]); - if (rc != GRN_SUCCESS) { - return rc; - } - } - expr->stack_depth -= n_args; - rc = grn_ts_expr_op_node_open(ctx, op_type, args, n_args, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - return rc; -} - -grn_rc -grn_ts_expr_push_bool(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_bool value) -{ - return grn_ts_expr_push_const(ctx, expr, GRN_TS_BOOL, &value); -} - -grn_rc -grn_ts_expr_push_int(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_int value) -{ - return grn_ts_expr_push_const(ctx, expr, GRN_TS_INT, &value); -} - -grn_rc -grn_ts_expr_push_float(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_float value) -{ - return grn_ts_expr_push_const(ctx, expr, GRN_TS_FLOAT, &value); -} - -grn_rc -grn_ts_expr_push_time(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_time value) -{ - return grn_ts_expr_push_const(ctx, expr, GRN_TS_TIME, &value); -} - -grn_rc -grn_ts_expr_push_text(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_text value) -{ - return grn_ts_expr_push_const(ctx, expr, GRN_TS_TEXT, &value); -} - -grn_rc -grn_ts_expr_push_geo(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_geo value) -{ - return grn_ts_expr_push_const(ctx, expr, GRN_TS_GEO, &value); -} - -grn_rc -grn_ts_expr_push_tokyo_geo(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_geo value) -{ - grn_rc rc = grn_ts_expr_push_const(ctx, expr, GRN_TS_GEO, &value); - if (rc != GRN_SUCCESS) { - return rc; - } - expr->stack[expr->stack_depth - 1]->data_type = GRN_DB_TOKYO_GEO_POINT; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_push_wgs84_geo(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_geo value) -{ - grn_rc rc = grn_ts_expr_push_const(ctx, expr, GRN_TS_GEO, &value); - if (rc != GRN_SUCCESS) { - return rc; - } - expr->stack[expr->stack_depth - 1]->data_type = GRN_DB_WGS84_GEO_POINT; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_push_bool_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_bool_vector value) -{ - return grn_ts_expr_push_const(ctx, expr, GRN_TS_BOOL_VECTOR, &value); -} - -grn_rc -grn_ts_expr_push_int_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_int_vector value) -{ - return grn_ts_expr_push_const(ctx, expr, GRN_TS_INT_VECTOR, &value); -} - -grn_rc -grn_ts_expr_push_float_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_float_vector value) -{ - return grn_ts_expr_push_const(ctx, expr, GRN_TS_FLOAT_VECTOR, &value); -} - -grn_rc -grn_ts_expr_push_time_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_time_vector value) -{ - return grn_ts_expr_push_const(ctx, expr, GRN_TS_TIME_VECTOR, &value); -} - -grn_rc -grn_ts_expr_push_text_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_text_vector value) -{ - return grn_ts_expr_push_const(ctx, expr, GRN_TS_TEXT_VECTOR, &value); -} - -grn_rc -grn_ts_expr_push_geo_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_vector value) -{ - return grn_ts_expr_push_const(ctx, expr, GRN_TS_GEO_VECTOR, &value); -} - -grn_rc -grn_ts_expr_push_tokyo_geo_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_vector value) -{ - grn_rc rc = grn_ts_expr_push_const(ctx, expr, GRN_TS_GEO_VECTOR, &value); - if (rc != GRN_SUCCESS) { - return rc; - } - expr->stack[expr->stack_depth - 1]->data_type = GRN_DB_TOKYO_GEO_POINT; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_push_wgs84_geo_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_vector value) -{ - grn_rc rc = grn_ts_expr_push_const(ctx, expr, GRN_TS_GEO_VECTOR, &value); - if (rc != GRN_SUCCESS) { - return rc; - } - expr->stack[expr->stack_depth - 1]->data_type = GRN_DB_TOKYO_GEO_POINT; - return GRN_SUCCESS; -} - -/* grn_ts_expr_reserve_bridges() extends a bridge buffer for a new bridge. */ -static grn_rc -grn_ts_expr_reserve_bridges(grn_ctx *ctx, grn_ts_expr *expr) -{ - size_t n_bytes, new_max_n_bridges; - grn_ts_expr_bridge *new_bridges; - if (expr->n_bridges < expr->max_n_bridges) { - return GRN_SUCCESS; - } - new_max_n_bridges = expr->n_bridges * 2; - if (!new_max_n_bridges) { - new_max_n_bridges = 1; - } - n_bytes = sizeof(grn_ts_expr_bridge) * new_max_n_bridges; - new_bridges = (grn_ts_expr_bridge *)GRN_REALLOC(expr->bridges, n_bytes); - if (!new_bridges) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, - "GRN_REALLOC failed: %" GRN_FMT_SIZE, - n_bytes); - } - expr->bridges = new_bridges; - expr->max_n_bridges = new_max_n_bridges; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_begin_subexpr(grn_ctx *ctx, grn_ts_expr *expr) -{ - grn_rc rc; - size_t max_n_args; - grn_obj *obj; - grn_ts_expr_node *node; - grn_ts_expr_bridge *bridge; if (!ctx) { return GRN_INVALID_ARGUMENT; } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { + if (!expr) { GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); } - max_n_args = expr->stack_depth; - if (expr->n_bridges) { - max_n_args -= expr->bridges[expr->n_bridges - 1].stack_depth; - } - if (!max_n_args) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - - /* Check whehter or not the latest node refers to a table. */ - node = expr->stack[expr->stack_depth - 1]; - if ((node->data_kind & ~GRN_TS_VECTOR_FLAG) != GRN_TS_REF) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->data_kind); - } - obj = grn_ctx_at(ctx, node->data_type); - if (!obj) { - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", - node->data_type); - } - if (!grn_ts_obj_is_table(ctx, obj)) { - grn_obj_unlink(ctx, obj); - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "not table: %d", node->data_type); - } - - /* Creates a bridge to a subexpression. */ - rc = grn_ts_expr_reserve_bridges(ctx, expr); - if (rc != GRN_SUCCESS) { - grn_obj_unlink(ctx, obj); - return rc; - } - bridge = &expr->bridges[expr->n_bridges++]; - grn_ts_expr_bridge_init(ctx, bridge); - bridge->src_table = expr->curr_table; - bridge->dest_table = obj; - bridge->stack_depth = expr->stack_depth; - expr->curr_table = bridge->dest_table; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_end_subexpr(grn_ctx *ctx, grn_ts_expr *expr) -{ - grn_rc rc; - grn_ts_expr_node **args, *node; - grn_ts_expr_bridge *bridge; - if (!ctx || !expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || - (expr->stack_depth < 2) || !expr->n_bridges) { - return GRN_INVALID_ARGUMENT; - } - /* Check whehter or not the subexpression is complete.*/ - bridge = &expr->bridges[expr->n_bridges - 1]; - if (expr->stack_depth != (bridge->stack_depth + 1)) { - return GRN_INVALID_ARGUMENT; - } - /* Creates a bridge node. */ - args = &expr->stack[expr->stack_depth - 2]; - rc = grn_ts_expr_bridge_node_open(ctx, args[0], args[1], &node); - if (rc != GRN_SUCCESS) { - return rc; - } - /* Note: grn_ts_expr_reserve_stack() is not required. */ - expr->stack_depth -= 2; - expr->stack[expr->stack_depth++] = node; - expr->curr_table = bridge->src_table; - grn_ts_expr_bridge_fin(ctx, bridge); - expr->n_bridges--; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_complete(grn_ctx *ctx, grn_ts_expr *expr) -{ - grn_rc rc; - grn_ts_expr_node *root; - if (!ctx || !expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - return GRN_INVALID_ARGUMENT; - } - if (expr->stack_depth != 1) { - return GRN_INVALID_ARGUMENT; - } - rc = grn_ts_expr_deref(ctx, expr, &expr->stack[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - root = expr->stack[0]; - switch (root->data_kind) { - case GRN_TS_REF: - case GRN_TS_REF_VECTOR: { - return GRN_INVALID_ARGUMENT; - } - default: { - break; - } - } - switch (root->type) { - case GRN_TS_EXPR_ID_NODE: { - expr->type = GRN_TS_EXPR_ID; - break; - } - case GRN_TS_EXPR_SCORE_NODE: { - expr->type = GRN_TS_EXPR_SCORE; - break; - } - case GRN_TS_EXPR_KEY_NODE: - case GRN_TS_EXPR_VALUE_NODE: { - expr->type = GRN_TS_EXPR_VARIABLE; - break; - } - case GRN_TS_EXPR_CONST_NODE: { - expr->type = GRN_TS_EXPR_CONST; - break; - } - case GRN_TS_EXPR_COLUMN_NODE: - case GRN_TS_EXPR_OP_NODE: - case GRN_TS_EXPR_BRIDGE_NODE: { - expr->type = GRN_TS_EXPR_VARIABLE; - break; - } - default: { - return GRN_INVALID_ARGUMENT; - } - } - expr->data_type = root->data_type; - expr->data_kind = root->data_kind; - expr->root = root; + grn_ts_expr_fin(ctx, expr); + GRN_FREE(expr); return GRN_SUCCESS; } @@ -1019,10 +158,12 @@ grn_ts_expr_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr *expr, const grn_ts_record *in, size_t n_in, grn_ts_buf *out) { - if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) || - (expr->type == GRN_TS_EXPR_BROKEN) || (!in && n_in) || !out) { + if (!ctx) { return GRN_INVALID_ARGUMENT; } + if (!expr || (!in && n_in) || !out) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } if (!n_in) { return GRN_SUCCESS; } @@ -1033,10 +174,12 @@ grn_rc grn_ts_expr_evaluate(grn_ctx *ctx, grn_ts_expr *expr, const grn_ts_record *in, size_t n_in, void *out) { - if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) || - (expr->type == GRN_TS_EXPR_BROKEN) || (!in && n_in) || (n_in && !out)) { + if (!ctx) { return GRN_INVALID_ARGUMENT; } + if (!expr || (!in && n_in) || (n_in && !out)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } if (!n_in) { return GRN_SUCCESS; } @@ -1048,11 +191,12 @@ grn_ts_expr_filter(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_record *in, size_t n_in, grn_ts_record *out, size_t *n_out) { - if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) || - (expr->type == GRN_TS_EXPR_BROKEN) || (!in && n_in) || - !out || !n_out) { + if (!ctx) { return GRN_INVALID_ARGUMENT; } + if (!expr || (!in && n_in) || !out || !n_out) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } if (!n_in) { *n_out = 0; return GRN_SUCCESS; @@ -1064,10 +208,12 @@ grn_rc grn_ts_expr_adjust(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_record *io, size_t n_io) { - if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) || - (expr->type == GRN_TS_EXPR_BROKEN) || (!io && n_io)) { + if (!ctx) { return GRN_INVALID_ARGUMENT; } + if (!expr || (!io && n_io)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } if (!n_io) { return GRN_SUCCESS; } Modified: lib/ts/ts_expr.h (+18 -161) =================================================================== --- lib/ts/ts_expr.h 2015-11-16 14:59:23 +0900 (8dfcaca) +++ lib/ts/ts_expr.h 2015-11-16 15:17:14 +0900 (d32ce9f) @@ -19,9 +19,11 @@ #ifndef GRN_TS_EXPR_H #define GRN_TS_EXPR_H +#include "../grn.h" + #include "ts_buf.h" #include "ts_expr_node.h" -#include "ts_op.h" +#include "ts_str.h" #include "ts_types.h" #ifdef __cplusplus @@ -33,13 +35,10 @@ extern "C" { */ typedef enum { - GRN_TS_EXPR_INCOMPLETE, /* An incomplete expression. */ - GRN_TS_EXPR_BROKEN, /* A broken expression. */ - /* Any operation fails for a broken expression. */ - GRN_TS_EXPR_ID, /* An expression associated with _id. */ - GRN_TS_EXPR_SCORE, /* An expression associated with _score. */ - GRN_TS_EXPR_CONST, /* A const. */ - GRN_TS_EXPR_VARIABLE /* An expression that contains a variable. */ + GRN_TS_EXPR_ID, /* IDs (_id). */ + GRN_TS_EXPR_SCORE, /* Scores (_score). */ + GRN_TS_EXPR_CONST, /* A const. */ + GRN_TS_EXPR_VARIABLE /* An expression that contains a variable. */ } grn_ts_expr_type; /*------------------------------------------------------------- @@ -47,170 +46,28 @@ typedef enum { */ typedef struct { - grn_obj *src_table; /* The source table of a bridge (no ref. count). */ - grn_obj *dest_table; /* The destination table of a bridge. */ - size_t stack_depth; /* The stack depth (position) of a bridge. */ -} grn_ts_expr_bridge; - -typedef struct { - grn_obj *table; /* Associated table. */ - grn_obj *curr_table; /* Current table (no ref. count). */ - grn_ts_expr_type type; /* Expression type. */ - grn_ts_data_kind data_kind; /* Abstract data type. */ - grn_ts_data_type data_type; /* Detailed data type. */ - grn_ts_expr_node *root; /* Root node. */ - grn_ts_expr_node **stack; /* Node stack. */ - size_t stack_depth; /* Node stack's current depth. */ - size_t stack_size; /* Node stack's size (capacity). */ - grn_ts_expr_bridge *bridges; /* Bridges to subexpressions. */ - size_t n_bridges; /* Number of bridges (subexpression depth). */ - size_t max_n_bridges; /* Max. number (capacity) of bridges. */ + grn_obj *table; /* Associated table. */ + grn_ts_expr_type type; /* Expression type. */ + grn_ts_data_kind data_kind; /* Abstract data type. */ + grn_ts_data_type data_type; /* Detailed data type. */ + grn_ts_expr_node *root; /* Root node. */ } grn_ts_expr; -/* grn_ts_expr_open() creates an empty expression. */ -grn_rc grn_ts_expr_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr **expr); +/* grn_ts_expr_open() creates an expression. */ +grn_rc grn_ts_expr_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr_node *root, + grn_ts_expr **expr); -/* grn_ts_expr_parse() creates an expression from a string. */ -grn_rc grn_ts_expr_parse(grn_ctx *ctx, grn_obj *table, - const char *str_ptr, size_t str_size, +/* grn_ts_expr_parse() parses a string and creates an expression. */ +grn_rc grn_ts_expr_parse(grn_ctx *ctx, grn_obj *table, grn_ts_str str, grn_ts_expr **expr); /* grn_ts_expr_close() destroys an expression. */ grn_rc grn_ts_expr_close(grn_ctx *ctx, grn_ts_expr *expr); -/* - * grn_ts_expr_get_table() returns the associated table. - * If arguments are invalid, the return value is NULL. - */ -grn_obj *grn_ts_expr_get_table(grn_ctx *ctx, grn_ts_expr *expr); - -/* - * grn_ts_expr_get_type() returns the expression type. - * If arguments are invalid, the return value is GRN_EXPR_BROKEN. - */ -grn_ts_expr_type grn_ts_expr_get_type(grn_ctx *ctx, grn_ts_expr *expr); - -/* - * grn_ts_expr_get_data_kind() returns the data kind. - * If arguments are invalid, the return value is GRN_TS_VOID. - */ -grn_ts_data_kind grn_ts_expr_get_data_kind(grn_ctx *ctx, grn_ts_expr *expr); - -/* - * grn_ts_expr_get_data_type() returns the data type. - * If arguments are invalid, the return value is GRN_DB_VOID. - */ - -grn_ts_data_type grn_ts_expr_get_data_type(grn_ctx *ctx, grn_ts_expr *expr); - -/* - * grn_ts_expr_get_root() returns the root node. - * If arguments are invalid, the return value is NULL. - */ -grn_ts_expr_node *grn_ts_expr_get_root(grn_ctx *ctx, grn_ts_expr *expr); - -/* grn_ts_expr_push() parses a string and pushes the result. */ -grn_rc grn_ts_expr_push(grn_ctx *ctx, grn_ts_expr *expr, - const char *str_ptr, size_t str_size); - -/* grn_ts_expr_push_name() pushes a named object. */ -grn_rc grn_ts_expr_push_name(grn_ctx *ctx, grn_ts_expr *expr, - const char *name_ptr, size_t name_size); - -/* - * grn_ts_expr_push_obj() pushes an object. - * - * Acceptable objects are as follows: - * - Consts - * - GRN_BULK: GRN_DB_*. - * - GRN_UVECTOR: GRN_DB_* except GRN_DB_[SHORT/LONG_]TEXT. - * - GRN_VECTOR: GRN_DB_[SHORT/LONG_]TEXT. - * - Columns - * - GRN_ACCESSOR: _id, _score, _key, and _value. - * - GRN_COLUMN_FIX_SIZE: GRN_DB_* except GRN_DB_[SHORT/LONG_]TEXT. - * - GRN_COLUMN_VAR_SIZE: GRN_DB_[SHORT/LONG_]TEXT. - */ -grn_rc grn_ts_expr_push_obj(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj); - -/* grn_ts_expr_push_id() pushes "_id". */ -grn_rc grn_ts_expr_push_id(grn_ctx *ctx, grn_ts_expr *expr); -/* grn_ts_expr_push_score() pushes "_score". */ -grn_rc grn_ts_expr_push_score(grn_ctx *ctx, grn_ts_expr *expr); -/* grn_ts_expr_push_key() pushes "_key". */ -grn_rc grn_ts_expr_push_key(grn_ctx *ctx, grn_ts_expr *expr); -/* grn_ts_expr_push_key() pushes "_value". */ -grn_rc grn_ts_expr_push_value(grn_ctx *ctx, grn_ts_expr *expr); -/* grn_ts_expr_push_const() pushes a const. */ -grn_rc grn_ts_expr_push_const(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_data_kind kind, const void *value); -/* grn_ts_expr_push_column() pushes a column. */ -grn_rc grn_ts_expr_push_column(grn_ctx *ctx, grn_ts_expr *expr, - grn_obj *column); -/* grn_ts_expr_push_op() pushes an operator. */ -grn_rc grn_ts_expr_push_op(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_op_type op_type); - -/* grn_ts_expr_push_bool() pushes a Bool const. */ -grn_rc grn_ts_expr_push_bool(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_bool value); -/* grn_ts_expr_push_int() pushes an Int64 const. */ -grn_rc grn_ts_expr_push_int(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_int value); -/* grn_ts_expr_push_float() pushes a Float const. */ -grn_rc grn_ts_expr_push_float(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_float value); -/* grn_ts_expr_push_time() pushes a Time const. */ -grn_rc grn_ts_expr_push_time(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_time value); -/* grn_ts_expr_push_text() pushes a Text const. */ -grn_rc grn_ts_expr_push_text(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_text value); -/* grn_ts_expr_push_geo() pushes a GeoPoint const. */ -grn_rc grn_ts_expr_push_geo(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo value); -/* grn_ts_expr_push_tokyo_geo() pushes a TokyoGeoPoint const. */ -grn_rc grn_ts_expr_push_tokyo_geo(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo value); -/* grn_ts_expr_push_wgs84_geo() pushes a WGS84GeoPoint const. */ -grn_rc grn_ts_expr_push_wgs84_geo(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo value); -/* grn_ts_expr_push_bool_vector() pushes a Bool vector const. */ -grn_rc grn_ts_expr_push_bool_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_bool_vector value); -/* grn_ts_expr_push_int_vector() pushes an Int64 vector const. */ -grn_rc grn_ts_expr_push_int_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_int_vector value); -/* grn_ts_expr_push_float_vector() pushes a Float vector const. */ -grn_rc grn_ts_expr_push_float_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_float_vector value); -/* grn_ts_expr_push_time_vector() pushes a Time vector const. */ -grn_rc grn_ts_expr_push_time_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_time_vector value); -/* grn_ts_expr_push_text_vector() pushes a Text vector const. */ -grn_rc grn_ts_expr_push_text_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_text_vector value); -/* grn_ts_expr_push_geo_vector() pushes a GeoPoint vector const. */ -grn_rc grn_ts_expr_push_geo_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_vector value); -/* grn_ts_expr_push_tokyo_geo_vector() pushes a TokyoGeoPoint vector const. */ -grn_rc grn_ts_expr_push_tokyo_geo_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_vector value); -/* grn_ts_expr_push_wgs84_geo_vector() pushes a WGS84GeoPoint vector const. */ -grn_rc grn_ts_expr_push_wgs84_geo_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_vector value); - -/* grn_ts_expr_begin_subexpr() begins a subexpression. */ -grn_rc grn_ts_expr_begin_subexpr(grn_ctx *ctx, grn_ts_expr *expr); - -/* grn_ts_expr_end_subexpr() ends a subexpression. */ -grn_rc grn_ts_expr_end_subexpr(grn_ctx *ctx, grn_ts_expr *expr); - -/* grn_rc grn_ts_expr_complete() completes an expression. */ -grn_rc grn_ts_expr_complete(grn_ctx *ctx, grn_ts_expr *expr); - /* grn_ts_expr_evaluate() evaluates an expression. */ grn_rc grn_ts_expr_evaluate(grn_ctx *ctx, grn_ts_expr *expr, const grn_ts_record *in, size_t n_in, void *out); + /* grn_ts_expr_evaluate_to_buf() evaluates an expression. */ grn_rc grn_ts_expr_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr *expr, const grn_ts_record *in, size_t n_in, Added: lib/ts/ts_expr_builder.c (+759 -0) 100644 =================================================================== --- /dev/null +++ lib/ts/ts_expr_builder.c 2015-11-16 15:17:14 +0900 (a7d69c4) @@ -0,0 +1,759 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ts_expr_builder.h" + +#include <string.h> + +#include "../grn_ctx.h" +#include "../grn_db.h" + +#include "ts_log.h" +#include "ts_util.h" + +/*------------------------------------------------------------- + * grn_ts_expr_bridge. + */ + +/* grn_ts_expr_bridge_init() initializes a bridge. */ +static void +grn_ts_expr_bridge_init(grn_ctx *ctx, grn_ts_expr_bridge *bridge) +{ + memset(bridge, 0, sizeof(*bridge)); + bridge->src_table = NULL; + bridge->dest_table = NULL; +} + +/* grn_ts_expr_bridge_fin() finalizes a bridge. */ +static void +grn_ts_expr_bridge_fin(grn_ctx *ctx, grn_ts_expr_bridge *bridge) +{ + if (bridge->dest_table) { + grn_obj_unlink(ctx, bridge->dest_table); + } + /* Note: bridge->src_table does not increment a reference count. */ +} + +/*------------------------------------------------------------- + * grn_ts_expr_builder. + */ + +/* grn_ts_expr_builder_init() initializes an expression builder. */ +static void +grn_ts_expr_builder_init(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + memset(builder, 0, sizeof(*builder)); + builder->table = NULL; + builder->curr_table = NULL; + builder->nodes = NULL; + builder->bridges = NULL; +} + +/* grn_ts_expr_builder_fin() finalizes an expression builder. */ +static void +grn_ts_expr_builder_fin(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + size_t i; + if (builder->bridges) { + for (i = 0; i < builder->n_bridges; i++) { + grn_ts_expr_bridge_fin(ctx, &builder->bridges[i]); + } + GRN_FREE(builder->bridges); + } + if (builder->nodes) { + for (i = 0; i < builder->n_nodes; i++) { + if (builder->nodes[i]) { + grn_ts_expr_node_close(ctx, builder->nodes[i]); + } + } + GRN_FREE(builder->nodes); + } + /* Note: builder->curr_table does not increment a reference count. */ + if (builder->table) { + grn_obj_unlink(ctx, builder->table); + } +} + +grn_rc +grn_ts_expr_builder_open(grn_ctx *ctx, grn_obj *table, + grn_ts_expr_builder **builder) +{ + grn_rc rc; + grn_ts_expr_builder *new_builder; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!table || !grn_ts_obj_is_table(ctx, table) || !builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + new_builder = GRN_MALLOCN(grn_ts_expr_builder, 1); + if (!new_builder) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE, + sizeof(grn_ts_expr_builder)); + } + rc = grn_ts_obj_increment_ref_count(ctx, table); + if (rc != GRN_SUCCESS) { + GRN_FREE(new_builder); + return rc; + } + grn_ts_expr_builder_init(ctx, new_builder); + new_builder->table = table; + new_builder->curr_table = table; + *builder = new_builder; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_builder_close(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + grn_ts_expr_builder_fin(ctx, builder); + return GRN_SUCCESS; +} + +/* grn_ts_expr_deref() dereferences a node. */ +static grn_rc +grn_ts_expr_builder_deref(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_expr_node **node_ptr) +{ + grn_ts_expr_node *node = *node_ptr; + while (node->data_kind == GRN_TS_REF) { + grn_rc rc; + grn_ts_expr_node *key_node, *bridge_node; + grn_id table_id = node->data_type; + grn_obj *table = grn_ctx_at(ctx, table_id); + if (!table) { + return GRN_OBJECT_CORRUPT; + } + if (!grn_ts_obj_is_table(ctx, table)) { + grn_obj_unlink(ctx, table); + return GRN_OBJECT_CORRUPT; + } + rc = grn_ts_expr_key_node_open(ctx, table, &key_node); + grn_obj_unlink(ctx, table); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_bridge_node_open(ctx, node, key_node, &bridge_node); + if (rc != GRN_SUCCESS) { + return rc; + } + node = bridge_node; + } + *node_ptr = node; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_builder_complete(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_expr **expr) +{ + grn_rc rc; + grn_ts_expr *new_expr; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder || (builder->n_nodes != 1) || builder->n_bridges || !expr) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_builder_deref(ctx, builder, &builder->nodes[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_open(ctx, builder->table, builder->nodes[0], &new_expr); + if (rc != GRN_SUCCESS) { + return rc; + } + builder->n_nodes = 0; + *expr = new_expr; + return GRN_SUCCESS; +} + +/* + * grn_ts_expr_builder_push_node() pushes a node. + * The given node will be closed on failure. + */ +static grn_rc +grn_ts_expr_builder_push_node(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_expr_node *node) +{ + if (builder->n_nodes == builder->max_n_nodes) { + size_t n_bytes, new_max_n_nodes; + grn_ts_expr_node **new_nodes; + new_max_n_nodes = builder->n_nodes ? (builder->n_nodes * 2) : 1; + n_bytes = sizeof(grn_ts_expr_node *) * new_max_n_nodes; + new_nodes = (grn_ts_expr_node **)GRN_REALLOC(builder->nodes, n_bytes); + if (!new_nodes) { + grn_ts_expr_node_close(ctx, node); + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, n_bytes); + } + builder->nodes = new_nodes; + builder->max_n_nodes = new_max_n_nodes; + } + builder->nodes[builder->n_nodes++] = node; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_builder_push_name(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_str name) +{ + grn_obj *column; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder || !grn_ts_str_is_name(name)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + if (grn_ts_str_is_id_name(name)) { + return grn_ts_expr_builder_push_id(ctx, builder); + } + if (grn_ts_str_is_score_name(name)) { + return grn_ts_expr_builder_push_score(ctx, builder); + } + if (grn_ts_str_is_key_name(name)) { + return grn_ts_expr_builder_push_key(ctx, builder); + } + if (grn_ts_str_is_value_name(name)) { + return grn_ts_expr_builder_push_value(ctx, builder); + } + /* grn_obj_column() returns a column or accessor. */ + column = grn_obj_column(ctx, builder->curr_table, name.ptr, name.size); + if (!column) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "object not found: \"%.*s\"", + (int)name.size, name.ptr); + } + return grn_ts_expr_builder_push_obj(ctx, builder, column); +} + +#define GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(TYPE, KIND, kind)\ + case GRN_DB_ ## TYPE: {\ + grn_ts_ ## kind value = (grn_ts_ ## kind)GRN_ ## TYPE ## _VALUE(obj);\ + return grn_ts_expr_builder_push_const(ctx, builder,\ + GRN_TS_ ## KIND, obj->header.domain,\ + &value);\ + } +/* grn_ts_expr_push_builder_bulk() pushes a scalar const. */ +static grn_rc +grn_ts_expr_builder_push_bulk(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_obj *obj) +{ + switch (obj->header.domain) { + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(BOOL, BOOL, bool) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(INT8, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(INT16, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(INT32, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(INT64, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(UINT8, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(UINT16, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(UINT32, INT, int) + /* The behavior is undefined if a value is greater than 2^63 - 1. */ + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(UINT64, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(FLOAT, FLOAT, float) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(TIME, TIME, time) + case GRN_DB_SHORT_TEXT: + case GRN_DB_TEXT: + case GRN_DB_LONG_TEXT: { + grn_ts_text value = { GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj) }; + return grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_TEXT, + obj->header.domain, &value); + } + case GRN_DB_TOKYO_GEO_POINT: + case GRN_DB_WGS84_GEO_POINT: { + grn_ts_geo value; + GRN_GEO_POINT_VALUE(obj, value.latitude, value.longitude); + return grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_GEO, + obj->header.domain, &value); + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "not bulk"); + } + } +} +#undef GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE + +#define GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(TYPE, KIND, kind)\ + case GRN_DB_ ## TYPE: {\ + grn_ts_ ## kind ##_vector value = { (grn_ts_ ## kind *)GRN_BULK_HEAD(obj),\ + grn_uvector_size(ctx, obj) };\ + return grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_ ## KIND,\ + obj->header.domain, &value);\ + } +#define GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(TYPE, KIND, kind)\ + case GRN_DB_ ## TYPE: {\ + size_t i;\ + grn_rc rc;\ + grn_ts_ ## kind *buf;\ + grn_ts_ ## kind ## _vector value = { NULL, grn_uvector_size(ctx, obj) };\ + if (!value.size) {\ + return grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_ ## KIND,\ + obj->header.domain, &value);\ + }\ + buf = GRN_MALLOCN(grn_ts_ ## kind, value.size);\ + if (!buf) {\ + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE,\ + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1",\ + sizeof(grn_ts_ ## kind));\ + }\ + for (i = 0; i < value.size; i++) {\ + buf[i] = GRN_ ## TYPE ##_VALUE_AT(obj, i);\ + }\ + value.ptr = buf;\ + rc = grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_ ## KIND,\ + obj->header.domain, &value);\ + GRN_FREE(buf);\ + return rc;\ + } +/* grn_ts_expr_builder_push_uvector() pushes an array of fixed-size values. */ +static grn_rc +grn_ts_expr_builder_push_uvector(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_obj *obj) +{ + switch (obj->header.domain) { + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(BOOL, BOOL, bool) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT8, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT16, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT32, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(INT64, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT8, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT16, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT32, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(UINT64, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(TIME, TIME, time) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(TOKYO_GEO_POINT, GEO, geo) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(WGS84_GEO_POINT, GEO, geo) + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data type: %d", + obj->header.domain); + } + } +} +#undef GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST +#undef GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE + +/* grn_ts_expr_builder_push_vector() pushes a Text vector. */ +static grn_rc +grn_ts_expr_builder_push_vector(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_obj *obj) +{ + switch (obj->header.domain) { + case GRN_DB_SHORT_TEXT: + case GRN_DB_TEXT: + case GRN_DB_LONG_TEXT: { + size_t i; + grn_rc rc; + grn_ts_text *buf; + grn_ts_text_vector value = { NULL, grn_vector_size(ctx, obj) }; + if (!value.size) { + return grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_TEXT_VECTOR, + obj->header.domain, &value); + } + buf = GRN_MALLOCN(grn_ts_text, value.size); + if (!buf) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: " + "%" GRN_FMT_SIZE " x %" GRN_FMT_SIZE, + sizeof(grn_ts_text), value.size); + } + for (i = 0; i < value.size; i++) { + buf[i].size = grn_vector_get_element(ctx, obj, i, &buf[i].ptr, + NULL, NULL); + } + value.ptr = buf; + rc = grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_TEXT_VECTOR, + obj->header.domain, &value); + GRN_FREE(buf); + return rc; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data type: %d", + obj->header.domain); + } + } +} + +static grn_rc +grn_ts_expr_builder_push_single_accessor(grn_ctx *ctx, + grn_ts_expr_builder *builder, + grn_accessor *accessor) +{ + switch (accessor->action) { + case GRN_ACCESSOR_GET_ID: { + return grn_ts_expr_builder_push_id(ctx, builder); + } + case GRN_ACCESSOR_GET_SCORE: { + return grn_ts_expr_builder_push_score(ctx, builder); + } + case GRN_ACCESSOR_GET_KEY: { + if (accessor->obj != builder->curr_table) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table conflict"); + } + return grn_ts_expr_builder_push_key(ctx, builder); + } + case GRN_ACCESSOR_GET_VALUE: { + if (accessor->obj != builder->curr_table) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table conflict"); + } + return grn_ts_expr_builder_push_value(ctx, builder); + } + case GRN_ACCESSOR_GET_COLUMN_VALUE: { + return grn_ts_expr_builder_push_column(ctx, builder, accessor->obj); + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid accessor action: %d", + accessor->action); + } + } +} + +static grn_rc +grn_ts_expr_builder_push_accessor(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_accessor *accessor) +{ + grn_rc rc = grn_ts_expr_builder_push_single_accessor(ctx, builder, accessor); + if (rc != GRN_SUCCESS) { + return rc; + } + for (accessor = accessor->next; accessor; accessor = accessor->next) { + rc = grn_ts_expr_builder_begin_subexpr(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_builder_push_single_accessor(ctx, builder, accessor); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_builder_end_subexpr(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_builder_push_obj(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_obj *obj) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder || !obj) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + switch (obj->header.type) { + case GRN_BULK: { + return grn_ts_expr_builder_push_bulk(ctx, builder, obj); + } + case GRN_UVECTOR: { + return grn_ts_expr_builder_push_uvector(ctx, builder, obj); + } + case GRN_VECTOR: { + return grn_ts_expr_builder_push_vector(ctx, builder, obj); + } + case GRN_ACCESSOR: { + return grn_ts_expr_builder_push_accessor(ctx, builder, + (grn_accessor *)obj); + } + case GRN_COLUMN_FIX_SIZE: + case GRN_COLUMN_VAR_SIZE: { + return grn_ts_expr_builder_push_column(ctx, builder, obj); + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid object type: %d", + obj->header.type); + } + } +} + +grn_rc +grn_ts_expr_builder_push_id(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_rc rc; + grn_ts_expr_node *node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_id_node_open(ctx, &node); + if (rc == GRN_SUCCESS) { + rc = grn_ts_expr_builder_push_node(ctx, builder, node); + } + return rc; +} + +grn_rc +grn_ts_expr_builder_push_score(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_rc rc; + grn_ts_expr_node *node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_score_node_open(ctx, &node); + if (rc == GRN_SUCCESS) { + rc = grn_ts_expr_builder_push_node(ctx, builder, node); + } + return rc; +} + +grn_rc +grn_ts_expr_builder_push_key(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_rc rc; + grn_ts_expr_node *node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_key_node_open(ctx, builder->curr_table, &node); + if (rc == GRN_SUCCESS) { + rc = grn_ts_expr_builder_push_node(ctx, builder, node); + } + return rc; +} + +grn_rc +grn_ts_expr_builder_push_value(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_rc rc; + grn_ts_expr_node *node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_value_node_open(ctx, builder->curr_table, &node); + if (rc == GRN_SUCCESS) { + rc = grn_ts_expr_builder_push_node(ctx, builder, node); + } + return rc; +} + +grn_rc +grn_ts_expr_builder_push_const(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_data_kind kind, grn_ts_data_type type, + const void *value) +{ + grn_rc rc; + grn_ts_expr_node *node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_const_node_open(ctx, kind, type, value, &node); + if (rc == GRN_SUCCESS) { + rc = grn_ts_expr_builder_push_node(ctx, builder, node); + } + return rc; +} + +grn_rc +grn_ts_expr_builder_push_column(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_obj *column) +{ + grn_rc rc; + grn_ts_expr_node *node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder || !column || !grn_ts_obj_is_column(ctx, column) || + (DB_OBJ(builder->curr_table)->id != column->header.domain)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_column_node_open(ctx, column, &node); + if (rc == GRN_SUCCESS) { + rc = grn_ts_expr_builder_push_node(ctx, builder, node); + } + return rc; +} + +grn_rc +grn_ts_expr_builder_push_op(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_op_type op_type) +{ + grn_rc rc; + grn_ts_expr_node **args, *node; + size_t i, n_args, max_n_args; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + n_args = grn_ts_op_get_n_args(op_type); + if (!n_args) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, + "invalid #arguments: %" GRN_FMT_SIZE, + n_args); + } + max_n_args = builder->n_nodes; + if (builder->n_bridges) { + max_n_args -= builder->bridges[builder->n_bridges - 1].stack_depth; + } + if (n_args > max_n_args) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, + "invalid #arguments: %" GRN_FMT_SIZE ", %" GRN_FMT_SIZE, + n_args, builder->n_nodes); + } + /* Arguments are the top n_args nodes in the stack. */ + args = &builder->nodes[builder->n_nodes - n_args]; + for (i = 0; i < n_args; i++) { + /* + * FIXME: Operators "==" and "!=" should compare arguments as references + * if possible. + */ + rc = grn_ts_expr_builder_deref(ctx, builder, &args[i]); + if (rc != GRN_SUCCESS) { + return rc; + } + } + builder->n_nodes -= n_args; + rc = grn_ts_expr_op_node_open(ctx, op_type, args, n_args, &node); + if (rc == GRN_SUCCESS) { + builder->nodes[builder->n_nodes++] = node; + } + return rc; +} + +/* grn_ts_expr_builder_push_bridge() pushes a bridge. */ +static grn_rc +grn_ts_expr_builder_push_bridge(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_expr_bridge *bridge) +{ + if (builder->n_bridges == builder->max_n_bridges) { + size_t n_bytes, new_max_n_bridges; + grn_ts_expr_bridge *new_bridges; + new_max_n_bridges = builder->n_bridges ? (builder->n_bridges * 2) : 1; + n_bytes = sizeof(grn_ts_expr_bridge) * new_max_n_bridges; + new_bridges = (grn_ts_expr_bridge *)GRN_REALLOC(builder->bridges, n_bytes); + if (!new_bridges) { + grn_ts_expr_bridge_fin(ctx, bridge); + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, n_bytes); + } + builder->bridges = new_bridges; + builder->max_n_bridges = new_max_n_bridges; + } + builder->bridges[builder->n_bridges++] = *bridge; + builder->curr_table = bridge->dest_table; + return GRN_SUCCESS; +} + +/* grn_ts_expr_builder_pop_bridge() pops a bridge. */ +static void +grn_ts_expr_builder_pop_bridge(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_ts_expr_bridge *bridge = &builder->bridges[builder->n_bridges - 1]; + builder->curr_table = bridge->src_table; + grn_ts_expr_bridge_fin(ctx, bridge); + builder->n_bridges--; +} + +grn_rc +grn_ts_expr_builder_begin_subexpr(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_rc rc; + size_t max_n_args; + grn_obj *obj; + grn_ts_expr_node *node; + grn_ts_expr_bridge bridge; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + max_n_args = builder->n_nodes; + if (builder->n_bridges) { + max_n_args -= builder->bridges[builder->n_bridges - 1].stack_depth; + } + if (!max_n_args) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + /* Check whehter or not the latest node refers to a table. */ + node = builder->nodes[builder->n_nodes - 1]; + if ((node->data_kind & ~GRN_TS_VECTOR_FLAG) != GRN_TS_REF) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->data_kind); + } + obj = grn_ctx_at(ctx, node->data_type); + if (!obj) { + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", + node->data_type); + } + if (!grn_ts_obj_is_table(ctx, obj)) { + grn_obj_unlink(ctx, obj); + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "not table: %d", node->data_type); + } + /* Creates a bridge to a subexpression. */ + grn_ts_expr_bridge_init(ctx, &bridge); + bridge.src_table = builder->curr_table; + bridge.dest_table = obj; + bridge.stack_depth = builder->n_nodes; + rc = grn_ts_expr_builder_push_bridge(ctx, builder, &bridge); + if (rc != GRN_SUCCESS) { + grn_obj_unlink(ctx, obj); + return rc; + } + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_builder_end_subexpr(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_rc rc; + grn_ts_expr_node **args, *node; + grn_ts_expr_bridge *bridge; + if (!ctx || !builder || (builder->n_nodes < 2) || !builder->n_bridges) { + return GRN_INVALID_ARGUMENT; + } + /* Check whehter or not the subexpression is complete.*/ + bridge = &builder->bridges[builder->n_bridges - 1]; + if (builder->n_nodes != (bridge->stack_depth + 1)) { + return GRN_INVALID_ARGUMENT; + } + /* Creates a bridge node. */ + args = &builder->nodes[builder->n_nodes - 2]; + rc = grn_ts_expr_bridge_node_open(ctx, args[0], args[1], &node); + if (rc != GRN_SUCCESS) { + return rc; + } + /* Note: The following grn_ts_expr_push_node() must not fail. */ + builder->n_nodes -= 2; + grn_ts_expr_builder_push_node(ctx, builder, node); + grn_ts_expr_builder_pop_bridge(ctx, builder); + return GRN_SUCCESS; +} Added: lib/ts/ts_expr_builder.h (+129 -0) 100644 =================================================================== --- /dev/null +++ lib/ts/ts_expr_builder.h 2015-11-16 15:17:14 +0900 (a886459) @@ -0,0 +1,129 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_TS_EXPR_BUILDER_H +#define GRN_TS_EXPR_BUILDER_H + +#include "../grn.h" + +#include "ts_buf.h" +#include "ts_expr.h" +#include "ts_expr_node.h" +#include "ts_op.h" +#include "ts_str.h" +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + grn_obj *src_table; /* The source table of a bridge (no ref. count). */ + grn_obj *dest_table; /* The destination table of a bridge. */ + size_t stack_depth; /* The stack depth (position) of a bridge. */ +} grn_ts_expr_bridge; + +typedef struct { + grn_obj *table; /* Associated table. */ + grn_obj *curr_table; /* Current table (no ref. count). */ + grn_ts_expr_node **nodes; /* Node stack. */ + size_t n_nodes; /* Number of nodes (stack depth). */ + size_t max_n_nodes; /* Maximum number of nodes (stack capacity). */ + grn_ts_expr_bridge *bridges; /* Bridges to subexpressions. */ + size_t n_bridges; /* Number of bridges (subexpression depth). */ + size_t max_n_bridges; /* Max. number (capacity) of bridges. */ +} grn_ts_expr_builder; + +/* grn_ts_expr_builder_open() creates an expression builder. */ +grn_rc grn_ts_expr_builder_open(grn_ctx *ctx, grn_obj *table, + grn_ts_expr_builder **builder); + +/* grn_ts_expr_builder_close() destroys an expression builder. */ +grn_rc grn_ts_expr_builder_close(grn_ctx *ctx, grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_complete() completes an expression. */ +grn_rc grn_ts_expr_builder_complete(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_expr **expr); + +/* grn_ts_expr_builder_push_name() pushes a named object. */ +grn_rc grn_ts_expr_builder_push_name(grn_ctx *ctx, + grn_ts_expr_builder *builder, + grn_ts_str name); + +/* + * TODO: Update the comment. + * + * grn_ts_expr_builder_push_obj() pushes an object. + * + * Acceptable objects are as follows: + * - Consts + * - GRN_BULK: GRN_DB_*. + * - GRN_UVECTOR: GRN_DB_* except GRN_DB_[SHORT/LONG_]TEXT. + * - GRN_VECTOR: GRN_DB_[SHORT/LONG_]TEXT. + * - Columns + * - GRN_ACCESSOR: _id, _score, _key, and _value. + * - GRN_COLUMN_FIX_SIZE: GRN_DB_* except GRN_DB_[SHORT/LONG_]TEXT. + * - GRN_COLUMN_VAR_SIZE: GRN_DB_[SHORT/LONG_]TEXT. + */ +grn_rc grn_ts_expr_builder_push_obj(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_obj *obj); + +/* grn_ts_expr_builder_push_id() pushes "_id". */ +grn_rc grn_ts_expr_builder_push_id(grn_ctx *ctx, grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_push_score() pushes "_score". */ +grn_rc grn_ts_expr_builder_push_score(grn_ctx *ctx, + grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_push_key() pushes "_key". */ +grn_rc grn_ts_expr_builder_push_key(grn_ctx *ctx, + grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_push_value() pushes "_value". */ +grn_rc grn_ts_expr_builder_push_value(grn_ctx *ctx, + grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_push_const() pushes a const. */ +grn_rc grn_ts_expr_builder_push_const(grn_ctx *ctx, + grn_ts_expr_builder *builder, + grn_ts_data_kind kind, + grn_ts_data_type type, + const void *value); + +/* grn_ts_expr_builder_push_column() pushes a column. */ +grn_rc grn_ts_expr_builder_push_column(grn_ctx *ctx, + grn_ts_expr_builder *builder, + grn_obj *column); + +/* grn_ts_expr_builder_push_op() pushes an operator. */ +grn_rc grn_ts_expr_builder_push_op(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_op_type op_type); + +/* grn_ts_expr_builder_begin_subexpr() begins a subexpression. */ +grn_rc grn_ts_expr_builder_begin_subexpr(grn_ctx *ctx, + grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_end_subexpr() ends a subexpression. */ +grn_rc grn_ts_expr_builder_end_subexpr(grn_ctx *ctx, + grn_ts_expr_builder *builder); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_TS_EXPR_BUILDER_H */ Modified: lib/ts/ts_expr_node.c (+10 -5) =================================================================== --- lib/ts/ts_expr_node.c 2015-11-16 14:59:23 +0900 (3dfd33f) +++ lib/ts/ts_expr_node.c 2015-11-16 15:17:14 +0900 (5539f77) @@ -2175,10 +2175,11 @@ grn_ts_expr_const_node_check_value(grn_ctx *ctx, grn_ts_data_kind kind, #undef GRN_TS_EXPR_CONST_NODE_CHECK_VALUE grn_rc -grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind kind, +grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind data_kind, + grn_ts_data_type data_type, const void *value, grn_ts_expr_node **node) { - grn_rc rc = grn_ts_expr_const_node_check_value(ctx, kind, value); + grn_rc rc = grn_ts_expr_const_node_check_value(ctx, data_kind, value); if (rc != GRN_SUCCESS) { return rc; } @@ -2189,9 +2190,13 @@ grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind kind, sizeof(grn_ts_expr_const_node)); } grn_ts_expr_const_node_init(ctx, new_node); - new_node->data_kind = kind; - new_node->data_type = grn_ts_data_kind_to_type(kind); - if (kind & GRN_TS_VECTOR_FLAG) { + new_node->data_kind = data_kind; + if (data_type != GRN_DB_VOID) { + new_node->data_type = data_type; + } else { + new_node->data_type = grn_ts_data_kind_to_type(data_kind); + } + if (data_kind & GRN_TS_VECTOR_FLAG) { rc = grn_ts_expr_const_node_set_vector(ctx, new_node, value); } else { rc = grn_ts_expr_const_node_set_scalar(ctx, new_node, value); Modified: lib/ts/ts_expr_node.h (+4 -1) =================================================================== --- lib/ts/ts_expr_node.h 2015-11-16 14:59:23 +0900 (cab0cae) +++ lib/ts/ts_expr_node.h 2015-11-16 15:17:14 +0900 (8ef6e42) @@ -19,6 +19,8 @@ #ifndef GRN_TS_EXPR_NODE_H #define GRN_TS_EXPR_NODE_H +#include "../grn.h" + #include "ts_buf.h" #include "ts_op.h" #include "ts_types.h" @@ -68,7 +70,8 @@ grn_rc grn_ts_expr_value_node_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr_node **node); /* grn_ts_expr_const_node_open() creates a node associated with a const. */ -grn_rc grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind kind, +grn_rc grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind data_kind, + grn_ts_data_type data_type, const void *value, grn_ts_expr_node **node); /* grn_ts_expr_column_node_open() creates a node associated with a column. */ Modified: lib/ts/ts_expr_parser.c (+59 -25) =================================================================== --- lib/ts/ts_expr_parser.c 2015-11-16 14:59:23 +0900 (5e83335) +++ lib/ts/ts_expr_parser.c 2015-11-16 15:17:14 +0900 (45cd097) @@ -24,6 +24,7 @@ #include "ts_log.h" #include "ts_str.h" +#include "ts_util.h" /*------------------------------------------------------------- * grn_ts_expr_parser. @@ -76,7 +77,7 @@ typedef grn_ts_expr_token grn_ts_expr_bridge_token; typedef grn_ts_expr_token grn_ts_expr_bracket_token; struct grn_ts_expr_parser { - grn_ts_expr *expr; /* Associated expression. */ + grn_ts_expr_builder *builder; /* Builder. */ grn_ts_buf str_buf; /* Buffer for a source string. */ grn_ts_expr_token **tokens; /* Tokens. */ size_t n_tokens; /* Number of tokens. */ @@ -326,11 +327,10 @@ grn_ts_expr_token_close(grn_ctx *ctx, grn_ts_expr_token *token) /* grn_ts_expr_parser_init() initializes a parser. */ static void -grn_ts_expr_parser_init(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_parser *parser) +grn_ts_expr_parser_init(grn_ctx *ctx, grn_ts_expr_parser *parser) { memset(parser, 0, sizeof(*parser)); - parser->expr = expr; + parser->builder = NULL; grn_ts_buf_init(ctx, &parser->str_buf); parser->tokens = NULL; parser->dummy_tokens = NULL; @@ -359,28 +359,52 @@ grn_ts_expr_parser_fin(grn_ctx *ctx, grn_ts_expr_parser *parser) GRN_FREE(parser->tokens); } grn_ts_buf_fin(ctx, &parser->str_buf); + if (parser->builder) { + grn_ts_expr_builder_close(ctx, parser->builder); + } } grn_rc -grn_ts_expr_parser_open(grn_ctx *ctx, grn_ts_expr *expr, +grn_ts_expr_parser_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr_parser **parser) { - grn_ts_expr_parser *new_parser = GRN_MALLOCN(grn_ts_expr_parser, 1); + grn_rc rc; + grn_ts_expr_parser *new_parser; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!table || !grn_ts_obj_is_table(ctx, table) || !parser) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + new_parser = GRN_MALLOCN(grn_ts_expr_parser, 1); if (!new_parser) { GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", sizeof(grn_ts_expr_parser)); } - grn_ts_expr_parser_init(ctx, expr, new_parser); + grn_ts_expr_parser_init(ctx, new_parser); + rc = grn_ts_expr_builder_open(ctx, table, &new_parser->builder); + if (rc != GRN_SUCCESS) { + grn_ts_expr_parser_fin(ctx, new_parser); + GRN_FREE(new_parser); + return rc; + } *parser = new_parser; return GRN_SUCCESS; } -void +grn_rc grn_ts_expr_parser_close(grn_ctx *ctx, grn_ts_expr_parser *parser) { + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!parser) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } grn_ts_expr_parser_fin(ctx, parser); GRN_FREE(parser); + return GRN_SUCCESS; } /* grn_ts_expr_parser_tokenize_start() creates the start token. */ @@ -879,17 +903,24 @@ grn_ts_expr_parser_push_const(grn_ctx *ctx, grn_ts_expr_parser *parser, { switch (token->data_kind) { case GRN_TS_BOOL: { - return grn_ts_expr_push_bool(ctx, parser->expr, token->content.as_bool); + return grn_ts_expr_builder_push_const(ctx, parser->builder, + GRN_TS_BOOL, GRN_DB_VOID, + &token->content.as_bool); } case GRN_TS_INT: { - return grn_ts_expr_push_int(ctx, parser->expr, token->content.as_int); + return grn_ts_expr_builder_push_const(ctx, parser->builder, + GRN_TS_INT, GRN_DB_VOID, + &token->content.as_int); } case GRN_TS_FLOAT: { - return grn_ts_expr_push_float(ctx, parser->expr, - token->content.as_float); + return grn_ts_expr_builder_push_const(ctx, parser->builder, + GRN_TS_FLOAT, GRN_DB_VOID, + &token->content.as_float); } case GRN_TS_TEXT: { - return grn_ts_expr_push_text(ctx, parser->expr, token->content.as_text); + return grn_ts_expr_builder_push_const(ctx, parser->builder, + GRN_TS_TEXT, GRN_DB_VOID, + &token->content.as_text); } default: { GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", @@ -903,8 +934,7 @@ static grn_rc grn_ts_expr_parser_push_name(grn_ctx *ctx, grn_ts_expr_parser *parser, grn_ts_expr_name_token *token) { - return grn_ts_expr_push_name(ctx, parser->expr, - token->src.ptr, token->src.size); + return grn_ts_expr_builder_push_name(ctx, parser->builder, token->src); } /* grn_ts_expr_parser_push_op() pushes a token to an expression. */ @@ -912,7 +942,7 @@ static grn_rc grn_ts_expr_parser_push_op(grn_ctx *ctx, grn_ts_expr_parser *parser, grn_ts_expr_op_token *token) { - return grn_ts_expr_push_op(ctx, parser->expr, token->op_type); + return grn_ts_expr_builder_push_op(ctx, parser->builder, token->op_type); } /* @@ -939,7 +969,7 @@ grn_ts_expr_parser_apply_one(grn_ctx *ctx, grn_ts_expr_parser *parser, /* Check the number of arguments. */ switch (stack[depth - 2]->type) { case GRN_TS_EXPR_BRIDGE_TOKEN: { - rc = grn_ts_expr_end_subexpr(ctx, parser->expr); + rc = grn_ts_expr_builder_end_subexpr(ctx, parser->builder); if (rc != GRN_SUCCESS) { return rc; } @@ -1040,7 +1070,7 @@ static grn_rc grn_ts_expr_parser_analyze_bridge(grn_ctx *ctx, grn_ts_expr_parser *parser, grn_ts_expr_bridge_token *token) { - grn_rc rc = grn_ts_expr_begin_subexpr(ctx, parser->expr); + grn_rc rc = grn_ts_expr_builder_begin_subexpr(ctx, parser->builder); if (rc != GRN_SUCCESS) { return rc; } @@ -1212,18 +1242,22 @@ grn_ts_expr_parser_analyze(grn_ctx *ctx, grn_ts_expr_parser *parser) grn_rc grn_ts_expr_parser_parse(grn_ctx *ctx, grn_ts_expr_parser *parser, - const char *str_ptr, size_t str_size) + grn_ts_str str, grn_ts_expr **expr) { grn_rc rc; - grn_ts_str str; - rc = grn_ts_buf_reserve(ctx, &parser->str_buf, str_size + 1); + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!parser || (!str.ptr && str.size)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_buf_reserve(ctx, &parser->str_buf, str.size + 1); if (rc != GRN_SUCCESS) { return rc; } - grn_memcpy(parser->str_buf.ptr, str_ptr, str_size); - ((char *)parser->str_buf.ptr)[str_size] = '\0'; + grn_memcpy(parser->str_buf.ptr, str.ptr, str.size); + ((char *)parser->str_buf.ptr)[str.size] = '\0'; str.ptr = (const char *)parser->str_buf.ptr; - str.size = str_size; rc = grn_ts_expr_parser_tokenize(ctx, parser, str); if (rc != GRN_SUCCESS) { return rc; @@ -1232,5 +1266,5 @@ grn_ts_expr_parser_parse(grn_ctx *ctx, grn_ts_expr_parser *parser, if (rc != GRN_SUCCESS) { return rc; } - return GRN_SUCCESS; + return grn_ts_expr_builder_complete(ctx, parser->builder, expr); } Modified: lib/ts/ts_expr_parser.h (+6 -8) =================================================================== --- lib/ts/ts_expr_parser.h 2015-11-16 14:59:23 +0900 (64f0d71) +++ lib/ts/ts_expr_parser.h 2015-11-16 15:17:14 +0900 (1164561) @@ -20,7 +20,8 @@ #define GRN_TS_EXPR_PARSER_H #include "ts_expr.h" -#include "ts_op.h" +#include "ts_expr_builder.h" +#include "ts_str.h" #include "ts_types.h" #ifdef __cplusplus @@ -30,18 +31,15 @@ extern "C" { typedef struct grn_ts_expr_parser grn_ts_expr_parser; /* grn_ts_expr_parser_open() creates a parser. */ -grn_rc grn_ts_expr_parser_open(grn_ctx *ctx, grn_ts_expr *expr, +grn_rc grn_ts_expr_parser_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr_parser **parser); /* grn_ts_expr_parser_close() destroys a parser. */ -void grn_ts_expr_parser_close(grn_ctx *ctx, grn_ts_expr_parser *parser); +grn_rc grn_ts_expr_parser_close(grn_ctx *ctx, grn_ts_expr_parser *parser); -/* - * grn_ts_expr_parser_parse() parses a string and pushes nodes into an - * expression. - */ +/* grn_ts_expr_parser_parse() parses a string and creates an expression. */ grn_rc grn_ts_expr_parser_parse(grn_ctx *ctx, grn_ts_expr_parser *parser, - const char *str_ptr, size_t str_size); + grn_ts_str str, grn_ts_expr **expr); #ifdef __cplusplus } Modified: lib/ts/ts_str.h (+2 -0) =================================================================== --- lib/ts/ts_str.h 2015-11-16 14:59:23 +0900 (4a26aca) +++ lib/ts/ts_str.h 2015-11-16 15:17:14 +0900 (5def7d6) @@ -19,6 +19,8 @@ #ifndef GRN_TS_STR_H #define GRN_TS_STR_H +#include "../grn.h" + #include "ts_types.h" #ifdef __cplusplus Modified: lib/ts/ts_util.c (+0 -1) =================================================================== --- lib/ts/ts_util.c 2015-11-16 14:59:23 +0900 (3d6b47c) +++ lib/ts/ts_util.c 2015-11-16 15:17:14 +0900 (0fed481) @@ -23,7 +23,6 @@ #include "../grn_pat.h" #include "ts_log.h" -#include "ts_types.h" grn_rc grn_ts_obj_increment_ref_count(grn_ctx *ctx, grn_obj *obj)