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 ECAD24696C4 for ; Fri, 27 Dec 2019 17:05:08 +0300 (MSK) From: imeevma@tarantool.org Date: Fri, 27 Dec 2019 17:05:07 +0300 Message-Id: <9b2bf828e3b58765ba76c59479a8bbd29d39b52b.1577455413.git.imeevma@gmail.com> In-Reply-To: References: Subject: [Tarantool-patches] [PATCH v5 3/3] box: add SQL settings to _session_settings 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 Part of #4511 @TarantoolBot document Title: _session_settings system space The _session_settings system space used to view or change session settings. This space uses a new engine. This allows us to create tuples on the fly when the get() or select() methods are called. This engine does not support the insert(), replace(), and delete() methods. The only way to change the setting value is update(), which can only be used with the "=" operation. Because space creates a tuple on the fly, it allows us to get a tuple without saving it anywhere. But this means that every time we get a tuple from this system space, it is a new tuple, even if they look the same: tarantool> s = box.space._session_settings tarantool> name = 'sql_default_engine' tarantool> s:get({name}) == s:get({name}) --- - false ... Currently, this space contains only SQL settings, since the only session settings are SQL settings. List of currently available session settings: sql_default_engine sql_defer_foreign_keys sql_full_column_names sql_full_metadata sql_recursive_triggers sql_reverse_unordered_selects Debug build also have debug settings that could be obtained from this sysview: sql_parser_trace sql_select_trace sql_trace sql_vdbe_addoptrace sql_vdbe_debug sql_vdbe_eqp sql_vdbe_listing sql_vdbe_trace sql_where_trace Example of usage: tarantool> s = box.space._session_settings -- View session settings values. tarantool> s:get({'sql_default_engine'}) --- - ['sql_default_engine', 'memtx'] ... tarantool> s:select() --- - - ['sql_default_engine', 'memtx'] - ['sql_defer_foreign_keys', false] - ['sql_full_column_names', false] - ['sql_full_metadata', false] - ['sql_recursive_triggers', true] - ['sql_reverse_unordered_selects', false] ... tarantool> s:select('sql_g', {iterator='LE'}) --- - - ['sql_full_column_names', false] - ['sql_full_metadata', false] - ['sql_defer_foreign_keys', false] - ['sql_default_engine', 'memtx'] ... -- Change session setting value. tarantool> s:update('sql_default_engine', {{'=', 'value', 'vinyl'}}) --- - ['sql_default_engine', 'vinyl'] ... --- src/box/errcode.h | 1 + src/box/session_settings.h | 1 + src/box/sql.c | 5 + src/box/sql/build.c | 222 ++++++++++++++++++++ ...h-4511-access-settings-from-any-frontend.result | 225 +++++++++++++++++---- ...4511-access-settings-from-any-frontend.test.lua | 105 ++++++++-- test/box/misc.result | 1 + 7 files changed, 506 insertions(+), 54 deletions(-) diff --git a/src/box/errcode.h b/src/box/errcode.h index c660b1c..11894fc 100644 --- a/src/box/errcode.h +++ b/src/box/errcode.h @@ -258,6 +258,7 @@ struct errcode_record { /*203 */_(ER_BOOTSTRAP_READONLY, "Trying to bootstrap a local read-only instance as master") \ /*204 */_(ER_SQL_FUNC_WRONG_RET_COUNT, "SQL expects exactly one argument returned from %s, got %d")\ /*205 */_(ER_FUNC_INVALID_RETURN_TYPE, "Function '%s' returned value of invalid type: expected %s got %s") \ + /*206 */_(ER_SESSION_SETTING_INVALID_VALUE, "Session setting %s expected a value of type %s") \ /* * !IMPORTANT! Please follow instructions at start of the file diff --git a/src/box/session_settings.h b/src/box/session_settings.h index 7415e0e..25490a7 100644 --- a/src/box/session_settings.h +++ b/src/box/session_settings.h @@ -41,6 +41,7 @@ * type list is used by setting iterators. */ enum session_setting_type { + SESSION_SETTING_SQL, session_setting_type_MAX, }; diff --git a/src/box/sql.c b/src/box/sql.c index f1df555..cc82617 100644 --- a/src/box/sql.c +++ b/src/box/sql.c @@ -64,9 +64,14 @@ static const uint32_t default_sql_flags = SQL_ShortColNames | SQL_AutoIndex | SQL_RecTriggers; +extern void +sql_session_settings_init(); + void sql_init() { + sql_session_settings_init(); + default_flags |= default_sql_flags; current_session()->sql_flags |= default_sql_flags; diff --git a/src/box/sql/build.c b/src/box/sql/build.c index a106dc3..c7c4901 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -57,6 +57,7 @@ #include "box/tuple_format.h" #include "box/coll_id_cache.h" #include "box/user.h" +#include "box/session_settings.h" void sql_finish_coding(struct Parse *parse_context) @@ -3295,3 +3296,224 @@ sql_fieldno_by_name(struct Parse *parse_context, struct Expr *field_name, *fieldno = i; return 0; } + +/** + * Identifiers of all SQL session setings. The identifier of the + * option is equal to its place in the sorted list of session + * options of current module. + * + * It is IMPORTANT that these options are sorted by name. If this + * is not the case, the result returned by the _session_settings + * space iterator will not be sorted properly. + */ +enum { + SQL_SESSION_SETTING_DEFAULT_ENGINE = 0, + SQL_SESSION_SETTING_DEFER_FOREIGN_KEYS, + SQL_SESSION_SETTING_FULL_COLUMN_NAMES, + SQL_SESSION_SETTING_FULL_METADATA, +#ifndef NDEBUG + SQL_SESSION_SETTING_PARSER_TRACE, +#endif + SQL_SESSION_SETTING_RECURSIVE_TRIGGERS, + SQL_SESSION_SETTING_REVERSE_UNORDERED_SELECTS, +#ifndef NDEBUG + SQL_SESSION_SETTING_SELECT_TRACE, + SQL_SESSION_SETTING_TRACE, + SQL_SESSION_SETTING_VDBE_ADDOPTRACE, + SQL_SESSION_SETTING_VDBE_DEBUG, + SQL_SESSION_SETTING_VDBE_EQP, + SQL_SESSION_SETTING_VDBE_LISTING, + SQL_SESSION_SETTING_VDBE_TRACE, + SQL_SESSION_SETTING_WHERE_TRACE, +#endif + sql_session_setting_MAX, +}; + +static const char *sql_session_setting_strs[sql_session_setting_MAX] = { + "sql_default_engine", + "sql_defer_foreign_keys", + "sql_full_column_names", + "sql_full_metadata", +#ifndef NDEBUG + "sql_parser_trace", +#endif + "sql_recursive_triggers", + "sql_reverse_unordered_selects", +#ifndef NDEBUG + "sql_select_trace", + "sql_trace", + "sql_vdbe_addoptrace", + "sql_vdbe_debug", + "sql_vdbe_eqp", + "sql_vdbe_listing", + "sql_vdbe_trace", + "sql_where_trace", +#endif +}; + +/** + * A local structure that allows to establish a connection between + * parameter and its field type and mask, if it has one. + */ +struct sql_option_metadata +{ + uint32_t field_type; + uint32_t mask; +}; + +/** + * Variable that contains SQL session option field types and masks + * if they have one or 0 if don't have. + * + * It is IMPORTANT that these options sorted by name. + */ +static struct sql_option_metadata sql_session_opts[] = { + /** SQL_SESSION_SETTING_DEFAULT_ENGINE */ + {FIELD_TYPE_STRING, 0}, + /** SQL_SESSION_SETTING_DEFER_FOREIGN_KEYS */ + {FIELD_TYPE_BOOLEAN, SQL_DeferFKs}, + /** SQL_SESSION_SETTING_FULL_COLUMN_NAMES */ + {FIELD_TYPE_BOOLEAN, SQL_FullColNames}, + /** SQL_SESSION_SETTING_FULL_METADATA */ + {FIELD_TYPE_BOOLEAN, SQL_FullMetadata}, +#ifndef NDEBUG + /** SQL_SESSION_SETTING_PARSER_TRACE */ + {FIELD_TYPE_BOOLEAN, PARSER_TRACE_FLAG}, +#endif + /** SQL_SESSION_SETTING_RECURSIVE_TRIGGERS */ + {FIELD_TYPE_BOOLEAN, SQL_RecTriggers}, + /** SQL_SESSION_SETTING_REVERSE_UNORDERED_SELECTS */ + {FIELD_TYPE_BOOLEAN, SQL_ReverseOrder}, +#ifndef NDEBUG + /** SQL_SESSION_SETTING_SELECT_TRACE */ + {FIELD_TYPE_BOOLEAN, SQL_SelectTrace}, + /** SQL_SESSION_SETTING_TRACE */ + {FIELD_TYPE_BOOLEAN, SQL_SqlTrace}, + /** SQL_SESSION_SETTING_VDBE_ADDOPTRACE */ + {FIELD_TYPE_BOOLEAN, SQL_VdbeAddopTrace}, + /** SQL_SESSION_SETTING_VDBE_DEBUG */ + {FIELD_TYPE_BOOLEAN, + SQL_SqlTrace | SQL_VdbeListing | SQL_VdbeTrace}, + /** SQL_SESSION_SETTING_VDBE_EQP */ + {FIELD_TYPE_BOOLEAN, SQL_VdbeEQP}, + /** SQL_SESSION_SETTING_VDBE_LISTING */ + {FIELD_TYPE_BOOLEAN, SQL_VdbeListing}, + /** SQL_SESSION_SETTING_VDBE_TRACE */ + {FIELD_TYPE_BOOLEAN, SQL_VdbeTrace}, + /** SQL_SESSION_SETTING_WHERE_TRACE */ + {FIELD_TYPE_BOOLEAN, SQL_WhereTrace}, +#endif +}; + +static void +sql_session_setting_get(int id, const char **mp_pair, const char **mp_pair_end) +{ + assert(id >= 0 && id < sql_session_setting_MAX); + struct session *session = current_session(); + uint32_t flags = session->sql_flags; + struct sql_option_metadata *opt = &sql_session_opts[id]; + uint32_t mask = opt->mask; + const char *name = sql_session_setting_strs[id]; + size_t name_len = strlen(name); + size_t engine_len; + const char *engine; + size_t size = mp_sizeof_array(2) + mp_sizeof_str(name_len); + /* + * Currently, SQL session settings are of a boolean or + * string type. + */ + bool is_bool = opt->field_type == FIELD_TYPE_BOOLEAN; + if (is_bool) { + size += mp_sizeof_bool(true); + } else { + assert(id == SQL_SESSION_SETTING_DEFAULT_ENGINE); + engine = sql_storage_engine_strs[session->sql_default_engine]; + engine_len = strlen(engine); + size += mp_sizeof_str(engine_len); + } + + char *pos = static_alloc(size); + assert(pos != NULL); + char *pos_end = mp_encode_array(pos, 2); + pos_end = mp_encode_str(pos_end, name, name_len); + if (is_bool) + pos_end = mp_encode_bool(pos_end, (flags & mask) == mask); + else + pos_end = mp_encode_str(pos_end, engine, engine_len); + *mp_pair = pos; + *mp_pair_end = pos_end; +} + +static int +sql_set_boolean_option(int id, bool value) +{ + struct session *session = current_session(); + struct sql_option_metadata *option = &sql_session_opts[id]; + assert(option->field_type == FIELD_TYPE_BOOLEAN); + if (value) + session->sql_flags |= option->mask; + else + session->sql_flags &= ~option->mask; +#ifndef NDEBUG + if (id == SQL_SESSION_SETTING_PARSER_TRACE) { + if (value) + sqlParserTrace(stdout, "parser: "); + else + sqlParserTrace(NULL, NULL); + } +#endif + return 0; +} + +static int +sql_set_string_option(int id, const char *value) +{ + assert(sql_session_opts[id].field_type = FIELD_TYPE_STRING); + assert(id == SQL_SESSION_SETTING_DEFAULT_ENGINE); + (void)id; + enum sql_storage_engine engine = STR2ENUM(sql_storage_engine, value); + if (engine == sql_storage_engine_MAX) { + diag_set(ClientError, ER_NO_SUCH_ENGINE, value); + return -1; + } + current_session()->sql_default_engine = engine; + return 0; +} + +static int +sql_session_setting_set(int id, const char *mp_value) +{ + assert(id >= 0 && id < sql_session_setting_MAX); + enum mp_type mtype = mp_typeof(*mp_value); + enum field_type stype = sql_session_opts[id].field_type; + uint32_t len; + const char *tmp; + switch(stype) { + case FIELD_TYPE_BOOLEAN: + if (mtype != MP_BOOL) + break; + return sql_set_boolean_option(id, mp_decode_bool(&mp_value)); + case FIELD_TYPE_STRING: + if (mtype != MP_STR) + break; + tmp = mp_decode_str(&mp_value, &len); + tmp = tt_cstr(tmp, len); + return sql_set_string_option(id, tmp); + default: + unreachable(); + } + diag_set(ClientError, ER_SESSION_SETTING_INVALID_VALUE, + sql_session_setting_strs[id], field_type_strs[stype]); + return -1; +} + +void +sql_session_settings_init() +{ + struct session_setting_module *module = + &session_setting_modules[SESSION_SETTING_SQL]; + module->settings = sql_session_setting_strs; + module->setting_count = sql_session_setting_MAX; + module->get = sql_session_setting_get; + module->set = sql_session_setting_set; +} 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 75d53cf..4e68129 100644 --- a/test/box/gh-4511-access-settings-from-any-frontend.result +++ b/test/box/gh-4511-access-settings-from-any-frontend.result @@ -45,72 +45,229 @@ 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'}) +-- +-- Check select() method of session_settings space. Should work +-- the same way as an ordinary space with an index of the type +-- "TREE". +-- +t = box.schema.space.create('settings', {format = s:format()}) + | --- + | ... +_ = t:create_index('primary') + | --- + | ... +for _,value in s:pairs() do t:insert(value) end + | --- + | ... + +test_run:cmd('setopt delimiter ";"') + | --- + | - true + | ... +function check_sorting(ss, ts, key) + local iterators_list = {'ALL', 'REQ', 'EQ', 'GE', 'GT', 'LE', 'LT'} + for _, it in pairs(iterators_list) do + local view_space = ss:select({key}, {iterator = it}) + local test_space = ts:select({key}, {iterator = it}) + for key, value in pairs(view_space) do + if test_space[key].name ~= value.name then + return { + err = 'bad sorting', type = it, + exp = test_space[key].name, got = value.name + } + end + end + end +end; | --- | ... -s:select() +test_run:cmd('setopt delimiter ""'); | --- - | - [] + | - true | ... -s:select({}, {iterator='EQ'}) + +check_sorting(s, t) | --- - | - [] | ... -s:select({}, {iterator='ALL'}) +check_sorting(s, t, 'abcde') | --- - | - [] | ... -s:select({}, {iterator='GE'}) +check_sorting(s, t, 'sql_d') | --- - | - [] | ... -s:select({}, {iterator='GT'}) +check_sorting(s, t, 'sql_v') | --- - | - [] | ... -s:select({}, {iterator='REQ'}) +check_sorting(s, t, 'sql_defer_foreign_keys') | --- - | - [] | ... -s:select({}, {iterator='LE'}) + +t:drop() | --- - | - [] | ... -s:select({}, {iterator='LT'}) + +-- Check get() method of session_settings space. +s:get({'sql_defer_foreign_keys'}) | --- - | - [] + | - ['sql_defer_foreign_keys', false] | ... -s:select({'a'}, {iterator='EQ'}) +s:get({'sql_recursive_triggers'}) | --- - | - [] + | - ['sql_recursive_triggers', true] | ... -s:select({'a'}, {iterator='ALL'}) +s:get({'sql_reverse_unordered_selects'}) | --- - | - [] + | - ['sql_reverse_unordered_selects', false] | ... -s:select({'a'}, {iterator='GE'}) +s:get({'sql_default_engine'}) | --- - | - [] + | - ['sql_default_engine', 'memtx'] | ... -s:select({'a'}, {iterator='GT'}) +s:get({'abcd'}) | --- - | - [] | ... -s:select({'a'}, {iterator='REQ'}) + +-- Check pairs() method of session_settings space. +t = {} | --- - | - [] | ... -s:select({'a'}, {iterator='LE'}) +for key, value in s:pairs() do table.insert(t, {key, value}) end | --- - | - [] | ... -s:select({'a'}, {iterator='LT'}) +#t == s:count() | --- - | - [] + | - true | ... --- Currently there is nothing to update, but update() should work. -s:update('some_option', {{'=', 'value', true}}) +-- Check update() method of session_settings space. + +-- Correct updates. +s:update('sql_defer_foreign_keys', {{'=', 'value', true}}) + | --- + | - ['sql_defer_foreign_keys', true] + | ... +s:update({'sql_defer_foreign_keys'}, {{'=', 2, false}}) + | --- + | - ['sql_defer_foreign_keys', false] + | ... +s:update('sql_default_engine', {{'=', 2, 'vinyl'}}) + | --- + | - ['sql_default_engine', 'vinyl'] + | ... +s:update('sql_default_engine', {{':', 'value', 1, 5, 'memtx'}}) + | --- + | - ['sql_default_engine', 'memtx'] + | ... +s:update('a', {{'=', 2, 1}}) + | --- + | ... + +-- Inorrect updates. +s:update({{'sql_defer_foreign_keys'}}, {{'=', 'value', true}}) + | --- + | - error: 'Supplied key type of part 0 does not match index part type: expected string' + | ... + +s:update('sql_defer_foreign_keys', {'=', 'value', true}) + | --- + | - error: Illegal parameters, update operation must be an array {op,..} + | ... +s:update('sql_defer_foreign_keys', {{'=', 'value', true}, {'=', 2, true}}) + | --- + | - ['sql_defer_foreign_keys', true] + | ... +s:update('sql_defer_foreign_keys', {{}}) + | --- + | - error: Illegal parameters, update operation must be an array {op,..}, got empty + | array + | ... +s:update('sql_defer_foreign_keys', {{'='}}) + | --- + | - error: Unknown UPDATE operation + | ... +s:update('sql_defer_foreign_keys', {{'=', 'value'}}) + | --- + | - error: Unknown UPDATE operation + | ... +s:update('sql_defer_foreign_keys', {{'=', 'value', true, 1}}) + | --- + | - error: Unknown UPDATE operation + | ... + +s:update('sql_defer_foreign_keys', {{'+', 'value', 2}}) + | --- + | - error: 'Argument type in operation ''+'' on field ''value'' does not match field + | type: expected a number' + | ... +s:update('sql_defer_foreign_keys', {{'-', 'value', 2}}) + | --- + | - error: 'Argument type in operation ''-'' on field ''value'' does not match field + | type: expected a number' + | ... +s:update('sql_defer_foreign_keys', {{'&', 'value', 2}}) + | --- + | - error: 'Argument type in operation ''&'' on field ''value'' does not match field + | type: expected a positive integer' + | ... +s:update('sql_defer_foreign_keys', {{'|', 'value', 2}}) + | --- + | - error: 'Argument type in operation ''|'' on field ''value'' does not match field + | type: expected a positive integer' + | ... +s:update('sql_defer_foreign_keys', {{'^', 'value', 2}}) + | --- + | - error: 'Argument type in operation ''^'' on field ''value'' does not match field + | type: expected a positive integer' + | ... +s:update('sql_defer_foreign_keys', {{'!', 'value', 2}}) + | --- + | - error: Tuple field count 3 does not match space field count 2 + | ... +s:update('sql_defer_foreign_keys', {{'#', 'value', 2}}) + | --- + | - error: Tuple field count 1 does not match space field count 2 + | ... +s:update('sql_defer_foreign_keys', {{1, 'value', true}}) + | --- + | - error: Illegal parameters, update operation name must be a string + | ... +s:update('sql_defer_foreign_keys', {{{1}, 'value', true}}) + | --- + | - error: Illegal parameters, update operation name must be a string + | ... + +s:update('sql_defer_foreign_keys', {{'=', {'value'}, true}}) + | --- + | - error: Illegal parameters, field id must be a number or a string + | ... +s:update('sql_defer_foreign_keys', {{'=', 1, 'new_key'}}) + | --- + | - error: Attempt to modify a tuple field which is part of index 'primary' in space + | '_session_settings' + | ... +s:update('sql_defer_foreign_keys', {{'=', 'name', 'new_key'}}) + | --- + | - error: Attempt to modify a tuple field which is part of index 'primary' in space + | '_session_settings' + | ... +s:update('sql_defer_foreign_keys', {{'=', 3, true}}) + | --- + | - error: Tuple field count 3 does not match space field count 2 + | ... +s:update('sql_defer_foreign_keys', {{'=', 'some text', true}}) + | --- + | - error: Field 'some text' was not found in the tuple + | ... + +s:update('sql_defer_foreign_keys', {{'=', 'value', 1}}) + | --- + | - error: Session setting sql_defer_foreign_keys expected a value of type boolean + | ... +s:update('sql_defer_foreign_keys', {{'=', 'value', {1}}}) + | --- + | - error: Session setting sql_defer_foreign_keys expected a value of type boolean + | ... +s:update('sql_defer_foreign_keys', {{'=', 'value', '1'}}) | --- + | - error: Session setting sql_defer_foreign_keys expected a value of type boolean | ... 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 3304454..9642f68 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 @@ -19,23 +19,88 @@ 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}}) +-- +-- Check select() method of session_settings space. Should work +-- the same way as an ordinary space with an index of the type +-- "TREE". +-- +t = box.schema.space.create('settings', {format = s:format()}) +_ = t:create_index('primary') +for _,value in s:pairs() do t:insert(value) end + +test_run:cmd('setopt delimiter ";"') +function check_sorting(ss, ts, key) + local iterators_list = {'ALL', 'REQ', 'EQ', 'GE', 'GT', 'LE', 'LT'} + for _, it in pairs(iterators_list) do + local view_space = ss:select({key}, {iterator = it}) + local test_space = ts:select({key}, {iterator = it}) + for key, value in pairs(view_space) do + if test_space[key].name ~= value.name then + return { + err = 'bad sorting', type = it, + exp = test_space[key].name, got = value.name + } + end + end + end +end; +test_run:cmd('setopt delimiter ""'); + +check_sorting(s, t) +check_sorting(s, t, 'abcde') +check_sorting(s, t, 'sql_d') +check_sorting(s, t, 'sql_v') +check_sorting(s, t, 'sql_defer_foreign_keys') + +t:drop() + +-- Check get() method of session_settings space. +s:get({'sql_defer_foreign_keys'}) +s:get({'sql_recursive_triggers'}) +s:get({'sql_reverse_unordered_selects'}) +s:get({'sql_default_engine'}) +s:get({'abcd'}) + +-- Check pairs() method of session_settings space. +t = {} +for key, value in s:pairs() do table.insert(t, {key, value}) end +#t == s:count() + +-- Check update() method of session_settings space. + +-- Correct updates. +s:update('sql_defer_foreign_keys', {{'=', 'value', true}}) +s:update({'sql_defer_foreign_keys'}, {{'=', 2, false}}) +s:update('sql_default_engine', {{'=', 2, 'vinyl'}}) +s:update('sql_default_engine', {{':', 'value', 1, 5, 'memtx'}}) +s:update('a', {{'=', 2, 1}}) + +-- Inorrect updates. +s:update({{'sql_defer_foreign_keys'}}, {{'=', 'value', true}}) + +s:update('sql_defer_foreign_keys', {'=', 'value', true}) +s:update('sql_defer_foreign_keys', {{'=', 'value', true}, {'=', 2, true}}) +s:update('sql_defer_foreign_keys', {{}}) +s:update('sql_defer_foreign_keys', {{'='}}) +s:update('sql_defer_foreign_keys', {{'=', 'value'}}) +s:update('sql_defer_foreign_keys', {{'=', 'value', true, 1}}) + +s:update('sql_defer_foreign_keys', {{'+', 'value', 2}}) +s:update('sql_defer_foreign_keys', {{'-', 'value', 2}}) +s:update('sql_defer_foreign_keys', {{'&', 'value', 2}}) +s:update('sql_defer_foreign_keys', {{'|', 'value', 2}}) +s:update('sql_defer_foreign_keys', {{'^', 'value', 2}}) +s:update('sql_defer_foreign_keys', {{'!', 'value', 2}}) +s:update('sql_defer_foreign_keys', {{'#', 'value', 2}}) +s:update('sql_defer_foreign_keys', {{1, 'value', true}}) +s:update('sql_defer_foreign_keys', {{{1}, 'value', true}}) + +s:update('sql_defer_foreign_keys', {{'=', {'value'}, true}}) +s:update('sql_defer_foreign_keys', {{'=', 1, 'new_key'}}) +s:update('sql_defer_foreign_keys', {{'=', 'name', 'new_key'}}) +s:update('sql_defer_foreign_keys', {{'=', 3, true}}) +s:update('sql_defer_foreign_keys', {{'=', 'some text', true}}) + +s:update('sql_defer_foreign_keys', {{'=', 'value', 1}}) +s:update('sql_defer_foreign_keys', {{'=', 'value', {1}}}) +s:update('sql_defer_foreign_keys', {{'=', 'value', '1'}}) diff --git a/test/box/misc.result b/test/box/misc.result index d2a2030..004faaa 100644 --- a/test/box/misc.result +++ b/test/box/misc.result @@ -554,6 +554,7 @@ t; 203: box.error.BOOTSTRAP_READONLY 204: box.error.SQL_FUNC_WRONG_RET_COUNT 205: box.error.FUNC_INVALID_RETURN_TYPE + 206: box.error.SESSION_SETTING_INVALID_VALUE ... test_run:cmd("setopt delimiter ''"); --- -- 2.7.4