[Tarantool-patches] [PATCH v5 2/3] box: introduce _session_settings system space
imeevma at tarantool.org
imeevma at tarantool.org
Fri Dec 27 17:05:05 MSK 2019
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 <COPYRIGHT HOLDER> ``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
+ * <COPYRIGHT HOLDER> 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 <COPYRIGHT HOLDER> ``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
+ * <COPYRIGHT HOLDER> 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
More information about the Tarantool-patches
mailing list