susumu.yata
null+****@clear*****
Mon Nov 9 14:12:30 JST 2015
susumu.yata 2015-11-09 14:12:30 +0900 (Mon, 09 Nov 2015) New Revision: 4478eab3cf6ae2c2e78f293e47ab88ff34c3df48 https://github.com/groonga/groonga/commit/4478eab3cf6ae2c2e78f293e47ab88ff34c3df48 Message: grn_ts: move definitions of grn_ts_expr into lib/ts/ts_expr Copied files: lib/ts/ts_expr.c (from lib/ts.c) lib/ts/ts_expr.h (from lib/grn_ts.h) Modified files: lib/grn_ts.h lib/ts.c lib/ts/sources.am Modified: lib/grn_ts.h (+33 -281) =================================================================== --- lib/grn_ts.h 2015-11-09 13:36:05 +0900 (c815433) +++ lib/grn_ts.h 2015-11-09 14:12:30 +0900 (184ed38) @@ -20,7 +20,6 @@ #define GRN_TS_H #include <stddef.h> -#include <stdint.h> #include "grn.h" @@ -29,343 +28,96 @@ extern "C" { #endif /*------------------------------------------------------------- - * Enumeration types. - */ - -/* grn_builtin_type or table ID. */ -typedef grn_id grn_ts_data_type; - -enum { GRN_TS_VECTOR_FLAG = 1 << 7 }; - -typedef enum { - GRN_TS_VOID = 0, /* GRN_DB_VOID */ - GRN_TS_BOOL = 1, /* GRN_DB_BOOL */ - GRN_TS_INT = 2, /* GRN_DB_[U]INT(8/16/32/64) */ - GRN_TS_FLOAT = 3, /* GRN_DB_FLOAT */ - GRN_TS_TIME = 4, /* GRN_DB_TIME */ - GRN_TS_TEXT = 5, /* GRN_DB_[SHORT_/LONG_]TEST */ - GRN_TS_GEO_POINT = 6, /* GRN_DB_(TOKYO/WGS84)_GEO_POINT */ - GRN_TS_REF = 7, /* Table reference. */ - GRN_TS_BOOL_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_BOOL, - GRN_TS_INT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_INT, - GRN_TS_FLOAT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_FLOAT, - GRN_TS_TIME_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_TIME, - GRN_TS_TEXT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_TEXT, - GRN_TS_GEO_POINT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_GEO_POINT, - GRN_TS_REF_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_REF -} grn_ts_data_kind; - -typedef enum { - /* Invalid operator. */ - GRN_TS_OP_NOP, - - /* Unary operators. */ - GRN_TS_OP_LOGICAL_NOT, /* !X */ - GRN_TS_OP_BITWISE_NOT, /* ~X */ - GRN_TS_OP_POSITIVE, /* +X */ - GRN_TS_OP_NEGATIVE, /* -X */ - - /* Binary operators. */ - GRN_TS_OP_LOGICAL_AND, /* X && Y */ - GRN_TS_OP_LOGICAL_OR, /* X || Y */ - GRN_TS_OP_LOGICAL_SUB, /* X &! Y */ - GRN_TS_OP_BITWISE_AND, /* X & Y */ - GRN_TS_OP_BITWISE_OR, /* X | Y */ - GRN_TS_OP_BITWISE_XOR, /* X ^ Y */ - GRN_TS_OP_EQUAL, /* X == Y */ - GRN_TS_OP_NOT_EQUAL, /* X != Y */ - GRN_TS_OP_LESS, /* X < Y */ - GRN_TS_OP_LESS_EQUAL, /* X <= Y */ - GRN_TS_OP_GREATER, /* X > Y */ - GRN_TS_OP_GREATER_EQUAL, /* X >= Y */ - GRN_TS_OP_SHIFT_ARITHMETIC_LEFT, /* X << Y */ - GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT, /* X >> Y */ - GRN_TS_OP_SHIFT_LOGICAL_LEFT, /* X <<< Y */ - GRN_TS_OP_SHIFT_LOGICAL_RIGHT, /* X >>> Y */ - GRN_TS_OP_PLUS, /* X + Y */ - GRN_TS_OP_MINUS, /* X - Y */ - GRN_TS_OP_MULTIPLICATION, /* X * Y */ - GRN_TS_OP_DIVISION, /* X / Y */ - GRN_TS_OP_MODULUS /* X % Y */ -} grn_ts_op_type; - -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_type; - -typedef enum { - GRN_TS_EXPR_ID_NODE, /* Associated with the ID (_id). */ - GRN_TS_EXPR_SCORE_NODE, /* Asscoaited with the score (_score). */ - GRN_TS_EXPR_KEY_NODE, /* Asscoaited with the key (_key). */ - GRN_TS_EXPR_VALUE_NODE, /* Asscoaited with the embedded value (_value). */ - GRN_TS_EXPR_CONST_NODE, /* Associated with a const. */ - GRN_TS_EXPR_COLUMN_NODE, /* Associated with a column. */ - GRN_TS_EXPR_OP_NODE, /* Associated with an operator. */ - GRN_TS_EXPR_BRIDGE_NODE /* Associated with a bridge to a subexpression. */ -} grn_ts_expr_node_type; - -/*------------------------------------------------------------- * Built-in data types. */ -/* ID (_id), score (_score), and record types. */ +/* ID (_id). */ typedef grn_id grn_ts_id; + +/* Score (_score). */ typedef float grn_ts_score; + +/* Record (_id, _score). */ typedef struct { grn_ts_id id; grn_ts_score score; } grn_ts_record; /* Built-in scalar data types. */ + +/* Bool. */ typedef grn_bool grn_ts_bool; + +/* Int. */ typedef int64_t grn_ts_int; + +/* Float. */ typedef double grn_ts_float; + +/* Time. */ typedef int64_t grn_ts_time; + +/* Text. */ typedef struct { const char *ptr; size_t size; } grn_ts_text; + +/* GeoPoint. */ typedef grn_geo_point grn_ts_geo_point; typedef grn_geo_point grn_ts_tokyo_geo_point; typedef grn_geo_point grn_ts_wgs84_geo_point; + +/* Ref. */ typedef grn_ts_record grn_ts_ref; /* Built-in vector data types. */ + +/* BoolVector. */ typedef struct { const grn_ts_bool *ptr; size_t size; } grn_ts_bool_vector; + +/* IntVector. */ typedef struct { const grn_ts_int *ptr; size_t size; } grn_ts_int_vector; + +/* FloatVector. */ typedef struct { const grn_ts_float *ptr; size_t size; } grn_ts_float_vector; + +/* TimeVector. */ typedef struct { const grn_ts_time *ptr; size_t size; } grn_ts_time_vector; + +/* TextVector. */ typedef struct { const grn_ts_text *ptr; size_t size; } grn_ts_text_vector; + +/* GeoPointVector. */ typedef struct { const grn_ts_geo_point *ptr; size_t size; } grn_ts_geo_point_vector; typedef grn_ts_geo_point_vector grn_ts_tokyo_geo_point_vector; typedef grn_ts_geo_point_vector grn_ts_wgs84_geo_point_vector; + +/* RefVector. */ typedef struct { const grn_ts_ref *ptr; size_t size; } grn_ts_ref_vector; /*------------------------------------------------------------- - * Expression components. - */ - -#define GRN_TS_EXPR_NODE_COMMON_MEMBERS\ - grn_ts_expr_node_type type; /* Node type. */\ - grn_ts_data_kind data_kind; /* Abstract data type. */\ - grn_ts_data_type data_type; /* Detailed data type. */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS -} grn_ts_expr_node; - -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 **nodes; /* Buffer for a node stack. */ - size_t n_nodes; /* Number of nodes. */ - size_t max_n_nodes; /* Max. number (capacity) of nodes. */ - 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_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_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 **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 column. */ -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_point() pushes a GeoPoint const. */ -grn_rc grn_ts_expr_push_geo_point(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_point value); -/* grn_ts_expr_push_tokyo_geo_point() pushes a TokyoGeoPoint const. */ -grn_rc grn_ts_expr_push_tokyo_geo_point(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_point value); -/* grn_ts_expr_push_wgs84_geo_point() pushes a WGS84GeoPoint const. */ -grn_rc grn_ts_expr_push_wgs84_geo_point(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_point 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_point_vector() pushes a GeoPoint vector const. */ -grn_rc grn_ts_expr_push_geo_point_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_point_vector value); -/* - * grn_ts_expr_push_tokyo_geo_point_vector() pushes a TokyoGeoPoint vector - * const. - */ -grn_rc grn_ts_expr_push_tokyo_geo_point_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_point_vector value); -/* - * grn_ts_expr_push_wgs84_geo_point_vector() pushes a WGS84GeoPoint vector - * const. - */ -grn_rc grn_ts_expr_push_wgs84_geo_point_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_point_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_filter() filters records. */ -grn_rc 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); - -/* grn_ts_expr_adjust() updates scores. */ -grn_rc grn_ts_expr_adjust(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_record *io, size_t n_io); - -/*------------------------------------------------------------- * API. */ Modified: lib/ts.c (+10 -6946) =================================================================== --- lib/ts.c 2015-11-09 13:36:05 +0900 (5410343) +++ lib/ts.c 2015-11-09 14:12:30 +0900 (2d73b94) @@ -20,22 +20,11 @@ #include "grn_ts.h" -#include <ctype.h> -#include <math.h> -#include <stdlib.h> -#include <string.h> - -#include "grn_ctx_impl.h" -#include "grn_dat.h" -#include "grn_db.h" -#include "grn_geo.h" -#include "grn_hash.h" #include "grn_output.h" -#include "grn_pat.h" -#include "grn_store.h" #include "grn_str.h" #include "ts/ts_buf.h" +#include "ts/ts_expr.h" #include "ts/ts_log.h" #include "ts/ts_str.h" @@ -45,202 +34,6 @@ enum { GRN_TS_BATCH_SIZE = 1024 }; -/*------------------------------------------------------------- - * Built-in data kinds. - */ - -typedef union { - grn_ts_bool as_bool; - grn_ts_int as_int; - grn_ts_float as_float; - grn_ts_time as_time; - grn_ts_text as_text; - grn_ts_geo_point as_geo_point; - grn_ts_ref as_ref; - grn_ts_bool_vector as_bool_vector; - grn_ts_int_vector as_int_vector; - grn_ts_float_vector as_float_vector; - grn_ts_time_vector as_time_vector; - grn_ts_text_vector as_text_vector; - grn_ts_geo_point_vector as_geo_point_vector; - grn_ts_ref_vector as_ref_vector; -} grn_ts_any; - -/* grn_ts_bool_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_bool_is_valid(grn_ts_bool value) { - return GRN_TRUE; -} - -/* grn_ts_int_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_int_is_valid(grn_ts_int value) { - return GRN_TRUE; -} - -/* grn_ts_float_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_float_is_valid(grn_ts_float value) { - return !isnan(value); -} - -/* grn_ts_time_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_time_is_valid(grn_ts_time value) { - return GRN_TRUE; -} - -/* grn_ts_text_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_text_is_valid(grn_ts_text value) { - return value.ptr || !value.size; -} - -/* grn_ts_geo_point_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_geo_point_is_valid(grn_ts_geo_point value) { - return ((value.latitude >= GRN_GEO_MIN_LATITUDE) && - (value.latitude <= GRN_GEO_MAX_LATITUDE)) && - ((value.longitude >= GRN_GEO_MIN_LONGITUDE) && - (value.longitude <= GRN_GEO_MAX_LONGITUDE)); -} - -#define GRN_TS_VECTOR_IS_VALID(type)\ - if (value.size) {\ - size_t i;\ - if (!value.ptr) {\ - return GRN_FALSE;\ - }\ - for (i = 0; i < value.size; i++) {\ - if (!grn_ts_ ## type ## _is_valid(value.ptr[i])) {\ - return GRN_FALSE;\ - }\ - }\ - }\ - return GRN_TRUE; -/* grn_ts_bool_vector_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_bool_vector_is_valid(grn_ts_bool_vector value) { - GRN_TS_VECTOR_IS_VALID(bool) -} - -/* grn_ts_int_vector_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_int_vector_is_valid(grn_ts_int_vector value) { - GRN_TS_VECTOR_IS_VALID(int) -} - -/* grn_ts_float_vector_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_float_vector_is_valid(grn_ts_float_vector value) { - GRN_TS_VECTOR_IS_VALID(float) -} - -/* grn_ts_time_vector_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_time_vector_is_valid(grn_ts_time_vector value) { - GRN_TS_VECTOR_IS_VALID(time) -} - -/* grn_ts_text_vector_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_text_vector_is_valid(grn_ts_text_vector value) { - GRN_TS_VECTOR_IS_VALID(text) -} - -/* - * grn_ts_geo_point_vector_is_valid() returns whether a value is valid or not. - */ -inline static grn_ts_bool -grn_ts_geo_point_vector_is_valid(grn_ts_geo_point_vector value) { - GRN_TS_VECTOR_IS_VALID(geo_point) -} -#undef GRN_TS_VECTOR_IS_VALID - -/* grn_ts_bool_zero() returns a zero. */ -inline static grn_ts_bool -grn_ts_bool_zero(void) { - return GRN_FALSE; -} - -/* grn_ts_int_zero() returns a zero. */ -inline static grn_ts_int -grn_ts_int_zero(void) { - return 0; -} - -/* grn_ts_float_zero() returns a zero. */ -inline static grn_ts_float -grn_ts_float_zero(void) { - return 0.0; -} - -/* grn_ts_time_zero() returns a zero. */ -inline static grn_ts_time -grn_ts_time_zero(void) { - return 0; -} - -/* grn_ts_text_zero() returns a zero. */ -inline static grn_ts_text -grn_ts_text_zero(void) { - return (grn_ts_text){ NULL, 0 }; -} - -/* grn_ts_geo_point_zero() returns a zero. */ -inline static grn_ts_geo_point -grn_ts_geo_point_zero(void) { - return (grn_ts_geo_point){ 0, 0 }; -} - -/* grn_ts_geo_point_zero() returns a zero. */ -inline static grn_ts_ref -grn_ts_ref_zero(void) { - return (grn_ts_ref){ 0, 0.0 }; -} - -/* grn_ts_bool_vector_zero() returns a zero. */ -inline static grn_ts_bool_vector -grn_ts_bool_vector_zero(void) { - return (grn_ts_bool_vector){ NULL, 0 }; -} - -/* grn_ts_int_vector_zero() returns a zero. */ -inline static grn_ts_int_vector -grn_ts_int_vector_zero(void) { - return (grn_ts_int_vector){ NULL, 0 }; -} - -/* grn_ts_float_vector_zero() returns a zero. */ -inline static grn_ts_float_vector -grn_ts_float_vector_zero(void) { - return (grn_ts_float_vector){ NULL, 0 }; -} - -/* grn_ts_time_vector_zero() returns a zero. */ -inline static grn_ts_time_vector -grn_ts_time_vector_zero(void) { - return (grn_ts_time_vector){ NULL, 0 }; -} - -/* grn_ts_text_vector_zero() returns a zero. */ -inline static grn_ts_text_vector -grn_ts_text_vector_zero(void) { - return (grn_ts_text_vector){ NULL, 0 }; -} - -/* grn_ts_geo_point_vector_zero() returns a zero. */ -inline static grn_ts_geo_point_vector -grn_ts_geo_point_vector_zero(void) { - return (grn_ts_geo_point_vector){ NULL, 0 }; -} - -/* grn_ts_ref_vector_zero() returns a zero. */ -inline static grn_ts_ref_vector -grn_ts_ref_vector_zero(void) { - return (grn_ts_ref_vector){ NULL, 0 }; -} - /* grn_ts_bool_output() outputs a value. */ static grn_rc grn_ts_bool_output(grn_ctx *ctx, grn_ts_bool value) { @@ -353,6756 +146,27 @@ grn_ts_geo_point_vector_output(grn_ctx *ctx, grn_ts_geo_point_vector value) { } #undef GRN_TS_VECTOR_OUTPUT -/* grn_ts_data_type_to_kind() returns a kind associated with a type. */ -static grn_ts_data_kind -grn_ts_data_type_to_kind(grn_ts_data_type type) { - switch (type) { - case GRN_DB_VOID: { - return GRN_TS_VOID; - } - case GRN_DB_BOOL: { - return GRN_TS_BOOL; - } - case GRN_DB_INT8: - case GRN_DB_INT16: - case GRN_DB_INT32: - case GRN_DB_INT64: - case GRN_DB_UINT8: - case GRN_DB_UINT16: - case GRN_DB_UINT32: - case GRN_DB_UINT64: { - return GRN_TS_INT; - } - case GRN_DB_FLOAT: { - return GRN_TS_FLOAT; - } - case GRN_DB_TIME: { - return GRN_TS_TIME; - } - case GRN_DB_SHORT_TEXT: - case GRN_DB_TEXT: - case GRN_DB_LONG_TEXT: { - return GRN_TS_TEXT; - } - case GRN_DB_TOKYO_GEO_POINT: - case GRN_DB_WGS84_GEO_POINT: { - return GRN_TS_GEO_POINT; - } - default: { - return GRN_TS_REF; - } - } -} - -/* grn_ts_data_kind_to_type() returns a type associated with a kind. */ -static grn_ts_data_type -grn_ts_data_kind_to_type(grn_ts_data_kind kind) { - switch (kind & ~GRN_TS_VECTOR_FLAG) { - case GRN_TS_BOOL: { - return GRN_DB_BOOL; - } - case GRN_TS_INT: { - return GRN_DB_INT64; - } - case GRN_TS_FLOAT: { - return GRN_DB_FLOAT; - } - case GRN_TS_TIME: { - return GRN_DB_TIME; - } - case GRN_TS_TEXT: { - return GRN_DB_TEXT; - } - case GRN_TS_GEO_POINT: { - /* GRN_DB_TOKYO_GEO_POINT or GRN_DB_WGS84_GEO_POINT. */ - return GRN_DB_VOID; - } - case GRN_TS_REF: { - /* - * grn_ts_data_kind does not have enough information to get a correct - * table ID. - */ - return GRN_DB_VOID; - } - default: { - return GRN_DB_VOID; - } - } -} - -/*------------------------------------------------------------- - * Operators. - */ - -/* Operator precedence. */ -typedef int grn_ts_op_precedence; - -/* grn_ts_op_get_n_args() returns the number of arguments. */ -static size_t -grn_ts_op_get_n_args(grn_ts_op_type op_type) { - switch (op_type) { - case GRN_TS_OP_LOGICAL_NOT: /* !X */ - case GRN_TS_OP_BITWISE_NOT: /* ~X */ - case GRN_TS_OP_POSITIVE: /* +X */ - case GRN_TS_OP_NEGATIVE: { /* -X */ - return 1; - } - case GRN_TS_OP_LOGICAL_AND: /* X && Y */ - case GRN_TS_OP_LOGICAL_OR: /* X || Y */ - case GRN_TS_OP_LOGICAL_SUB: /* X &! Y */ - case GRN_TS_OP_BITWISE_AND: /* X & Y */ - case GRN_TS_OP_BITWISE_OR: /* X | Y */ - case GRN_TS_OP_BITWISE_XOR: /* X ^ Y */ - case GRN_TS_OP_EQUAL: /* X == Y */ - case GRN_TS_OP_NOT_EQUAL: /* X != Y */ - case GRN_TS_OP_LESS: /* X < Y */ - case GRN_TS_OP_LESS_EQUAL: /* X <= Y */ - case GRN_TS_OP_GREATER: /* X > Y */ - case GRN_TS_OP_GREATER_EQUAL: /* X >= Y */ - case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: /* X << Y */ - case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: /* X >> Y */ - case GRN_TS_OP_SHIFT_LOGICAL_LEFT: /* X <<< Y */ - case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: /* X >>> Y */ - case GRN_TS_OP_PLUS: /* X + Y */ - case GRN_TS_OP_MINUS: /* X - Y */ - case GRN_TS_OP_MULTIPLICATION: /* X * Y */ - case GRN_TS_OP_DIVISION: /* X / Y */ - case GRN_TS_OP_MODULUS: { /* X % Y */ - return 2; - } - default: { - return 0; - } - } -} - -/* - * grn_ts_op_get_precedence() returns the precedence. - * A prior operator has a higher precedence. - */ -static grn_ts_op_precedence -grn_ts_op_get_precedence(grn_ts_op_type op_type) { - switch (op_type) { - case GRN_TS_OP_LOGICAL_NOT: - case GRN_TS_OP_BITWISE_NOT: - case GRN_TS_OP_POSITIVE: - case GRN_TS_OP_NEGATIVE: { - return 14; - } - case GRN_TS_OP_LOGICAL_AND: { - return 5; - } - case GRN_TS_OP_LOGICAL_OR: { - return 3; - } - case GRN_TS_OP_LOGICAL_SUB: { - return 4; - } - case GRN_TS_OP_BITWISE_AND: { - return 8; - } - case GRN_TS_OP_BITWISE_OR: { - return 6; - } - case GRN_TS_OP_BITWISE_XOR: { - return 7; - } - case GRN_TS_OP_EQUAL: - case GRN_TS_OP_NOT_EQUAL: { - return 9; - } - case GRN_TS_OP_LESS: - case GRN_TS_OP_LESS_EQUAL: - case GRN_TS_OP_GREATER: - case GRN_TS_OP_GREATER_EQUAL: { - return 10; - } - case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: - case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: - case GRN_TS_OP_SHIFT_LOGICAL_LEFT: - case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: { - return 11; - } - case GRN_TS_OP_PLUS: - case GRN_TS_OP_MINUS: { - return 12; - } - case GRN_TS_OP_MULTIPLICATION: - case GRN_TS_OP_DIVISION: - case GRN_TS_OP_MODULUS: { - return 13; +/* grn_ts_table_has_key() returns whether or not a table has _key. */ +static grn_ts_bool +grn_ts_table_has_key(grn_ctx *ctx, grn_obj *table) { + switch (table->header.type) { + case GRN_TABLE_HASH_KEY: + case GRN_TABLE_PAT_KEY: + case GRN_TABLE_DAT_KEY: { + return GRN_TRUE; } default: { - return 0; + return GRN_FALSE; } } } -/* FIXME: The following implementation assumes that NaN values don't appear. */ - -/* grn_ts_op_logical_not_bool() returns !arg. */ -inline static grn_ts_bool -grn_ts_op_logical_not_bool(grn_ts_bool arg) { - return !arg; -} - -/* grn_ts_op_bitwise_not_bool() returns ~arg. */ -inline static grn_ts_bool -grn_ts_op_bitwise_not_bool(grn_ts_bool arg) { - return !arg; -} - -/* grn_ts_op_bitwise_not_int() returns ~arg. */ -inline static grn_ts_int -grn_ts_op_bitwise_not_int(grn_ts_int arg) { - return ~arg; -} - -/* grn_ts_op_positive_int() returns +arg. */ -inline static grn_ts_int -grn_ts_op_positive_int(grn_ts_int arg) { - return arg; -} - -/* grn_ts_op_positive_float() returns +arg. */ -inline static grn_ts_float -grn_ts_op_positive_float(grn_ts_float arg) { - return arg; -} - -/* grn_ts_op_negative_int() returns -arg. */ -inline static grn_ts_int -grn_ts_op_negative_int(grn_ts_int arg) { - return -arg; -} - -/* grn_ts_op_negative_float() returns -arg. */ -inline static grn_ts_float -grn_ts_op_negative_float(grn_ts_float arg) { - return -arg; -} - -/* grn_ts_op_bitwise_and_bool() returns lhs & rhs. */ -inline static grn_ts_bool -grn_ts_op_bitwise_and_bool(grn_ts_bool lhs, grn_ts_bool rhs) { - return lhs & rhs; -} - -/* grn_ts_op_bitwise_and_int() returns lhs & rhs. */ -inline static grn_ts_int -grn_ts_op_bitwise_and_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs & rhs; -} - -/* grn_ts_op_bitwise_or_bool() returns lhs | rhs. */ -inline static grn_ts_bool -grn_ts_op_bitwise_or_bool(grn_ts_bool lhs, grn_ts_bool rhs) { - return lhs | rhs; -} - -/* grn_ts_op_bitwise_or_int() returns lhs | rhs. */ -inline static grn_ts_int -grn_ts_op_bitwise_or_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs | rhs; -} - -/* grn_ts_op_bitwise_xor_bool() returns lhs ^ rhs. */ -inline static grn_ts_bool -grn_ts_op_bitwise_xor_bool(grn_ts_bool lhs, grn_ts_bool rhs) { - return lhs ^ rhs; -} - -/* grn_ts_op_bitwise_xor_int() returns lhs ^ rhs. */ -inline static grn_ts_int -grn_ts_op_bitwise_xor_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs ^ rhs; -} - -/* grn_ts_op_equal_bool() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_bool(grn_ts_bool lhs, grn_ts_bool rhs) { - return lhs == rhs; -} - -/* grn_ts_op_equal_int() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs == rhs; -} - -/* grn_ts_op_equal_float() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_float(grn_ts_float lhs, grn_ts_float rhs) { - /* To suppress warnings, "lhs == rhs" is not used. */ - return (lhs <= rhs) && (lhs >= rhs); -} - -/* grn_ts_op_equal_time() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_time(grn_ts_time lhs, grn_ts_time rhs) { - return lhs == rhs; -} - -/* grn_ts_op_equal_text() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_text(grn_ts_text lhs, grn_ts_text rhs) { - return (lhs.size == rhs.size) && !memcmp(lhs.ptr, rhs.ptr, lhs.size); -} - -/* grn_ts_op_equal_geo_point() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_geo_point(grn_ts_geo_point lhs, grn_ts_geo_point rhs) { - return (lhs.latitude == rhs.latitude) && (lhs.longitude == rhs.longitude); -} - -/* grn_ts_op_equal_ref() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_ref(grn_ts_ref lhs, grn_ts_ref rhs) { - /* Ignore scores. */ - return lhs.id == rhs.id; -} - -#define GRN_TS_OP_EQUAL_VECTOR(kind)\ - size_t i;\ - if (lhs.size != rhs.size) {\ - return GRN_FALSE;\ - }\ - for (i = 0; i < lhs.size; i++) {\ - if (!grn_ts_op_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - return GRN_FALSE;\ - }\ - }\ - return GRN_TRUE; -/* grn_ts_op_equal_bool_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_bool_vector(grn_ts_bool_vector lhs, grn_ts_bool_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(bool) -} - -/* grn_ts_op_equal_int_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(int) -} - -/* grn_ts_op_equal_float_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_float_vector(grn_ts_float_vector lhs, - grn_ts_float_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(float) -} - -/* grn_ts_op_equal_time_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(time) -} - -/* grn_ts_op_equal_text_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(text) -} - -/* grn_ts_op_equal_geo_point_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_geo_point_vector(grn_ts_geo_point_vector lhs, - grn_ts_geo_point_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(geo_point) -} - -/* grn_ts_op_equal_ref_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_ref_vector(grn_ts_ref_vector lhs, grn_ts_ref_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(ref) -} -#undef GRN_TS_OP_EQUAL_VECTOR - -/* grn_ts_op_not_equal_bool() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_bool(grn_ts_bool lhs, grn_ts_bool rhs) { - return lhs != rhs; -} - -/* grn_ts_op_not_equal_int() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs != rhs; -} - -/* grn_ts_op_not_equal_float() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_float(grn_ts_float lhs, grn_ts_float rhs) { - /* To suppress warnings, "lhs != rhs" is not used. */ - return (lhs < rhs) || (lhs > rhs); -} - -/* grn_ts_op_not_equal_time() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_time(grn_ts_time lhs, grn_ts_time rhs) { - return lhs != rhs; -} - -/* grn_ts_op_not_equal_text() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_text(grn_ts_text lhs, grn_ts_text rhs) { - return (lhs.size != rhs.size) || memcmp(lhs.ptr, rhs.ptr, lhs.size); -} - -/* grn_ts_op_not_equal_geo_point() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_geo_point(grn_ts_geo_point lhs, grn_ts_geo_point rhs) { - return (lhs.latitude != rhs.latitude) || (lhs.longitude != rhs.longitude); -} - -/* grn_ts_op_not_equal_ref() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_ref(grn_ts_ref lhs, grn_ts_ref rhs) { - /* Ignore scores. */ - return lhs.id != rhs.id; -} - -#define GRN_TS_OP_NOT_EQUAL_VECTOR(kind)\ - size_t i;\ - if (lhs.size != rhs.size) {\ - return GRN_TRUE;\ - }\ - for (i = 0; i < lhs.size; i++) {\ - if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - return GRN_TRUE;\ - }\ - }\ - return GRN_FALSE; -/* grn_ts_op_not_equal_bool_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_bool_vector(grn_ts_bool_vector lhs, - grn_ts_bool_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(bool) -} - -/* grn_ts_op_not_equal_int_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(int) -} - -/* grn_ts_op_not_equal_float_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_float_vector(grn_ts_float_vector lhs, - grn_ts_float_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(float) -} - -/* grn_ts_op_not_equal_time_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_time_vector(grn_ts_time_vector lhs, - grn_ts_time_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(time) -} - -/* grn_ts_op_not_equal_text_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_text_vector(grn_ts_text_vector lhs, - grn_ts_text_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(text) -} - -/* grn_ts_op_not_equal_geo_point_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_geo_point_vector(grn_ts_geo_point_vector lhs, - grn_ts_geo_point_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(geo_point) -} - -/* grn_ts_op_not_equal_ref_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_ref_vector(grn_ts_ref_vector lhs, grn_ts_ref_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(ref) -} -#undef GRN_TS_OP_NOT_EQUAL_VECTOR - -/* grn_ts_op_less_int() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs < rhs; -} - -/* grn_ts_op_less_float() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_float(grn_ts_float lhs, grn_ts_float rhs) { - return lhs < rhs; -} - -/* grn_ts_op_less_time() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_time(grn_ts_time lhs, grn_ts_time rhs) { - return lhs < rhs; -} - -/* grn_ts_op_less_text() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_text(grn_ts_text lhs, grn_ts_text rhs) { - size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; - int cmp = memcmp(lhs.ptr, rhs.ptr, min_size); - return cmp ? (cmp < 0) : (lhs.size < rhs.size); -} - -#define GRN_TS_OP_LESS_VECTOR(kind)\ - size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\ - for (i = 0; i < min_size; i++) {\ - if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - if (grn_ts_op_less_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - return GRN_TRUE;\ - }\ - }\ - }\ - return lhs.size < rhs.size; -/* grn_ts_op_less_int_vector() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) { - GRN_TS_OP_LESS_VECTOR(int) -} - -/* grn_ts_op_less_float_vector() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_float_vector(grn_ts_float_vector lhs, grn_ts_float_vector rhs) { - GRN_TS_OP_LESS_VECTOR(float) -} - -/* grn_ts_op_less_time_vector() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) { - GRN_TS_OP_LESS_VECTOR(time) -} - -/* grn_ts_op_less_text_vector() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) { - GRN_TS_OP_LESS_VECTOR(text) -} -#undef GRN_TS_OP_LESS_VECTOR - -/* grn_ts_op_less_equal_int() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs <= rhs; -} - -/* grn_ts_op_less_equal_float() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_float(grn_ts_float lhs, grn_ts_float rhs) { - return lhs <= rhs; -} - -/* grn_ts_op_less_equal_time() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_time(grn_ts_time lhs, grn_ts_time rhs) { - return lhs <= rhs; -} - -/* grn_ts_op_less_equal_text() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_text(grn_ts_text lhs, grn_ts_text rhs) { - size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; - int cmp = memcmp(lhs.ptr, rhs.ptr, min_size); - return cmp ? (cmp < 0) : (lhs.size <= rhs.size); -} - -#define GRN_TS_OP_LESS_EQUAL_VECTOR(kind)\ - size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\ - for (i = 0; i < min_size; i++) {\ - if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - if (grn_ts_op_less_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - return GRN_TRUE;\ - }\ - }\ - }\ - return lhs.size <= rhs.size; -/* grn_ts_op_less_equal_int_vector() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) { - GRN_TS_OP_LESS_EQUAL_VECTOR(int) -} - -/* grn_ts_op_less_equal_float_vector() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_float_vector(grn_ts_float_vector lhs, - grn_ts_float_vector rhs) { - GRN_TS_OP_LESS_EQUAL_VECTOR(float) -} - -/* grn_ts_op_less_equal_time_vector() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_time_vector(grn_ts_time_vector lhs, - grn_ts_time_vector rhs) { - GRN_TS_OP_LESS_EQUAL_VECTOR(time) -} - -/* grn_ts_op_less_equal_text_vector() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_text_vector(grn_ts_text_vector lhs, - grn_ts_text_vector rhs) { - GRN_TS_OP_LESS_EQUAL_VECTOR(text) -} -#undef GRN_TS_OP_LESS_EQUAL_VECTOR - -/* grn_ts_op_greater_int() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs > rhs; -} - -/* grn_ts_op_greater_float() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_float(grn_ts_float lhs, grn_ts_float rhs) { - return lhs > rhs; -} - -/* grn_ts_op_greater_time() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_time(grn_ts_time lhs, grn_ts_time rhs) { - return lhs > rhs; -} - -/* grn_ts_op_greater_text() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_text(grn_ts_text lhs, grn_ts_text rhs) { - size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; - int cmp = memcmp(lhs.ptr, rhs.ptr, min_size); - return cmp ? (cmp > 0) : (lhs.size > rhs.size); -} - -#define GRN_TS_OP_GREATER_VECTOR(kind)\ - size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\ - for (i = 0; i < min_size; i++) {\ - if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - if (grn_ts_op_greater_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - return GRN_TRUE;\ - }\ - }\ - }\ - return lhs.size > rhs.size; -/* grn_ts_op_greater_int_vector() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) { - GRN_TS_OP_GREATER_VECTOR(int) -} - -/* grn_ts_op_greater_float_vector() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_float_vector(grn_ts_float_vector lhs, - grn_ts_float_vector rhs) { - GRN_TS_OP_GREATER_VECTOR(float) -} - -/* grn_ts_op_greater_time_vector() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) { - GRN_TS_OP_GREATER_VECTOR(time) -} - -/* grn_ts_op_greater_text_vector() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) { - GRN_TS_OP_GREATER_VECTOR(text) -} -#undef GRN_TS_OP_GREATER_VECTOR - -/* grn_ts_op_greater_equal_int() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs >= rhs; -} - -/* grn_ts_op_greater_equal_float() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_float(grn_ts_float lhs, grn_ts_float rhs) { - return lhs >= rhs; -} - -/* grn_ts_op_greater_equal_time() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_time(grn_ts_time lhs, grn_ts_time rhs) { - return lhs >= rhs; -} - -/* grn_ts_op_greater_equal_text() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_text(grn_ts_text lhs, grn_ts_text rhs) { - size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; - int cmp = memcmp(lhs.ptr, rhs.ptr, min_size); - return cmp ? (cmp > 0) : (lhs.size >= rhs.size); -} - -#define GRN_TS_OP_GREATER_EQUAL_VECTOR(kind)\ - size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\ - for (i = 0; i < min_size; i++) {\ - if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - if (grn_ts_op_greater_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - return GRN_TRUE;\ - }\ - }\ - }\ - return lhs.size >= rhs.size; -/* grn_ts_op_greater_equal_int_vector() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_int_vector(grn_ts_int_vector lhs, - grn_ts_int_vector rhs) { - GRN_TS_OP_GREATER_EQUAL_VECTOR(int) -} - -/* grn_ts_op_greater_equal_float_vector() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_float_vector(grn_ts_float_vector lhs, - grn_ts_float_vector rhs) { - GRN_TS_OP_GREATER_EQUAL_VECTOR(float) -} - -/* grn_ts_op_greater_equal_time_vector() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_time_vector(grn_ts_time_vector lhs, - grn_ts_time_vector rhs) { - GRN_TS_OP_GREATER_EQUAL_VECTOR(time) -} - -/* grn_ts_op_greater_equal_text_vector() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_text_vector(grn_ts_text_vector lhs, - grn_ts_text_vector rhs) { - GRN_TS_OP_GREATER_EQUAL_VECTOR(text) -} -#undef GRN_TS_OP_GREATER_EQUAL_VECTOR - -/* grn_ts_op_shift_arithmetic_left() returns lhs << rhs. */ -inline static grn_ts_int -grn_ts_op_shift_arithmetic_left(grn_ts_int lhs, grn_ts_int rhs) { - return lhs << rhs; -} - -/* grn_ts_op_shift_arithmetic_right() returns lhs << rhs. */ -inline static grn_ts_int -grn_ts_op_shift_arithmetic_right(grn_ts_int lhs, grn_ts_int rhs) { - return lhs >> rhs; -} - -/* grn_ts_op_shift_logical_left() returns lhs << rhs. */ -inline static grn_ts_int -grn_ts_op_shift_logical_left(grn_ts_int lhs, grn_ts_int rhs) { - return lhs << rhs; -} - -/* grn_ts_op_shift_logical_right() returns lhs << rhs. */ -inline static grn_ts_int -grn_ts_op_shift_logical_right(grn_ts_int lhs, grn_ts_int rhs) { - return (uint64_t)lhs >> rhs; -} - -/* grn_ts_op_plus_int() returns lhs + rhs. */ -inline static grn_ts_int -grn_ts_op_plus_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs + rhs; -} - -/* grn_ts_op_plus_float() returns lhs + rhs. */ -inline static grn_ts_float -grn_ts_op_plus_float(grn_ts_float lhs, grn_ts_float rhs) { - return lhs + rhs; -} - -/* grn_ts_op_plus_time_int() returns lhs + rhs (Time + Int = Time). */ -inline static grn_ts_time -grn_ts_op_plus_time_int(grn_ts_time lhs, grn_ts_int rhs) { - return lhs + (rhs * 1000000); -} - -/* grn_ts_op_plus_time_float() returns lhs + rhs (Time + Float = Time). */ -inline static grn_ts_time -grn_ts_op_plus_time_float(grn_ts_time lhs, grn_ts_float rhs) { - return lhs + (grn_ts_int)(rhs * 1000000.0); -} - -/* grn_ts_op_minus_int() returns lhs - rhs. */ -inline static grn_ts_int -grn_ts_op_minus_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs - rhs; -} - -/* grn_ts_op_minus_float() returns lhs - rhs. */ -inline static grn_ts_float -grn_ts_op_minus_float(grn_ts_float lhs, grn_ts_float rhs) { - return lhs - rhs; -} - -/* grn_ts_op_minus_time_time() returns lhs - rhs (Time - Time = Float). */ -inline static grn_ts_float -grn_ts_op_minus_time_time(grn_ts_time lhs, grn_ts_time rhs) { - return (lhs - rhs) * 0.000001; -} - -/* grn_ts_op_minus_time_int() returns lhs - rhs (Time - Int = Time). */ -inline static grn_ts_time -grn_ts_op_minus_time_int(grn_ts_time lhs, grn_ts_int rhs) { - return lhs - (rhs * 1000000); -} - -/* grn_ts_op_minus_time_float() returns lhs - rhs (Time - Float = Time). */ -inline static grn_ts_time -grn_ts_op_minus_time_float(grn_ts_time lhs, grn_ts_float rhs) { - return lhs - (grn_ts_int)(rhs * 1000000.0); -} - -/* grn_ts_op_multiplication_int() returns lhs * rhs. */ -inline static grn_ts_int -grn_ts_op_multiplication_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs * rhs; -} - -/* grn_ts_op_multiplication_float() returns lhs * rhs. */ -inline static grn_ts_float -grn_ts_op_multiplication_float(grn_ts_float lhs, grn_ts_float rhs) { - return lhs * rhs; -} - -/* - * grn_ts_op_division_int() returns lhs / rhs. - * - * This function causes a critical error in the following cases: - * - rhs == 0 - * - (lhs == INT64_MIN) && (rhs == -1) - */ -inline static grn_ts_int -grn_ts_op_division_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs / rhs; -} - -/* grn_ts_op_division_float() returns lhs / rhs. */ -inline static grn_ts_float -grn_ts_op_division_float(grn_ts_float lhs, grn_ts_float rhs) { - return lhs / rhs; -} - -/* - * grn_ts_op_modulus_int() returns lhs % rhs. - * - * This function causes a critical error in the following cases: - * - rhs == 0 - * - (lhs == INT64_MIN) && (rhs == -1) - */ -inline static grn_ts_int -grn_ts_op_modulus_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs % rhs; -} - -/* grn_ts_op_modulus_float() returns lhs % rhs. */ -inline static grn_ts_float -grn_ts_op_modulus_float(grn_ts_float lhs, grn_ts_float rhs) { - return fmod(lhs, rhs); -} - -/*------------------------------------------------------------- - * Groonga objects. - */ - -/* grn_ts_obj_increment_ref_count() increments an object reference count. */ -static grn_rc -grn_ts_obj_increment_ref_count(grn_ctx *ctx, grn_obj *obj) { - grn_id id = grn_obj_id(ctx, obj); - grn_obj *obj_clone = grn_ctx_at(ctx, id); - if (!obj_clone) { - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", id); - } - if (obj_clone != obj) { - grn_obj_unlink(ctx, obj_clone); - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "wrong object: %p != %p", - obj, obj_clone); - } - return GRN_SUCCESS; -} - /* grn_ts_obj_is_table() returns whether or not an object is a table. */ static grn_ts_bool grn_ts_obj_is_table(grn_ctx *ctx, grn_obj *obj) { return grn_obj_is_table(ctx, obj); } -/* grn_ts_obj_is_column() returns whether or not an object is a column. */ -static grn_ts_bool -grn_ts_obj_is_column(grn_ctx *ctx, grn_obj *obj) { - switch (obj->header.type) { - case GRN_COLUMN_FIX_SIZE: - case GRN_COLUMN_VAR_SIZE: { - return GRN_TRUE; - } - /* GRN_COLUMN_INDEX is not supported. */ - default: { - return GRN_FALSE; - } - } -} - -/* - * grn_ts_ja_get_value() gets a value from ja and writes it to buf. Note the a - * value is appended to the end of buf. - */ -static grn_rc -grn_ts_ja_get_value(grn_ctx *ctx, grn_ja *ja, grn_ts_id id, - grn_ts_buf *buf, size_t *value_size) { - grn_rc rc; - uint32_t size; - grn_io_win iw; - char *ptr = (char *)grn_ja_ref(ctx, ja, id, &iw, &size); - if (!ptr) { - if (value_size) { - *value_size = 0; - } - return GRN_SUCCESS; - } - rc = grn_ts_buf_write(ctx, buf, ptr, size); - grn_ja_unref(ctx, &iw); - if (rc != GRN_SUCCESS) { - return rc; - } - if (value_size) { - *value_size = size; - } - return GRN_SUCCESS; -} - -#define GRN_TS_TABLE_GET_KEY(type)\ - uint32_t key_size;\ - const void *key_ptr = _grn_ ## type ## _key(ctx, type, id, &key_size);\ - if (!key_ptr) {\ - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "_grn_" #type "_key failed: %u", id);\ - }\ -/* grn_ts_hash_get_bool_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_bool_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_bool *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const grn_ts_bool *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_int8_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_int8_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const int8_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_int16_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_int16_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const int16_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_int32_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_int32_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const int32_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_int64_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_int64_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const int64_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_uint8_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_uint8_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const uint8_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_uint16_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_uint16_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const uint16_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_uint32_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_uint32_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const uint32_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_uint64_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_uint64_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = (grn_ts_int)*(const uint64_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_float_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_float_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_float *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const grn_ts_float *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_time_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_time_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_time *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const grn_ts_time *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_geo_point_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_geo_point_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_geo_point *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const grn_ts_geo_point *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_text_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_text_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_text *key) { - GRN_TS_TABLE_GET_KEY(hash) - key->ptr = key_ptr; - key->size = key_size; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_ref_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_ref_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_ref *key) { - GRN_TS_TABLE_GET_KEY(hash) - key->id = *(const grn_ts_id *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_bool_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_bool_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_bool *key) { - GRN_TS_TABLE_GET_KEY(pat) - *key = *(const grn_ts_bool *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_int8_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_int8_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - int8_t tmp; - GRN_TS_TABLE_GET_KEY(pat) - grn_ntohi(&tmp, key_ptr, sizeof(tmp)); - *key = tmp; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_int16_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_int16_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - int16_t tmp; - GRN_TS_TABLE_GET_KEY(pat) - grn_ntohi(&tmp, key_ptr, sizeof(tmp)); - *key = tmp; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_int32_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_int32_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - int32_t tmp; - GRN_TS_TABLE_GET_KEY(pat) - grn_ntohi(&tmp, key_ptr, sizeof(tmp)); - *key = tmp; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_int64_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_int64_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(pat) - grn_ntohi(key, key_ptr, sizeof(grn_ts_int)); - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_uint8_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_uint8_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(pat) - *key = *(const uint8_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_uint16_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_uint16_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - uint16_t tmp; - GRN_TS_TABLE_GET_KEY(pat) - grn_ntoh(&tmp, key_ptr, sizeof(tmp)); - *key = tmp; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_uint32_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_uint32_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - uint32_t tmp; - GRN_TS_TABLE_GET_KEY(pat) - grn_ntoh(&tmp, key_ptr, sizeof(tmp)); - *key = tmp; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_uint64_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_uint64_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(pat) - grn_ntoh(key, key_ptr, sizeof(grn_ts_int)); - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_float_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_float_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_float *key) { - int64_t tmp; - GRN_TS_TABLE_GET_KEY(pat) - grn_ntoh(&tmp, key_ptr, sizeof(tmp)); - tmp ^= (((tmp ^ ((int64_t)1 << 63)) >> 63) | ((int64_t)1 << 63)); - *(int64_t *)key = tmp; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_time_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_time_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_time *key) { - GRN_TS_TABLE_GET_KEY(pat) - grn_ntohi(key, key_ptr, sizeof(grn_ts_time)); - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_geo_point_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_geo_point_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_geo_point *key) { - GRN_TS_TABLE_GET_KEY(pat) - grn_ntog(key, key_ptr, sizeof(grn_ts_geo_point)); - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_text_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_text_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_text *key) { - GRN_TS_TABLE_GET_KEY(pat) - key->ptr = key_ptr; - key->size = key_size; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_ref_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_ref_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_ref *key) { - GRN_TS_TABLE_GET_KEY(pat) - grn_ntoh(&key->id, key_ptr, sizeof(key->id)); - return GRN_SUCCESS; -} - -/* grn_ts_dat_get_text_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_dat_get_text_key(grn_ctx *ctx, grn_dat *dat, grn_ts_id id, - grn_ts_text *key) { - GRN_TS_TABLE_GET_KEY(dat) - key->ptr = key_ptr; - key->size = key_size; - return GRN_SUCCESS; -} -#undef GRN_TS_TABLE_GET_KEY - -/* grn_ts_table_has_key() returns whether or not a table has _key. */ -static grn_ts_bool -grn_ts_table_has_key(grn_ctx *ctx, grn_obj *table) { - switch (table->header.type) { - case GRN_TABLE_HASH_KEY: - case GRN_TABLE_PAT_KEY: - case GRN_TABLE_DAT_KEY: { - return GRN_TRUE; - } - default: { - return GRN_FALSE; - } - } -} - -/* grn_ts_table_has_value() returns whether or not a table has _value. */ -static grn_ts_bool -grn_ts_table_has_value(grn_ctx *ctx, grn_obj *table) { - return DB_OBJ(table)->range != GRN_DB_VOID; -} - -/* - * grn_ts_table_get_value() gets a reference to a value (_value). On failure, - * this function returns NULL. - */ -static const void * -grn_ts_table_get_value(grn_ctx *ctx, grn_obj *table, grn_ts_id id) { - switch (table->header.type) { - case GRN_TABLE_HASH_KEY: { - uint32_t size; - return grn_hash_get_value_(ctx, (grn_hash *)table, id, &size); - } - case GRN_TABLE_PAT_KEY: { - uint32_t size; - return grn_pat_get_value_(ctx, (grn_pat *)table, id, &size); - } - /* GRN_TABLE_DAT_KEY does not support _value. */ - case GRN_TABLE_NO_KEY: { - return _grn_array_get_value(ctx, (grn_array *)table, id); - } - default: { - return NULL; - } - } -} - -/*------------------------------------------------------------- - * grn_ts_expr_id_node. - */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS -} grn_ts_expr_id_node; - -/* grn_ts_expr_id_node_init() initializes a node. */ -static void -grn_ts_expr_id_node_init(grn_ctx *ctx, grn_ts_expr_id_node *node) { - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_ID_NODE; - node->data_kind = GRN_TS_INT; - node->data_type = GRN_DB_UINT32; -} - -/* grn_ts_expr_id_node_fin() finalizes a node. */ -static void -grn_ts_expr_id_node_fin(grn_ctx *ctx, grn_ts_expr_id_node *node) { - /* Nothing to do. */ -} - -/* grn_ts_expr_id_node_open() creates a node associated with IDs (_id). */ -static grn_rc -grn_ts_expr_id_node_open(grn_ctx *ctx, grn_ts_expr_node **node) { - grn_ts_expr_id_node *new_node = GRN_MALLOCN(grn_ts_expr_id_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_id_node)); - } - grn_ts_expr_id_node_init(ctx, new_node); - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_id_node_close() destroys a node. */ -static void -grn_ts_expr_id_node_close(grn_ctx *ctx, grn_ts_expr_id_node *node) { - grn_ts_expr_id_node_fin(ctx, node); - GRN_FREE(node); -} - -/* grn_ts_expr_id_node_evaluate() outputs IDs. */ -static grn_rc -grn_ts_expr_id_node_evaluate(grn_ctx *ctx, grn_ts_expr_id_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - size_t i; - grn_ts_int *out_ptr = (grn_ts_int *)out; - for (i = 0; i < n_in; i++) { - out_ptr[i] = (grn_ts_int)in[i].id; - } - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_score_node. - */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS -} grn_ts_expr_score_node; - -/* grn_ts_expr_score_node_init() initializes a node. */ -static void -grn_ts_expr_score_node_init(grn_ctx *ctx, grn_ts_expr_score_node *node) { - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_SCORE_NODE; - node->data_kind = GRN_TS_FLOAT; - node->data_type = GRN_DB_FLOAT; -} - -/* grn_ts_expr_score_node_fin() finalizes a node. */ -static void -grn_ts_expr_score_node_fin(grn_ctx *ctx, grn_ts_expr_score_node *node) { - /* Nothing to do. */ -} - -/* - * grn_ts_expr_score_node_open() creates a node associated with scores - * (_score). - */ -static grn_rc -grn_ts_expr_score_node_open(grn_ctx *ctx, grn_ts_expr_node **node) { - grn_ts_expr_score_node *new_node = GRN_MALLOCN(grn_ts_expr_score_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_score_node)); - } - grn_ts_expr_score_node_init(ctx, new_node); - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_score_node_close() destroys a node. */ -static void -grn_ts_expr_score_node_close(grn_ctx *ctx, grn_ts_expr_score_node *node) { - grn_ts_expr_score_node_fin(ctx, node); - GRN_FREE(node); -} - -/* grn_ts_expr_score_node_evaluate() outputs scores. */ -static grn_rc -grn_ts_expr_score_node_evaluate(grn_ctx *ctx, grn_ts_expr_score_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i; - grn_ts_float *out_ptr = (grn_ts_float *)out; - for (i = 0; i < n_in; i++) { - out_ptr[i] = (grn_ts_float)in[i].score; - } - return GRN_SUCCESS; -} - -/* grn_ts_expr_score_node_adjust() does nothing. */ -static grn_rc -grn_ts_expr_score_node_adjust(grn_ctx *ctx, grn_ts_expr_score_node *node, - grn_ts_record *io, size_t n_io) { - /* Nothing to do. */ - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_key_node. - */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS - grn_obj *table; - grn_ts_buf buf; -} grn_ts_expr_key_node; - -/* grn_ts_expr_key_node_init() initializes a node. */ -static void -grn_ts_expr_key_node_init(grn_ctx *ctx, grn_ts_expr_key_node *node) { - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_KEY_NODE; - node->table = NULL; - grn_ts_buf_init(ctx, &node->buf); -} - -/* grn_ts_expr_key_node_fin() finalizes a node. */ -static void -grn_ts_expr_key_node_fin(grn_ctx *ctx, grn_ts_expr_key_node *node) { - grn_ts_buf_fin(ctx, &node->buf); - if (node->table) { - grn_obj_unlink(ctx, node->table); - } -} - -/* grn_ts_expr_key_node_open() creates a node associated with keys (_key). */ -static grn_rc -grn_ts_expr_key_node_open(grn_ctx *ctx, grn_obj *table, - grn_ts_expr_node **node) { - grn_rc rc; - grn_ts_expr_key_node *new_node; - if (!grn_ts_table_has_key(ctx, table)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "the table has no _key"); - } - new_node = GRN_MALLOCN(grn_ts_expr_key_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_key_node)); - } - grn_ts_expr_key_node_init(ctx, new_node); - rc = grn_ts_obj_increment_ref_count(ctx, table); - if (rc != GRN_SUCCESS) { - grn_ts_expr_key_node_fin(ctx, new_node); - GRN_FREE(new_node); - return rc; - } - new_node->data_kind = grn_ts_data_type_to_kind(table->header.domain); - new_node->data_type = table->header.domain; - new_node->table = table; - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_key_node_close() destroys a node. */ -static void -grn_ts_expr_key_node_close(grn_ctx *ctx, grn_ts_expr_key_node *node) { - grn_ts_expr_key_node_fin(ctx, node); - GRN_FREE(node); -} - -#define GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(table, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - for (i = 0; i < n_in; i++) {\ - rc = grn_ts_ ## table ## _get_ ## kind ## _key(ctx, table, in[i].id,\ - &out_ptr[i]);\ - if (rc != GRN_SUCCESS) {\ - out_ptr[i] = grn_ts_ ## kind ## _zero();\ - }\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(table, TYPE, type)\ - case GRN_DB_ ## TYPE: {\ - grn_ts_int *out_ptr = (grn_ts_int *)out;\ - for (i = 0; i < n_in; i++) {\ - rc = grn_ts_ ## table ## _get_ ## type ## _key(ctx, table, in[i].id,\ - &out_ptr[i]);\ - if (rc != GRN_SUCCESS) {\ - out_ptr[i] = grn_ts_int_zero();\ - }\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(table)\ - case GRN_TS_TEXT: {\ - char *buf_ptr;\ - grn_ts_text *out_ptr = (grn_ts_text *)out;\ - node->buf.pos = 0;\ - for (i = 0; i < n_in; i++) {\ - grn_ts_text key;\ - rc = grn_ts_ ## table ## _get_text_key(ctx, table, in[i].id, &key);\ - if (rc != GRN_SUCCESS) {\ - key = grn_ts_text_zero();\ - }\ - rc = grn_ts_buf_write(ctx, &node->buf, key.ptr, key.size);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - out_ptr[i].size = key.size;\ - }\ - buf_ptr = (char *)node->buf.ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i].ptr = buf_ptr;\ - buf_ptr += out_ptr[i].size;\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE(table)\ - case GRN_TS_REF: {\ - grn_ts_ref *out_ptr = (grn_ts_ref *)out;\ - for (i = 0; i < n_in; i++) {\ - rc = grn_ts_ ## table ## _get_ref_key(ctx, table, in[i].id,\ - &out_ptr[i]);\ - if (rc != GRN_SUCCESS) {\ - out_ptr[i] = grn_ts_ref_zero();\ - }\ - out_ptr[i].score = in[i].score;\ - }\ - return GRN_SUCCESS;\ - } -/* grn_ts_expr_key_node_evaluate() outputs keys. */ -static grn_rc -grn_ts_expr_key_node_evaluate(grn_ctx *ctx, grn_ts_expr_key_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i; - grn_rc rc; - switch (node->table->header.type) { - case GRN_TABLE_HASH_KEY: { - grn_hash *hash = (grn_hash *)node->table; - switch (node->data_kind) { - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, BOOL, bool) - case GRN_TS_INT: { - switch (node->data_type) { - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT8, int8) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT16, int16) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT32, int32) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT64, int64) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT8, uint8) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT16, uint16) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT32, uint32) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT64, uint64) - } - } - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, FLOAT, float) - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, TIME, time) - GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(hash) - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, GEO_POINT, geo_point) - GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE(hash) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } - } - case GRN_TABLE_PAT_KEY: { - grn_pat *pat = (grn_pat *)node->table; - switch (node->data_kind) { - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, BOOL, bool) - case GRN_TS_INT: { - switch (node->data_type) { - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT8, int8) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT16, int16) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT32, int32) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT64, int64) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT8, uint8) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT16, uint16) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT32, uint32) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT64, uint64) - } - } - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, FLOAT, float) - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, TIME, time) - GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(pat) - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, GEO_POINT, geo_point) - GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE(pat) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } - } - case GRN_TABLE_DAT_KEY: { - grn_dat *dat = (grn_dat *)node->table; - switch (node->data_kind) { - GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(dat) - /* GRN_TABLE_DAT_KEY supports only Text. */ - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } - } - /* GRN_TABLE_NO_KEY doesn't support _key. */ - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid table type: %d", - node->table->header.type); - } - } -} -#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE -#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE -#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE -#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE - -/* grn_ts_expr_key_node_filter() filters records. */ -static grn_rc -grn_ts_expr_key_node_filter(grn_ctx *ctx, grn_ts_expr_key_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, count; - grn_ts_bool key; - switch (node->table->header.type) { - case GRN_TABLE_HASH_KEY: { - grn_hash *hash = (grn_hash *)node->table; - for (i = 0, count = 0; i < n_in; i++) { - grn_rc rc = grn_ts_hash_get_bool_key(ctx, hash, in[i].id, &key); - if (rc != GRN_SUCCESS) { - key = grn_ts_bool_zero(); - } - if (key) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; - } - case GRN_TABLE_PAT_KEY: { - grn_pat *pat = (grn_pat *)node->table; - for (i = 0, count = 0; i < n_in; i++) { - grn_rc rc = grn_ts_pat_get_bool_key(ctx, pat, in[i].id, &key); - if (rc != GRN_SUCCESS) { - key = grn_ts_bool_zero(); - } - if (key) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; - } - /* GRN_TABLE_DAT_KEY and GRN_TABLE_NO_KEY don't support a Bool key. */ - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid table type: %d", - node->table->header.type); - } - } -} - -/* grn_ts_expr_key_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_key_node_adjust(grn_ctx *ctx, grn_ts_expr_key_node *node, - grn_ts_record *io, size_t n_io) { - size_t i; - grn_ts_float key; - switch (node->table->header.type) { - case GRN_TABLE_HASH_KEY: { - grn_hash *hash = (grn_hash *)node->table; - for (i = 0; i < n_io; i++) { - grn_rc rc = grn_ts_hash_get_float_key(ctx, hash, io[i].id, &key); - if (rc != GRN_SUCCESS) { - key = grn_ts_float_zero(); - } - io[i].score = (grn_ts_score)key; - } - return GRN_SUCCESS; - } - case GRN_TABLE_PAT_KEY: { - grn_pat *pat = (grn_pat *)node->table; - for (i = 0; i < n_io; i++) { - grn_rc rc = grn_ts_pat_get_float_key(ctx, pat, io[i].id, &key); - if (rc != GRN_SUCCESS) { - key = grn_ts_float_zero(); - } - io[i].score = (grn_ts_score)key; - } - return GRN_SUCCESS; - } - /* GRN_TABLE_DAT_KEY and GRN_TABLE_NO_KEY don't support a Float key. */ - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid table type: %d", - node->table->header.type); - } - } -} - -/*------------------------------------------------------------- - * grn_ts_expr_value_node. - */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS - grn_obj *table; -} grn_ts_expr_value_node; - -/* grn_ts_expr_value_node_init() initializes a node. */ -static void -grn_ts_expr_value_node_init(grn_ctx *ctx, grn_ts_expr_value_node *node) { - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_VALUE_NODE; - node->table = NULL; -} - -/* grn_ts_expr_value_node_fin() finalizes a node. */ -static void -grn_ts_expr_value_node_fin(grn_ctx *ctx, grn_ts_expr_value_node *node) { - if (node->table) { - grn_obj_unlink(ctx, node->table); - } -} - -/* - * grn_ts_expr_value_node_open() creates a node associated with values - * (_value). - */ -static grn_rc -grn_ts_expr_value_node_open(grn_ctx *ctx, grn_obj *table, - grn_ts_expr_node **node) { - grn_rc rc; - grn_ts_expr_value_node *new_node; - if (!grn_ts_table_has_value(ctx, table)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table has no _value"); - } - new_node = GRN_MALLOCN(grn_ts_expr_value_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_value_node)); - } - grn_ts_expr_value_node_init(ctx, new_node); - rc = grn_ts_obj_increment_ref_count(ctx, table); - if (rc != GRN_SUCCESS) { - GRN_FREE(new_node); - return rc; - } - new_node->data_kind = grn_ts_data_type_to_kind(DB_OBJ(table)->range); - new_node->data_type = DB_OBJ(table)->range; - new_node->table = table; - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_value_node_close() destroys a node. */ -static void -grn_ts_expr_value_node_close(grn_ctx *ctx, grn_ts_expr_value_node *node) { - grn_ts_expr_value_node_fin(ctx, node); - GRN_FREE(node); -} - -#define GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - size_t i;\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - for (i = 0; i < n_in; i++) {\ - const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id);\ - if (ptr) {\ - out_ptr[i] = *(const grn_ts_ ## kind *)ptr;\ - } else {\ - out_ptr[i] = grn_ts_ ## kind ## _zero();\ - }\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(TYPE, type)\ - case GRN_DB_ ## TYPE: {\ - size_t i;\ - grn_ts_int *out_ptr = (grn_ts_int *)out;\ - for (i = 0; i < n_in; i++) {\ - const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id);\ - if (ptr) {\ - out_ptr[i] = (grn_ts_int)*(const type ## _t *)ptr;\ - } else {\ - out_ptr[i] = grn_ts_int_zero();\ - }\ - }\ - return GRN_SUCCESS;\ - } -/* grn_ts_expr_value_node_evaluate() outputs values. */ -static grn_rc -grn_ts_expr_value_node_evaluate(grn_ctx *ctx, grn_ts_expr_value_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->data_kind) { - GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(BOOL, bool) - case GRN_TS_INT: { - switch (node->data_type) { - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT8, int8) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT16, int16) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT32, int32) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT64, int64) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT8, uint8) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT16, uint16) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT32, uint32) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT64, uint64) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d", - node->data_type); - } - } - } - GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(FLOAT, float) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(TIME, time) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(GEO_POINT, geo_point) - case GRN_TS_REF: { - size_t i; - grn_ts_ref *out_ptr = (grn_ts_ref *)out; - for (i = 0; i < n_in; i++) { - const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id); - if (ptr) { - out_ptr[i].id = *(const grn_ts_id *)ptr; - out_ptr[i].score = in[i].score; - } else { - out_ptr[i] = grn_ts_ref_zero(); - } - } - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE -#undef GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE - -/* grn_ts_expr_value_node_filter() filters records. */ -static grn_rc -grn_ts_expr_value_node_filter(grn_ctx *ctx, grn_ts_expr_value_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, count = 0; - for (i = 0; i < n_in; i++) { - const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id); - if (ptr && *(const grn_ts_bool *)ptr) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; -} - -/* grn_ts_expr_value_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_value_node_adjust(grn_ctx *ctx, grn_ts_expr_value_node *node, - grn_ts_record *io, size_t n_io) { - size_t i; - for (i = 0; i < n_io; i++) { - const void *ptr = grn_ts_table_get_value(ctx, node->table, io[i].id); - if (ptr) { - io[i].score = (grn_ts_score)*(const grn_ts_float *)ptr; - } - } - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_const_node. - */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS - grn_ts_any content; - grn_ts_buf text_buf; - grn_ts_buf vector_buf; -} grn_ts_expr_const_node; - -/* grn_ts_expr_const_node_init() initializes a node. */ -static void -grn_ts_expr_const_node_init(grn_ctx *ctx, grn_ts_expr_const_node *node) { - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_CONST_NODE; - grn_ts_buf_init(ctx, &node->text_buf); - grn_ts_buf_init(ctx, &node->vector_buf); -} - -/* grn_ts_expr_const_node_fin() finalizes a node. */ -static void -grn_ts_expr_const_node_fin(grn_ctx *ctx, grn_ts_expr_const_node *node) { - grn_ts_buf_fin(ctx, &node->vector_buf); - grn_ts_buf_fin(ctx, &node->text_buf); -} - -#define GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - node->content.as_ ## kind = *(const grn_ts_ ## kind *)value;\ - return GRN_SUCCESS;\ - } -/* grn_ts_expr_const_node_set_scalar() sets a scalar value. */ -static grn_rc -grn_ts_expr_const_node_set_scalar(grn_ctx *ctx, grn_ts_expr_const_node *node, - const void *value) { - switch (node->data_kind) { - GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(BOOL, bool) - GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(INT, int) - GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(FLOAT, float) - GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(TIME, time) - case GRN_TS_TEXT: { - grn_ts_text text_value = *(const grn_ts_text *)value; - grn_rc rc = grn_ts_buf_write(ctx, &node->text_buf, - text_value.ptr, text_value.size); - if (rc != GRN_SUCCESS) { - return rc; - } - node->content.as_text.ptr = (const char *)node->text_buf.ptr; - node->content.as_text.size = text_value.size; - return GRN_SUCCESS; - } - GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(GEO_POINT, geo_point) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE - -#define GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(KIND, kind)\ - case GRN_TS_ ## KIND ## _VECTOR: {\ - grn_rc rc;\ - size_t n_bytes;\ - const grn_ts_ ## kind *buf_ptr;\ - grn_ts_ ## kind ## _vector vector;\ - vector = *(const grn_ts_ ## kind ## _vector *)value;\ - n_bytes = sizeof(grn_ts_ ## kind) * vector.size;\ - rc = grn_ts_buf_write(ctx, &node->vector_buf, vector.ptr, n_bytes);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - buf_ptr = (const grn_ts_ ## kind *)node->vector_buf.ptr;\ - node->content.as_ ## kind ## _vector.ptr = buf_ptr;\ - node->content.as_ ## kind ## _vector.size = vector.size;\ - return GRN_SUCCESS;\ - } -/* grn_ts_expr_const_node_set_vector() sets a vector value. */ -static grn_rc -grn_ts_expr_const_node_set_vector(grn_ctx *ctx, grn_ts_expr_const_node *node, - const void *value) { - switch (node->data_kind) { - GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(BOOL, bool) - GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(INT, int) - GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(FLOAT, float) - GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(TIME, time) - case GRN_TS_TEXT_VECTOR: { - grn_rc rc; - size_t i, n_bytes, offset, total_size; - grn_ts_text_vector vector = *(const grn_ts_text_vector *)value; - grn_ts_text *vector_buf; - char *text_buf; - n_bytes = sizeof(grn_ts_text) * vector.size; - rc = grn_ts_buf_resize(ctx, &node->vector_buf, n_bytes); - if (rc != GRN_SUCCESS) { - return rc; - } - vector_buf = (grn_ts_text *)node->vector_buf.ptr; - total_size = 0; - for (i = 0; i < vector.size; i++) { - total_size += vector.ptr[i].size; - } - rc = grn_ts_buf_resize(ctx, &node->text_buf, total_size); - if (rc != GRN_SUCCESS) { - return rc; - } - text_buf = (char *)node->text_buf.ptr; - offset = 0; - for (i = 0; i < vector.size; i++) { - grn_memcpy(text_buf + offset, vector.ptr[i].ptr, vector.ptr[i].size); - vector_buf[i].ptr = text_buf + offset; - vector_buf[i].size = vector.ptr[i].size; - offset += vector.ptr[i].size; - } - node->content.as_text_vector.ptr = vector_buf; - node->content.as_text_vector.size = vector.size; - return GRN_SUCCESS; - } - GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(GEO_POINT, geo_point) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE - -/* grn_ts_expr_const_node_open() creates a node associated with a const. */ -static grn_rc -grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind kind, - const void *value, grn_ts_expr_node **node) { - grn_rc rc; - grn_ts_expr_const_node *new_node = GRN_MALLOCN(grn_ts_expr_const_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - 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) { - 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); - } - if (rc != GRN_SUCCESS) { - grn_ts_expr_const_node_fin(ctx, new_node); - GRN_FREE(new_node); - return rc; - } - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_const_node_close() destroys a node. */ -static void -grn_ts_expr_const_node_close(grn_ctx *ctx, grn_ts_expr_const_node *node) { - grn_ts_expr_const_node_fin(ctx, node); - GRN_FREE(node); -} - -#define GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - size_t i;\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = node->content.as_ ## kind;\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(KIND, kind)\ - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(KIND ## _VECTOR, kind ## _vector) -/* grn_ts_expr_const_node_evaluate() outputs the stored const. */ -static grn_rc -grn_ts_expr_const_node_evaluate(grn_ctx *ctx, grn_ts_expr_const_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->data_kind) { - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(BOOL, bool) - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(INT, int) - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(FLOAT, float) - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(TIME, time) - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(TEXT, text) - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(GEO_POINT, geo_point) - GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(BOOL, bool) - GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(INT, int) - GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(FLOAT, float) - GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(TIME, time) - GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(TEXT, text) - GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(GEO_POINT, geo_point) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE -#undef GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE - -/* grn_ts_expr_const_node_filter() filters records. */ -static grn_rc -grn_ts_expr_const_node_filter(grn_ctx *ctx, grn_ts_expr_const_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - if (node->content.as_bool) { - /* All the records pass through the filter. */ - if (in != out) { - size_t i; - for (i = 0; i < n_in; i++) { - out[i] = in[i]; - } - } - *n_out = n_in; - } else { - /* All the records are discarded. */ - *n_out = 0; - } - return GRN_SUCCESS; -} - -/* grn_ts_expr_const_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_const_node_adjust(grn_ctx *ctx, grn_ts_expr_const_node *node, - grn_ts_record *io, size_t n_io) { - size_t i; - grn_ts_score score = (grn_ts_score)node->content.as_float; - for (i = 0; i < n_io; i++) { - io[i].score = score; - } - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_column_node. - */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS - grn_obj *column; - grn_ts_buf buf; - grn_ts_buf body_buf; -} grn_ts_expr_column_node; - -/* grn_ts_expr_column_node_init() initializes a node. */ -static void -grn_ts_expr_column_node_init(grn_ctx *ctx, grn_ts_expr_column_node *node) { - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_COLUMN_NODE; - node->column = NULL; - grn_ts_buf_init(ctx, &node->buf); - grn_ts_buf_init(ctx, &node->body_buf); -} - -/* grn_ts_expr_column_node_fin() finalizes a node. */ -static void -grn_ts_expr_column_node_fin(grn_ctx *ctx, grn_ts_expr_column_node *node) { - grn_ts_buf_fin(ctx, &node->body_buf); - grn_ts_buf_fin(ctx, &node->buf); - if (node->column) { - grn_obj_unlink(ctx, node->column); - } -} - -#define GRN_TS_EXPR_COLUMN_NODE_OPEN_CASE(TYPE)\ - case GRN_DB_ ## TYPE: {\ - GRN_ ## TYPE ## _INIT(&new_node->buf, GRN_OBJ_VECTOR);\ - break;\ - } -/* grn_ts_expr_column_node_open() creates a node associated with a column. */ -static grn_rc -grn_ts_expr_column_node_open(grn_ctx *ctx, grn_obj *column, - grn_ts_expr_node **node) { - grn_rc rc; - grn_ts_expr_column_node *new_node = GRN_MALLOCN(grn_ts_expr_column_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_column_node)); - } - grn_ts_expr_column_node_init(ctx, new_node); - new_node->data_kind = grn_ts_data_type_to_kind(DB_OBJ(column)->range); - if (column->header.type == GRN_COLUMN_VAR_SIZE) { - grn_obj_flags type = column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK; - if (type == GRN_OBJ_COLUMN_VECTOR) { - new_node->data_kind |= GRN_TS_VECTOR_FLAG; - } - } - new_node->data_type = DB_OBJ(column)->range; - rc = grn_ts_obj_increment_ref_count(ctx, column); - if (rc != GRN_SUCCESS) { - grn_ts_expr_column_node_fin(ctx, new_node); - GRN_FREE(new_node); - return rc; - } - new_node->column = column; - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} -#undef GRN_TS_EXPR_COLUMN_NODE_OPEN_CASE - -/* grn_ts_expr_column_node_close() destroys a node. */ -static void -grn_ts_expr_column_node_close(grn_ctx *ctx, grn_ts_expr_column_node *node) { - grn_ts_expr_column_node_fin(ctx, node); - GRN_FREE(node); -} - -#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - size_t i;\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - grn_ra *ra = (grn_ra *)node->column;\ - grn_ra_cache cache;\ - GRN_RA_CACHE_INIT(ra, &cache);\ - for (i = 0; i < n_in; i++) {\ - grn_ts_ ## kind *ptr = NULL;\ - if (in[i].id) {\ - ptr = (grn_ts_ ## kind *)grn_ra_ref_cache(ctx, ra, in[i].id, &cache);\ - }\ - out_ptr[i] = ptr ? *ptr : grn_ts_ ## kind ## _zero();\ - }\ - GRN_RA_CACHE_FIN(ra, &cache);\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(TYPE, type)\ - case GRN_DB_ ## TYPE: {\ - size_t i;\ - grn_ts_int *out_ptr = (grn_ts_int *)out;\ - grn_ra *ra = (grn_ra *)node->column;\ - grn_ra_cache cache;\ - GRN_RA_CACHE_INIT(ra, &cache);\ - for (i = 0; i < n_in; i++) {\ - type ## _t *ptr = NULL;\ - if (in[i].id) {\ - ptr = (type ## _t *)grn_ra_ref_cache(ctx, ra, in[i].id, &cache);\ - }\ - out_ptr[i] = ptr ? (grn_ts_int)*ptr : grn_ts_int_zero();\ - }\ - GRN_RA_CACHE_FIN(ra, &cache);\ - return GRN_SUCCESS;\ - } -/* grn_ts_expr_column_node_evaluate_scalar() outputs scalar column values. */ -static grn_rc -grn_ts_expr_column_node_evaluate_scalar(grn_ctx *ctx, - grn_ts_expr_column_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->data_kind) { - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(BOOL, bool) - case GRN_TS_INT: { - switch (node->data_type) { - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT8, int8) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT16, int16) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT32, int32) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT64, int64) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT8, uint8) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT16, uint16) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT32, uint32) - /* The behavior is undefined if a value is greater than 2^63 - 1. */ - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT64, uint64) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d", - node->data_type); - } - } - } - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(FLOAT, float) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(TIME, time) - case GRN_TS_TEXT: { - size_t i, size; - char *buf_ptr; - grn_ja *ja = (grn_ja *)node->column; - grn_ts_text *out_ptr = (grn_ts_text *)out; - /* Read column values into node->buf and save the size of each value. */ - node->buf.pos = 0; - for (i = 0; i < n_in; i++) { - grn_rc rc = grn_ts_ja_get_value(ctx, ja, in[i].id, &node->buf, &size); - out_ptr[i].size = (rc == GRN_SUCCESS) ? size : 0; - } - buf_ptr = (char *)node->buf.ptr; - for (i = 0; i < n_in; i++) { - out_ptr[i].ptr = buf_ptr; - buf_ptr += out_ptr[i].size; - } - return GRN_SUCCESS; - } - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(GEO_POINT, geo_point) - case GRN_TS_REF: { - size_t i; - grn_ts_ref *out_ptr = (grn_ts_ref *)out; - grn_ra *ra = (grn_ra *)node->column; - grn_ra_cache cache; - GRN_RA_CACHE_INIT(ra, &cache); - for (i = 0; i < n_in; i++) { - grn_ts_id *ptr = NULL; - if (in[i].id) { - ptr = (grn_ts_id *)grn_ra_ref_cache(ctx, ra, in[i].id, &cache); - } - out_ptr[i].id = ptr ? *ptr : GRN_ID_NIL; - out_ptr[i].score = in[i].score; - } - GRN_RA_CACHE_FIN(ra, &cache); - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE -#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE - -/* - * grn_ts_expr_column_node_evaluate_text_vector() outputs text vector column - * values. - */ -static grn_rc -grn_ts_expr_column_node_evaluate_text_vector(grn_ctx *ctx, - grn_ts_expr_column_node *node, - const grn_ts_record *in, - size_t n_in, void *out) { - grn_rc rc; - char *buf_ptr; - size_t i, j, n_bytes, n_values, total_n_bytes = 0, total_n_values = 0; - grn_ts_text *text_ptr; - grn_ts_text_vector *out_ptr = (grn_ts_text_vector *)out; - /* Read encoded values into node->body_buf and get the size of each value. */ - node->body_buf.pos = 0; - for (i = 0; i < n_in; i++) { - char *ptr; - rc = grn_ts_ja_get_value(ctx, (grn_ja *)node->column, in[i].id, - &node->body_buf, &n_bytes); - if (rc == GRN_SUCCESS) { - ptr = (char *)node->body_buf.ptr + total_n_bytes; - GRN_B_DEC(n_values, ptr); - } else { - n_bytes = 0; - n_values = 0; - } - grn_memcpy(&out_ptr[i].ptr, &n_bytes, sizeof(n_bytes)); - out_ptr[i].size = n_values; - total_n_bytes += n_bytes; - total_n_values += n_values; - } - /* Resize node->buf. */ - n_bytes = sizeof(grn_ts_text) * total_n_values; - rc = grn_ts_buf_reserve(ctx, &node->buf, n_bytes); - if (rc != GRN_SUCCESS) { - return rc; - } - /* Decode values and compose the result. */ - buf_ptr = (char *)node->body_buf.ptr; - text_ptr = (grn_ts_text *)node->buf.ptr; - for (i = 0; i < n_in; i++) { - char *ptr = buf_ptr; - grn_memcpy(&n_bytes, &out_ptr[i].ptr, sizeof(n_bytes)); - buf_ptr += n_bytes; - GRN_B_DEC(n_values, ptr); - out_ptr[i].ptr = text_ptr; - for (j = 0; j < out_ptr[i].size; j++) { - GRN_B_DEC(text_ptr[j].size, ptr); - } - for (j = 0; j < out_ptr[i].size; j++) { - text_ptr[j].ptr = ptr; - ptr += text_ptr[j].size; - } - text_ptr += out_ptr[i].size; - } - return GRN_SUCCESS; -} - -/* - * grn_ts_expr_column_node_evaluate_ref_vector() outputs ref vector column - * values. - */ -static grn_rc -grn_ts_expr_column_node_evaluate_ref_vector(grn_ctx *ctx, - grn_ts_expr_column_node *node, - const grn_ts_record *in, - size_t n_in, void *out) { - grn_rc rc; - size_t i, j, n_bytes, offset = 0; - grn_ts_id *buf_ptr; - grn_ts_ref *ref_ptr; - grn_ts_ref_vector *out_ptr = (grn_ts_ref_vector *)out; - /* Read column values into node->body_buf and get the size of each value. */ - node->body_buf.pos = 0; - for (i = 0; i < n_in; i++) { - size_t size; - rc = grn_ts_ja_get_value(ctx, (grn_ja *)node->column, in[i].id, - &node->body_buf, &size); - if (rc == GRN_SUCCESS) { - out_ptr[i].size = size / sizeof(grn_ts_id); - offset += out_ptr[i].size; - } else { - out_ptr[i].size = 0; - } - } - /* Resize node->buf. */ - n_bytes = sizeof(grn_ts_ref) * offset; - rc = grn_ts_buf_reserve(ctx, &node->buf, n_bytes); - if (rc != GRN_SUCCESS) { - return rc; - } - /* Compose the result. */ - buf_ptr = (grn_ts_id *)node->body_buf.ptr; - ref_ptr = (grn_ts_ref *)node->buf.ptr; - for (i = 0; i < n_in; i++) { - out_ptr[i].ptr = ref_ptr; - for (j = 0; j < out_ptr[i].size; j++, buf_ptr++, ref_ptr++) { - ref_ptr->id = *buf_ptr; - ref_ptr->score = in[i].score; - } - } - return GRN_SUCCESS; -} - -#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(KIND, kind)\ - case GRN_TS_ ## KIND ## _VECTOR: {\ - size_t i;\ - grn_ts_ ## kind *buf_ptr;\ - grn_ts_ ## kind ## _vector *out_ptr = (grn_ts_ ## kind ## _vector *)out;\ - /* Read column values into node->buf and save the size of each value. */\ - node->buf.pos = 0;\ - for (i = 0; i < n_in; i++) {\ - size_t n_bytes;\ - grn_rc rc = grn_ts_ja_get_value(ctx, (grn_ja *)node->column, in[i].id,\ - &node->buf, &n_bytes);\ - if (rc == GRN_SUCCESS) {\ - out_ptr[i].size = n_bytes / sizeof(grn_ts_ ## kind);\ - } else {\ - out_ptr[i].size = 0;\ - }\ - }\ - buf_ptr = (grn_ts_ ## kind *)node->buf.ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i].ptr = buf_ptr;\ - buf_ptr += out_ptr[i].size;\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(TYPE, type)\ - case GRN_DB_ ## TYPE: {\ - size_t i, j;\ - grn_ts_int *buf_ptr;\ - grn_ts_int_vector *out_ptr = (grn_ts_int_vector *)out;\ - /* - * Read column values into body_buf and typecast the values to grn_ts_int. - * Then, store the grn_ts_int values into node->buf and save the size of - * each value. - */\ - node->buf.pos = 0;\ - for (i = 0; i < n_in; i++) {\ - grn_rc rc;\ - size_t n_bytes, new_n_bytes;\ - node->body_buf.pos = 0;\ - rc = grn_ts_ja_get_value(ctx, (grn_ja *)node->column, in[i].id,\ - &node->body_buf, &n_bytes);\ - if (rc == GRN_SUCCESS) {\ - out_ptr[i].size = n_bytes / sizeof(type ## _t);\ - } else {\ - out_ptr[i].size = 0;\ - }\ - new_n_bytes = node->buf.pos + (sizeof(grn_ts_int) * out_ptr[i].size);\ - rc = grn_ts_buf_reserve(ctx, &node->buf, new_n_bytes);\ - if (rc == GRN_SUCCESS) {\ - type ## _t *src_ptr = (type ## _t *)node->body_buf.ptr;\ - grn_ts_int *dest_ptr;\ - dest_ptr = (grn_ts_int *)((char *)node->buf.ptr + node->buf.pos);\ - for (j = 0; j < out_ptr[i].size; j++) {\ - dest_ptr[j] = (grn_ts_int)src_ptr[j];\ - }\ - node->buf.pos = new_n_bytes;\ - } else {\ - out_ptr[i].size = 0;\ - }\ - }\ - buf_ptr = (grn_ts_int *)node->buf.ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i].ptr = buf_ptr;\ - buf_ptr += out_ptr[i].size;\ - }\ - return GRN_SUCCESS;\ - } -/* grn_ts_expr_column_node_evaluate_vector() outputs vector column values. */ -static grn_rc -grn_ts_expr_column_node_evaluate_vector(grn_ctx *ctx, - grn_ts_expr_column_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->data_kind) { - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(BOOL, bool) - case GRN_TS_INT_VECTOR: { - switch (node->data_type) { - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT8, int8) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT16, int16) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT32, int32) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT64, int64) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT8, uint8) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT16, uint16) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT32, uint32) - /* The behavior is undefined if a value is greater than 2^63 - 1. */ - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT64, uint64) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d", - node->data_type); - } - } - } - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(FLOAT, float) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(TIME, time) - case GRN_TS_TEXT_VECTOR: { - return grn_ts_expr_column_node_evaluate_text_vector(ctx, node, in, n_in, - out); - } - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(GEO_POINT, geo_point) - case GRN_TS_REF_VECTOR: { - return grn_ts_expr_column_node_evaluate_ref_vector(ctx, node, in, n_in, - out); - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE -#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE - -/* grn_ts_expr_column_node_evaluate() outputs column values. */ -static grn_rc -grn_ts_expr_column_node_evaluate(grn_ctx *ctx, grn_ts_expr_column_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - if (node->data_kind & GRN_TS_VECTOR_FLAG) { - return grn_ts_expr_column_node_evaluate_vector(ctx, node, in, n_in, out); - } else { - return grn_ts_expr_column_node_evaluate_scalar(ctx, node, in, n_in, out); - } -} - -/* grn_ts_expr_column_node_filter() filters records. */ -static grn_rc -grn_ts_expr_column_node_filter(grn_ctx *ctx, grn_ts_expr_column_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, count = 0; - grn_ra *ra = (grn_ra *)node->column; - grn_ra_cache cache; - GRN_RA_CACHE_INIT(ra, &cache); - for (i = 0; i < n_in; i++) { - grn_ts_bool *ptr = NULL; - if (in[i].id) { - ptr = grn_ra_ref_cache(ctx, ra, in[i].id, &cache); - } - if (ptr && *ptr) { - out[count++] = in[i]; - } - } - GRN_RA_CACHE_FIN(ra, &cache); - *n_out = count; - return GRN_SUCCESS; -} - -/* grn_ts_expr_column_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_column_node_adjust(grn_ctx *ctx, grn_ts_expr_column_node *node, - grn_ts_record *io, size_t n_io) { - size_t i; - grn_ra *ra = (grn_ra *)node->column; - grn_ra_cache cache; - GRN_RA_CACHE_INIT(ra, &cache); - for (i = 0; i < n_io; i++) { - grn_ts_float *ptr = NULL; - if (io[i].id) { - ptr = grn_ra_ref_cache(ctx, ra, io[i].id, &cache); - } - if (ptr) { - io[i].score = (grn_ts_score)*ptr; - } - } - GRN_RA_CACHE_FIN(ra, &cache); - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_op_node. - */ - -enum { - GRN_TS_EXPR_OP_NODE_MAX_N_ARGS = 3, - GRN_TS_EXPR_OP_NODE_N_BUFS = 3 -}; - -/* Forward declarations. */ -static grn_rc grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node, - const grn_ts_record *in, size_t n_in, - void *out); -static grn_rc grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, - grn_ts_expr_node *node, - const grn_ts_record *in, - size_t n_in, - grn_ts_buf *out); -static grn_rc grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out); -static grn_rc grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node, - grn_ts_record *io, size_t n_io); - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS - grn_ts_op_type op_type; - grn_ts_expr_node *args[GRN_TS_EXPR_OP_NODE_MAX_N_ARGS]; - size_t n_args; - grn_ts_buf bufs[GRN_TS_EXPR_OP_NODE_N_BUFS]; -} grn_ts_expr_op_node; - -/* grn_ts_expr_op_node_init() initializes a node. */ -static void -grn_ts_expr_op_node_init(grn_ctx *ctx, grn_ts_expr_op_node *node) { - size_t i; - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_OP_NODE; - for (i = 0; i < GRN_TS_EXPR_OP_NODE_MAX_N_ARGS; i++) { - node->args[i] = NULL; - } - for (i = 0; i < GRN_TS_EXPR_OP_NODE_N_BUFS; i++) { - grn_ts_buf_init(ctx, &node->bufs[i]); - } -} - -/* grn_ts_expr_op_node_fin() finalizes a node. */ -static void -grn_ts_expr_op_node_fin(grn_ctx *ctx, grn_ts_expr_op_node *node) { - size_t i; - for (i = 0; i < GRN_TS_EXPR_OP_NODE_N_BUFS; i++) { - grn_ts_buf_fin(ctx, &node->bufs[i]); - } -} - -/* - * grn_ts_op_plus_check_args() checks arguments. Note that arguments are - * rearranged in some cases. - */ -static grn_rc -grn_ts_op_plus_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) { - switch (node->args[0]->data_kind) { - case GRN_TS_INT: { - switch (node->args[1]->data_kind) { - case GRN_TS_INT: { - /* Int + Int = Int. */ - node->data_kind = GRN_TS_INT; - node->data_type = GRN_DB_INT64; - return GRN_SUCCESS; - } - case GRN_TS_TIME: { - /* Int + Time = Time + Int = Time. */ - grn_ts_expr_node *tmp = node->args[0]; - node->args[0] = node->args[1]; - node->args[1] = tmp; - node->data_kind = GRN_TS_TIME; - node->data_type = GRN_DB_TIME; - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[1]->data_kind); - } - } - } - case GRN_TS_FLOAT: { - switch (node->args[1]->data_kind) { - case GRN_TS_FLOAT: { - /* Float + Float = Float. */ - node->data_kind = GRN_TS_FLOAT; - node->data_type = GRN_DB_FLOAT; - return GRN_SUCCESS; - } - case GRN_TS_TIME: { - /* Float + Time = Time + Float = Time. */ - grn_ts_expr_node *tmp = node->args[0]; - node->args[0] = node->args[1]; - node->args[1] = tmp; - node->data_kind = GRN_TS_TIME; - node->data_type = GRN_DB_TIME; - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[1]->data_kind); - } - } - } - case GRN_TS_TIME: { - switch (node->args[1]->data_kind) { - case GRN_TS_INT: - case GRN_TS_FLOAT: { - /* Time + Int or Float = Time. */ - node->data_kind = GRN_TS_TIME; - node->data_type = GRN_DB_TIME; - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[1]->data_kind); - } - } - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} - -/* grn_ts_op_minus_check_args() checks arguments. */ -static grn_rc -grn_ts_op_minus_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) { - switch (node->args[0]->data_kind) { - case GRN_TS_INT: { - if (node->args[1]->data_kind != GRN_TS_INT) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[1]->data_kind); - } - /* Int - Int = Int. */ - node->data_kind = GRN_TS_INT; - node->data_type = GRN_DB_INT64; - return GRN_SUCCESS; - } - case GRN_TS_FLOAT: { - if (node->args[1]->data_kind != GRN_TS_FLOAT) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[1]->data_kind); - } - /* Float - Float = Float. */ - node->data_kind = GRN_TS_FLOAT; - node->data_type = GRN_DB_FLOAT; - return GRN_SUCCESS; - } - case GRN_TS_TIME: { - switch (node->args[1]->data_kind) { - case GRN_TS_INT: - case GRN_TS_FLOAT: { - /* Time - Int or Float = Time. */ - node->data_kind = GRN_TS_TIME; - node->data_type = GRN_DB_TIME; - return GRN_SUCCESS; - } - case GRN_TS_TIME: { - /* Time - Time = Float. */ - node->data_kind = GRN_TS_FLOAT; - node->data_type = GRN_DB_FLOAT; - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[1]->data_kind); - } - } - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} - -/* - * grn_ts_expr_op_node_check_args() checks the combination of an operator and - * its arguments. - */ -static grn_rc -grn_ts_expr_op_node_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) { - switch (node->op_type) { - case GRN_TS_OP_LOGICAL_NOT: { - if (node->args[0]->data_kind != GRN_TS_BOOL) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - node->data_kind = GRN_TS_BOOL; - node->data_type = GRN_DB_BOOL; - return GRN_SUCCESS; - } - case GRN_TS_OP_BITWISE_NOT: { - switch (node->args[0]->data_kind) { - case GRN_TS_BOOL: - case GRN_TS_INT: { - node->data_kind = node->args[0]->data_kind; - node->data_type = grn_ts_data_kind_to_type(node->data_kind); - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } - } - case GRN_TS_OP_POSITIVE: - case GRN_TS_OP_NEGATIVE: { - if ((node->args[0]->data_kind != GRN_TS_INT) && - (node->args[0]->data_kind != GRN_TS_FLOAT)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - node->data_kind = node->args[0]->data_kind; - node->data_type = grn_ts_data_kind_to_type(node->data_kind); - return GRN_SUCCESS; - } - case GRN_TS_OP_LOGICAL_AND: - case GRN_TS_OP_LOGICAL_OR: - case GRN_TS_OP_LOGICAL_SUB: { - if ((node->args[0]->data_kind != GRN_TS_BOOL) || - (node->args[1]->data_kind != GRN_TS_BOOL)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d, %d", - node->args[0]->data_kind, node->args[1]->data_kind); - } - node->data_kind = GRN_TS_BOOL; - node->data_type = GRN_DB_BOOL; - return GRN_SUCCESS; - } - case GRN_TS_OP_BITWISE_AND: - case GRN_TS_OP_BITWISE_OR: - case GRN_TS_OP_BITWISE_XOR: { - if (node->args[0]->data_kind != node->args[1]->data_kind) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data kind conflict: %d != %d", - node->args[0]->data_kind, node->args[1]->data_kind); - } - switch (node->args[0]->data_kind) { - case GRN_TS_BOOL: - case GRN_TS_INT: { - node->data_kind = node->args[0]->data_kind; - node->data_type = grn_ts_data_kind_to_type(node->data_kind); - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } - node->data_kind = GRN_TS_BOOL; - node->data_type = GRN_DB_BOOL; - return GRN_SUCCESS; - } - case GRN_TS_OP_EQUAL: - case GRN_TS_OP_NOT_EQUAL: { - grn_ts_data_kind scalar_data_kind; - if (node->args[0]->data_kind != node->args[1]->data_kind) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data kind conflict: %d != %d", - node->args[0]->data_kind, node->args[1]->data_kind); - } - scalar_data_kind = node->args[0]->data_kind & ~GRN_TS_VECTOR_FLAG; - if (((scalar_data_kind == GRN_TS_REF) || - (scalar_data_kind == GRN_TS_GEO_POINT)) && - (node->args[0]->data_type != node->args[1]->data_type)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data type conflict: %d != %d", - node->args[0]->data_type, node->args[1]->data_type); - } - node->data_kind = GRN_TS_BOOL; - node->data_type = GRN_DB_BOOL; - return GRN_SUCCESS; - } - case GRN_TS_OP_LESS: - case GRN_TS_OP_LESS_EQUAL: - case GRN_TS_OP_GREATER: - case GRN_TS_OP_GREATER_EQUAL: { - if (node->args[0]->data_kind != node->args[1]->data_kind) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data kind conflict: %d != %d", - node->args[0]->data_kind, node->args[1]->data_kind); - } - switch (node->args[0]->data_kind) { - case GRN_TS_INT: - case GRN_TS_FLOAT: - case GRN_TS_TIME: - case GRN_TS_TEXT: - case GRN_TS_INT_VECTOR: - case GRN_TS_FLOAT_VECTOR: - case GRN_TS_TIME_VECTOR: - case GRN_TS_TEXT_VECTOR: { - node->data_kind = GRN_TS_BOOL; - node->data_type = GRN_DB_BOOL; - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } - case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: - case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: - case GRN_TS_OP_SHIFT_LOGICAL_LEFT: - case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: { - if ((node->args[0]->data_kind != GRN_TS_INT) || - (node->args[1]->data_kind != GRN_TS_INT)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d, %d", - node->args[0]->data_kind, - node->args[1]->data_kind); - } - node->data_kind = GRN_TS_INT; - node->data_type = GRN_DB_INT64; - return GRN_SUCCESS; - } - case GRN_TS_OP_PLUS: { - return grn_ts_op_plus_check_args(ctx, node); - } - case GRN_TS_OP_MINUS: { - return grn_ts_op_minus_check_args(ctx, node); - } - case GRN_TS_OP_MULTIPLICATION: - case GRN_TS_OP_DIVISION: - case GRN_TS_OP_MODULUS: { - if (node->args[0]->data_kind != node->args[1]->data_kind) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, - "data kind conflict: %d != %d", - node->args[0]->data_kind, - node->args[1]->data_kind); - } - switch (node->args[0]->data_kind) { - case GRN_TS_INT: - case GRN_TS_FLOAT: { - node->data_kind = node->args[0]->data_kind; - node->data_type = grn_ts_data_kind_to_type(node->data_kind); - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } - } - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid operator: %d", - node->op_type); - } - } -} - -/* grn_ts_expr_op_node_open() creates a node associated with an operator. */ -static grn_rc -grn_ts_expr_op_node_open(grn_ctx *ctx, grn_ts_op_type op_type, - grn_ts_expr_node **args, size_t n_args, - grn_ts_expr_node **node) { - size_t i; - grn_rc rc; - grn_ts_expr_op_node *new_node = GRN_MALLOCN(grn_ts_expr_op_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_op_node)); - } - grn_ts_expr_op_node_init(ctx, new_node); - new_node->op_type = op_type; - for (i = 0; i < n_args; i++) { - new_node->args[i] = args[i]; - } - new_node->n_args = n_args; - - /* Check arguments. */ - rc = grn_ts_expr_op_node_check_args(ctx, new_node); - if (rc == GRN_SUCCESS) { - if (new_node->data_kind == GRN_TS_VOID) { - GRN_TS_ERR(GRN_OBJECT_CORRUPT, "invalid data kind: %d", GRN_TS_VOID); - rc = ctx->rc; - } else if (new_node->data_type == GRN_DB_VOID) { - GRN_TS_ERR(GRN_OBJECT_CORRUPT, "invalid data type: %d", GRN_DB_VOID); - rc = ctx->rc; - } - } - if (rc != GRN_SUCCESS) { - grn_ts_expr_op_node_fin(ctx, new_node); - GRN_FREE(new_node); - return rc; - } - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_op_node_close() destroys a node. */ -static void -grn_ts_expr_op_node_close(grn_ctx *ctx, grn_ts_expr_op_node *node) { - grn_ts_expr_op_node_fin(ctx, node); - GRN_FREE(node); -} - -/* grn_ts_op_logical_not_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_logical_not_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i; - grn_ts_bool *out_ptr = (grn_ts_bool *)out; - grn_rc rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out); - if (rc != GRN_SUCCESS) { - return rc; - } - for (i = 0; i < n_in; i++) { - out_ptr[i] = grn_ts_op_logical_not_bool(out_ptr[i]); - } - return GRN_SUCCESS; -} - -/* grn_ts_op_bitwise_not_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_bitwise_not_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i; - grn_rc rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out); - if (rc != GRN_SUCCESS) { - return rc; - } - switch (node->data_kind) { - case GRN_TS_BOOL: { - grn_ts_bool *out_ptr = (grn_ts_bool *)out; - for (i = 0; i < n_in; i++) { - out_ptr[i] = grn_ts_op_bitwise_not_bool(out_ptr[i]); - } - return GRN_SUCCESS; - } - case GRN_TS_INT: { - grn_ts_int *out_ptr = (grn_ts_int *)out; - for (i = 0; i < n_in; i++) { - out_ptr[i] = grn_ts_op_bitwise_not_int(out_ptr[i]); - } - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} - -#define GRN_TS_OP_SIGN_EVALUATE_CASE(type, KIND, kind) \ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(out_ptr[i]);\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_OP_SIGN_EVALUATE(type) \ - size_t i;\ - grn_rc rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - switch (node->data_kind) {\ - GRN_TS_OP_SIGN_EVALUATE_CASE(type, INT, int)\ - GRN_TS_OP_SIGN_EVALUATE_CASE(type, FLOAT, float)\ - default: {\ - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ - node->data_kind);\ - }\ - } -/* grn_ts_op_positive_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_positive_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - GRN_TS_OP_SIGN_EVALUATE(positive) -} - -/* grn_ts_op_negative_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_negative_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - GRN_TS_OP_SIGN_EVALUATE(negative) -} -#undef GRN_TS_OP_SIGN_EVALUATE -#undef GRN_TS_OP_SIGN_EVALUATE_CASE - -/* grn_ts_op_logical_and_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_logical_and_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i, j, count; - grn_rc rc; - grn_ts_bool *buf_ptrs[2], *out_ptr = (grn_ts_bool *)out; - grn_ts_buf *tmp_in_buf = &node->bufs[2]; - grn_ts_record *tmp_in; - - /* Evaluate the 1st argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr; - - /* Create a list of true records. */ - rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp_in = (grn_ts_record *)tmp_in_buf->ptr; - count = 0; - for (i = 0; i < n_in; i++) { - if (buf_ptrs[0][i]) { - tmp_in[count++] = in[i]; - } - } - - /* Evaluate the 2nd argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count, - &node->bufs[1]); - buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr; - - /* Merge the results. */ - count = 0; - for (i = 0, j = 0; i < n_in; i++) { - out_ptr[count++] = buf_ptrs[0][i] && buf_ptrs[1][j++]; - } - return GRN_SUCCESS; -} - -/* grn_ts_op_logical_or_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_logical_or_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i, j, count; - grn_rc rc; - grn_ts_bool *buf_ptrs[2], *out_ptr = (grn_ts_bool *)out; - grn_ts_buf *tmp_in_buf = &node->bufs[2]; - grn_ts_record *tmp_in; - - /* Evaluate the 1st argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr; - - /* Create a list of false records. */ - rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp_in = (grn_ts_record *)tmp_in_buf->ptr; - count = 0; - for (i = 0; i < n_in; i++) { - if (!buf_ptrs[0][i]) { - tmp_in[count++] = in[i]; - } - } - - /* Evaluate the 2nd argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count, - &node->bufs[1]); - buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr; - - /* Merge the results. */ - count = 0; - for (i = 0, j = 0; i < n_in; i++) { - out_ptr[count++] = buf_ptrs[0][i] || buf_ptrs[1][j++]; - } - return GRN_SUCCESS; -} - -/* grn_ts_op_logical_sub_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_logical_sub_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i, j, count; - grn_rc rc; - grn_ts_bool *buf_ptrs[2], *out_ptr = (grn_ts_bool *)out; - grn_ts_buf *tmp_in_buf = &node->bufs[2]; - grn_ts_record *tmp_in; - - /* Evaluate the 1st argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr; - - /* Create a list of true records. */ - rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp_in = (grn_ts_record *)tmp_in_buf->ptr; - count = 0; - for (i = 0; i < n_in; i++) { - if (buf_ptrs[0][i]) { - tmp_in[count++] = in[i]; - } - } - - /* Evaluate the 2nd argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count, - &node->bufs[1]); - buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr; - - /* Merge the results. */ - count = 0; - for (i = 0, j = 0; i < n_in; i++) { - out_ptr[count++] = buf_ptrs[0][i] && - grn_ts_op_logical_not_bool(buf_ptrs[1][j++]); - } - return GRN_SUCCESS; -} - -#define GRN_TS_OP_BITWISE_EVALUATE_CASE(type, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - /* - * Use the output buffer to put evaluation results of the 1st argument, - * because the data kind is same. - */\ - size_t i;\ - grn_rc rc;\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc == GRN_SUCCESS) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ - in, n_in, &node->bufs[0]);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_ ## kind *buf_ptr = (grn_ts_ ## kind *)node->bufs[0].ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_bitwise_ ## type ## _ ## kind(out_ptr[i],\ - buf_ptr[i]);\ - }\ - }\ - }\ - return rc;\ - } -/* grn_ts_op_bitwise_and_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_bitwise_and_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->args[0]->data_kind) { - GRN_TS_OP_BITWISE_EVALUATE_CASE(and, BOOL, bool) - GRN_TS_OP_BITWISE_EVALUATE_CASE(and, INT, int) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} - -/* grn_ts_op_bitwise_or_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_bitwise_or_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->args[0]->data_kind) { - GRN_TS_OP_BITWISE_EVALUATE_CASE(or, BOOL, bool) - GRN_TS_OP_BITWISE_EVALUATE_CASE(or, INT, int) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} - -/* grn_ts_op_bitwise_xor_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_bitwise_xor_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->args[0]->data_kind) { - GRN_TS_OP_BITWISE_EVALUATE_CASE(xor, BOOL, bool) - GRN_TS_OP_BITWISE_EVALUATE_CASE(xor, INT, int) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} -#undef GRN_TS_OP_BITWISE_EVALUATE_CASE - -#define GRN_TS_OP_CHK_EVALUATE_CASE(type, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *buf_ptrs[] = {\ - (grn_ts_ ## kind *)node->bufs[0].ptr,\ - (grn_ts_ ## kind *)node->bufs[1].ptr\ - };\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i],\ - buf_ptrs[1][i]);\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, KIND, kind)\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, KIND ## _VECTOR, kind ## _vector) -#define GRN_TS_OP_CHK_EVALUATE(type)\ - size_t i;\ - grn_rc rc;\ - grn_ts_bool *out_ptr = (grn_ts_bool *)out;\ - if (node->args[0]->data_kind == GRN_TS_BOOL) {\ - /* - * Use the output buffer to put evaluation results of the 1st argument, - * because the data kind is same. - */\ - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_buf *buf = &node->bufs[0];\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ - in, n_in, buf);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_bool *buf_ptr = (grn_ts_bool *)buf->ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_ ## type ## _bool(out_ptr[i], buf_ptr[i]);\ - }\ - }\ - }\ - return rc;\ - }\ - for (i = 0; i < 2; i++) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ - &node->bufs[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - switch (node->args[0]->data_kind) {\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, INT, int)\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, FLOAT, float)\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, TIME, time)\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, TEXT, text)\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, GEO_POINT, geo_point)\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, REF, ref)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, BOOL, bool)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, INT, int)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, FLOAT, float)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, TIME, time)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, TEXT, text)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, GEO_POINT, geo_point)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, REF, ref)\ - default: {\ - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ - node->args[0]->data_kind);\ - }\ - } -/* grn_ts_op_equal_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - GRN_TS_OP_CHK_EVALUATE(equal) -} - -/* grn_ts_op_not_equal_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_not_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - GRN_TS_OP_CHK_EVALUATE(not_equal) -} -#undef GRN_TS_OP_CHK_EVALUATE -#undef GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE -#undef GRN_TS_OP_CHK_EVALUATE_CASE - -#define GRN_TS_OP_CMP_EVALUATE_CASE(type, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *buf_ptrs[] = {\ - (grn_ts_ ## kind *)node->bufs[0].ptr,\ - (grn_ts_ ## kind *)node->bufs[1].ptr\ - };\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i],\ - buf_ptrs[1][i]);\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, KIND, kind)\ - GRN_TS_OP_CMP_EVALUATE_CASE(type, KIND ## _VECTOR, kind ## _vector) -#define GRN_TS_OP_CMP_EVALUATE(type)\ - size_t i;\ - grn_rc rc;\ - grn_ts_bool *out_ptr = (grn_ts_bool *)out;\ - for (i = 0; i < 2; i++) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ - &node->bufs[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - switch (node->args[0]->data_kind) {\ - GRN_TS_OP_CMP_EVALUATE_CASE(type, INT, int)\ - GRN_TS_OP_CMP_EVALUATE_CASE(type, FLOAT, float)\ - GRN_TS_OP_CMP_EVALUATE_CASE(type, TIME, time)\ - GRN_TS_OP_CMP_EVALUATE_CASE(type, TEXT, text)\ - GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, INT, int)\ - GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, FLOAT, float)\ - GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, TIME, time)\ - GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, TEXT, text)\ - default: {\ - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ - node->args[0]->data_kind);\ - }\ - } -/* grn_ts_op_less_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_less_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - GRN_TS_OP_CMP_EVALUATE(less) -} - -/* grn_ts_op_less_equal_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_less_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - GRN_TS_OP_CMP_EVALUATE(less_equal) -} - -/* grn_ts_op_greater_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_greater_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - GRN_TS_OP_CMP_EVALUATE(greater) -} - -/* grn_ts_op_greater_equal_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_greater_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - GRN_TS_OP_CMP_EVALUATE(greater_equal) -} -#undef GRN_TS_OP_CMP_EVALUATE -#undef GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE -#undef GRN_TS_OP_CMP_EVALUATE_CASE - -#define GRN_TS_OP_SHIFT_EVALUATE(type)\ - size_t i;\ - grn_rc rc;\ - grn_ts_int *out_ptr = (grn_ts_int *)out;\ - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc == GRN_SUCCESS) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ - in, n_in, &node->bufs[0]);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_int *buf_ptr = (grn_ts_int *)node->bufs[0].ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_shift_ ## type(out_ptr[i], buf_ptr[i]);\ - }\ - }\ - }\ - return rc; -/* grn_ts_op_shift_arithmetic_left_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_shift_arithmetic_left_evaluate(grn_ctx *ctx, - grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - GRN_TS_OP_SHIFT_EVALUATE(arithmetic_left) -} - -/* grn_ts_op_shift_arithmetic_right_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_shift_arithmetic_right_evaluate(grn_ctx *ctx, - grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - GRN_TS_OP_SHIFT_EVALUATE(arithmetic_right) -} - -/* grn_ts_op_shift_logical_left_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_shift_logical_left_evaluate(grn_ctx *ctx, - grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - GRN_TS_OP_SHIFT_EVALUATE(logical_left) -} - -/* grn_ts_op_shift_logical_right_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_shift_logical_right_evaluate(grn_ctx *ctx, - grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - GRN_TS_OP_SHIFT_EVALUATE(logical_right) -} -#undef GRN_TS_OP_SHIFT_EVALUATE - -#define GRN_TS_OP_ARITH_EVALUATE_CASE(type, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - /* - * Use the output buffer to put evaluation results of the 1st argument, - * because the data kind is same. - */\ - size_t i;\ - grn_rc rc;\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc == GRN_SUCCESS) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ - in, n_in, &node->bufs[0]);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_ ## kind *buf_ptr = (grn_ts_ ## kind *)node->bufs[0].ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(out_ptr[i],\ - buf_ptr[i]);\ - }\ - }\ - }\ - return rc;\ - } -#define GRN_TS_OP_ARITH_EVALUATE_TIME_CASE(type, KIND, lhs, rhs)\ - case GRN_TS_ ## KIND: {\ - /* - * Use the output buffer to put evaluation results of the 1st argument, - * because the data kind is same. - */\ - size_t i;\ - grn_rc rc;\ - grn_ts_ ## lhs *out_ptr = (grn_ts_ ## lhs *)out;\ - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc == GRN_SUCCESS) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ - in, n_in, &node->bufs[0]);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_ ## rhs *buf_ptr = (grn_ts_ ## rhs *)node->bufs[0].ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_ ## type ## _ ## lhs ## _ ## rhs(out_ptr[i],\ - buf_ptr[i]);\ - }\ - }\ - }\ - return rc;\ - } -/* grn_ts_op_plus_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_plus_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - switch (node->args[0]->data_kind) { - GRN_TS_OP_ARITH_EVALUATE_CASE(plus, INT, int) - GRN_TS_OP_ARITH_EVALUATE_CASE(plus, FLOAT, float) - case GRN_TS_TIME: { - switch (node->args[1]->data_kind) { - GRN_TS_OP_ARITH_EVALUATE_TIME_CASE(plus, INT, time, int) - GRN_TS_OP_ARITH_EVALUATE_TIME_CASE(plus, FLOAT, time, float) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "data kind conflict: %d, %d", - node->args[0]->data_kind, - node->args[1]->data_kind); - } - } - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} - -/* grn_ts_op_minus_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_minus_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - switch (node->args[0]->data_kind) { - GRN_TS_OP_ARITH_EVALUATE_CASE(minus, INT, int) - GRN_TS_OP_ARITH_EVALUATE_CASE(minus, FLOAT, float) - case GRN_TS_TIME: { - switch (node->args[1]->data_kind) { - GRN_TS_OP_ARITH_EVALUATE_TIME_CASE(minus, INT, time, int) - GRN_TS_OP_ARITH_EVALUATE_TIME_CASE(minus, FLOAT, time, float) - case GRN_TS_TIME: { - size_t i; - grn_rc rc; - grn_ts_float *out_ptr = (grn_ts_float *)out; - grn_ts_time *buf_ptrs[2]; - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], in, n_in, - &node->bufs[1]); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptrs[0] = (grn_ts_time *)node->bufs[0].ptr; - buf_ptrs[1] = (grn_ts_time *)node->bufs[1].ptr; - for (i = 0; i < n_in; i++) { - out_ptr[i] = grn_ts_op_minus_time_time(buf_ptrs[0][i], - buf_ptrs[1][i]); - } - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "data kind conflict: %d, %d", - node->args[0]->data_kind, - node->args[1]->data_kind); - } - } - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} -#undef GRN_TS_OP_ARITH_EVALUATE_TIME_CASE - -/* grn_ts_op_multiplication_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_multiplication_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->data_kind) { - GRN_TS_OP_ARITH_EVALUATE_CASE(multiplication, INT, int) - GRN_TS_OP_ARITH_EVALUATE_CASE(multiplication, FLOAT, float) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} - -/* grn_ts_op_division_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_division_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - switch (node->data_kind) { - case GRN_TS_INT: { - /* Specialized to detect a critical error. */ - size_t i; - grn_rc rc; - grn_ts_int *out_ptr = (grn_ts_int *)out; - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], - in, n_in, &node->bufs[0]); - if (rc == GRN_SUCCESS) { - grn_ts_int *buf_ptr = (grn_ts_int *)node->bufs[0].ptr; - for (i = 0; i < n_in; i++) { - if (!buf_ptr[i]) { - GRN_TS_ERR(GRN_INVALID_ARGUMENT, "integer division by zero"); - rc = ctx->rc; - break; - } else if ((out_ptr[i] == INT64_MIN) && (buf_ptr[i] == -1)) { - GRN_TS_ERR(GRN_INVALID_ARGUMENT, "integer division overflow"); - rc = ctx->rc; - break; - } - out_ptr[i] = grn_ts_op_division_int(out_ptr[i], buf_ptr[i]); - } - } - } - return rc; - } - GRN_TS_OP_ARITH_EVALUATE_CASE(division, FLOAT, float) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} - -/* grn_ts_op_modulus_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_modulus_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - switch (node->data_kind) { - case GRN_TS_INT: { - /* Specialized to detect a critical error. */ - size_t i; - grn_rc rc; - grn_ts_int *out_ptr = (grn_ts_int *)out; - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], - in, n_in, &node->bufs[0]); - if (rc == GRN_SUCCESS) { - grn_ts_int *buf_ptr = (grn_ts_int *)node->bufs[0].ptr; - for (i = 0; i < n_in; i++) { - if (!buf_ptr[i]) { - GRN_TS_ERR(GRN_INVALID_ARGUMENT, "integer division by zero"); - rc = ctx->rc; - break; - } else if ((out_ptr[i] == INT64_MIN) && (buf_ptr[i] == -1)) { - GRN_TS_ERR(GRN_INVALID_ARGUMENT, "integer division overflow"); - rc = ctx->rc; - break; - } - out_ptr[i] = grn_ts_op_modulus_int(out_ptr[i], buf_ptr[i]); - } - } - } - return rc; - } - GRN_TS_OP_ARITH_EVALUATE_CASE(modulus, FLOAT, float) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_OP_ARITH_EVALUATE_CASE - -/* grn_ts_expr_op_node_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_expr_op_node_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->op_type) { - case GRN_TS_OP_LOGICAL_NOT: { - return grn_ts_op_logical_not_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_BITWISE_NOT: { - return grn_ts_op_bitwise_not_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_POSITIVE: { - return grn_ts_op_positive_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_NEGATIVE: { - return grn_ts_op_negative_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_LOGICAL_AND: { - return grn_ts_op_logical_and_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_LOGICAL_OR: { - return grn_ts_op_logical_or_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_LOGICAL_SUB: { - return grn_ts_op_logical_sub_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_BITWISE_AND: { - return grn_ts_op_bitwise_and_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_BITWISE_OR: { - return grn_ts_op_bitwise_or_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_BITWISE_XOR: { - return grn_ts_op_bitwise_xor_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_EQUAL: { - return grn_ts_op_equal_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_NOT_EQUAL: { - return grn_ts_op_not_equal_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_LESS: { - return grn_ts_op_less_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_LESS_EQUAL: { - return grn_ts_op_less_equal_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_GREATER: { - return grn_ts_op_greater_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_GREATER_EQUAL: { - return grn_ts_op_greater_equal_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: { - return grn_ts_op_shift_arithmetic_left_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: { - return grn_ts_op_shift_arithmetic_right_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_SHIFT_LOGICAL_LEFT: { - return grn_ts_op_shift_logical_left_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: { - return grn_ts_op_shift_logical_right_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_PLUS: { - return grn_ts_op_plus_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_MINUS: { - return grn_ts_op_minus_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_MULTIPLICATION: { - return grn_ts_op_multiplication_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_DIVISION: { - return grn_ts_op_division_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_MODULUS: { - return grn_ts_op_modulus_evaluate(ctx, node, in, n_in, out); - } - // TODO: Add operators. - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "operator not supported: %d", node->op_type); - } - } -} - -/* grn_ts_op_logical_not_filter() filters records. */ -static grn_rc -grn_ts_op_logical_not_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, count; - grn_rc rc; - grn_ts_bool *buf_ptr; - rc = grn_ts_buf_reserve(ctx, &node->bufs[0], sizeof(grn_ts_bool) * n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptr = (grn_ts_bool *)node->bufs[0].ptr; - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, buf_ptr); - if (rc != GRN_SUCCESS) { - return rc; - } - for (i = 0, count = 0; i < n_in; i++) { - if (grn_ts_op_logical_not_bool(buf_ptr[i])) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; -} - -/* grn_ts_op_bitwise_not_filter() filters records. */ -static grn_rc -grn_ts_op_bitwise_not_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, count; - grn_rc rc; - grn_ts_bool *buf_ptr; - rc = grn_ts_buf_reserve(ctx, &node->bufs[0], sizeof(grn_ts_bool) * n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptr = (grn_ts_bool *)node->bufs[0].ptr; - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, buf_ptr); - if (rc != GRN_SUCCESS) { - return rc; - } - for (i = 0, count = 0; i < n_in; i++) { - if (grn_ts_op_bitwise_not_bool(buf_ptr[i])) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; -} - -/* grn_ts_op_logical_and_filter() filters records. */ -static grn_rc -grn_ts_op_logical_and_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - grn_rc rc = grn_ts_expr_node_filter(ctx, node->args[0], in, n_in, - out, n_out); - if (rc != GRN_SUCCESS) { - return rc; - } - return grn_ts_expr_node_filter(ctx, node->args[1], out, *n_out, out, n_out); -} - -/* grn_ts_op_logical_or_filter() filters records. */ -static grn_rc -grn_ts_op_logical_or_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, j, count; - grn_rc rc; - grn_ts_bool *buf_ptrs[2]; - grn_ts_buf *tmp_in_buf = &node->bufs[2]; - grn_ts_record *tmp_in; - - /* Evaluate the 1st argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr; - - /* Create a list of false records. */ - rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp_in = (grn_ts_record *)tmp_in_buf->ptr; - count = 0; - for (i = 0; i < n_in; i++) { - if (!buf_ptrs[0][i]) { - tmp_in[count++] = in[i]; - } - } - - /* Evaluate the 2nd argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count, - &node->bufs[1]); - buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr; - - /* Merge the results. */ - count = 0; - for (i = 0, j = 0; i < n_in; i++) { - if (buf_ptrs[0][i] || buf_ptrs[1][j++]) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; -} - -/* grn_ts_op_logical_sub_filter() filters records. */ -static grn_rc -grn_ts_op_logical_sub_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, n, count; - grn_ts_bool *buf_ptr; - grn_rc rc = grn_ts_expr_node_filter(ctx, node->args[0], in, n_in, out, &n); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], out, n, - &node->bufs[0]); - buf_ptr = (grn_ts_bool *)node->bufs[0].ptr; - for (i = 0, count = 0; i < n; i++) { - if (grn_ts_op_logical_not_bool(buf_ptr[i])) { - out[count++] = out[i]; - } - } - *n_out = count; - return GRN_SUCCESS; -} - -#define GRN_TS_OP_BITWISE_FILTER(type)\ - size_t i, count = 0;\ - grn_ts_bool *buf_ptrs[2];\ - for (i = 0; i < 2; i++) {\ - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ - &node->bufs[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - buf_ptrs[i] = (grn_ts_bool *)node->bufs[i].ptr;\ - }\ - for (i = 0; i < n_in; i++) {\ - if (grn_ts_op_bitwise_ ## type ## _bool(buf_ptrs[0][i], buf_ptrs[1][i])) {\ - out[count++] = in[i];\ - }\ - }\ - *n_out = count;\ - return GRN_SUCCESS;\ -/* grn_ts_op_bitwise_and_filter() filters records. */ -static grn_rc -grn_ts_op_bitwise_and_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_BITWISE_FILTER(and); -} - -/* grn_ts_op_bitwise_or_filter() filters records. */ -static grn_rc -grn_ts_op_bitwise_or_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_BITWISE_FILTER(or); -} - -/* grn_ts_op_bitwise_xor_filter() filters records. */ -static grn_rc -grn_ts_op_bitwise_xor_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_BITWISE_FILTER(xor); -} -#undef GRN_TS_OP_BITWISE_FILTER_CASE - -#define GRN_TS_OP_CHK_FILTER_CASE(type, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *buf_ptrs[] = {\ - (grn_ts_ ## kind *)node->bufs[0].ptr,\ - (grn_ts_ ## kind *)node->bufs[1].ptr\ - };\ - for (i = 0; i < n_in; i++) {\ - if (grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i], buf_ptrs[1][i])) {\ - out[count++] = in[i];\ - }\ - }\ - *n_out = count;\ - return GRN_SUCCESS;\ - } -#define GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, KIND, kind)\ - GRN_TS_OP_CHK_FILTER_CASE(type, KIND ## _VECTOR, kind ## _vector) -#define GRN_TS_OP_CHK_FILTER(type)\ - size_t i, count = 0;\ - for (i = 0; i < 2; i++) {\ - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ - &node->bufs[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - switch (node->args[0]->data_kind) {\ - GRN_TS_OP_CHK_FILTER_CASE(type, BOOL, bool)\ - GRN_TS_OP_CHK_FILTER_CASE(type, INT, int)\ - GRN_TS_OP_CHK_FILTER_CASE(type, FLOAT, float)\ - GRN_TS_OP_CHK_FILTER_CASE(type, TIME, time)\ - GRN_TS_OP_CHK_FILTER_CASE(type, TEXT, text)\ - GRN_TS_OP_CHK_FILTER_CASE(type, GEO_POINT, geo_point)\ - GRN_TS_OP_CHK_FILTER_CASE(type, REF, ref)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, BOOL, bool)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, INT, int)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, FLOAT, float)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, TIME, time)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, TEXT, text)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, GEO_POINT, geo_point)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, REF, ref)\ - default: {\ - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ - node->args[0]->data_kind);\ - }\ - } -/* grn_ts_op_equal_filter() filters records. */ -static grn_rc -grn_ts_op_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_CHK_FILTER(equal) -} - -/* grn_ts_op_not_equal_filter() filters records. */ -static grn_rc -grn_ts_op_not_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_CHK_FILTER(not_equal) -} -#undef GRN_TS_OP_CHK_FILTER -#undef GRN_TS_OP_CHK_FILTER_VECTOR_CASE -#undef GRN_TS_OP_CHK_FILTER_CASE - -#define GRN_TS_OP_CMP_FILTER_CASE(type, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *buf_ptrs[] = {\ - (grn_ts_ ## kind *)node->bufs[0].ptr,\ - (grn_ts_ ## kind *)node->bufs[1].ptr\ - };\ - for (i = 0; i < n_in; i++) {\ - if (grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i], buf_ptrs[1][i])) {\ - out[count++] = in[i];\ - }\ - }\ - *n_out = count;\ - return GRN_SUCCESS;\ - } -#define GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, KIND, kind)\ - GRN_TS_OP_CMP_FILTER_CASE(type, KIND ## _VECTOR, kind ## _vector) -#define GRN_TS_OP_CMP_FILTER(type)\ - size_t i, count = 0;\ - for (i = 0; i < 2; i++) {\ - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ - &node->bufs[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - switch (node->args[0]->data_kind) {\ - GRN_TS_OP_CMP_FILTER_CASE(type, INT, int)\ - GRN_TS_OP_CMP_FILTER_CASE(type, FLOAT, float)\ - GRN_TS_OP_CMP_FILTER_CASE(type, TIME, time)\ - GRN_TS_OP_CMP_FILTER_CASE(type, TEXT, text)\ - GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, INT, int)\ - GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, FLOAT, float)\ - GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, TIME, time)\ - GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, TEXT, text)\ - default: {\ - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ - node->args[0]->data_kind);\ - }\ - } -/* grn_ts_op_less_filter() filters records. */ -static grn_rc -grn_ts_op_less_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_CMP_FILTER(less) -} - -/* grn_ts_op_less_equal_filter() filters records. */ -static grn_rc -grn_ts_op_less_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_CMP_FILTER(less_equal) -} - -/* grn_ts_op_greater_filter() filters records. */ -static grn_rc -grn_ts_op_greater_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_CMP_FILTER(greater) -} - -/* grn_ts_op_greater_equal_filter() filters records. */ -static grn_rc -grn_ts_op_greater_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_CMP_FILTER(greater_equal) -} -#undef GRN_TS_OP_CMP_FILTER -#undef GRN_TS_OP_CMP_FILTER_VECTOR_CASE -#undef GRN_TS_OP_CMP_FILTER_CASE - -/* grn_ts_expr_op_node_filter() filters records. */ -static grn_rc -grn_ts_expr_op_node_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - switch (node->op_type) { - case GRN_TS_OP_LOGICAL_NOT: { - return grn_ts_op_logical_not_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_BITWISE_NOT: { - return grn_ts_op_bitwise_not_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_LOGICAL_AND: { - return grn_ts_op_logical_and_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_LOGICAL_OR: { - return grn_ts_op_logical_or_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_LOGICAL_SUB: { - return grn_ts_op_logical_sub_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_BITWISE_AND: { - return grn_ts_op_bitwise_and_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_BITWISE_OR: { - return grn_ts_op_bitwise_or_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_BITWISE_XOR: { - return grn_ts_op_bitwise_xor_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_EQUAL: { - return grn_ts_op_equal_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_NOT_EQUAL: { - return grn_ts_op_not_equal_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_LESS: { - return grn_ts_op_less_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_LESS_EQUAL: { - return grn_ts_op_less_equal_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_GREATER: { - return grn_ts_op_greater_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_GREATER_EQUAL: { - return grn_ts_op_greater_equal_filter(ctx, node, in, n_in, out, n_out); - } - // TODO: Add operators. - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "operator not supported: %d", node->op_type); - } - } -} - -#define GRN_TS_OP_SIGN_ADJUST(type)\ - size_t i, count = 0;\ - grn_ts_float *buf_ptr;\ - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], io, n_io,\ - &node->bufs[0]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - buf_ptr = (grn_ts_float *)node->bufs[0].ptr;\ - for (i = 0; i < n_io; i++) {\ - grn_ts_float result = grn_ts_op_ ## type ## _float(buf_ptr[i]);\ - io[count++].score = (grn_ts_score)result;\ - }\ - return GRN_SUCCESS; -/* grn_ts_op_positive_adjust() updates scores. */ -static grn_rc -grn_ts_op_positive_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_SIGN_ADJUST(positive) -} - -/* grn_ts_op_negative_adjust() updates scores. */ -static grn_rc -grn_ts_op_negative_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_SIGN_ADJUST(negative) -} -#undef GRN_TS_OP_SIGN_ADJUST - -#define GRN_TS_OP_ARITH_ADJUST(type)\ - size_t i, count = 0;\ - grn_ts_float *buf_ptrs[2];\ - for (i = 0; i < 2; i++) {\ - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], io, n_io,\ - &node->bufs[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - buf_ptrs[0] = (grn_ts_float *)node->bufs[0].ptr;\ - buf_ptrs[1] = (grn_ts_float *)node->bufs[1].ptr;\ - for (i = 0; i < n_io; i++) {\ - grn_ts_float result = grn_ts_op_ ## type ## _float(buf_ptrs[0][i],\ - buf_ptrs[1][i]);\ - io[count++].score = (grn_ts_score)result;\ - }\ - return GRN_SUCCESS; -/* grn_ts_op_plus_adjust() updates scores. */ -static grn_rc -grn_ts_op_plus_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_ARITH_ADJUST(plus) -} - -/* grn_ts_op_minus_adjust() updates scores. */ -static grn_rc -grn_ts_op_minus_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_ARITH_ADJUST(minus) -} - -/* grn_ts_op_multiplication_adjust() updates scores. */ -static grn_rc -grn_ts_op_multiplication_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_ARITH_ADJUST(multiplication) -} - -/* grn_ts_op_division_adjust() updates scores. */ -static grn_rc -grn_ts_op_division_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_ARITH_ADJUST(division) -} - -/* grn_ts_op_modulus_adjust() updates scores. */ -static grn_rc -grn_ts_op_modulus_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_ARITH_ADJUST(modulus) -} -#undef GRN_TS_OP_ARITH_ADJUST - -/* grn_ts_expr_op_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_op_node_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - switch (node->op_type) { - case GRN_TS_OP_POSITIVE: { - return grn_ts_op_positive_adjust(ctx, node, io, n_io); - } - case GRN_TS_OP_NEGATIVE: { - return grn_ts_op_negative_adjust(ctx, node, io, n_io); - } - case GRN_TS_OP_PLUS: { - return grn_ts_op_plus_adjust(ctx, node, io, n_io); - } - case GRN_TS_OP_MINUS: { - return grn_ts_op_minus_adjust(ctx, node, io, n_io); - } - case GRN_TS_OP_MULTIPLICATION: { - return grn_ts_op_multiplication_adjust(ctx, node, io, n_io); - } - case GRN_TS_OP_DIVISION: { - return grn_ts_op_division_adjust(ctx, node, io, n_io); - } - case GRN_TS_OP_MODULUS: { - return grn_ts_op_modulus_adjust(ctx, node, io, n_io); - } - // TODO: Add operators. - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "operator not supported: %d", node->op_type); - } - } -} - -/*------------------------------------------------------------- - * grn_ts_expr_bridge_node. - */ - -enum { GRN_TS_EXPR_BRIDGE_NODE_N_BUFS = 2 }; - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS - grn_ts_expr_node *src; - grn_ts_expr_node *dest; - grn_ts_buf bufs[GRN_TS_EXPR_BRIDGE_NODE_N_BUFS]; -} grn_ts_expr_bridge_node; - -/* grn_ts_expr_bridge_node_init() initializes a node. */ -static void -grn_ts_expr_bridge_node_init(grn_ctx *ctx, grn_ts_expr_bridge_node *node) { - size_t i; - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_BRIDGE_NODE; - node->src = NULL; - node->dest = NULL; - for (i = 0; i < GRN_TS_EXPR_BRIDGE_NODE_N_BUFS; i++) { - grn_ts_buf_init(ctx, &node->bufs[i]); - } -} - -/* grn_ts_expr_bridge_node_fin() finalizes a node. */ -static void -grn_ts_expr_bridge_node_fin(grn_ctx *ctx, grn_ts_expr_bridge_node *node) { - size_t i; - for (i = 0; i < GRN_TS_EXPR_BRIDGE_NODE_N_BUFS; i++) { - grn_ts_buf_fin(ctx, &node->bufs[i]); - } -} - -/* grn_ts_expr_bridge_node_open() creates a node associated with a bridge. */ -static grn_rc -grn_ts_expr_bridge_node_open(grn_ctx *ctx, grn_ts_expr_node *src, - grn_ts_expr_node *dest, grn_ts_expr_node **node) { - grn_ts_expr_bridge_node *new_node = GRN_MALLOCN(grn_ts_expr_bridge_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_bridge_node)); - } - grn_ts_expr_bridge_node_init(ctx, new_node); - new_node->data_kind = dest->data_kind; - new_node->data_type = dest->data_type; - new_node->src = src; - new_node->dest = dest; - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_bridge_node_close() destroys a node. */ -static void -grn_ts_expr_bridge_node_close(grn_ctx *ctx, grn_ts_expr_bridge_node *node) { - grn_ts_expr_bridge_node_fin(ctx, node); - GRN_FREE(node); -} - -/* grn_ts_expr_bridge_node_evaluate() evaluates a bridge. */ -static grn_rc -grn_ts_expr_bridge_node_evaluate(grn_ctx *ctx, grn_ts_expr_bridge_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - grn_ts_record *tmp; - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->src, in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp = (grn_ts_record *)node->bufs[0].ptr; - return grn_ts_expr_node_evaluate(ctx, node->dest, tmp, n_in, out); -} - -/* grn_ts_expr_bridge_node_filter() filters records. */ -static grn_rc -grn_ts_expr_bridge_node_filter(grn_ctx *ctx, grn_ts_expr_bridge_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, count; - grn_ts_bool *values; - grn_ts_record *tmp; - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->src, in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp = (grn_ts_record *)node->bufs[0].ptr; - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->dest, in, n_in, - &node->bufs[1]); - if (rc != GRN_SUCCESS) { - return rc; - } - values = (grn_ts_bool *)&node->bufs[1].ptr; - for (i = 0, count = 0; i < n_in; i++) { - if (values[i]) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; -} - -/* grn_ts_expr_bridge_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_bridge_node_adjust(grn_ctx *ctx, grn_ts_expr_bridge_node *node, - grn_ts_record *io, size_t n_io) { - size_t i; - grn_ts_record *tmp; - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->src, io, n_io, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp = (grn_ts_record *)node->bufs[0].ptr; - rc = grn_ts_expr_node_adjust(ctx, node->dest, tmp, n_io); - if (rc != GRN_SUCCESS) { - return rc; - } - for (i = 0; i < n_io; i++) { - io[i].score = tmp[i].score; - } - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_node. - */ - -#define GRN_TS_EXPR_NODE_CLOSE_CASE(TYPE, type)\ - case GRN_TS_EXPR_ ## TYPE ## _NODE: {\ - grn_ts_expr_ ## type ## _node *type ## _node;\ - type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ - grn_ts_expr_ ## type ## _node_close(ctx, type ## _node);\ - return;\ - } -/* grn_ts_expr_node_close() destroys a node. */ -static void -grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node) { - switch (node->type) { - GRN_TS_EXPR_NODE_CLOSE_CASE(ID, id) - GRN_TS_EXPR_NODE_CLOSE_CASE(SCORE, score) - GRN_TS_EXPR_NODE_CLOSE_CASE(KEY, key) - GRN_TS_EXPR_NODE_CLOSE_CASE(VALUE, value) - GRN_TS_EXPR_NODE_CLOSE_CASE(CONST, const) - GRN_TS_EXPR_NODE_CLOSE_CASE(COLUMN, column) - GRN_TS_EXPR_NODE_CLOSE_CASE(OP, op) - GRN_TS_EXPR_NODE_CLOSE_CASE(BRIDGE, bridge) - } -} -#undef GRN_TS_EXPR_NODE_CLOSE_CASE - -#define GRN_TS_EXPR_NODE_EVALUATE_CASE(TYPE, type)\ - case GRN_TS_EXPR_ ## TYPE ## _NODE: {\ - grn_ts_expr_ ## type ## _node *type ## _node;\ - type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ - return grn_ts_expr_ ## type ## _node_evaluate(ctx, type ## _node,\ - in, n_in, out);\ - } -/* grn_ts_expr_node_evaluate() evaluates a subtree. */ -static grn_rc -grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - switch (node->type) { - GRN_TS_EXPR_NODE_EVALUATE_CASE(ID, id) - GRN_TS_EXPR_NODE_EVALUATE_CASE(SCORE, score) - GRN_TS_EXPR_NODE_EVALUATE_CASE(KEY, key) - GRN_TS_EXPR_NODE_EVALUATE_CASE(VALUE, value) - GRN_TS_EXPR_NODE_EVALUATE_CASE(CONST, const) - GRN_TS_EXPR_NODE_EVALUATE_CASE(COLUMN, column) - GRN_TS_EXPR_NODE_EVALUATE_CASE(OP, op) - GRN_TS_EXPR_NODE_EVALUATE_CASE(BRIDGE, bridge) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, - "invalid node type: %d", node->type); - } - } -} -#undef GRN_TS_EXPR_NODE_EVALUATE_CASE - -#define GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_rc rc = grn_ts_buf_reserve(ctx, out, sizeof(grn_ts_ ## kind) * n_in);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - return grn_ts_expr_node_evaluate(ctx, node, in, n_in, out->ptr);\ - } -#define GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(KIND, kind)\ - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(KIND ## _VECTOR, kind ## _vector) -/* grn_ts_expr_node_evaluate_to_buf() evaluates a subtree. */ -static grn_rc -grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_buf *out) { - switch (node->data_kind) { - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(BOOL, bool) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(INT, int) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(FLOAT, float) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(TIME, time) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(TEXT, text) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(GEO_POINT, geo_point) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(REF, ref) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(BOOL, bool) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(INT, int) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(FLOAT, float) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(TIME, time) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(TEXT, text) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(GEO_POINT, geo_point) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(REF, ref) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, - "invalid data kind: %d", node->data_kind); - } - } -} -#undef GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE -#undef GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE - -#define GRN_TS_EXPR_NODE_FILTER_CASE(TYPE, type)\ - case GRN_TS_EXPR_ ## TYPE ## _NODE: {\ - grn_ts_expr_ ## type ## _node *type ## _node;\ - type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ - return grn_ts_expr_ ## type ## _node_filter(ctx, type ## _node,\ - in, n_in, out, n_out);\ - } -/* grn_ts_expr_node_filter() filters records. */ -static grn_rc -grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - if (node->data_kind != GRN_TS_BOOL) { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "invalid data kind: %d", node->data_kind); - } - switch (node->type) { - GRN_TS_EXPR_NODE_FILTER_CASE(KEY, key) - GRN_TS_EXPR_NODE_FILTER_CASE(VALUE, value) - GRN_TS_EXPR_NODE_FILTER_CASE(CONST, const) - GRN_TS_EXPR_NODE_FILTER_CASE(COLUMN, column) - GRN_TS_EXPR_NODE_FILTER_CASE(OP, op) - GRN_TS_EXPR_NODE_FILTER_CASE(BRIDGE, bridge) - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "invalid node type: %d", node->type); - } - } -} -#undef GRN_TS_EXPR_NODE_FILTER_CASE - -#define GRN_TS_EXPR_NODE_ADJUST_CASE(TYPE, type)\ - case GRN_TS_EXPR_ ## TYPE ## _NODE: {\ - grn_ts_expr_ ## type ## _node *type ## _node;\ - type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ - return grn_ts_expr_ ## type ## _node_adjust(ctx, type ## _node, io, n_io);\ - } -/* grn_ts_expr_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node, - grn_ts_record *io, size_t n_io) { - if (node->data_kind != GRN_TS_FLOAT) { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "invalid data kind: %d", node->data_kind); - } - switch (node->type) { - GRN_TS_EXPR_NODE_ADJUST_CASE(SCORE, score) - GRN_TS_EXPR_NODE_ADJUST_CASE(KEY, key) - GRN_TS_EXPR_NODE_ADJUST_CASE(VALUE, value) - GRN_TS_EXPR_NODE_ADJUST_CASE(CONST, const) - GRN_TS_EXPR_NODE_ADJUST_CASE(COLUMN, column) - GRN_TS_EXPR_NODE_ADJUST_CASE(OP, op) - GRN_TS_EXPR_NODE_ADJUST_CASE(BRIDGE, bridge) - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "invalid node type: %d", node->type); - } - } -} -#undef GRN_TS_EXPR_NODE_ADJUST_CASE - -/*------------------------------------------------------------- - * grn_ts_expr_parser. - */ - -/* - * FIXME: A grn_ts_expr_parser object is designed to parse one expression - * string. grn_ts_expr_parser_parse() should not be called more than - * once. - */ - -typedef enum { - GRN_TS_EXPR_DUMMY_TOKEN, /* No extra data. */ - GRN_TS_EXPR_START_TOKEN, /* No extra data. */ - GRN_TS_EXPR_END_TOKEN, /* No extra data. */ - GRN_TS_EXPR_CONST_TOKEN, /* +data_kind, content and buf. */ - GRN_TS_EXPR_NAME_TOKEN, /* +name. */ - GRN_TS_EXPR_OP_TOKEN, /* +op_type. */ - GRN_TS_EXPR_BRIDGE_TOKEN, /* No extra data. */ - GRN_TS_EXPR_BRACKET_TOKEN /* No extra data. */ -} grn_ts_expr_token_type; - -#define GRN_TS_EXPR_TOKEN_COMMON_MEMBERS\ - grn_ts_str src; /* Source string. */\ - grn_ts_expr_token_type type; /* Token type. */ - -typedef struct { - GRN_TS_EXPR_TOKEN_COMMON_MEMBERS -} grn_ts_expr_token; - -typedef grn_ts_expr_token grn_ts_expr_dummy_token; -typedef grn_ts_expr_token grn_ts_expr_start_token; -typedef grn_ts_expr_token grn_ts_expr_end_token; - -typedef struct { - GRN_TS_EXPR_TOKEN_COMMON_MEMBERS - grn_ts_data_kind data_kind; /* The data kind of the const. */ - grn_ts_any content; /* The const. */ - grn_ts_buf buf; /* Buffer for content.as_text. */ -} grn_ts_expr_const_token; - -typedef grn_ts_expr_token grn_ts_expr_name_token; - -typedef struct { - GRN_TS_EXPR_TOKEN_COMMON_MEMBERS - grn_ts_op_type op_type; /* Operator type. */ -} grn_ts_expr_op_token; - -typedef grn_ts_expr_token grn_ts_expr_bridge_token; -typedef grn_ts_expr_token grn_ts_expr_bracket_token; - -typedef struct { - grn_ts_expr *expr; /* Associated expression. */ - grn_ts_buf str_buf; /* Buffer for a source string. */ - grn_ts_expr_token **tokens; /* Tokens. */ - size_t n_tokens; /* Number of tokens. */ - size_t max_n_tokens; /* Max. number of tokens. */ - grn_ts_expr_dummy_token *dummy_tokens; /* Dummy tokens. */ - size_t n_dummy_tokens; /* Number of dummy tokens. */ - grn_ts_expr_token **stack; /* Token stack. */ - size_t stack_depth; /* Token stack's current depth. */ -} grn_ts_expr_parser; - -#define GRN_TS_EXPR_TOKEN_INIT(TYPE)\ - memset(token, 0, sizeof(*token));\ - token->type = GRN_TS_EXPR_ ## TYPE ## _TOKEN;\ - token->src = src; -/* grn_ts_expr_dummy_token_init() initializes a token. */ -static void -grn_ts_expr_dummy_token_init(grn_ctx *ctx, grn_ts_expr_dummy_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(DUMMY) -} - -/* grn_ts_expr_start_token_init() initializes a token. */ -static void -grn_ts_expr_start_token_init(grn_ctx *ctx, grn_ts_expr_start_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(START) -} - -/* grn_ts_expr_end_token_init() initializes a token. */ -static void -grn_ts_expr_end_token_init(grn_ctx *ctx, grn_ts_expr_end_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(END) -} - -/* grn_ts_expr_const_token_init() initializes a token. */ -static void -grn_ts_expr_const_token_init(grn_ctx *ctx, grn_ts_expr_const_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(CONST); - grn_ts_buf_init(ctx, &token->buf); -} - -/* grn_ts_expr_name_token_init() initializes a token. */ -static void -grn_ts_expr_name_token_init(grn_ctx *ctx, grn_ts_expr_name_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(NAME); -} - -/* grn_ts_expr_op_token_init() initializes a token. */ -static void -grn_ts_expr_op_token_init(grn_ctx *ctx, grn_ts_expr_op_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(OP); -} - -/* grn_ts_expr_bridge_token_init() initializes a token. */ -static void -grn_ts_expr_bridge_token_init(grn_ctx *ctx, grn_ts_expr_bridge_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(BRIDGE) -} - -/* grn_ts_expr_bracket_token_init() initializes a token. */ -static void -grn_ts_expr_bracket_token_init(grn_ctx *ctx, grn_ts_expr_bracket_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(BRACKET) -} -#undef GRN_TS_EXPR_TOKEN_INIT - -/* grn_ts_expr_dummy_token_fin() finalizes a token. */ -static void -grn_ts_expr_dummy_token_fin(grn_ctx *ctx, grn_ts_expr_dummy_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_start_token_fin() finalizes a token. */ -static void -grn_ts_expr_start_token_fin(grn_ctx *ctx, grn_ts_expr_start_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_end_token_fin() finalizes a token. */ -static void -grn_ts_expr_end_token_fin(grn_ctx *ctx, grn_ts_expr_end_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_const_token_fin() finalizes a token. */ -static void -grn_ts_expr_const_token_fin(grn_ctx *ctx, grn_ts_expr_const_token *token) { - grn_ts_buf_fin(ctx, &token->buf); -} - -/* grn_ts_expr_name_token_fin() finalizes a token. */ -static void -grn_ts_expr_name_token_fin(grn_ctx *ctx, grn_ts_expr_name_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_op_token_fin() finalizes a token. */ -static void -grn_ts_expr_op_token_fin(grn_ctx *ctx, grn_ts_expr_op_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_bridge_token_fin() finalizes a token. */ -static void -grn_ts_expr_bridge_token_fin(grn_ctx *ctx, grn_ts_expr_bridge_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_bracket_token_fin() finalizes a token. */ -static void -grn_ts_expr_bracket_token_fin(grn_ctx *ctx, grn_ts_expr_bracket_token *token) { - /* Nothing to do. */ -} - -#define GRN_TS_EXPR_TOKEN_OPEN(TYPE, type)\ - grn_ts_expr_ ## type ## _token *new_token;\ - new_token = GRN_MALLOCN(grn_ts_expr_ ## type ## _token, 1);\ - if (!new_token) {\ - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",\ - sizeof(grn_ts_expr_ ## type ## _token));\ - }\ - grn_ts_expr_ ## type ## _token_init(ctx, new_token, src);\ - *token = new_token; -/* grn_ts_expr_dummy_token_open() creates a token. */ -/* -static grn_rc -grn_ts_expr_dummy_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_dummy_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(DUMMY, dummy) - return GRN_SUCCESS; -} -*/ - -/* grn_ts_expr_start_token_open() creates a token. */ -static grn_rc -grn_ts_expr_start_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_start_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(START, start) - return GRN_SUCCESS; -} - -/* grn_ts_expr_end_token_open() creates a token. */ -static grn_rc -grn_ts_expr_end_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_end_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(END, end) - return GRN_SUCCESS; -} - -/* grn_ts_expr_const_token_open() creates a token. */ -static grn_rc -grn_ts_expr_const_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_const_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(CONST, const) - return GRN_SUCCESS; -} - -/* grn_ts_expr_name_token_open() creates a token. */ -static grn_rc -grn_ts_expr_name_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_name_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(NAME, name) - return GRN_SUCCESS; -} - -/* grn_ts_expr_op_token_open() creates a token. */ -static grn_rc -grn_ts_expr_op_token_open(grn_ctx *ctx, grn_ts_str src, grn_ts_op_type op_type, - grn_ts_expr_op_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(OP, op) - new_token->op_type = op_type; - return GRN_SUCCESS; -} - -/* grn_ts_expr_bridge_token_open() creates a token. */ -static grn_rc -grn_ts_expr_bridge_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_bridge_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(BRIDGE, bridge) - return GRN_SUCCESS; -} - -/* grn_ts_expr_bracket_token_open() creates a token. */ -static grn_rc -grn_ts_expr_bracket_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_bracket_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(BRACKET, bracket) - return GRN_SUCCESS; -} -#undef GRN_TS_EXPR_TOKEN_OPEN - -#define GRN_TS_EXPR_TOKEN_CLOSE_CASE(TYPE, type)\ - case GRN_TS_EXPR_ ## TYPE ## _TOKEN: {\ - grn_ts_expr_ ## type ## _token *type ## _token;\ - type ## _token = (grn_ts_expr_ ## type ## _token *)token;\ - grn_ts_expr_ ## type ## _token_fin(ctx, type ## _token);\ - break;\ - } -/* grn_ts_expr_token_close() destroys a token. */ -static void -grn_ts_expr_token_close(grn_ctx *ctx, grn_ts_expr_token *token) { - switch (token->type) { - GRN_TS_EXPR_TOKEN_CLOSE_CASE(DUMMY, dummy) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(START, start) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(END, end) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(CONST, const) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(NAME, name) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(OP, op) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(BRACKET, bracket) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(BRIDGE, bridge) - } - GRN_FREE(token); -} -#undef GRN_TS_EXPR_TOKEN_CLOSE_CASE - -/* 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) { - memset(parser, 0, sizeof(*parser)); - parser->expr = expr; - grn_ts_buf_init(ctx, &parser->str_buf); - parser->tokens = NULL; - parser->dummy_tokens = NULL; - parser->stack = NULL; -} - -/* grn_ts_expr_parser_fin() finalizes a parser. */ -static void -grn_ts_expr_parser_fin(grn_ctx *ctx, grn_ts_expr_parser *parser) { - if (parser->stack) { - GRN_FREE(parser->stack); - } - if (parser->dummy_tokens) { - size_t i; - for (i = 0; i < parser->n_dummy_tokens; i++) { - grn_ts_expr_dummy_token_fin(ctx, &parser->dummy_tokens[i]); - } - GRN_FREE(parser->dummy_tokens); - } - if (parser->tokens) { - size_t i; - for (i = 0; i < parser->n_tokens; i++) { - grn_ts_expr_token_close(ctx, parser->tokens[i]); - } - GRN_FREE(parser->tokens); - } - grn_ts_buf_fin(ctx, &parser->str_buf); -} - -/* grn_ts_expr_parser_open() creates a parser. */ -static grn_rc -grn_ts_expr_parser_open(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_parser **parser) { - grn_ts_expr_parser *new_parser = GRN_MALLOCN(grn_ts_expr_parser, 1); - if (!new_parser) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_parser)); - } - grn_ts_expr_parser_init(ctx, expr, new_parser); - *parser = new_parser; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_close() destroys a parser. */ -static void -grn_ts_expr_parser_close(grn_ctx *ctx, grn_ts_expr_parser *parser) { - grn_ts_expr_parser_fin(ctx, parser); - GRN_FREE(parser); -} - -/* grn_ts_expr_parser_tokenize_start() creates the start token. */ -static grn_rc -grn_ts_expr_parser_tokenize_start(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_ts_str token_str = { str.ptr, 0 }; - grn_ts_expr_start_token *new_token; - grn_rc rc = grn_ts_expr_start_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_end() creates the end token. */ -static grn_rc -grn_ts_expr_parser_tokenize_end(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_ts_str token_str = { str.ptr, 0 }; - grn_ts_expr_end_token *new_token; - grn_rc rc = grn_ts_expr_end_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_number() tokenizes an Int or Float literal. */ -static grn_rc -grn_ts_expr_parser_tokenize_number(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - char *end; - grn_rc rc; - grn_ts_int int_value; - grn_ts_str token_str; - grn_ts_expr_const_token *new_token; - - int_value = strtol(str.ptr, &end, 0); - if ((end != str.ptr) && (*end != '.')) { - if (grn_ts_byte_is_name_char(*end)) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, - "unterminated Int literal: \"%.*s\"", - (int)str.size, str.ptr); - } - token_str.ptr = str.ptr; - token_str.size = end - str.ptr; - rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - new_token->data_kind = GRN_TS_INT; - new_token->content.as_int = int_value; - } else { - grn_ts_float float_value = strtod(str.ptr, &end); - if (end == str.ptr) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid number literal: \"%.*s\"", - (int)str.size, str.ptr); - } - if (grn_ts_byte_is_name_char(*end)) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, - "unterminated Float literal: \"%.*s\"", - (int)str.size, str.ptr); - } - token_str.ptr = str.ptr; - token_str.size = end - str.ptr; - rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - new_token->data_kind = GRN_TS_FLOAT; - new_token->content.as_float = float_value; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_text() tokenizes a Text literal. */ -static grn_rc -grn_ts_expr_parser_tokenize_text(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - size_t i, n_escapes = 0; - grn_rc rc; - grn_ts_str token_str; - grn_ts_expr_const_token *new_token; - for (i = 1; i < str.size; i++) { - if (str.ptr[i] == '\\') { - i++; - n_escapes++; - } else if (str.ptr[i] == '"') { - break; - } - } - if (i >= str.size) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "no closing double quote: \"%.*s\"", - (int)str.size, str.ptr); - } - token_str.ptr = str.ptr; - token_str.size = i + 1; - rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - new_token->data_kind = GRN_TS_TEXT; - if (n_escapes) { - char *buf_ptr; - const char *str_ptr = str.ptr + 1; - size_t size = token_str.size - 2 - n_escapes; - rc = grn_ts_buf_resize(ctx, &new_token->buf, size); - if (rc != GRN_SUCCESS) { - grn_ts_expr_token_close(ctx, (grn_ts_expr_token *)new_token); - return rc; - } - buf_ptr = (char *)new_token->buf.ptr; - for (i = 0; i < size; i++) { - if (str_ptr[i] == '\\') { - str_ptr++; - } - buf_ptr[i] = str_ptr[i]; - } - new_token->content.as_text.ptr = buf_ptr; - new_token->content.as_text.size = size; - } else { - new_token->content.as_text.ptr = token_str.ptr + 1; - new_token->content.as_text.size = token_str.size - 2; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_name() tokenizes a Bool literal or a name. */ -static grn_rc -grn_ts_expr_parser_tokenize_name(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - size_t i; - grn_ts_str token_str; - for (i = 1; i < str.size; i++) { - if (!grn_ts_byte_is_name_char(str.ptr[i])) { - break; - } - } - token_str.ptr = str.ptr; - token_str.size = i; - - if (grn_ts_str_is_bool(token_str)) { - grn_ts_expr_const_token *new_token; - grn_rc rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - new_token->data_kind = GRN_TS_BOOL; - if (token_str.ptr[0] == 't') { - new_token->content.as_bool = GRN_TRUE; - } else { - new_token->content.as_bool = GRN_FALSE; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; - } - return grn_ts_expr_name_token_open(ctx, token_str, token); -} - -/* grn_ts_expr_parser_tokenize_bridge() tokenizes a bridge. */ -static grn_rc -grn_ts_expr_parser_tokenize_bridge(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_ts_str token_str = { str.ptr, 1 }; - grn_ts_expr_bridge_token *new_token; - grn_rc rc = grn_ts_expr_bridge_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_bracket() tokenizes a bracket. */ -static grn_rc -grn_ts_expr_parser_tokenize_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, - grn_ts_expr_token **token) { - grn_ts_str token_str = { str.ptr, 1 }; - grn_ts_expr_bracket_token *new_token; - grn_rc rc = grn_ts_expr_bracket_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* - * grn_ts_expr_parsre_tokenize_sign() tokenizes an operator '+' or '-'. - * Note that '+' and '-' have two roles each. - * '+' is GRN_TS_OP_POSITIVE or GRN_TS_OP_PLUS. - * '-' is GRN_TS_OP_NEGATIVE or GRN_TS_OP_MINUS. - */ -static grn_rc -grn_ts_expr_parser_tokenize_sign(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - size_t n_args; - grn_rc rc; - grn_ts_op_type op_type; - grn_ts_str token_str = { str.ptr, 1 }; - grn_ts_expr_token *prev_token = parser->tokens[parser->n_tokens - 1]; - grn_ts_expr_op_token *new_token; - switch (prev_token->type) { - case GRN_TS_EXPR_START_TOKEN: - case GRN_TS_EXPR_OP_TOKEN: { - n_args = 1; - break; - } - case GRN_TS_EXPR_CONST_TOKEN: - case GRN_TS_EXPR_NAME_TOKEN: { - n_args = 2; - break; - } - case GRN_TS_EXPR_BRACKET_TOKEN: { - grn_ts_str bracket; - const grn_ts_expr_bracket_token *bracket_token; - bracket_token = (const grn_ts_expr_bracket_token *)prev_token; - bracket = bracket_token->src; - switch (bracket.ptr[0]) { - case '(': case '[': { - n_args = 1; - break; - } - case ')': case ']': { - n_args = 2; - break; - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "undefined bracket: \"%.*s\"", - (int)bracket.size, bracket.ptr); - } - } - break; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence: %d", - prev_token->type); - } - } - if (token_str.ptr[0] == '+') { - op_type = (n_args == 1) ? GRN_TS_OP_POSITIVE : GRN_TS_OP_PLUS; - } else { - op_type = (n_args == 1) ? GRN_TS_OP_NEGATIVE : GRN_TS_OP_MINUS; - } - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_op() tokenizes an operator. */ -static grn_rc -grn_ts_expr_parser_tokenize_op(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_rc rc = GRN_SUCCESS; - grn_ts_str token_str = str; - grn_ts_op_type op_type; - grn_ts_expr_op_token *new_token; - switch (str.ptr[0]) { - case '+': case '-': { - return grn_ts_expr_parser_tokenize_sign(ctx, parser, str, token); - } - case '!': { - if ((str.size >= 2) && (str.ptr[1] == '=')) { - token_str.size = 2; - op_type = GRN_TS_OP_NOT_EQUAL; - } else { - token_str.size = 1; - op_type = GRN_TS_OP_LOGICAL_NOT; - } - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); - break; - } -#define GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE(label, TYPE_1, TYPE_2, TYPE_3,\ - TYPE_EQUAL)\ - case label: {\ - if ((str.size >= 2) && (str.ptr[1] == '=')) {\ - token_str.size = 2;\ - op_type = GRN_TS_OP_ ## TYPE_EQUAL;\ - } else if ((str.size >= 2) && (str.ptr[1] == label)) {\ - if ((str.size >= 3) && (str.ptr[2] == label)) {\ - token_str.size = 3;\ - op_type = GRN_TS_OP_ ## TYPE_3;\ - } else {\ - token_str.size = 2;\ - op_type = GRN_TS_OP_ ## TYPE_2;\ - }\ - } else {\ - token_str.size = 1;\ - op_type = GRN_TS_OP_ ## TYPE_1;\ - }\ - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token);\ - break;\ - } - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('<', LESS, SHIFT_ARITHMETIC_LEFT, - SHIFT_LOGICAL_LEFT, LESS_EQUAL) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('>', GREATER, SHIFT_ARITHMETIC_RIGHT, - SHIFT_LOGICAL_RIGHT, GREATER_EQUAL) -#undef GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE - case '&': { - if ((str.size >= 2) && (str.ptr[1] == '&')) { - token_str.size = 2; - op_type = GRN_TS_OP_LOGICAL_AND; - } else if ((str.size >= 2) && (str.ptr[1] == '&')) { - token_str.size = 2; - op_type = GRN_TS_OP_LOGICAL_SUB; - } else { - token_str.size = 1; - op_type = GRN_TS_OP_BITWISE_AND; - } - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); - break; - } - case '|': { - if ((str.size >= 2) && (str.ptr[1] == '|')) { - token_str.size = 2; - op_type = GRN_TS_OP_LOGICAL_OR; - } else { - token_str.size = 1; - op_type = GRN_TS_OP_BITWISE_OR; - } - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); - break; - } - case '=': { - if ((str.size < 2) || (str.ptr[1] != '=')) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, - "single equal not available: =\"%.*s\"", - (int)str.size, str.ptr); - } - token_str.size = 2; - rc = grn_ts_expr_op_token_open(ctx, token_str, GRN_TS_OP_EQUAL, - &new_token); - break; - } -#define GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE(label, TYPE)\ - case label: {\ - token_str.size = 1;\ - rc = grn_ts_expr_op_token_open(ctx, token_str, GRN_TS_OP_ ## TYPE,\ - &new_token);\ - break;\ - } - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('~', BITWISE_NOT) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('^', BITWISE_XOR) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('*', MULTIPLICATION) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('/', DIVISION) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('%', MODULUS) -#undef GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid character: \"%.*s\"", - (int)str.size, str.ptr); - } - } - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_next() extracts the next token. */ -static grn_rc -grn_ts_expr_parser_tokenize_next(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_ts_str rest; - if (!parser->n_tokens) { - return grn_ts_expr_parser_tokenize_start(ctx, parser, str, token); - } - rest = grn_ts_str_trim_left(str); - if (!rest.size) { - return grn_ts_expr_parser_tokenize_end(ctx, parser, rest, token); - } - if (grn_ts_str_has_number_prefix(rest)) { - return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token); - } - if (rest.ptr[0] == '"') { - return grn_ts_expr_parser_tokenize_text(ctx, parser, rest, token); - } - if (grn_ts_byte_is_name_char(rest.ptr[0])) { - return grn_ts_expr_parser_tokenize_name(ctx, parser, rest, token); - } - switch (rest.ptr[0]) { - case '(': case ')': case '[': case ']': { - return grn_ts_expr_parser_tokenize_bracket(ctx, parser, rest, token); - } - case '.': { - return grn_ts_expr_parser_tokenize_bridge(ctx, parser, rest, token); - } - default: { - return grn_ts_expr_parser_tokenize_op(ctx, parser, rest, token); - } - } -} - -/* - * grn_ts_expr_parser_reserve_tokens() extends a token buffer for a new token. - */ -static grn_rc -grn_ts_expr_parser_reserve_tokens(grn_ctx *ctx, grn_ts_expr_parser *parser) { - size_t i, n_bytes, new_max_n_tokens; - grn_ts_expr_token **new_tokens; - if (parser->n_tokens < parser->max_n_tokens) { - return GRN_SUCCESS; - } - new_max_n_tokens = parser->n_tokens * 2; - if (!new_max_n_tokens) { - new_max_n_tokens = 1; - } - n_bytes = sizeof(grn_ts_expr_token *) * new_max_n_tokens; - new_tokens = (grn_ts_expr_token **)GRN_REALLOC(parser->tokens, n_bytes); - if (!new_tokens) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_REALLOC failed: %zu", - n_bytes); - } - for (i = parser->n_tokens; i < new_max_n_tokens; i++) { - new_tokens[i] = NULL; - } - parser->tokens = new_tokens; - parser->max_n_tokens = new_max_n_tokens; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize() tokenizes a string. */ -static grn_rc -grn_ts_expr_parser_tokenize(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str) { - grn_ts_str rest = str; - const char *end = str.ptr + str.size; - grn_ts_expr_token *token = NULL; - GRN_TS_DEBUG("str = \"%.*s\"", (int)str.size, str.ptr); - do { - grn_rc rc = grn_ts_expr_parser_reserve_tokens(ctx, parser); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_parser_tokenize_next(ctx, parser, rest, &token); - if (rc != GRN_SUCCESS) { - return rc; - } - if ((token->type != GRN_TS_EXPR_START_TOKEN) && - (token->type != GRN_TS_EXPR_END_TOKEN)) { - GRN_TS_DEBUG("token = \"%.*s\"", (int)token->src.size, token->src.ptr); - } - parser->tokens[parser->n_tokens++] = token; - rest.ptr = token->src.ptr + token->src.size; - rest.size = end - rest.ptr; - } while (token->type != GRN_TS_EXPR_END_TOKEN); - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_push_const() pushes a token to an expression. */ -static grn_rc -grn_ts_expr_parser_push_const(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_const_token *token) { - switch (token->data_kind) { - case GRN_TS_BOOL: { - return grn_ts_expr_push_bool(ctx, parser->expr, token->content.as_bool); - } - case GRN_TS_INT: { - return grn_ts_expr_push_int(ctx, parser->expr, token->content.as_int); - } - case GRN_TS_FLOAT: { - return grn_ts_expr_push_float(ctx, parser->expr, - token->content.as_float); - } - case GRN_TS_TEXT: { - return grn_ts_expr_push_text(ctx, parser->expr, token->content.as_text); - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - token->data_kind); - } - } -} - -/* grn_ts_expr_parser_push_name() pushes a token to an expression. */ -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); -} - -/* grn_ts_expr_parser_push_op() pushes a token to an expression. */ -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); -} - -/* - * grn_ts_expr_parser_apply_one() applies a bridge or prior operator. - * If there is no target, this function returns GRN_END_OF_DATA. - */ -// FIXME: Support a ternary operator. -static grn_rc -grn_ts_expr_parser_apply_one(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_op_precedence precedence_threshold) { - grn_rc rc; - grn_ts_str src; - grn_ts_expr_token **stack = parser->stack; - grn_ts_expr_dummy_token *dummy_token; - size_t n_args, depth = parser->stack_depth; - if (depth < 2) { - return GRN_END_OF_DATA; - } - if (stack[depth - 1]->type != GRN_TS_EXPR_DUMMY_TOKEN) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "argument must be dummy token"); - } - - /* 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); - if (rc != GRN_SUCCESS) { - return rc; - } - n_args = 2; - break; - } - case GRN_TS_EXPR_OP_TOKEN: { - grn_ts_expr_op_token *op_token; - grn_ts_op_precedence precedence; - op_token = (grn_ts_expr_op_token *)stack[depth - 2]; - precedence = grn_ts_op_get_precedence(op_token->op_type); - if (precedence < precedence_threshold) { - return GRN_END_OF_DATA; - } - rc = grn_ts_expr_parser_push_op(ctx, parser, op_token); - if (rc != GRN_SUCCESS) { - return rc; - } - n_args = grn_ts_op_get_n_args(op_token->op_type); - break; - } - default: { - return GRN_END_OF_DATA; - } - } - - /* Concatenate the source strings. */ - switch (n_args) { - case 1: { - grn_ts_expr_token *arg = stack[depth - 1]; - src.ptr = stack[depth - 2]->src.ptr; - src.size = (arg->src.ptr + arg->src.size) - src.ptr; - break; - } - case 2: { - grn_ts_expr_token *args[2] = { stack[depth - 3], stack[depth - 1] }; - src.ptr = args[0]->src.ptr; - src.size = (args[1]->src.ptr + args[1]->src.size) - src.ptr; - break; - } - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "invalid #arguments: %zu", n_args); - } - } - - /* Replace the operator and argument tokens with a dummy token. */ - dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; - GRN_TS_DEBUG("dummy token: \"%.*s\"", (int)src.size, src.ptr); - grn_ts_expr_dummy_token_init(ctx, dummy_token, src); - depth -= n_args + 1; - stack[depth++] = dummy_token; - parser->stack_depth = depth; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_apply() applies bridges and prior operators. */ -static grn_rc -grn_ts_expr_parser_apply(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_op_precedence precedence_threshold) { - for ( ; ; ) { - grn_rc rc = grn_ts_expr_parser_apply_one(ctx, parser, - precedence_threshold); - if (rc == GRN_END_OF_DATA) { - return GRN_SUCCESS; - } else if (rc != GRN_SUCCESS) { - return rc; - } - } -} - -/* grn_ts_expr_parser_analyze_op() analyzes a token. */ -static grn_rc -grn_ts_expr_parser_analyze_op(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_op_token *token) { - size_t n_args = grn_ts_op_get_n_args(token->op_type); - grn_ts_expr_token *ex_token = parser->stack[parser->stack_depth - 1]; - if (n_args == 1) { - if (ex_token->type == GRN_TS_EXPR_DUMMY_TOKEN) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - } else if (n_args == 2) { - grn_ts_op_precedence precedence = grn_ts_op_get_precedence(token->op_type); - grn_rc rc = grn_ts_expr_parser_apply(ctx, parser, precedence); - if (rc != GRN_SUCCESS) { - return rc; - } - } - parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_analyze_bridge() analyzes a token. */ -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); - if (rc != GRN_SUCCESS) { - return rc; - } - parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_analyze_bracket() analyzes a token. */ -static grn_rc -grn_ts_expr_parser_analyze_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_bracket_token *token) { - grn_ts_expr_token *ex_token = parser->stack[parser->stack_depth - 1]; - switch (token->src.ptr[0]) { - case '(': { - if (ex_token->type == GRN_TS_EXPR_DUMMY_TOKEN) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; - return GRN_SUCCESS; - } - case '[': { - if (ex_token->type != GRN_TS_EXPR_DUMMY_TOKEN) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; - return GRN_SUCCESS; - } - case ')': case ']': { - grn_ts_expr_token *ex_ex_token; - grn_rc rc = grn_ts_expr_parser_apply(ctx, parser, 0); - if (rc != GRN_SUCCESS) { - return rc; - } - if (parser->stack_depth < 2) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - ex_ex_token = parser->stack[parser->stack_depth - 2]; - if (ex_ex_token->type != GRN_TS_EXPR_BRACKET_TOKEN) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - if (token->src.ptr[0] == ')') { - size_t depth = parser->stack_depth; - grn_ts_str src; - grn_ts_expr_dummy_token *dummy_token; - if (ex_ex_token->src.ptr[0] != '(') { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - src.ptr = ex_ex_token->src.ptr; - src.size = (token->src.ptr + token->src.size) - src.ptr; - dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; - GRN_TS_DEBUG("dummy token: \"%.*s\"", (int)src.size, src.ptr); - grn_ts_expr_dummy_token_init(ctx, dummy_token, src); - parser->stack[depth - 2] = dummy_token; - parser->stack_depth--; - // TODO: Apply a function. - } else if (token->src.ptr[0] == ']') { - size_t depth = parser->stack_depth; - if (ex_ex_token->src.ptr[0] != '[') { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - parser->stack[depth - 2] = parser->stack[depth - 1]; - parser->stack_depth--; - // TODO: Push a subscript operator. - } - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "undefined bracket: \"%.*s\"", - (int)token->src.size, token->src.ptr); - } - } -} - -/* grn_ts_expr_parser_analyze_token() analyzes a token. */ -static grn_rc -grn_ts_expr_parser_analyze_token(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_token *token) { - switch (token->type) { - case GRN_TS_EXPR_START_TOKEN: { - parser->stack[parser->stack_depth++] = token; - return GRN_SUCCESS; - } - case GRN_TS_EXPR_END_TOKEN: { - return grn_ts_expr_parser_apply(ctx, parser, 0); - } - case GRN_TS_EXPR_CONST_TOKEN: { - grn_ts_expr_const_token *const_token = (grn_ts_expr_const_token *)token; - grn_ts_expr_dummy_token *dummy_token; - grn_rc rc = grn_ts_expr_parser_push_const(ctx, parser, const_token); - if (rc != GRN_SUCCESS) { - return rc; - } - dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; - grn_ts_expr_dummy_token_init(ctx, dummy_token, token->src); - parser->stack[parser->stack_depth++] = dummy_token; - return GRN_SUCCESS; - } - case GRN_TS_EXPR_NAME_TOKEN: { - grn_ts_expr_name_token *name_token = (grn_ts_expr_name_token *)token; - grn_ts_expr_dummy_token *dummy_token; - grn_rc rc = grn_ts_expr_parser_push_name(ctx, parser, name_token); - if (rc != GRN_SUCCESS) { - return rc; - } - dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; - grn_ts_expr_dummy_token_init(ctx, dummy_token, token->src); - parser->stack[parser->stack_depth++] = dummy_token; - return GRN_SUCCESS; - } - case GRN_TS_EXPR_OP_TOKEN: { - grn_ts_expr_op_token *op_token = (grn_ts_expr_op_token *)token; - return grn_ts_expr_parser_analyze_op(ctx, parser, op_token); - } - case GRN_TS_EXPR_BRIDGE_TOKEN: { - grn_ts_expr_bridge_token *bridge_token; - bridge_token = (grn_ts_expr_bridge_token *)token; - return grn_ts_expr_parser_analyze_bridge(ctx, parser, bridge_token); - } - case GRN_TS_EXPR_BRACKET_TOKEN: { - grn_ts_expr_bracket_token *bracket_token; - bracket_token = (grn_ts_expr_bracket_token *)token; - return grn_ts_expr_parser_analyze_bracket(ctx, parser, bracket_token); - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid token type: %d", - token->type); - } - } -} - -/* grn_ts_expr_parser_analyze() analyzes tokens. */ -static grn_rc -grn_ts_expr_parser_analyze(grn_ctx *ctx, grn_ts_expr_parser *parser) { - size_t i; - - /* Reserve temporary work spaces. */ - parser->dummy_tokens = GRN_MALLOCN(grn_ts_expr_dummy_token, - parser->n_tokens); - if (!parser->dummy_tokens) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x %zu", - sizeof(grn_ts_expr_dummy_token), parser->n_tokens); - } - parser->stack = GRN_MALLOCN(grn_ts_expr_token *, parser->n_tokens); - if (!parser->stack) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x %zu", - sizeof(grn_ts_expr_token *), parser->n_tokens); - } - - /* Analyze tokens. */ - for (i = 0; i < parser->n_tokens; i++) { - grn_rc rc; - rc = grn_ts_expr_parser_analyze_token(ctx, parser, parser->tokens[i]); - if (rc != GRN_SUCCESS) { - return rc; - } - } - if (parser->stack_depth != 2) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "tokens left in stack: %zu", - parser->stack_depth); - } - return GRN_SUCCESS; -} - -/* - * grn_ts_expr_parser_parse() parses a string and pushes nodes into an - * expression. - */ -static grn_rc -grn_ts_expr_parser_parse(grn_ctx *ctx, grn_ts_expr_parser *parser, - const char *str_ptr, size_t str_size) { - grn_rc rc; - grn_ts_str str; - 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'; - 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; - } - rc = grn_ts_expr_parser_analyze(ctx, parser); - if (rc != GRN_SUCCESS) { - return rc; - } - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * 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->nodes = 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) { - GRN_FREE(expr->stack); - } - if (expr->nodes) { - for (i = 0; i < expr->n_nodes; i++) { - if (expr->nodes[i]) { - grn_ts_expr_node_close(ctx, expr->nodes[i]); - } - } - GRN_FREE(expr->nodes); - } - /* 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_rc rc; - grn_ts_expr *new_expr; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!table || !grn_ts_obj_is_table(ctx, table) || !expr) { - 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, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr)); - } - rc = grn_ts_obj_increment_ref_count(ctx, table); - if (rc != GRN_SUCCESS) { - GRN_FREE(new_expr); - return rc; - } - grn_ts_expr_init(ctx, new_expr); - new_expr->table = table; - new_expr->curr_table = table; - *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_rc rc; - grn_ts_expr *new_expr; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!table || !grn_ts_obj_is_table(ctx, table) || - (!str_ptr && str_size) || !expr) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_open(ctx, table, &new_expr); - 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); - } - if (rc != GRN_SUCCESS) { - grn_ts_expr_close(ctx, new_expr); - return rc; - } - *expr = new_expr; - return GRN_SUCCESS; -} - -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_nodes() extends a node buffer for a new node. */ -static grn_rc -grn_ts_expr_reserve_nodes(grn_ctx *ctx, grn_ts_expr *expr) { - size_t i, n_bytes, new_max_n_nodes; - grn_ts_expr_node **new_nodes; - if (expr->n_nodes < expr->max_n_nodes) { - return GRN_SUCCESS; - } - new_max_n_nodes = expr->n_nodes * 2; - if (!new_max_n_nodes) { - new_max_n_nodes = 1; - } - n_bytes = sizeof(grn_ts_expr_node *) * new_max_n_nodes; - new_nodes = (grn_ts_expr_node **)GRN_REALLOC(expr->nodes, n_bytes); - if (!new_nodes) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_REALLOC failed: %zu", - n_bytes); - } - for (i = expr->n_nodes; i < new_max_n_nodes; i++) { - new_nodes[i] = NULL; - } - expr->nodes = new_nodes; - expr->max_n_nodes = new_max_n_nodes; - return GRN_SUCCESS; -} - -#define GRN_TS_EXPR_OPEN_NODE(call)\ - grn_rc rc = grn_ts_expr_reserve_nodes(ctx, expr);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - rc = call;\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - expr->nodes[expr->n_nodes++] = *node;\ - return GRN_SUCCESS; -/* - * grn_ts_expr_open_id_node() opens and registers an ID node. - * Registered nodes will be closed in grn_ts_expr_fin(). - */ -static grn_rc -grn_ts_expr_open_id_node(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_node **node) { - GRN_TS_EXPR_OPEN_NODE(grn_ts_expr_id_node_open(ctx, node)) -} - -/* - * grn_ts_expr_open_score_node() opens and registers a score node. - * Registered nodes will be closed in grn_ts_expr_fin(). - */ -static grn_rc -grn_ts_expr_open_score_node(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_node **node) { - GRN_TS_EXPR_OPEN_NODE(grn_ts_expr_score_node_open(ctx, node)) -} - -/* - * grn_ts_expr_open_key_node() opens and registers a key node. - * Registered nodes will be closed in grn_ts_expr_fin(). - */ -static grn_rc -grn_ts_expr_open_key_node(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_node **node) { - GRN_TS_EXPR_OPEN_NODE(grn_ts_expr_key_node_open(ctx, expr->curr_table, node)) -} - -/* - * grn_ts_expr_open_value_node() opens and registers a value node. - * Registered nodes will be closed in grn_ts_expr_fin(). - */ -static grn_rc -grn_ts_expr_open_value_node(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_node **node) { - GRN_TS_EXPR_OPEN_NODE(grn_ts_expr_value_node_open(ctx, expr->curr_table, - node)) -} - -/* - * grn_ts_expr_open_const_node() opens and registers a const node. - * Registered nodes will be closed in grn_ts_expr_fin(). - */ -static grn_rc -grn_ts_expr_open_const_node(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_data_kind kind, const void *value, - grn_ts_expr_node **node) { - GRN_TS_EXPR_OPEN_NODE(grn_ts_expr_const_node_open(ctx, kind, value, node)) -} - -/* - * grn_ts_expr_open_column_node() opens and registers a column node. - * Registered nodes will be closed in grn_ts_expr_fin(). - */ -static grn_rc -grn_ts_expr_open_column_node(grn_ctx *ctx, grn_ts_expr *expr, - grn_obj *column, grn_ts_expr_node **node) { - GRN_TS_EXPR_OPEN_NODE(grn_ts_expr_column_node_open(ctx, column, node)) -} - -/* - * grn_ts_expr_open_op_node() opens and registers an operator node. - * Registered nodes will be closed in grn_ts_expr_fin(). - */ -static grn_rc -grn_ts_expr_open_op_node(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_op_type op_type, grn_ts_expr_node **args, - size_t n_args, grn_ts_expr_node **node) { - GRN_TS_EXPR_OPEN_NODE(grn_ts_expr_op_node_open(ctx, op_type, args, n_args, - node)) -} - -/* - * grn_ts_expr_open_bridge_node() opens and registers a bridge node. - * Registered nodes will be closed in grn_ts_expr_fin(). - */ -static grn_rc -grn_ts_expr_open_bridge_node(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_node *src, grn_ts_expr_node *dest, - grn_ts_expr_node **node) { - GRN_TS_EXPR_OPEN_NODE(grn_ts_expr_bridge_node_open(ctx, src, dest, node)) -} -#undef GRN_TS_EXPR_OPEN_NODE - -/* 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: %zu", - 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_point value; - GRN_GEO_POINT_VALUE(obj, value.latitude, value.longitude); - return grn_ts_expr_push_tokyo_geo_point(ctx, expr, value); - } - case GRN_DB_WGS84_GEO_POINT: { - grn_ts_geo_point value; - GRN_GEO_POINT_VALUE(obj, value.latitude, value.longitude); - return grn_ts_expr_push_wgs84_geo_point(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: %zu 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_point) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(WGS84_GEO_POINT, wgs84_geo_point) - 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: %zu x %zu", - 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_open_id_node(ctx, expr, &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_open_score_node(ctx, expr, &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_open_key_node(ctx, expr, &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_open_value_node(ctx, expr, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -#define GRN_TS_EXPR_PUSH_CONST_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - return grn_ts_expr_push_ ## kind(ctx, expr,\ - *(const grn_ts_ ## kind *)value);\ - } -grn_rc -grn_ts_expr_push_const(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_data_kind kind, const void *value) { - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || !value) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - switch (kind) { - GRN_TS_EXPR_PUSH_CONST_CASE(BOOL, bool) - GRN_TS_EXPR_PUSH_CONST_CASE(INT, int) - GRN_TS_EXPR_PUSH_CONST_CASE(FLOAT, float) - GRN_TS_EXPR_PUSH_CONST_CASE(TIME, time) - GRN_TS_EXPR_PUSH_CONST_CASE(TEXT, text) - GRN_TS_EXPR_PUSH_CONST_CASE(GEO_POINT, geo_point) - GRN_TS_EXPR_PUSH_CONST_CASE(BOOL_VECTOR, bool_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(INT_VECTOR, int_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(FLOAT_VECTOR, float_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(TIME_VECTOR, time_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(TEXT_VECTOR, text_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(GEO_POINT_VECTOR, geo_point_vector) - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", kind); - } - } -} -#undef GRN_TS_EXPR_PUSH_CONST_CASE - -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_open_column_node(ctx, expr, 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; - 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: %zu", n_args); - } - if (n_args > expr->stack_depth) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid #arguments: %zu, %zu", - 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; - } - } - rc = grn_ts_expr_open_op_node(ctx, expr, op_type, args, n_args, &node); - if (rc == GRN_SUCCESS) { - expr->stack_depth -= n_args; - expr->stack[expr->stack_depth++] = node; - } - return rc; -} - -#define GRN_TS_EXPR_PUSH_CONST(KIND, kind)\ - grn_rc rc;\ - grn_ts_expr_node *node;\ - if (!ctx) {\ - return GRN_INVALID_ARGUMENT;\ - }\ - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) ||\ - !grn_ts_ ## kind ## _is_valid(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_open_const_node(ctx, expr, GRN_TS_ ## KIND,\ - &value, &node);\ - if (rc == GRN_SUCCESS) {\ - expr->stack[expr->stack_depth++] = node;\ - }\ - } -grn_rc -grn_ts_expr_push_bool(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_bool value) { - GRN_TS_EXPR_PUSH_CONST(BOOL, bool) - return rc; -} - -grn_rc -grn_ts_expr_push_int(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_int value) { - GRN_TS_EXPR_PUSH_CONST(INT, int) - return rc; -} - -grn_rc -grn_ts_expr_push_float(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_float value) { - GRN_TS_EXPR_PUSH_CONST(FLOAT, float) - return rc; -} - -grn_rc -grn_ts_expr_push_time(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_time value) { - GRN_TS_EXPR_PUSH_CONST(TIME, time) - return rc; -} - -grn_rc -grn_ts_expr_push_text(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_text value) { - GRN_TS_EXPR_PUSH_CONST(TEXT, text) - return rc; -} - -grn_rc -grn_ts_expr_push_geo_point(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_point value) { - GRN_TS_EXPR_PUSH_CONST(GEO_POINT, geo_point) - return rc; -} - -grn_rc -grn_ts_expr_push_tokyo_geo_point(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_point value) { - GRN_TS_EXPR_PUSH_CONST(GEO_POINT, geo_point) - node->data_type = GRN_DB_TOKYO_GEO_POINT; - return rc; -} - -grn_rc -grn_ts_expr_push_wgs84_geo_point(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_point value) { - GRN_TS_EXPR_PUSH_CONST(GEO_POINT, geo_point) - node->data_type = GRN_DB_WGS84_GEO_POINT; - return rc; -} - -grn_rc -grn_ts_expr_push_bool_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_bool_vector value) { - GRN_TS_EXPR_PUSH_CONST(BOOL_VECTOR, bool_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_int_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_int_vector value) { - GRN_TS_EXPR_PUSH_CONST(INT_VECTOR, int_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_float_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_float_vector value) { - GRN_TS_EXPR_PUSH_CONST(FLOAT_VECTOR, float_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_time_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_time_vector value) { - GRN_TS_EXPR_PUSH_CONST(TIME_VECTOR, time_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_text_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_text_vector value) { - GRN_TS_EXPR_PUSH_CONST(TEXT_VECTOR, text_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_geo_point_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_point_vector value) { - GRN_TS_EXPR_PUSH_CONST(GEO_POINT_VECTOR, geo_point_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_tokyo_geo_point_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_point_vector value) { - GRN_TS_EXPR_PUSH_CONST(GEO_POINT_VECTOR, geo_point_vector) - node->data_type = GRN_DB_TOKYO_GEO_POINT; - return rc; -} - -grn_rc -grn_ts_expr_push_wgs84_geo_point_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_point_vector value) { - GRN_TS_EXPR_PUSH_CONST(GEO_POINT_VECTOR, geo_point_vector) - node->data_type = GRN_DB_TOKYO_GEO_POINT; - return rc; -} -#undef GRN_TS_EXPR_PUSH_CONST - -/* 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: %zu", - 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; - 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) || !expr->stack_depth) { - 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_open_bridge_node(ctx, expr, 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; - return GRN_SUCCESS; -} - -/* grn_ts_expr_evaluate_to_buf() evaluates an expression. */ -static grn_rc -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) { - return GRN_INVALID_ARGUMENT; - } - if (!n_in) { - return GRN_SUCCESS; - } - return grn_ts_expr_node_evaluate_to_buf(ctx, expr->root, in, n_in, out); -} - -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)) { - return GRN_INVALID_ARGUMENT; - } - if (!n_in) { - return GRN_SUCCESS; - } - return grn_ts_expr_node_evaluate(ctx, expr->root, in, n_in, out); -} - -grn_rc -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) { - return GRN_INVALID_ARGUMENT; - } - if (!n_in) { - *n_out = 0; - return GRN_SUCCESS; - } - return grn_ts_expr_node_filter(ctx, expr->root, in, n_in, out, n_out); -} - -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)) { - return GRN_INVALID_ARGUMENT; - } - if (!n_io) { - return GRN_SUCCESS; - } - return grn_ts_expr_node_adjust(ctx, expr->root, io, n_io); -} - /*------------------------------------------------------------- * grn_ts_writer. */ Modified: lib/ts/sources.am (+2 -0) =================================================================== --- lib/ts/sources.am 2015-11-09 13:36:05 +0900 (c51787a) +++ lib/ts/sources.am 2015-11-09 14:12:30 +0900 (31ec497) @@ -1,6 +1,8 @@ libgrnts_la_SOURCES = \ ts_buf.c \ ts_buf.h \ + ts_expr.c \ + ts_expr.h \ ts_log.h \ ts_str.c \ ts_str.h Copied: lib/ts/ts_expr.c (+12 -739) 91% =================================================================== --- lib/ts.c 2015-11-09 13:36:05 +0900 (5410343) +++ lib/ts/ts_expr.c 2015-11-09 14:12:30 +0900 (a2d5611) @@ -16,34 +16,23 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* TS is an acronym for "Turbo Selector". */ +#include "ts_expr.h" -#include "grn_ts.h" - -#include <ctype.h> #include <math.h> #include <stdlib.h> #include <string.h> -#include "grn_ctx_impl.h" -#include "grn_dat.h" -#include "grn_db.h" -#include "grn_geo.h" -#include "grn_hash.h" -#include "grn_output.h" -#include "grn_pat.h" -#include "grn_store.h" -#include "grn_str.h" - -#include "ts/ts_buf.h" -#include "ts/ts_log.h" -#include "ts/ts_str.h" - -/*------------------------------------------------------------- - * Miscellaneous. - */ +#include "../grn_ctx_impl.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" -enum { GRN_TS_BATCH_SIZE = 1024 }; +#include "ts_buf.h" +#include "ts_log.h" +#include "ts_str.h" /*------------------------------------------------------------- * Built-in data kinds. @@ -241,118 +230,6 @@ grn_ts_ref_vector_zero(void) { return (grn_ts_ref_vector){ NULL, 0 }; } -/* grn_ts_bool_output() outputs a value. */ -static grn_rc -grn_ts_bool_output(grn_ctx *ctx, grn_ts_bool value) { - if (value) { - return grn_bulk_write(ctx, ctx->impl->outbuf, "true", 4); - } else { - return grn_bulk_write(ctx, ctx->impl->outbuf, "false", 5); - } -} - -/* grn_ts_int_output() outputs a value. */ -static grn_rc -grn_ts_int_output(grn_ctx *ctx, grn_ts_int value) { - return grn_text_lltoa(ctx, ctx->impl->outbuf, value); -} - -/* grn_ts_float_output() outputs a value. */ -static grn_rc -grn_ts_float_output(grn_ctx *ctx, grn_ts_float value) { - return grn_text_ftoa(ctx, ctx->impl->outbuf, value); -} - -/* grn_ts_time_output() outputs a value. */ -static grn_rc -grn_ts_time_output(grn_ctx *ctx, grn_ts_time value) { - return grn_text_ftoa(ctx, ctx->impl->outbuf, value * 0.000001); -} - -/* grn_ts_text_output() outputs a value. */ -static grn_rc -grn_ts_text_output(grn_ctx *ctx, grn_ts_text value) { - return grn_text_esc(ctx, ctx->impl->outbuf, value.ptr, value.size); -} - -/* grn_ts_geo_point_output() outputs a value. */ -static grn_rc -grn_ts_geo_point_output(grn_ctx *ctx, grn_ts_geo_point value) { - grn_rc rc = grn_bulk_write(ctx, ctx->impl->outbuf, "\"", 1); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_text_itoa(ctx, ctx->impl->outbuf, value.latitude); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_bulk_write(ctx, ctx->impl->outbuf, "x", 1); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_text_itoa(ctx, ctx->impl->outbuf, value.longitude); - if (rc != GRN_SUCCESS) { - return rc; - } - return grn_bulk_write(ctx, ctx->impl->outbuf, "\"", 1); -} - -#define GRN_TS_VECTOR_OUTPUT(kind)\ - size_t i;\ - grn_rc rc = grn_bulk_write(ctx, ctx->impl->outbuf, "[", 1);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - for (i = 0; i < value.size; ++i) {\ - if (i) {\ - rc = grn_bulk_write(ctx, ctx->impl->outbuf, ",", 1);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - rc = grn_ts_ ## kind ## _output(ctx, value.ptr[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - return grn_bulk_write(ctx, ctx->impl->outbuf, "]", 1); -/* grn_ts_bool_vector_output() outputs a value. */ -static grn_rc -grn_ts_bool_vector_output(grn_ctx *ctx, grn_ts_bool_vector value) { - GRN_TS_VECTOR_OUTPUT(bool) -} - -/* grn_ts_int_vector_output() outputs a value. */ -static grn_rc -grn_ts_int_vector_output(grn_ctx *ctx, grn_ts_int_vector value) { - GRN_TS_VECTOR_OUTPUT(int) -} - -/* grn_ts_float_vector_output() outputs a value. */ -static grn_rc -grn_ts_float_vector_output(grn_ctx *ctx, grn_ts_float_vector value) { - GRN_TS_VECTOR_OUTPUT(float) -} - -/* grn_ts_time_vector_output() outputs a value. */ -static grn_rc -grn_ts_time_vector_output(grn_ctx *ctx, grn_ts_time_vector value) { - GRN_TS_VECTOR_OUTPUT(time) -} - -/* grn_ts_text_vector_output() outputs a value. */ -static grn_rc -grn_ts_text_vector_output(grn_ctx *ctx, grn_ts_text_vector value) { - GRN_TS_VECTOR_OUTPUT(text) -} - -/* grn_ts_geo_point_vector_output() outputs a value. */ -static grn_rc -grn_ts_geo_point_vector_output(grn_ctx *ctx, grn_ts_geo_point_vector value) { - GRN_TS_VECTOR_OUTPUT(geo_point) -} -#undef GRN_TS_VECTOR_OUTPUT - /* grn_ts_data_type_to_kind() returns a kind associated with a type. */ static grn_ts_data_kind grn_ts_data_type_to_kind(grn_ts_data_type type) { @@ -7046,8 +6923,7 @@ grn_ts_expr_complete(grn_ctx *ctx, grn_ts_expr *expr) { return GRN_SUCCESS; } -/* grn_ts_expr_evaluate_to_buf() evaluates an expression. */ -static grn_rc +grn_rc 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) { @@ -7102,606 +6978,3 @@ grn_ts_expr_adjust(grn_ctx *ctx, grn_ts_expr *expr, } return grn_ts_expr_node_adjust(ctx, expr->root, io, n_io); } - -/*------------------------------------------------------------- - * grn_ts_writer. - */ - -typedef struct { - grn_ts_expr **exprs; - size_t n_exprs; - size_t max_n_exprs; - grn_obj name_buf; - grn_ts_str *names; - grn_ts_buf *bufs; -} grn_ts_writer; - -/* grn_ts_writer_init() initializes a writer. */ -static void -grn_ts_writer_init(grn_ctx *ctx, grn_ts_writer *writer) { - memset(writer, 0, sizeof(*writer)); - writer->exprs = NULL; - GRN_TEXT_INIT(&writer->name_buf, GRN_OBJ_VECTOR); - writer->names = NULL; - writer->bufs = NULL; -} - -/* grn_ts_writer_fin() finalizes a writer. */ -static void -grn_ts_writer_fin(grn_ctx *ctx, grn_ts_writer *writer) { - size_t i; - if (writer->bufs) { - for (i = 0; i < writer->n_exprs; i++) { - grn_ts_buf_fin(ctx, &writer->bufs[i]); - } - GRN_FREE(writer->bufs); - } - if (writer->names) { - GRN_FREE(writer->names); - } - GRN_OBJ_FIN(ctx, &writer->name_buf); - if (writer->exprs) { - for (i = 0; i < writer->n_exprs; i++) { - grn_ts_expr_close(ctx, writer->exprs[i]); - } - GRN_FREE(writer->exprs); - } -} - -/* - * grn_ts_writer_tokenize() extracts the first expression string. - * If the input is empty, this function returns GRN_END_OF_DATA. - */ -static grn_rc -grn_ts_writer_tokenize(grn_ctx *ctx, grn_ts_writer *writer, - grn_ts_str in, grn_ts_str *token, grn_ts_str *rest) { - size_t i; - char stack_top; - grn_rc rc = GRN_SUCCESS; - grn_ts_str str = in; - grn_ts_buf stack; - - /* Find a non-empty token. */ - grn_ts_buf_init(ctx, &stack); - for ( ; ; ) { - str = grn_ts_str_trim_left(str); - if (!str.size) { - rc = GRN_END_OF_DATA; - break; - } - for (i = 0; i < str.size; i++) { - if (stack.pos) { - if (str.ptr[i] == stack_top) { - if (--stack.pos) { - stack_top = ((char *)stack.ptr)[stack.pos - 1]; - } - continue; - } - if (stack_top == '"') { - /* Skip the next byte of an escape character. */ - if ((str.ptr[i] == '\\') && (i < (str.size - 1))) { - i++; - } - continue; - } - } else if (str.ptr[i] == ',') { - break; - } - switch (str.ptr[i]) { - case '(': { - stack_top = ')'; - rc = grn_ts_buf_write(ctx, &stack, &stack_top, 1); - break; - } - case '[': { - stack_top = ']'; - rc = grn_ts_buf_write(ctx, &stack, &stack_top, 1); - break; - } - case '{': { - stack_top = '}'; - rc = grn_ts_buf_write(ctx, &stack, &stack_top, 1); - break; - } - case '"': { - stack_top = '"'; - rc = grn_ts_buf_write(ctx, &stack, &stack_top, 1); - break; - } - } - if (rc != GRN_SUCCESS) { - break; - } - } - if (rc != GRN_SUCCESS) { - break; - } - if (i) { - /* Output the result. */ - token->ptr = str.ptr; - token->size = i; - if (token->size == str.size) { - rest->ptr = str.ptr + str.size; - rest->size = 0; - } else { - rest->ptr = str.ptr + token->size + 1; - rest->size = str.size - token->size - 1; - } - break; - } - str.ptr++; - str.size--; - } - grn_ts_buf_fin(ctx, &stack); - return rc; -} - -/* grn_ts_writer_expand() expands a wildcard. */ -static grn_rc -grn_ts_writer_expand(grn_ctx *ctx, grn_ts_writer *writer, - grn_obj *table, grn_ts_str str) { - grn_rc rc = GRN_SUCCESS; - grn_hash_cursor *cursor; - grn_hash *hash = grn_hash_create(ctx, NULL, sizeof(grn_ts_id), 0, - GRN_OBJ_TABLE_HASH_KEY | GRN_HASH_TINY); - if (!hash) { - return GRN_INVALID_ARGUMENT; - } - grn_table_columns(ctx, table, str.ptr, str.size - 1, (grn_obj *)hash); - if (ctx->rc != GRN_SUCCESS) { - return ctx->rc; - } - cursor = grn_hash_cursor_open(ctx, hash, NULL, 0, NULL, 0, 0, -1, 0); - if (!cursor) { - rc = GRN_INVALID_ARGUMENT; - } else { - while (grn_hash_cursor_next(ctx, cursor) != GRN_ID_NIL) { - char name_buf[GRN_TABLE_MAX_KEY_SIZE]; - size_t name_size; - grn_obj *column; - grn_ts_id *column_id; - if (!grn_hash_cursor_get_key(ctx, cursor, (void **)&column_id)) { - rc = GRN_INVALID_ARGUMENT; - break; - } - column = grn_ctx_at(ctx, *column_id); - if (!column) { - rc = GRN_INVALID_ARGUMENT; - break; - } - name_size = grn_column_name(ctx, column, name_buf, sizeof(name_buf)); - grn_obj_unlink(ctx, column); - rc = grn_vector_add_element(ctx, &writer->name_buf, - name_buf, name_size, 0, GRN_DB_TEXT); - if (rc != GRN_SUCCESS) { - break; - } - } - grn_hash_cursor_close(ctx, cursor); - } - grn_hash_close(ctx, hash); - return rc; -} - -/* grn_ts_writer_parse() parses output expressions. */ -static grn_rc -grn_ts_writer_parse(grn_ctx *ctx, grn_ts_writer *writer, - grn_obj *table, grn_ts_str str) { - grn_rc rc; - grn_ts_str rest = str; - for ( ; ; ) { - grn_ts_str token = { NULL, 0 }; - rc = grn_ts_writer_tokenize(ctx, writer, rest, &token, &rest); - if (rc != GRN_SUCCESS) { - return (rc == GRN_END_OF_DATA) ? GRN_SUCCESS : rc; - } - if ((token.ptr[token.size - 1] == '*') && - grn_ts_str_is_name_prefix((grn_ts_str){ token.ptr, token.size - 1 })) { - rc = grn_ts_writer_expand(ctx, writer, table, token); - if (rc != GRN_SUCCESS) { - return rc; - } - } else if (grn_ts_str_is_key_name(token) && - !grn_ts_table_has_key(ctx, table)) { - /* - * Skip _key if the table has no _key, because the default output_columns - * option contains _key. - */ - GRN_TS_DEBUG("skip \"_key\" because the table has no _key"); - } else { - rc = grn_vector_add_element(ctx, &writer->name_buf, - token.ptr, token.size, 0, GRN_DB_TEXT); - if (rc != GRN_SUCCESS) { - return rc; - } - } - } - return GRN_SUCCESS; -} - -/* grn_ts_writer_build() builds output expresions. */ -static grn_rc -grn_ts_writer_build(grn_ctx *ctx, grn_ts_writer *writer, grn_obj *table) { - size_t i, n_names = grn_vector_size(ctx, &writer->name_buf); - if (!n_names) { - return GRN_SUCCESS; - } - writer->names = GRN_MALLOCN(grn_ts_str, n_names); - if (!writer->names) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x %zu", - sizeof(grn_ts_str), n_names); - } - writer->exprs = GRN_MALLOCN(grn_ts_expr *, n_names); - if (!writer->exprs) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x %zu", - sizeof(grn_ts_expr *), n_names); - } - for (i = 0; i < n_names; i++) { - grn_rc rc; - grn_ts_expr *new_expr; - 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); - if (rc != GRN_SUCCESS) { - return rc; - } - writer->names[i].ptr = name_ptr; - writer->names[i].size = name_size; - writer->exprs[i] = new_expr; - writer->n_exprs++; - } - return GRN_SUCCESS; -} - -/* grn_ts_writer_open() creates a writer. */ -static grn_rc -grn_ts_writer_open(grn_ctx *ctx, grn_obj *table, grn_ts_str str, - grn_ts_writer **writer) { - grn_rc rc; - grn_ts_writer *new_writer = GRN_MALLOCN(grn_ts_writer, 1); - if (!new_writer) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_writer)); - } - grn_ts_writer_init(ctx, new_writer); - rc = grn_ts_writer_parse(ctx, new_writer, table, str); - if (rc == GRN_SUCCESS) { - rc = grn_ts_writer_build(ctx, new_writer, table); - } - if (rc != GRN_SUCCESS) { - grn_ts_writer_fin(ctx, new_writer); - GRN_FREE(new_writer); - return rc; - } - *writer = new_writer; - return GRN_SUCCESS; -} - -/* grn_ts_writer_close() destroys a writer. */ -static void -grn_ts_writer_close(grn_ctx *ctx, grn_ts_writer *writer) { - grn_ts_writer_fin(ctx, writer); - GRN_FREE(writer); -} - -/* TODO: Errors of output macros, such as GRN_TEXT_*(), are ignored. */ - -#define GRN_TS_WRITER_OUTPUT_HEADER_CASE(TYPE, name)\ - case GRN_DB_ ## TYPE: {\ - GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, name);\ - break;\ - } -/* grn_ts_writer_output_header() outputs names and data types. */ -static grn_rc -grn_ts_writer_output_header(grn_ctx *ctx, grn_ts_writer *writer) { - grn_rc rc; - GRN_OUTPUT_ARRAY_OPEN("COLUMNS", writer->n_exprs); - for (size_t i = 0; i < writer->n_exprs; ++i) { - GRN_OUTPUT_ARRAY_OPEN("COLUMN", 2); - rc = grn_text_esc(ctx, ctx->impl->outbuf, - writer->names[i].ptr, writer->names[i].size); - if (rc != GRN_SUCCESS) { - return rc; - } - GRN_TEXT_PUT(ctx, ctx->impl->outbuf, ",\"", 2); - switch (writer->exprs[i]->data_type) { - case GRN_DB_VOID: { - if (writer->exprs[i]->data_kind == GRN_TS_GEO_POINT) { - GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, "GeoPoint"); - } else { - GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, "Void"); - } - break; - } - GRN_TS_WRITER_OUTPUT_HEADER_CASE(BOOL, "Bool") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(INT8, "Int8") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(INT16, "Int16") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(INT32, "Int32") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(INT64, "Int64") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(UINT8, "UInt8") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(UINT16, "UInt16") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(UINT32, "UInt32") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(UINT64, "UInt64") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(FLOAT, "Float") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(TIME, "Time") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(SHORT_TEXT, "ShortText") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(TEXT, "Text") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(LONG_TEXT, "LongText") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(TOKYO_GEO_POINT, "TokyoGeoPoint") - GRN_TS_WRITER_OUTPUT_HEADER_CASE(WGS84_GEO_POINT, "WGS84GeoPoint") - default: { - char name_buf[GRN_TABLE_MAX_KEY_SIZE]; - size_t name_size; - grn_obj *obj = grn_ctx_at(ctx, writer->exprs[i]->data_type); - if (!obj) { - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", - writer->exprs[i]->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", - writer->exprs[i]->data_type); - } - name_size = grn_obj_name(ctx, obj, name_buf, sizeof(name_buf)); - GRN_TEXT_PUT(ctx, ctx->impl->outbuf, name_buf, name_size); - grn_obj_unlink(ctx, obj); - break; - } - } - GRN_TEXT_PUTC(ctx, ctx->impl->outbuf, '"'); - GRN_OUTPUT_ARRAY_CLOSE(); - } - GRN_OUTPUT_ARRAY_CLOSE(); /* COLUMNS. */ - return GRN_SUCCESS; -} -#undef GRN_TS_WRITER_OUTPUT_HEADER_CASE - -#define GRN_TS_WRITER_OUTPUT_BODY_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *value = (grn_ts_ ## kind *)writer->bufs[j].ptr;\ - grn_ts_ ## kind ## _output(ctx, value[i]);\ - break;\ - } -#define GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(KIND, kind)\ - GRN_TS_WRITER_OUTPUT_BODY_CASE(KIND ## _VECTOR, kind ## _vector) -/* - * grn_ts_writer_output_body() evaluates expressions and outputs the results. - */ -static grn_rc -grn_ts_writer_output_body(grn_ctx *ctx, grn_ts_writer *writer, - const grn_ts_record *in, size_t n_in) { - size_t i, j, count = 0; - writer->bufs = GRN_MALLOCN(grn_ts_buf, writer->n_exprs); - if (!writer->bufs) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x %zu", - sizeof(grn_ts_buf), writer->n_exprs); - } - for (i = 0; i < writer->n_exprs; i++) { - grn_ts_buf_init(ctx, &writer->bufs[i]); - } - while (count < n_in) { - size_t batch_size = GRN_TS_BATCH_SIZE; - if (batch_size > (n_in - count)) { - batch_size = n_in - count; - } - for (i = 0; i < writer->n_exprs; ++i) { - grn_rc rc = grn_ts_expr_evaluate_to_buf(ctx, writer->exprs[i], in + count, - batch_size, &writer->bufs[i]); - if (rc != GRN_SUCCESS) { - return rc; - } - } - for (i = 0; i < batch_size; ++i) { - GRN_OUTPUT_ARRAY_OPEN("HIT", writer->n_exprs); - for (j = 0; j < writer->n_exprs; ++j) { - if (j) { - GRN_TEXT_PUTC(ctx, ctx->impl->outbuf, ','); - } - switch (writer->exprs[j]->data_kind) { - GRN_TS_WRITER_OUTPUT_BODY_CASE(BOOL, bool); - GRN_TS_WRITER_OUTPUT_BODY_CASE(INT, int); - GRN_TS_WRITER_OUTPUT_BODY_CASE(FLOAT, float); - GRN_TS_WRITER_OUTPUT_BODY_CASE(TIME, time); - GRN_TS_WRITER_OUTPUT_BODY_CASE(TEXT, text); - GRN_TS_WRITER_OUTPUT_BODY_CASE(GEO_POINT, geo_point); - GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(BOOL, bool); - GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(INT, int); - GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(FLOAT, float); - GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(TIME, time); - GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(TEXT, text); - GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(GEO_POINT, geo_point); - default: { - break; - } - } - } - GRN_OUTPUT_ARRAY_CLOSE(); /* HITS. */ - } - count += batch_size; - } - return GRN_SUCCESS; -} -#undef GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE -#undef GRN_TS_WRITER_OUTPUT_BODY_CASE - -/* grn_ts_writer_output() outputs search results into the output buffer. */ -static grn_rc -grn_ts_writer_output(grn_ctx *ctx, grn_ts_writer *writer, - const grn_ts_record *in, size_t n_in, size_t n_hits) { - grn_rc rc; - GRN_OUTPUT_ARRAY_OPEN("RESULT", 1); - GRN_OUTPUT_ARRAY_OPEN("RESULTSET", 2 + n_in); - GRN_OUTPUT_ARRAY_OPEN("NHITS", 1); - rc = grn_text_ulltoa(ctx, ctx->impl->outbuf, n_hits); - if (rc != GRN_SUCCESS) { - return rc; - } - GRN_OUTPUT_ARRAY_CLOSE(); /* NHITS. */ - rc = grn_ts_writer_output_header(ctx, writer); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_writer_output_body(ctx, writer, in, n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - GRN_OUTPUT_ARRAY_CLOSE(); /* RESULTSET. */ - GRN_OUTPUT_ARRAY_CLOSE(); /* RESET. */ - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * API. - */ - -/* grn_ts_select_filter() applies a filter to all the records of a table. */ -static grn_rc -grn_ts_select_filter(grn_ctx *ctx, grn_obj *table, grn_ts_str str, - size_t offset, size_t limit, - grn_ts_record **out, size_t *n_out, size_t *n_hits) { - grn_rc rc; - grn_table_cursor *cursor; - grn_ts_expr *expr; - grn_ts_record *buf = NULL; - size_t buf_size = 0; - - *out = NULL; - *n_out = 0; - *n_hits = 0; - - cursor = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, - GRN_CURSOR_ASCENDING | GRN_CURSOR_BY_ID); - if (!cursor) { - return (ctx->rc != GRN_SUCCESS) ? ctx->rc : GRN_UNKNOWN_ERROR; - } - - rc = grn_ts_expr_parse(ctx, table, str.ptr, str.size, &expr); - if (rc == GRN_SUCCESS) { - for ( ; ; ) { - size_t i, batch_size; - grn_ts_record *batch; - - /* Extend the record buffer. */ - if (buf_size < (*n_out + GRN_TS_BATCH_SIZE)) { - size_t new_size = buf_size ? (buf_size * 2) : GRN_TS_BATCH_SIZE; - size_t n_bytes = sizeof(grn_ts_record) * new_size; - grn_ts_record *new_buf = (grn_ts_record *)GRN_REALLOC(buf, n_bytes); - if (!new_buf) { - GRN_TS_ERR(GRN_NO_MEMORY_AVAILABLE, - "GRN_REALLOC failed: %zu", n_bytes); - rc = ctx->rc; - break; - } - buf = new_buf; - buf_size = new_size; - } - - /* Read records from the cursor. */ - batch = buf + *n_out; - for (i = 0; i < GRN_TS_BATCH_SIZE; i++) { - batch[i].id = grn_table_cursor_next(ctx, cursor); - if (batch[i].id == GRN_ID_NIL) { - break; - } - batch[i].score = 0.0; - } - batch_size = i; - if (!batch_size) { - break; - } - - /* Apply the filter. */ - rc = grn_ts_expr_filter(ctx, expr, batch, batch_size, - batch, &batch_size); - if (rc != GRN_SUCCESS) { - break; - } - *n_hits += batch_size; - - /* Apply the offset and the limit. */ - if (offset) { - if (batch_size <= offset) { - offset -= batch_size; - batch_size = 0; - } else { - size_t n_bytes = sizeof(grn_ts_record) * (batch_size - offset); - grn_memmove(batch, batch + offset, n_bytes); - batch_size -= offset; - offset = 0; - } - } - if (batch_size <= limit) { - limit -= batch_size; - } else { - batch_size = limit; - limit = 0; - } - *n_out += batch_size; - } - /* Ignore a failure of destruction. */ - grn_ts_expr_close(ctx, expr); - } - /* Ignore a failure of destruction. */ - grn_table_cursor_close(ctx, cursor); - - if (rc != GRN_SUCCESS) { - if (buf) { - GRN_FREE(buf); - } - *n_out = 0; - *n_hits = 0; - return rc; - } - *out = buf; - return GRN_SUCCESS; -} - -/* grn_ts_select_output() outputs the results. */ -static grn_rc -grn_ts_select_output(grn_ctx *ctx, grn_obj *table, grn_ts_str str, - const grn_ts_record *in, size_t n_in, size_t n_hits) { - grn_ts_writer *writer; - grn_rc rc = grn_ts_writer_open(ctx, table, str, &writer); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_writer_output(ctx, writer, in, n_in, n_hits); - grn_ts_writer_close(ctx, writer); - return rc; -} - -grn_rc -grn_ts_select(grn_ctx *ctx, grn_obj *table, - const char *filter_ptr, size_t filter_size, - const char *output_columns_ptr, size_t output_columns_size, - size_t offset, size_t limit) { - grn_rc rc; - grn_ts_str filter = { filter_ptr, filter_size }; - grn_ts_str output_columns = { output_columns_ptr, output_columns_size }; - grn_ts_record *records = NULL; - size_t n_records, n_hits; - if (!ctx || !table || !grn_ts_obj_is_table(ctx, table) || - (!filter_ptr && filter_size) || - (!output_columns_ptr && output_columns_size)) { - return GRN_INVALID_ARGUMENT; - } - rc = grn_ts_select_filter(ctx, table, filter, offset, limit, - &records, &n_records, &n_hits); - if (rc == GRN_SUCCESS) { - rc = grn_ts_select_output(ctx, table, output_columns, - records, n_records, n_hits); - } - if (records) { - GRN_FREE(records); - } - if (rc != GRN_SUCCESS) { - GRN_BULK_REWIND(ctx->impl->outbuf); - if ((ctx->rc == GRN_SUCCESS) || !ctx->errbuf[0]) { - ERR(rc, "error message is missing"); - } else if (ctx->errlvl < GRN_LOG_ERROR) { - ctx->errlvl = GRN_LOG_ERROR; - } - } - return rc; -} Copied: lib/ts/ts_expr.h (+10 -85) 85% =================================================================== --- lib/grn_ts.h 2015-11-09 13:36:05 +0900 (c815433) +++ lib/ts/ts_expr.h 2015-11-09 14:12:30 +0900 (9344fce) @@ -16,13 +16,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef GRN_TS_H -#define GRN_TS_H +#ifndef GRN_TS_EXPR_H +#define GRN_TS_EXPR_H -#include <stddef.h> #include <stdint.h> -#include "grn.h" +#include "../grn_ts.h" + +#include "ts_buf.h" #ifdef __cplusplus extern "C" { @@ -111,64 +112,6 @@ typedef enum { } grn_ts_expr_node_type; /*------------------------------------------------------------- - * Built-in data types. - */ - -/* ID (_id), score (_score), and record types. */ -typedef grn_id grn_ts_id; -typedef float grn_ts_score; -typedef struct { - grn_ts_id id; - grn_ts_score score; -} grn_ts_record; - -/* Built-in scalar data types. */ -typedef grn_bool grn_ts_bool; -typedef int64_t grn_ts_int; -typedef double grn_ts_float; -typedef int64_t grn_ts_time; -typedef struct { - const char *ptr; - size_t size; -} grn_ts_text; -typedef grn_geo_point grn_ts_geo_point; -typedef grn_geo_point grn_ts_tokyo_geo_point; -typedef grn_geo_point grn_ts_wgs84_geo_point; -typedef grn_ts_record grn_ts_ref; - -/* Built-in vector data types. */ -typedef struct { - const grn_ts_bool *ptr; - size_t size; -} grn_ts_bool_vector; -typedef struct { - const grn_ts_int *ptr; - size_t size; -} grn_ts_int_vector; -typedef struct { - const grn_ts_float *ptr; - size_t size; -} grn_ts_float_vector; -typedef struct { - const grn_ts_time *ptr; - size_t size; -} grn_ts_time_vector; -typedef struct { - const grn_ts_text *ptr; - size_t size; -} grn_ts_text_vector; -typedef struct { - const grn_ts_geo_point *ptr; - size_t size; -} grn_ts_geo_point_vector; -typedef grn_ts_geo_point_vector grn_ts_tokyo_geo_point_vector; -typedef grn_ts_geo_point_vector grn_ts_wgs84_geo_point_vector; -typedef struct { - const grn_ts_ref *ptr; - size_t size; -} grn_ts_ref_vector; - -/*------------------------------------------------------------- * Expression components. */ @@ -355,6 +298,10 @@ 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, + grn_ts_buf *out); /* grn_ts_expr_filter() filters records. */ grn_rc grn_ts_expr_filter(grn_ctx *ctx, grn_ts_expr *expr, @@ -365,30 +312,8 @@ grn_rc grn_ts_expr_filter(grn_ctx *ctx, grn_ts_expr *expr, grn_rc grn_ts_expr_adjust(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_record *io, size_t n_io); -/*------------------------------------------------------------- - * API. - */ - -/* - * grn_ts_select() finds records passing through a filter and writes the values - * of output columns (the evaluation results of output expressions) into the - * output buffer (`ctx->impl->outbuf`). - * - * Note that the first `offset` records will be discarded and at most `limit` - * records will be output. - * - * On success, grn_ts_select() returns GRN_SUCCESS. - * On failure, grn_ts_select() returns an error code and set the details into - * `ctx`. - */ -grn_rc grn_ts_select(grn_ctx *ctx, grn_obj *table, - const char *filter_ptr, size_t filter_size, - const char *output_columns_ptr, - size_t output_columns_size, - size_t offset, size_t limit); - #ifdef __cplusplus } #endif -#endif /* GRN_TS_H */ +#endif /* GRN_TS_EXPR_H */