From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtpng3.m.smailru.net (smtpng3.m.smailru.net [94.100.177.149]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 8E6CA46970E for ; Fri, 27 Dec 2019 17:05:07 +0300 (MSK) From: imeevma@tarantool.org Date: Fri, 27 Dec 2019 17:05:05 +0300 Message-Id: <636502cf63bd55baee627913f1392176997c182b.1577455413.git.imeevma@gmail.com> In-Reply-To: References: Subject: [Tarantool-patches] [PATCH v5 2/3] box: introduce _session_settings system space List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: korablev@tarantool.org Cc: tarantool-patches@dev.tarantool.org This patch creates _session_settings system space. This space is used to view and change session settings. There are no settings at the moment, some will be added in the next patch. Part of #4511 --- src/box/CMakeLists.txt | 1 + src/box/bootstrap.snap | Bin 5921 -> 5975 bytes src/box/lua/space.cc | 2 + src/box/lua/upgrade.lua | 15 + src/box/schema_def.h | 8 + src/box/session_settings.c | 472 +++++++++++++++++++++ src/box/session_settings.h | 69 +++ src/box/virtual_engine.c | 54 ++- test/app-tap/tarantoolctl.test.lua | 4 +- test/box-py/bootstrap.result | 3 + test/box/access_sysview.result | 6 +- test/box/alter.result | 5 +- ...h-4511-access-settings-from-any-frontend.result | 108 ++++- ...4511-access-settings-from-any-frontend.test.lua | 37 ++ test/wal_off/alter.result | 2 +- 15 files changed, 770 insertions(+), 16 deletions(-) create mode 100644 src/box/session_settings.c create mode 100644 src/box/session_settings.h diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt index d79d52c..b57e90b 100644 --- a/src/box/CMakeLists.txt +++ b/src/box/CMakeLists.txt @@ -80,6 +80,7 @@ add_library(box STATIC sysview.c blackhole.c virtual_engine.c + session_settings.c vinyl.c vy_stmt.c vy_mem.c diff --git a/src/box/lua/space.cc b/src/box/lua/space.cc index f6e96f0..01b58af 100644 --- a/src/box/lua/space.cc +++ b/src/box/lua/space.cc @@ -653,6 +653,8 @@ box_lua_space_init(struct lua_State *L) lua_setfield(L, -2, "SPACE_SEQUENCE_ID"); lua_pushnumber(L, BOX_FUNC_INDEX_ID); lua_setfield(L, -2, "FUNC_INDEX_ID"); + lua_pushnumber(L, BOX_SESSION_SETTINGS_ID); + lua_setfield(L, -2, "SESSION_SETTINGS_ID"); lua_pushnumber(L, BOX_SYSTEM_ID_MIN); lua_setfield(L, -2, "SYSTEM_ID_MIN"); lua_pushnumber(L, BOX_SYSTEM_ID_MAX); diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua index 07f1e03..4dfd571 100644 --- a/src/box/lua/upgrade.lua +++ b/src/box/lua/upgrade.lua @@ -951,8 +951,23 @@ local function drop_func_collation() _func.index.name:alter({parts = {{'name', 'string'}}}) end +local function create_session_settings_space() + local _space = box.space[box.schema.SPACE_ID] + local _index = box.space[box.schema.INDEX_ID] + local format = {} + format[1] = {name='name', type='string'} + format[2] = {name='value', type='any'} + log.info("create space _session_settings") + _space:insert{box.schema.SESSION_SETTINGS_ID, ADMIN, '_session_settings', + 'virtual', 2, {temporary = true}, format} + log.info("create index _session_settings:primary") + _index:insert{box.schema.SESSION_SETTINGS_ID, 0, 'primary', 'tree', + {unique = true}, {{0, 'string'}}} +end + local function upgrade_to_2_3_1() drop_func_collation() + create_session_settings_space() end -------------------------------------------------------------------------------- diff --git a/src/box/schema_def.h b/src/box/schema_def.h index ba870ff..f86cd42 100644 --- a/src/box/schema_def.h +++ b/src/box/schema_def.h @@ -114,6 +114,8 @@ enum { BOX_CK_CONSTRAINT_ID = 364, /** Space id of _func_index. */ BOX_FUNC_INDEX_ID = 372, + /** Space id of _session_settings. */ + BOX_SESSION_SETTINGS_ID = 380, /** End of the reserved range of system spaces. */ BOX_SYSTEM_ID_MAX = 511, BOX_ID_NIL = 2147483647 @@ -277,6 +279,12 @@ enum { BOX_FUNC_INDEX_FUNCTION_ID = 2, }; +/** _session_settings fields. */ +enum { + BOX_SESSION_SETTINGS_FIELD_NAME = 0, + BOX_SESSION_SETTINGS_FIELD_VALUE = 1, +}; + /* * Different objects which can be subject to access * control. diff --git a/src/box/session_settings.c b/src/box/session_settings.c new file mode 100644 index 0000000..dd1874b --- /dev/null +++ b/src/box/session_settings.c @@ -0,0 +1,472 @@ +/* + * Copyright 2010-2019, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "session_settings.h" +#include "xrow_update.h" +#include "virtual_engine.h" +#include "column_mask.h" +#include "session.h" +#include "schema.h" +#include "tuple.h" +#include "xrow.h" +#include "sql.h" + +struct session_setting_module + session_setting_modules[session_setting_type_MAX] = {}; + +struct session_settings_index { + /** Base index. Must be the first member. */ + struct index base; + /** + * Format of the tuples iterators of this index return. It + * is stored here so as not to lookup space each time to + * get a format and create an iterator. + */ + struct tuple_format *format; +}; + +struct session_settings_iterator { + /** Base iterator. Must be the first member. */ + struct iterator base; + /** + * Format of the tuples this iterator returns. It is + * stored here so as not to lookup space each time to get + * a format for selected tuples. + */ + struct tuple_format *format; + /** + * ID of the current session settings module in the global + * list of the modules. + */ + int module_id; + /** ID of the setting in current module. */ + int setting_id; + /** Decoded key. */ + char *key; + /** True if the iterator returns only equal keys. */ + bool is_eq; + /** True if the iterator should include equal keys. */ + bool is_including; +}; + +static void +session_settings_iterator_free(struct iterator *ptr) +{ + struct session_settings_iterator *it = + (struct session_settings_iterator *)ptr; + free(it->key); + free(it); +} + +static int +session_settings_next_in_module(const struct session_setting_module *module, + int *sid, const char *key, bool is_eq, + bool is_including) +{ + int i = *sid; + int count = module->setting_count; + if (i >= count) + return -1; + if (key == NULL) + return 0; + assert(i >= 0); + const char **name = &module->settings[i]; + for (; i < count; ++i, ++name) { + int cmp = strcmp(*name, key); + if ((cmp == 0 && is_including) || + (cmp > 0 && !is_eq)) { + *sid = i; + return 0; + } + } + *sid = count; + return -1; +} + +static int +session_settings_prev_in_module(const struct session_setting_module *module, + int *sid, const char *key, bool is_eq, + bool is_including) +{ + int i = *sid; + int count = module->setting_count; + if (i < 0) + return -1; + if (key == NULL) + return 0; + if (i >= count) + i = count - 1; + const char **name = &module->settings[i]; + for (; i >= 0; --i, --name) { + int cmp = strcmp(*name, key); + if ((cmp == 0 && is_including) || + (cmp < 0 && !is_eq)) { + *sid = i; + return 0; + } + } + *sid = -1; + return -1; +} + +static int +session_settings_iterator_next(struct iterator *iterator, struct tuple **result) +{ + struct session_settings_iterator *it = + (struct session_settings_iterator *)iterator; + int mid = it->module_id, sid = it->setting_id; + struct session_setting_module *module; + const char *key = it->key; + bool is_including = it->is_including, is_eq = it->is_eq; + bool is_found = false; + for (; mid < session_setting_type_MAX; ++mid, sid = 0) { + module = &session_setting_modules[mid]; + if (session_settings_next_in_module(module, &sid, key, is_eq, + is_including) == 0) { + is_found = true; + break; + } + } + it->module_id = mid; + it->setting_id = sid + 1; + if (!is_found) { + *result = NULL; + return 0; + } + const char *mp_pair, *mp_pair_end; + module->get(sid, &mp_pair, &mp_pair_end); + *result = box_tuple_new(it->format, mp_pair, mp_pair_end); + return *result != NULL ? 0 : -1; +} + +static int +session_settings_iterator_prev(struct iterator *iterator, struct tuple **result) +{ + struct session_settings_iterator *it = + (struct session_settings_iterator *)iterator; + int mid = it->module_id, sid = it->setting_id; + struct session_setting_module *module; + const char *key = it->key; + bool is_including = it->is_including, is_eq = it->is_eq; + bool is_found = false; + for (; mid >= 0; --mid, sid = INT_MAX) { + module = &session_setting_modules[mid]; + if (session_settings_prev_in_module(module, &sid, key, is_eq, + is_including) == 0) { + is_found = true; + break; + } + } + it->module_id = mid; + it->setting_id = sid - 1; + if (!is_found) { + *result = NULL; + return 0; + } + const char *mp_pair, *mp_pair_end; + module->get(sid, &mp_pair, &mp_pair_end); + *result = box_tuple_new(it->format, mp_pair, mp_pair_end); + return *result != NULL ? 0 : -1; +} + +static void +session_settings_index_destroy(struct index *index) +{ + free(index); +} + +static struct iterator * +session_settings_index_create_iterator(struct index *base, + enum iterator_type type, const char *key, + uint32_t part_count) +{ + struct session_settings_index *index = + (struct session_settings_index *)base; + char *decoded_key = NULL; + if (part_count > 0) { + assert(part_count == 1); + assert(mp_typeof(*key) == MP_STR); + uint32_t len; + const char *name = mp_decode_str(&key, &len); + decoded_key = (char *)malloc(len + 1); + if (decoded_key == NULL) { + diag_set(OutOfMemory, len + 1, "malloc", "decoded_key"); + return NULL; + } + memcpy(decoded_key, name, len); + decoded_key[len] = '\0'; + } + struct session_settings_iterator *it = + (struct session_settings_iterator *)malloc(sizeof(*it)); + if (it == NULL) { + diag_set(OutOfMemory, sizeof(*it), "malloc", "it"); + free(decoded_key); + return NULL; + } + iterator_create(&it->base, base); + it->base.free = session_settings_iterator_free; + it->key = decoded_key; + it->is_eq = type == ITER_EQ || type == ITER_REQ; + it->is_including = it->is_eq || type == ITER_GE || type == ITER_ALL || + type == ITER_LE; + it->format = index->format; + if (!iterator_type_is_reverse(type)) { + it->base.next = session_settings_iterator_next; + it->module_id = 0; + it->setting_id = 0; + } else { + it->base.next = session_settings_iterator_prev; + it->module_id = session_setting_type_MAX - 1; + struct session_setting_module *module = + &session_setting_modules[it->module_id]; + it->setting_id = module->setting_count - 1; + } + return (struct iterator *)it; +} + +static int +session_settings_index_get(struct index *base, const char *key, + uint32_t part_count, struct tuple **result) +{ + struct session_settings_index *index = + (struct session_settings_index *) base; + assert(part_count == 1); + (void) part_count; + uint32_t len; + key = mp_decode_str(&key, &len); + key = tt_cstr(key, len); + struct session_setting_module *module = &session_setting_modules[0]; + struct session_setting_module *end = module + session_setting_type_MAX; + int sid = 0; + for (; module < end; ++module, sid = 0) { + if (session_settings_next_in_module(module, &sid, key, true, + true) == 0) + goto found; + } + *result = NULL; + return 0; +found:; + const char *mp_pair; + const char *mp_pair_end; + module->get(sid, &mp_pair, &mp_pair_end); + *result = box_tuple_new(index->format, mp_pair, mp_pair_end); + return *result != NULL ? 0 : -1; +} + +static const struct index_vtab session_settings_index_vtab = { + /* .destroy = */ session_settings_index_destroy, + /* .commit_create = */ generic_index_commit_create, + /* .abort_create = */ generic_index_abort_create, + /* .commit_modify = */ generic_index_commit_modify, + /* .commit_drop = */ generic_index_commit_drop, + /* .update_def = */ generic_index_update_def, + /* .depends_on_pk = */ generic_index_depends_on_pk, + /* .def_change_requires_rebuild = */ + generic_index_def_change_requires_rebuild, + /* .size = */ generic_index_size, + /* .bsize = */ generic_index_bsize, + /* .min = */ generic_index_min, + /* .max = */ generic_index_max, + /* .random = */ generic_index_random, + /* .count = */ generic_index_count, + /* .get = */ session_settings_index_get, + /* .replace = */ generic_index_replace, + /* .create_iterator = */ session_settings_index_create_iterator, + /* .create_snapshot_iterator = */ + generic_index_create_snapshot_iterator, + /* .stat = */ generic_index_stat, + /* .compact = */ generic_index_compact, + /* .reset_stat = */ generic_index_reset_stat, + /* .begin_build = */ generic_index_begin_build, + /* .reserve = */ generic_index_reserve, + /* .build_next = */ generic_index_build_next, + /* .end_build = */ generic_index_end_build, +}; + +static void +session_settings_space_destroy(struct space *space) +{ + free(space); +} + +static int +session_settings_space_execute_replace(struct space *space, struct txn *txn, + struct request *request, + struct tuple **result) +{ + (void)space; + (void)txn; + (void)request; + (void)result; + diag_set(ClientError, ER_UNSUPPORTED, "Session_settings space", + "replace()"); + return -1; +} + +static int +session_settings_space_execute_delete(struct space *space, struct txn *txn, + struct request *request, + struct tuple **result) +{ + (void)space; + (void)txn; + (void)request; + (void)result; + diag_set(ClientError, ER_UNSUPPORTED, "Session_settings space", + "delete()"); + return -1; +} + +static int +session_settings_space_execute_update(struct space *space, struct txn *txn, + struct request *request, + struct tuple **result) +{ + (void)txn; + struct tuple_format *format = space->format; + const char *old_data, *old_data_end, *new_data; + struct region *region = &fiber()->gc; + size_t used = region_used(region); + int rc = -1, sid = 0; + struct index_def *pk_def = space->index[0]->def; + uint64_t column_mask; + + const char *new_key, *key = request->key; + uint32_t new_size, new_key_len, key_len = mp_decode_array(&key); + if (key_len == 0) { + diag_set(ClientError, ER_EXACT_MATCH, 1, 0); + return -1; + } + if (key_len > 1 || mp_typeof(*key) != MP_STR) { + diag_set(ClientError, ER_KEY_PART_TYPE, 0, "string"); + return -1; + } + key = mp_decode_str(&key, &key_len); + key = tt_cstr(key, key_len); + struct session_setting_module *module = &session_setting_modules[0]; + struct session_setting_module *end = module + session_setting_type_MAX; + for (; module < end; ++module, sid = 0) { + if (session_settings_next_in_module(module, &sid, key, true, + true) == 0) + goto found; + } + *result = NULL; + return 0; +found: + module->get(sid, &old_data, &old_data_end); + new_data = xrow_update_execute(request->tuple, request->tuple_end, + old_data, old_data_end, format->dict, + &new_size, request->index_base, + &column_mask); + if (new_data == NULL) + goto finish; + *result = box_tuple_new(format, new_data, new_data + new_size); + if (*result == NULL) + goto finish; + + mp_decode_array(&new_data); + new_key = mp_decode_str(&new_data, &new_key_len); + if (!key_update_can_be_skipped(pk_def->key_def->column_mask, + column_mask)) { + if (key_len != new_key_len || + memcmp(key, new_key, key_len) != 0) { + diag_set(ClientError, ER_CANT_UPDATE_PRIMARY_KEY, + pk_def->name, space_name(space)); + goto finish; + } + } + if (module->set(sid, new_data) != 0) + goto finish; + rc = 0; +finish: + region_truncate(region, used); + return rc; +} + +static int +session_settings_space_execute_upsert(struct space *space, struct txn *txn, + struct request *request) +{ + (void)space; + (void)txn; + (void)request; + diag_set(ClientError, ER_UNSUPPORTED, "Session_settings space", + "upsert()"); + return -1; +} + +static struct index * +session_settings_space_create_index(struct space *space, struct index_def *def) +{ + assert(space->def->id == BOX_SESSION_SETTINGS_ID); + if (def->iid != 0) { + diag_set(ClientError, ER_UNSUPPORTED, "Session_settings space", + "create_index()"); + return NULL; + } + + struct session_settings_index *index = + (struct session_settings_index *)calloc(1, sizeof(*index)); + if (index == NULL) { + diag_set(OutOfMemory, sizeof(*index), "calloc", "index"); + return NULL; + } + if (index_create(&index->base, space->engine, + &session_settings_index_vtab, def) != 0) { + free(index); + return NULL; + } + + index->format = space->format; + return &index->base; +} + +const struct space_vtab session_settings_space_vtab = { + /* .destroy = */ session_settings_space_destroy, + /* .bsize = */ generic_space_bsize, + /* .execute_replace = */ session_settings_space_execute_replace, + /* .execute_delete = */ session_settings_space_execute_delete, + /* .execute_update = */ session_settings_space_execute_update, + /* .execute_upsert = */ session_settings_space_execute_upsert, + /* .ephemeral_replace = */ generic_space_ephemeral_replace, + /* .ephemeral_delete = */ generic_space_ephemeral_delete, + /* .ephemeral_rowid_next = */ generic_space_ephemeral_rowid_next, + /* .init_system_space = */ generic_init_system_space, + /* .init_ephemeral_space = */ generic_init_ephemeral_space, + /* .check_index_def = */ generic_space_check_index_def, + /* .create_index = */ session_settings_space_create_index, + /* .add_primary_key = */ generic_space_add_primary_key, + /* .drop_primary_key = */ generic_space_drop_primary_key, + /* .check_format = */ generic_space_check_format, + /* .build_index = */ generic_space_build_index, + /* .swap_index = */ generic_space_swap_index, + /* .prepare_alter = */ generic_space_prepare_alter, + /* .invalidate = */ generic_space_invalidate, +}; diff --git a/src/box/session_settings.h b/src/box/session_settings.h new file mode 100644 index 0000000..7415e0e --- /dev/null +++ b/src/box/session_settings.h @@ -0,0 +1,69 @@ +#pragma once +/* + * Copyright 2010-2019, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * Session has settings. Settings belong to different subsystems, + * such as SQL. Each subsystem registers here its session setting + * type and a set of settings with getter and setter functions. + * The self-registration of modules allows session setting code + * not to depend on all the subsystems. + * + * The types should be ordered in alphabetical order, because the + * type list is used by setting iterators. + */ +enum session_setting_type { + session_setting_type_MAX, +}; + +struct session_setting_module { + /** + * An array of setting names. All of them should have the + * same prefix. + */ + const char **settings; + /** Count of settings. */ + int setting_count; + /** + * Get a MessagePack encoded pair [name, value] for a + * setting having index @a id. Index is from the settings + * array. + */ + void (*get)(int id, const char **mp_pair, const char **mp_pair_end); + /** + * Set value of a setting by a given @a id from a + * MessagePack encoded buffer. Note, it is not a pair, but + * just value. + */ + int (*set)(int id, const char *mp_value); +}; + +extern struct session_setting_module session_setting_modules[]; diff --git a/src/box/virtual_engine.c b/src/box/virtual_engine.c index 9a59a3f..36eec83 100644 --- a/src/box/virtual_engine.c +++ b/src/box/virtual_engine.c @@ -29,8 +29,11 @@ * SUCH DAMAGE. */ #include "virtual_engine.h" +#include "tuple.h" #include "schema.h" +extern const struct space_vtab session_settings_space_vtab; + static void virtual_engine_shutdown(struct engine *engine) { @@ -41,13 +44,50 @@ static struct space * virtual_engine_create_space(struct engine *engine, struct space_def *def, struct rlist *key_list) { - (void)engine; - (void)def; - (void)key_list; - /* There are currently no spaces with this engine. */ - diag_set(ClientError, ER_UNSUPPORTED, "Tarantool", - "spaces with this engine."); - return NULL; + /* + * At the moment the only space that have this engine is + * _session_sessings. + */ + if (def->id != BOX_SESSION_SETTINGS_ID) { + diag_set(ClientError, ER_UNSUPPORTED, "Tarantool", + "non-system space with this engine."); + return NULL; + } + const struct space_vtab *space_vtab = &session_settings_space_vtab; + + struct space *space = (struct space *)calloc(1, sizeof(*space)); + if (space == NULL) { + diag_set(OutOfMemory, sizeof(*space), "calloc", "space"); + return NULL; + } + int key_count = 0; + struct key_def **keys = index_def_to_key_def(key_list, &key_count); + if (keys == NULL) { + free(space); + return NULL; + } + struct tuple_format *format = + tuple_format_new(&tuple_format_runtime->vtab, NULL, keys, + key_count, def->fields, def->field_count, + def->exact_field_count, def->dict, + def->opts.is_temporary, + def->opts.is_ephemeral); + if (format == NULL) { + free(space); + return NULL; + } + tuple_format_ref(format); + int rc = space_create(space, engine, space_vtab, def, key_list, format); + /* + * Format is now referenced by the space if space has beed + * created. + */ + tuple_format_unref(format); + if (rc != 0) { + free(space); + return NULL; + } + return space; } static const struct engine_vtab virtual_engine_vtab = { diff --git a/test/app-tap/tarantoolctl.test.lua b/test/app-tap/tarantoolctl.test.lua index 7a07860..4d70595 100755 --- a/test/app-tap/tarantoolctl.test.lua +++ b/test/app-tap/tarantoolctl.test.lua @@ -415,8 +415,8 @@ do check_ctlcat_xlog(test_i, dir, "--from=3 --to=6 --format=json --show-system --replica 1", "\n", 3) check_ctlcat_xlog(test_i, dir, "--from=3 --to=6 --format=json --show-system --replica 1 --replica 2", "\n", 3) check_ctlcat_xlog(test_i, dir, "--from=3 --to=6 --format=json --show-system --replica 2", "\n", 0) - check_ctlcat_snap(test_i, dir, "--space=280", "---\n", 24) - check_ctlcat_snap(test_i, dir, "--space=288", "---\n", 52) + check_ctlcat_snap(test_i, dir, "--space=280", "---\n", 25) + check_ctlcat_snap(test_i, dir, "--space=288", "---\n", 53) end) end) diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result index 938a763..f2ad75e 100644 --- a/test/box-py/bootstrap.result +++ b/test/box-py/bootstrap.result @@ -96,6 +96,8 @@ box.space._space:select{} 'type': 'boolean'}]] - [372, 1, '_func_index', 'memtx', 0, {}, [{'name': 'space_id', 'type': 'unsigned'}, {'name': 'index_id', 'type': 'unsigned'}, {'name': 'func_id', 'type': 'unsigned'}]] + - [380, 1, '_session_settings', 'virtual', 2, {'temporary': true}, [{'name': 'name', + 'type': 'string'}, {'name': 'value', 'type': 'any'}]] ... box.space._index:select{} --- @@ -153,6 +155,7 @@ box.space._index:select{} - [364, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned'], [1, 'string']]] - [372, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned'], [1, 'unsigned']]] - [372, 1, 'fid', 'tree', {'unique': false}, [[2, 'unsigned']]] + - [380, 0, 'primary', 'tree', {'unique': true}, [[0, 'string']]] ... box.space._user:select{} --- diff --git a/test/box/access_sysview.result b/test/box/access_sysview.result index 1f33dec..799d19f 100644 --- a/test/box/access_sysview.result +++ b/test/box/access_sysview.result @@ -246,11 +246,11 @@ box.session.su('guest') ... #box.space._vspace:select{} --- -- 25 +- 26 ... #box.space._vindex:select{} --- -- 53 +- 54 ... #box.space._vuser:select{} --- @@ -282,7 +282,7 @@ box.session.su('guest') ... #box.space._vindex:select{} --- -- 53 +- 54 ... #box.space._vuser:select{} --- diff --git a/test/box/alter.result b/test/box/alter.result index 9a2f991..f150faa 100644 --- a/test/box/alter.result +++ b/test/box/alter.result @@ -92,7 +92,7 @@ space = box.space[t[1]] ... space.id --- -- 373 +- 381 ... space.field_count --- @@ -137,7 +137,7 @@ space_deleted ... space:replace{0} --- -- error: Space '373' does not exist +- error: Space '381' does not exist ... _index:insert{_space.id, 0, 'primary', 'tree', {unique=true}, {{0, 'unsigned'}}} --- @@ -220,6 +220,7 @@ _index:select{} - [364, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned'], [1, 'string']]] - [372, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned'], [1, 'unsigned']]] - [372, 1, 'fid', 'tree', {'unique': false}, [[2, 'unsigned']]] + - [380, 0, 'primary', 'tree', {'unique': true}, [[0, 'string']]] ... -- modify indexes of a system space _index:delete{_index.id, 0} diff --git a/test/box/gh-4511-access-settings-from-any-frontend.result b/test/box/gh-4511-access-settings-from-any-frontend.result index 9874616..75d53cf 100644 --- a/test/box/gh-4511-access-settings-from-any-frontend.result +++ b/test/box/gh-4511-access-settings-from-any-frontend.result @@ -6,5 +6,111 @@ test_run = require('test_run').new() -- User cannot create spaces with this engine. s = box.schema.space.create('test', {engine = 'virtual'}) | --- - | - error: Tarantool does not support spaces with this engine. + | - error: Tarantool does not support non-system space with this engine. + | ... + +-- Check _session_settings space. +s = box.space._session_settings + | --- + | ... +s:format() + | --- + | - [{'name': 'name', 'type': 'string'}, {'name': 'value', 'type': 'any'}] + | ... + +-- Make sure that we cannot drop space. +s:drop() + | --- + | - error: Can't drop the primary key in a system space, space '_session_settings' + | ... + +-- +-- Make sure, that session_settings space doesn't support +-- create_index(), insert(), replace() and delete() methods. +-- +s:create_index('a') + | --- + | - error: Session_settings space does not support create_index() + | ... +s:insert({'a', 1}) + | --- + | - error: Session_settings space does not support replace() + | ... +s:delete({'b'}) + | --- + | - error: Session_settings space does not support delete() + | ... +s:replace({'sql_defer_foreign_keys', true}) + | --- + | - error: Session_settings space does not support replace() + | ... + +-- Check get() and select(). They should return nothing for now. +s:get({'a'}) + | --- + | ... +s:select() + | --- + | - [] + | ... +s:select({}, {iterator='EQ'}) + | --- + | - [] + | ... +s:select({}, {iterator='ALL'}) + | --- + | - [] + | ... +s:select({}, {iterator='GE'}) + | --- + | - [] + | ... +s:select({}, {iterator='GT'}) + | --- + | - [] + | ... +s:select({}, {iterator='REQ'}) + | --- + | - [] + | ... +s:select({}, {iterator='LE'}) + | --- + | - [] + | ... +s:select({}, {iterator='LT'}) + | --- + | - [] + | ... +s:select({'a'}, {iterator='EQ'}) + | --- + | - [] + | ... +s:select({'a'}, {iterator='ALL'}) + | --- + | - [] + | ... +s:select({'a'}, {iterator='GE'}) + | --- + | - [] + | ... +s:select({'a'}, {iterator='GT'}) + | --- + | - [] + | ... +s:select({'a'}, {iterator='REQ'}) + | --- + | - [] + | ... +s:select({'a'}, {iterator='LE'}) + | --- + | - [] + | ... +s:select({'a'}, {iterator='LT'}) + | --- + | - [] + | ... + +-- Currently there is nothing to update, but update() should work. +s:update('some_option', {{'=', 'value', true}}) + | --- | ... diff --git a/test/box/gh-4511-access-settings-from-any-frontend.test.lua b/test/box/gh-4511-access-settings-from-any-frontend.test.lua index 611caef..3304454 100644 --- a/test/box/gh-4511-access-settings-from-any-frontend.test.lua +++ b/test/box/gh-4511-access-settings-from-any-frontend.test.lua @@ -2,3 +2,40 @@ test_run = require('test_run').new() -- User cannot create spaces with this engine. s = box.schema.space.create('test', {engine = 'virtual'}) + +-- Check _session_settings space. +s = box.space._session_settings +s:format() + +-- Make sure that we cannot drop space. +s:drop() + +-- +-- Make sure, that session_settings space doesn't support +-- create_index(), insert(), replace() and delete() methods. +-- +s:create_index('a') +s:insert({'a', 1}) +s:delete({'b'}) +s:replace({'sql_defer_foreign_keys', true}) + +-- Check get() and select(). They should return nothing for now. +s:get({'a'}) +s:select() +s:select({}, {iterator='EQ'}) +s:select({}, {iterator='ALL'}) +s:select({}, {iterator='GE'}) +s:select({}, {iterator='GT'}) +s:select({}, {iterator='REQ'}) +s:select({}, {iterator='LE'}) +s:select({}, {iterator='LT'}) +s:select({'a'}, {iterator='EQ'}) +s:select({'a'}, {iterator='ALL'}) +s:select({'a'}, {iterator='GE'}) +s:select({'a'}, {iterator='GT'}) +s:select({'a'}, {iterator='REQ'}) +s:select({'a'}, {iterator='LE'}) +s:select({'a'}, {iterator='LT'}) + +-- Currently there is nothing to update, but update() should work. +s:update('some_option', {{'=', 'value', true}}) diff --git a/test/wal_off/alter.result b/test/wal_off/alter.result index 62cb11d..97f7e6f 100644 --- a/test/wal_off/alter.result +++ b/test/wal_off/alter.result @@ -28,7 +28,7 @@ end; ... #spaces; --- -- 65502 +- 65501 ... -- cleanup for k, v in pairs(spaces) do -- 2.7.4