diff options
Diffstat (limited to 'storage/mroonga/vendor/groonga/plugins/table/table.c')
-rw-r--r-- | storage/mroonga/vendor/groonga/plugins/table/table.c | 747 |
1 files changed, 747 insertions, 0 deletions
diff --git a/storage/mroonga/vendor/groonga/plugins/table/table.c b/storage/mroonga/vendor/groonga/plugins/table/table.c new file mode 100644 index 00000000000..a4fcd17bf90 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/table/table.c @@ -0,0 +1,747 @@ +/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* Copyright(C) 2012 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <string.h> + +#include "ctx.h" +#include "db.h" +#include "output.h" +#include "util.h" +#include <groonga/plugin.h> + +#define VAR GRN_PROC_GET_VAR_BY_OFFSET +#define TEXT_VALUE_LEN(x) GRN_TEXT_VALUE(x), GRN_TEXT_LEN(x) + +static grn_obj * +grn_ctx_get_table_by_name_or_id(grn_ctx *ctx, + const char *name, unsigned int name_len) +{ + grn_obj *table; + const char *end = name + name_len; + const char *rest = NULL; + grn_id id = grn_atoui(name, end, &rest); + if (rest == end) { + table = grn_ctx_at(ctx, id); + } else { + table = grn_ctx_get(ctx, name, name_len); + } + if (!GRN_OBJ_TABLEP(table)) { + ERR(GRN_INVALID_ARGUMENT, "invalid table name: <%.*s>", name_len, name); + if (table) { + grn_obj_unlink(ctx, table); + table = NULL; + } + } + return table; +} + +static void +grn_output_table_name_or_id(grn_ctx *ctx, grn_obj *table) +{ + if (table) { + if (((grn_db_obj *)table)->id & GRN_OBJ_TMP_OBJECT) { + GRN_OUTPUT_INT64(((grn_db_obj *)table)->id); + } else { + int name_len; + char name_buf[GRN_TABLE_MAX_KEY_SIZE]; + name_len = grn_obj_name(ctx, table, name_buf, GRN_TABLE_MAX_KEY_SIZE); + GRN_OUTPUT_STR(name_buf, name_len); + } + } else { + GRN_OUTPUT_INT64(0); + } +} + +static grn_bool +parse_bool_value(grn_ctx *ctx, grn_obj *text) +{ + grn_bool value = GRN_FALSE; + if (GRN_TEXT_LEN(text) == 3 && + memcmp("yes", GRN_TEXT_VALUE(text), 3) == 0) { + value = GRN_TRUE; + } + return value; +} + +static grn_operator +parse_set_operator_value(grn_ctx *ctx, grn_obj *text) +{ + grn_operator value = GRN_OP_OR; + if (GRN_TEXT_LEN(text) == 3) { + if (memcmp("and", GRN_TEXT_VALUE(text), 3) == 0) { + value = GRN_OP_AND; + } else if (memcmp("but", GRN_TEXT_VALUE(text), 3) == 0) { + value = GRN_OP_AND_NOT; + } + } else if (GRN_TEXT_LEN(text) == 6 && + memcmp("adjust", GRN_TEXT_VALUE(text), 6) == 0) { + value = GRN_OP_ADJUST; + } else if (GRN_TEXT_LEN(text) == 7 && + memcmp("and_not", GRN_TEXT_VALUE(text), 7) == 0) { + value = GRN_OP_AND_NOT; + } + return value; +} + +static grn_obj * +command_match(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *result_set = NULL; + grn_obj *table = grn_ctx_get_table_by_name_or_id(ctx, TEXT_VALUE_LEN(VAR(0))); + if (table) { + grn_expr_flags flags = GRN_EXPR_SYNTAX_QUERY; + grn_obj *v, *query, *columns = NULL; + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, query, v); + if (query) { + if (GRN_TEXT_LEN(VAR(1))) { + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, columns, v); + if (columns) { + grn_expr_parse(ctx, columns, TEXT_VALUE_LEN(VAR(1)), + NULL, GRN_OP_MATCH, GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT); + } + } + if (parse_bool_value(ctx, VAR(5))) { + flags |= GRN_EXPR_ALLOW_COLUMN; + } + if (parse_bool_value(ctx, VAR(6))) { + flags |= GRN_EXPR_ALLOW_PRAGMA; + } + grn_expr_parse(ctx, query, TEXT_VALUE_LEN(VAR(2)), + columns, GRN_OP_MATCH, GRN_OP_AND, flags); + if (GRN_TEXT_LEN(VAR(3))) { + result_set = grn_ctx_get_table_by_name_or_id(ctx, TEXT_VALUE_LEN(VAR(3))); + } else { + result_set = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY| + GRN_OBJ_WITH_SUBREC, + table, NULL); + } + if (result_set) { + grn_table_select(ctx, table, query, result_set, + parse_set_operator_value(ctx, VAR(4))); + } + grn_obj_unlink(ctx, columns); + grn_obj_unlink(ctx, query); + } + } + grn_output_table_name_or_id(ctx, result_set); + return NULL; +} + +static grn_obj * +command_filter_by_script(grn_ctx *ctx, int nargs, + grn_obj **args, grn_user_data *user_data) +{ + grn_obj *result_set = NULL; + grn_obj *table = grn_ctx_get_table_by_name_or_id(ctx, TEXT_VALUE_LEN(VAR(0))); + if (table) { + grn_expr_flags flags = GRN_EXPR_SYNTAX_SCRIPT; + grn_obj *v, *query; + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, query, v); + if (query) { + if (parse_bool_value(ctx, VAR(4))) { + flags |= GRN_EXPR_ALLOW_UPDATE; + } + grn_expr_parse(ctx, query, TEXT_VALUE_LEN(VAR(1)), + NULL, GRN_OP_MATCH, GRN_OP_AND, flags); + if (GRN_TEXT_LEN(VAR(2))) { + result_set = grn_ctx_get_table_by_name_or_id(ctx, TEXT_VALUE_LEN(VAR(2))); + } else { + result_set = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY| + GRN_OBJ_WITH_SUBREC, + table, NULL); + } + if (result_set) { + grn_table_select(ctx, table, query, result_set, + parse_set_operator_value(ctx, VAR(3))); + } + grn_obj_unlink(ctx, query); + } + } + grn_output_table_name_or_id(ctx, result_set); + return NULL; +} + +static grn_obj * +command_filter(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_operator operator = GRN_OP_NOP; + grn_obj *table, *column, *result_set = NULL; + if (!(table = grn_ctx_get_table_by_name_or_id(ctx, TEXT_VALUE_LEN(VAR(0))))) { + goto exit; + } + if (!(column = grn_obj_column(ctx, table, TEXT_VALUE_LEN(VAR(1))))) { + ERR(GRN_INVALID_ARGUMENT, "invalid column name: <%.*s>", + (int)GRN_TEXT_LEN(VAR(1)), GRN_TEXT_VALUE(VAR(1))); + goto exit; + } + if (GRN_TEXT_LEN(VAR(2)) == 0) { + ERR(GRN_INVALID_ARGUMENT, "missing mandatory argument: operator"); + goto exit; + } else { + uint32_t operator_len = GRN_TEXT_LEN(VAR(2)); + const char *operator_text = GRN_TEXT_VALUE(VAR(2)); + switch (operator_text[0]) { + case '<' : + if (operator_len == 1) { + operator = GRN_OP_LESS; + } + break; + } + if (operator == GRN_OP_NOP) { + ERR(GRN_INVALID_ARGUMENT, "invalid operator: <%.*s>", + operator_len, operator_text); + goto exit; + } + } + if (GRN_TEXT_LEN(VAR(4))) { + result_set = grn_ctx_get_table_by_name_or_id(ctx, TEXT_VALUE_LEN(VAR(4))); + } else { + result_set = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY| + GRN_OBJ_WITH_SUBREC, + table, NULL); + } + if (result_set) { + grn_column_filter(ctx, column, operator, VAR(3), result_set, + parse_set_operator_value(ctx, VAR(5))); + } +exit : + grn_output_table_name_or_id(ctx, result_set); + return NULL; +} + +static grn_obj * +command_group(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + const char *table = GRN_TEXT_VALUE(VAR(0)); + unsigned int table_len = GRN_TEXT_LEN(VAR(0)); + const char *key = GRN_TEXT_VALUE(VAR(1)); + unsigned int key_len = GRN_TEXT_LEN(VAR(1)); + const char *set = GRN_TEXT_VALUE(VAR(2)); + unsigned int set_len = GRN_TEXT_LEN(VAR(2)); + grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len); + grn_obj *set_ = NULL; + if (table_) { + uint32_t ngkeys; + grn_table_sort_key *gkeys; + gkeys = grn_table_sort_key_from_str(ctx, key, key_len, table_, &ngkeys); + if (gkeys) { + if (set_len) { + set_ = grn_ctx_get_table_by_name_or_id(ctx, set, set_len); + } else { + set_ = grn_table_create_for_group(ctx, NULL, 0, NULL, + gkeys[0].key, table_, 0); + } + if (set_) { + if (GRN_TEXT_LEN(VAR(3))) { + uint32_t gap = grn_atoui(GRN_TEXT_VALUE(VAR(3)), + GRN_BULK_CURR(VAR(3)), NULL); + grn_table_group_with_range_gap(ctx, table_, gkeys, set_, gap); + } else { + grn_table_group_result g = { + set_, 0, 0, 1, + GRN_TABLE_GROUP_CALC_COUNT, 0 + }; + grn_table_group(ctx, table_, gkeys, 1, &g, 1); + } + } + grn_table_sort_key_close(ctx, gkeys, ngkeys); + } + } + grn_output_table_name_or_id(ctx, set_); + return NULL; +} + +#define DEFAULT_LIMIT 10 + +static grn_obj * +command_sort(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + const char *table = GRN_TEXT_VALUE(VAR(0)); + unsigned int table_len = GRN_TEXT_LEN(VAR(0)); + const char *keys = GRN_TEXT_VALUE(VAR(1)); + unsigned int keys_len = GRN_TEXT_LEN(VAR(1)); + int offset = GRN_TEXT_LEN(VAR(2)) + ? grn_atoi(GRN_TEXT_VALUE(VAR(2)), GRN_BULK_CURR(VAR(2)), NULL) + : 0; + int limit = GRN_TEXT_LEN(VAR(3)) + ? grn_atoi(GRN_TEXT_VALUE(VAR(3)), GRN_BULK_CURR(VAR(3)), NULL) + : DEFAULT_LIMIT; + grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len); + grn_obj *sorted = NULL; + if (table_) { + uint32_t nkeys; + grn_table_sort_key *keys_; + if (keys_len && + (keys_ = grn_table_sort_key_from_str(ctx, keys, keys_len, + table_, &nkeys))) { + if ((sorted = grn_table_create(ctx, NULL, 0, NULL, + GRN_OBJ_TABLE_NO_KEY, NULL, table_))) { + int table_size = (int)grn_table_size(ctx, table_); + grn_normalize_offset_and_limit(ctx, table_size, &offset, &limit); + grn_table_sort(ctx, table_, offset, limit, sorted, keys_, nkeys); + grn_table_sort_key_close(ctx, keys_, nkeys); + } + } + } + grn_output_table_name_or_id(ctx, sorted); + return NULL; +} + +static grn_obj * +command_output(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + const char *table = GRN_TEXT_VALUE(VAR(0)); + unsigned int table_len = GRN_TEXT_LEN(VAR(0)); + const char *columns = GRN_TEXT_VALUE(VAR(1)); + unsigned int columns_len = GRN_TEXT_LEN(VAR(1)); + int offset = GRN_TEXT_LEN(VAR(2)) + ? grn_atoi(GRN_TEXT_VALUE(VAR(2)), GRN_BULK_CURR(VAR(2)), NULL) + : 0; + int limit = GRN_TEXT_LEN(VAR(3)) + ? grn_atoi(GRN_TEXT_VALUE(VAR(3)), GRN_BULK_CURR(VAR(3)), NULL) + : DEFAULT_LIMIT; + grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len); + if (table_) { + grn_obj_format format; + int table_size = (int)grn_table_size(ctx, table_); + GRN_OBJ_FORMAT_INIT(&format, table_size, 0, limit, offset); + format.flags = + GRN_OBJ_FORMAT_WITH_COLUMN_NAMES| + GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET; + /* TODO: accept only comma separated expr as columns */ + grn_obj_columns(ctx, table_, columns, columns_len, &format.columns); + GRN_OUTPUT_OBJ(table_, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); + } + return NULL; +} + +static grn_obj * +command_each(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + const char *table = GRN_TEXT_VALUE(VAR(0)); + unsigned int table_len = GRN_TEXT_LEN(VAR(0)); + const char *expr = GRN_TEXT_VALUE(VAR(1)); + unsigned int expr_len = GRN_TEXT_LEN(VAR(1)); + grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len); + if (table_) { + grn_obj *v, *expr_; + GRN_EXPR_CREATE_FOR_QUERY(ctx, table_, expr_, v); + if (expr_ && v) { + grn_table_cursor *tc; + grn_expr_parse(ctx, expr_, expr, expr_len, + NULL, GRN_OP_MATCH, GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE); + if ((tc = grn_table_cursor_open(ctx, table_, NULL, 0, + NULL, 0, 0, -1, 0))) { + grn_id id; + while ((id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) { + GRN_RECORD_SET(ctx, v, id); + grn_expr_exec(ctx, expr_, 0); + } + grn_table_cursor_close(ctx, tc); + } + grn_obj_unlink(ctx, expr_); + } + } + GRN_OUTPUT_BOOL(!ctx->rc); + return NULL; +} + +static grn_obj * +command_unlink(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + const char *table = GRN_TEXT_VALUE(VAR(0)); + unsigned int table_len = GRN_TEXT_LEN(VAR(0)); + grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len); + if (table_) { + grn_obj_unlink(ctx, table_); + } + GRN_OUTPUT_BOOL(!ctx->rc); + return NULL; +} + +static grn_obj * +command_add(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_load_(ctx, GRN_CONTENT_JSON, + GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0)), + NULL, 0, + GRN_TEXT_VALUE(VAR(1)), GRN_TEXT_LEN(VAR(1)), + NULL, 0, NULL, 0, 0); + GRN_OUTPUT_BOOL(ctx->impl->loader.nrecords); + if (ctx->impl->loader.table) { + grn_db_touch(ctx, DB_OBJ(ctx->impl->loader.table)->db); + } + return NULL; +} + +static grn_obj * +command_set(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + int table_name_len = GRN_TEXT_LEN(VAR(0)); + const char *table_name = GRN_TEXT_VALUE(VAR(0)); + grn_obj *table = grn_ctx_get(ctx, table_name, table_name_len); + if (table) { + grn_id id = GRN_ID_NIL; + int key_len = GRN_TEXT_LEN(VAR(2)); + int id_len = GRN_TEXT_LEN(VAR(5)); + if (key_len) { + const char *key = GRN_TEXT_VALUE(VAR(2)); + id = grn_table_get(ctx, table, key, key_len); + } else { + if (id_len) { + id = grn_atoui(GRN_TEXT_VALUE(VAR(5)), GRN_BULK_CURR(VAR(5)), NULL); + } + id = grn_table_at(ctx, table, id); + } + if (id) { + grn_obj obj; + grn_obj_format format; + GRN_RECORD_INIT(&obj, 0, ((grn_db_obj *)table)->id); + GRN_OBJ_FORMAT_INIT(&format, 1, 0, 1, 0); + GRN_RECORD_SET(ctx, &obj, id); + grn_obj_columns(ctx, table, + GRN_TEXT_VALUE(VAR(4)), + GRN_TEXT_LEN(VAR(4)), &format.columns); + format.flags = 0 /* GRN_OBJ_FORMAT_WITH_COLUMN_NAMES */; + GRN_OUTPUT_OBJ(&obj, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); + } + } else { + ERR(GRN_INVALID_ARGUMENT, + "nonexistent table name: <%.*s>", table_name_len, table_name); + } + return NULL; +} + +static grn_rc +command_get_resolve_parameters(grn_ctx *ctx, grn_user_data *user_data, + grn_obj **table, grn_id *id) +{ + const char *table_text, *id_text, *key_text; + int table_length, id_length, key_length; + + table_text = GRN_TEXT_VALUE(VAR(0)); + table_length = GRN_TEXT_LEN(VAR(0)); + if (table_length == 0) { + ERR(GRN_INVALID_ARGUMENT, "[table][get] table isn't specified"); + return ctx->rc; + } + + *table = grn_ctx_get(ctx, table_text, table_length); + if (!*table) { + ERR(GRN_INVALID_ARGUMENT, + "[table][get] table doesn't exist: <%.*s>", table_length, table_text); + return ctx->rc; + } + + key_text = GRN_TEXT_VALUE(VAR(1)); + key_length = GRN_TEXT_LEN(VAR(1)); + id_text = GRN_TEXT_VALUE(VAR(3)); + id_length = GRN_TEXT_LEN(VAR(3)); + switch ((*table)->header.type) { + case GRN_TABLE_NO_KEY: + if (key_length) { + ERR(GRN_INVALID_ARGUMENT, + "[table][get] should not specify key for NO_KEY table: <%.*s>: " + "table: <%.*s>", + key_length, key_text, + table_length, table_text); + return ctx->rc; + } + if (id_length) { + const char *rest = NULL; + *id = grn_atoi(id_text, id_text + id_length, &rest); + if (rest == id_text) { + ERR(GRN_INVALID_ARGUMENT, + "[table][get] ID should be a number: <%.*s>: table: <%.*s>", + id_length, id_text, + table_length, table_text); + } + } else { + ERR(GRN_INVALID_ARGUMENT, + "[table][get] ID isn't specified: table: <%.*s>", + table_length, table_text); + } + break; + case GRN_TABLE_HASH_KEY: + case GRN_TABLE_PAT_KEY: + case GRN_TABLE_DAT_KEY: + if (key_length && id_length) { + ERR(GRN_INVALID_ARGUMENT, + "[table][get] should not specify both key and ID: " + "key: <%.*s>: ID: <%.*s>: table: <%.*s>", + key_length, key_text, + id_length, id_text, + table_length, table_text); + return ctx->rc; + } + if (key_length) { + *id = grn_table_get(ctx, *table, key_text, key_length); + if (!*id) { + ERR(GRN_INVALID_ARGUMENT, + "[table][get] nonexistent key: <%.*s>: table: <%.*s>", + key_length, key_text, + table_length, table_text); + } + } else { + if (id_length) { + const char *rest = NULL; + *id = grn_atoi(id_text, id_text + id_length, &rest); + if (rest == id_text) { + ERR(GRN_INVALID_ARGUMENT, + "[table][get] ID should be a number: <%.*s>: table: <%.*s>", + id_length, id_text, + table_length, table_text); + } + } else { + ERR(GRN_INVALID_ARGUMENT, + "[table][get] key nor ID isn't specified: table: <%.*s>", + table_length, table_text); + } + } + break; + default: + ERR(GRN_INVALID_ARGUMENT, + "[table][get] not a table: <%.*s>", table_length, table_text); + break; + } + + return ctx->rc; +} + +static grn_obj * +command_get(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_id id = GRN_ID_NIL; + grn_obj *table = NULL; + if (!command_get_resolve_parameters(ctx, user_data, &table, &id)) { + grn_obj obj; + grn_obj_format format; + GRN_OUTPUT_ARRAY_OPEN("RESULT", 2); + GRN_RECORD_INIT(&obj, 0, ((grn_db_obj *)table)->id); + GRN_OBJ_FORMAT_INIT(&format, 1, 0, 1, 0); + GRN_RECORD_SET(ctx, &obj, id); + grn_obj_columns(ctx, table, GRN_TEXT_VALUE(VAR(2)), GRN_TEXT_LEN(VAR(2)), + &format.columns); + format.flags = + GRN_OBJ_FORMAT_WITH_COLUMN_NAMES | + GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET; + GRN_OUTPUT_OBJ(&obj, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); + GRN_OUTPUT_ARRAY_CLOSE(); + } + return NULL; +} + +static grn_obj * +command_push(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *table = grn_ctx_get(ctx, GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0))); + if (table) { + switch (table->header.type) { + case GRN_TABLE_NO_KEY: + { + grn_array *array = (grn_array *)table; + grn_table_queue *queue = grn_array_queue(ctx, array); + if (queue) { + MUTEX_LOCK(queue->mutex); + if (grn_table_queue_head(queue) == queue->cap) { + grn_array_clear_curr_rec(ctx, array); + } + grn_load_(ctx, GRN_CONTENT_JSON, + GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0)), + NULL, 0, + GRN_TEXT_VALUE(VAR(1)), GRN_TEXT_LEN(VAR(1)), + NULL, 0, NULL, 0, 0); + if (grn_table_queue_size(queue) == queue->cap) { + grn_table_queue_tail_increment(queue); + } + grn_table_queue_head_increment(queue); + COND_SIGNAL(queue->cond); + MUTEX_UNLOCK(queue->mutex); + GRN_OUTPUT_BOOL(ctx->impl->loader.nrecords); + if (ctx->impl->loader.table) { + grn_db_touch(ctx, DB_OBJ(ctx->impl->loader.table)->db); + } + } else { + ERR(GRN_OPERATION_NOT_SUPPORTED, "table '%.*s' doesn't support push", + (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0))); + } + } + break; + default : + ERR(GRN_OPERATION_NOT_SUPPORTED, "table '%.*s' doesn't support push", + (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0))); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "table '%.*s' does not exist.", + (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0))); + } + return NULL; +} + +static grn_obj * +command_pull(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *table = grn_ctx_get(ctx, GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0))); + if (table) { + switch (table->header.type) { + case GRN_TABLE_NO_KEY: + { + grn_array *array = (grn_array *)table; + grn_table_queue *queue = grn_array_queue(ctx, array); + if (queue) { + MUTEX_LOCK(queue->mutex); + while (grn_table_queue_size(queue) == 0) { + if (GRN_TEXT_LEN(VAR(2))) { + MUTEX_UNLOCK(queue->mutex); + GRN_OUTPUT_BOOL(0); + return NULL; + } + COND_WAIT(queue->cond, queue->mutex); + } + grn_table_queue_tail_increment(queue); + { + grn_obj obj; + grn_obj_format format; + GRN_RECORD_INIT(&obj, 0, ((grn_db_obj *)table)->id); + GRN_OBJ_FORMAT_INIT(&format, 1, 0, 1, 0); + GRN_RECORD_SET(ctx, &obj, grn_table_queue_tail(queue)); + grn_obj_columns(ctx, table, GRN_TEXT_VALUE(VAR(1)), GRN_TEXT_LEN(VAR(1)), + &format.columns); + format.flags = 0 /* GRN_OBJ_FORMAT_WITH_COLUMN_NAMES */; + GRN_OUTPUT_OBJ(&obj, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); + } + MUTEX_UNLOCK(queue->mutex); + } else { + ERR(GRN_OPERATION_NOT_SUPPORTED, "table '%.*s' doesn't support pull", + (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0))); + } + } + break; + default : + ERR(GRN_OPERATION_NOT_SUPPORTED, "table '%.*s' doesn't support pull", + (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0))); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "table '%.*s' does not exist.", + (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0))); + } + return NULL; +} + +grn_rc +GRN_PLUGIN_INIT(grn_ctx *ctx) +{ + return GRN_SUCCESS; +} + +grn_rc +GRN_PLUGIN_REGISTER(grn_ctx *ctx) +{ + grn_expr_var vars[18]; + + grn_plugin_expr_var_init(ctx, &vars[0], "table", -1); + grn_plugin_expr_var_init(ctx, &vars[1], "expression", -1); + grn_plugin_expr_var_init(ctx, &vars[2], "result_set", -1); + grn_plugin_expr_var_init(ctx, &vars[3], "set_operation", -1); + grn_plugin_expr_var_init(ctx, &vars[4], "allow_update", -1); + grn_plugin_command_create(ctx, "filter_by_script", -1, command_filter_by_script, 5, vars); + + grn_plugin_expr_var_init(ctx, &vars[0], "table", -1); + grn_plugin_expr_var_init(ctx, &vars[1], "column", -1); + grn_plugin_expr_var_init(ctx, &vars[2], "operator", -1); + grn_plugin_expr_var_init(ctx, &vars[3], "value", -1); + grn_plugin_expr_var_init(ctx, &vars[4], "result_set", -1); + grn_plugin_expr_var_init(ctx, &vars[5], "set_operation", -1); + grn_plugin_command_create(ctx, "filter", -1, command_filter, 6, vars); + + grn_plugin_expr_var_init(ctx, &vars[0], "table", -1); + grn_plugin_expr_var_init(ctx, &vars[1], "key", -1); + grn_plugin_expr_var_init(ctx, &vars[2], "result_set", -1); + grn_plugin_expr_var_init(ctx, &vars[3], "range_gap", -1); + grn_plugin_command_create(ctx, "group", -1, command_group, 4, vars); + + grn_plugin_expr_var_init(ctx, &vars[0], "table", -1); + grn_plugin_expr_var_init(ctx, &vars[1], "keys", -1); + grn_plugin_expr_var_init(ctx, &vars[2], "offset", -1); + grn_plugin_expr_var_init(ctx, &vars[3], "limit", -1); + grn_plugin_command_create(ctx, "sort", -1, command_sort, 4, vars); + + grn_plugin_expr_var_init(ctx, &vars[0], "table", -1); + grn_plugin_expr_var_init(ctx, &vars[1], "columns", -1); + grn_plugin_expr_var_init(ctx, &vars[2], "offset", -1); + grn_plugin_expr_var_init(ctx, &vars[3], "limit", -1); + grn_plugin_command_create(ctx, "output", -1, command_output, 4, vars); + + grn_plugin_expr_var_init(ctx, &vars[0], "table", -1); + grn_plugin_expr_var_init(ctx, &vars[1], "expression", -1); + grn_plugin_command_create(ctx, "each", -1, command_each, 2, vars); + + grn_plugin_expr_var_init(ctx, &vars[0], "table", -1); + grn_plugin_command_create(ctx, "unlink", -1, command_unlink, 1, vars); + + grn_plugin_expr_var_init(ctx, &vars[0], "table", -1); + grn_plugin_expr_var_init(ctx, &vars[1], "values", -1); + grn_plugin_expr_var_init(ctx, &vars[2], "key", -1); + grn_plugin_expr_var_init(ctx, &vars[3], "columns", -1); + grn_plugin_expr_var_init(ctx, &vars[4], "output_columns", -1); + grn_plugin_expr_var_init(ctx, &vars[5], "id", -1); + grn_plugin_command_create(ctx, "add", -1, command_add, 2, vars); + grn_plugin_command_create(ctx, "push", -1, command_push, 2, vars); + grn_plugin_command_create(ctx, "set", -1, command_set, 6, vars); + + grn_plugin_expr_var_init(ctx, &vars[0], "table", -1); + grn_plugin_expr_var_init(ctx, &vars[1], "key", -1); + grn_plugin_expr_var_init(ctx, &vars[2], "output_columns", -1); + grn_plugin_expr_var_init(ctx, &vars[3], "id", -1); + grn_plugin_command_create(ctx, "get", -1, command_get, 4, vars); + + grn_plugin_expr_var_init(ctx, &vars[0], "table", -1); + grn_plugin_expr_var_init(ctx, &vars[1], "output_columns", -1); + grn_plugin_expr_var_init(ctx, &vars[2], "non_block", -1); + grn_plugin_command_create(ctx, "pull", -1, command_pull, 3, vars); + + grn_plugin_expr_var_init(ctx, &vars[0], "table", -1); + grn_plugin_expr_var_init(ctx, &vars[1], "columns", -1); + grn_plugin_expr_var_init(ctx, &vars[2], "query", -1); + grn_plugin_expr_var_init(ctx, &vars[3], "result_set", -1); + grn_plugin_expr_var_init(ctx, &vars[4], "set_operation", -1); + grn_plugin_expr_var_init(ctx, &vars[5], "allow_column_expression", -1); + grn_plugin_expr_var_init(ctx, &vars[6], "allow_pragma", -1); + grn_plugin_command_create(ctx, "match", -1, command_match, 7, vars); + + return ctx->rc; +} + +grn_rc +GRN_PLUGIN_FIN(grn_ctx *ctx) +{ + return GRN_SUCCESS; +} |