[Tarantool-patches] [tarantool-patches] [PATCH v1 2/5] box: introduce _vsql_settings sysview

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Sat Oct 19 01:08:17 MSK 2019


Thanks for the patch!

See 14 comments below.

On 17/10/2019 16:40, imeevma at tarantool.org wrote:
> This patch creates the _vsql_settings sysview. This system view
> has custom methods get() and create_iterator(). This allows us
> to get SQL settings by creating a tuple on the fly without having
> to save it anywhere.
> 
> Part of #4511
> 
> @TarantoolBot document

1. I think, it is worth to create one doc request for the
whole feature - both SET command and _vsql_settings space.
They are useless without each other.

> Title: The _vsql_settings sysview
> Sysview _vsql_settings allows the user to get the current SQL
> parameters.
> 
> Currently available SQL settings:
> 'defer_foreign_keys'
> 'full_column_names'
> 'recursive_triggers'
> 'reverse_unordered_selects'
> 'sql_compound_select_limit'
> 'sql_default_engine'
> 
> In addition, SQL debugging settings can also be obtained from this
> system view in the debug build:
> 'parser_trace'
> 'select_trace'
> 'sql_trace'
> 'vdbe_addoptrace'
> 'vdbe_debug'
> 'vdbe_eqp'
> 'vdbe_listing'
> 'vdbe_trace'
> 'where_trace'
> 
> Example of usage:
> box.space._vsql_settings:get{'full_column_names'}
> box.space._vsql_settings:select{'defer_foreign_keys'}
> box.space._vsql_settings:select{'full_column_names', {iterator = 'LE'}}

2. There is a problem with having generic iterators. Because if
you allow to iterate over multiple settings, then you have
to do it like normal indexes do, with a strict order. Currently
you return settings without an order.

There is 2 options what to do:

- Ban all iterator types except =, and ban an empty key;

- Keep the settings sorted and return them like a tree
  index does. That might be useful in case we will agree
  to create a generic space _vsession_storage. Then by a
  prefix a user could select all settings of a specific
  subsystem. Like 'sql_', 'vinyl_', etc.

I am ok with both. Or maybe you will be able to find a third
solution.

Another problem is that: pairs() and select() somewhy return
different results.

tarantool> t = {}
---
...

tarantool> for k, v in box.space._vsql_settings:pairs() do table.insert(t, {k, v}) end
---
...

tarantool> t
---
- - - <iterator state>
    - ['defer_foreign_keys', false]
...

tarantool> box.space._vsql_settings:select()
---
- - ['defer_foreign_keys', false]
  - ['full_column_names', false]
  - ['recursive_triggers', true]
  - ['reverse_unordered_selects', false]
  - ['sql_compound_select_limit', 30]
  - ['sql_default_engine', 'memtx']
  - ['parser_trace', false]
  - ['select_trace', false]
  - ['sql_trace', false]
  - ['vdbe_addoptrace', false]
  - ['vdbe_debug', false]
  - ['vdbe_eqp', false]
  - ['vdbe_listing', false]
  - ['vdbe_trace', false]
  - ['where_trace', false]
...

As you see, pairs() stops after a first tuple. For other spaces
empty pairs and select work the same.

> ---
>  src/box/bootstrap.snap             | Bin 5934 -> 5973 bytes
>  src/box/lua/space.cc               |   2 +
>  src/box/lua/upgrade.lua            |  23 +++++
>  src/box/schema_def.h               |   2 +
>  src/box/sql.c                      | 203 +++++++++++++++++++++++++++++++++++++
>  src/box/sql.h                      |  66 ++++++++++++
>  src/box/sql/sqlInt.h               |  14 +--
>  src/box/sysview.c                  |  19 +++-
>  test/app-tap/tarantoolctl.test.lua |   4 +-
>  test/box-py/bootstrap.result       |   5 +-
>  test/box/access_misc.result        | 136 +++++++++++++------------
>  test/box/access_sysview.result     |   6 +-
>  test/box/alter.result              |   5 +-
>  test/box/sql.result                | 111 ++++++++++++++++++++
>  test/box/sql.test.lua              |  38 +++++++
>  test/wal_off/alter.result          |   2 +-
>  16 files changed, 542 insertions(+), 94 deletions(-)
> 
> diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua
> index 2abd75d..f105db8 100644
> --- a/src/box/lua/upgrade.lua
> +++ b/src/box/lua/upgrade.lua
> @@ -930,6 +930,28 @@ local function upgrade_to_2_3_0()
>  end
>  
>  --------------------------------------------------------------------------------
> +-- Tarantool 2.3.1
> +--------------------------------------------------------------------------------
> +
> +local function create_vsql_settings_sysview()
> +    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 _vsql_settings")
> +    _space:insert{box.schema.VSQL_SETTINGS_ID, ADMIN, '_vsql_settings',
> +                  'sysview', 0, setmap({}), format}
> +    log.info("create index _sql_settings:primary")

3. _vsql, not _sql

> +    _index:insert{box.schema.VSQL_SETTINGS_ID, 0, 'primary', 'tree',

4. See? You said it is 'tree' and the key is string, but select() returns
tuples in a mixed order:

  - ['sql_default_engine', 'memtx']
  - ['parser_trace', false]
  - ['select_trace', false]

's', 'p', 's' - clearly not an alphabetical order.

> +                  {unique = true}, {{0, 'string'}}}
> +end
> +
> diff --git a/src/box/schema_def.h b/src/box/schema_def.h
> index 85f652d..04e1e33 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 _vsql_settings. */
> +	BOX_VSQL_SETTINGS_ID = 380,

5. Usually system views are the original space ID + 1.
So here it would be 381. Sorry for the nit.

>  	/** End of the reserved range of system spaces. */
>  	BOX_SYSTEM_ID_MAX = 511,
>  	BOX_ID_NIL = 2147483647
> diff --git a/src/box/sql.c b/src/box/sql.c
> index f1df555..0c73caf 100644
> --- a/src/box/sql.c
> +++ b/src/box/sql.c
> @@ -1265,3 +1265,206 @@ vdbe_field_ref_prepare_tuple(struct vdbe_field_ref *field_ref,
>  	vdbe_field_ref_create(field_ref, tuple, tuple_data(tuple),
>  			      tuple->bsize);
>  }
> +
> +struct sql_option_metadata sql_options[] = {
> +	/* SQL_OPTION_DEFER_FOREIGN_KEYS */
> +	{"defer_foreign_keys", FIELD_TYPE_BOOLEAN, SQL_DeferFKs},
> +	/* SQL_OPTION_DEFER_FOREIGN_KEYS */

6. Double SQL_OPTION_DEFER_FOREIGN_KEYS.

> +	{"full_column_names", FIELD_TYPE_BOOLEAN, SQL_FullColNames},
> +	/* SQL_OPTION_RECURSIVE_TRIGGERS */
> +	{"recursive_triggers", FIELD_TYPE_BOOLEAN, SQL_RecTriggers},
> +	/* SQL_OPTION_REVERSE_UNORDERED_SELECTS */
> +	{"reverse_unordered_selects", FIELD_TYPE_BOOLEAN, SQL_ReverseOrder},
> +	/* SQL_OPTION_COMPOUND_SELECT_LIMIT */
> +	{"sql_compound_select_limit", FIELD_TYPE_INTEGER, 0},
> +	/* SQL_OPTION_DEFAULT_ENGINE */
> +	{"sql_default_engine", FIELD_TYPE_STRING, 0},
> +	/* SQL_OPTION_PARSER_TRACE */
> +	{"parser_trace", FIELD_TYPE_BOOLEAN, PARSER_TRACE_FLAG},
> +	/* SQL_OPTION_SELECT_TRACE */
> +	{"select_trace", FIELD_TYPE_BOOLEAN, SQL_SelectTrace},
> +	/* SQL_OPTION_TRACE */
> +	{"sql_trace", FIELD_TYPE_BOOLEAN, SQL_SqlTrace},
> +	/* SQL_OPTION_VDBE_ADDOPTRACE */
> +	{"vdbe_addoptrace", FIELD_TYPE_BOOLEAN, SQL_VdbeAddopTrace},
> +	/* SQL_OPTION_VDBE_DEBUG */
> +	{"vdbe_debug", FIELD_TYPE_BOOLEAN,
> +	 SQL_SqlTrace | SQL_VdbeListing | SQL_VdbeTrace},
> +	/* SQL_OPTION_VDBE_EQP */
> +	{"vdbe_eqp", FIELD_TYPE_BOOLEAN, SQL_VdbeEQP},
> +	/* SQL_OPTION_VDBE_LISTING */
> +	{"vdbe_listing", FIELD_TYPE_BOOLEAN, SQL_VdbeListing},
> +	/* SQL_OPTION_VDBE_TRACE */
> +	{"vdbe_trace", FIELD_TYPE_BOOLEAN, SQL_VdbeTrace},
> +	/* SQL_OPTION_WHERE_TRACE */
> +	{"where_trace", FIELD_TYPE_BOOLEAN, SQL_WhereTrace},
> +};
> +
> +static inline int
> +sql_option_id_by_key(const char *key)

7. From the API it looks like the key is a normal string,
but in fact it is a MessagePack encoded string. Please,
say it somewhere in the function name/comment/parameter name.

> +{
> +	uint32_t len;
> +	struct region *region = &fiber()->gc;
> +	size_t svp = region_used(region);
> +	const char *tmp = mp_decode_str(&key, &len);
> +	char *str = region_alloc(region, len + 1);

8. Please, use tt_cstr. It is much faster and simpler.

> +	strncpy(str, tmp, len);
> +	str[len] = '\0';
> +	int id;
> +	for (id = 0; id < SQL_OPTION_max; ++id) {
> +		if (strcmp(str, sql_options[id].name) == 0)
> +			break;
> +	}
> +	region_truncate(region, svp);
> +	return id;
> +}
> +
> +/**
> + * Create tuple that contains name and value of the option.
> + *
> + * @param format format for new tuple.
> + * @param option_id id of option to return.
> + * @param result[out] new tuple.

9. Please, use capital letters in the sentences beginning.

10. [out] modifier stands right after param:

        @param[out]

> + */
> +static int
> +sql_option_tuple(struct tuple_format *format, int option_id,
> +		 struct tuple **result)
> +{
> +	if (option_id < 0 || option_id >= SQL_OPTION_max) {
> +		*result = NULL;
> +		return 0;
> +	}
> +	int limit = 0;
> +	const char *engine = NULL;
> +	struct region *region = &fiber()->gc;
> +	struct session *session = current_session();
> +	uint32_t flags = session->sql_flags;
> +	uint32_t option_flag = sql_options[option_id].flag;
> +	/* Change to format->*_field_count */

11. Sorry, I didn't understand the comment. Change what? Why
not to change now?

> +	uint32_t column_count = 2;
> +	size_t size = mp_sizeof_array(column_count) +
> +		      mp_sizeof_str(strlen(sql_options[option_id].name));
> +	if (sql_options[option_id].field_type == FIELD_TYPE_BOOLEAN) {
> +		size += mp_sizeof_bool(true);
> +	} else if (option_id == SQL_OPTION_DEFAULT_ENGINE) {
> +		engine = sql_storage_engine_strs[session->sql_default_engine];
> +		size += mp_sizeof_str(strlen(engine));
> +	} else {
> +		assert(option_id == SQL_OPTION_COMPOUND_SELECT_LIMIT);
> +		limit = sql_get()->aLimit[SQL_LIMIT_COMPOUND_SELECT];
> +		size += mp_sizeof_uint(limit);
> +	}
> +
> +	size_t svp = region_used(region);
> +	char *pos_ret = region_alloc(region, size);
> +	if (pos_ret == NULL) {
> +		diag_set(OutOfMemory, size, "region_alloc", "pos_ret");
> +		return -1;
> +	}
> +	char *pos = mp_encode_array(pos_ret, column_count);
> +	pos = mp_encode_str(pos, sql_options[option_id].name,
> +			    strlen(sql_options[option_id].name));
> +	if (sql_options[option_id].field_type == FIELD_TYPE_BOOLEAN)
> +		pos = mp_encode_bool(pos, (flags & option_flag) == option_flag);
> +	else if (option_id == SQL_OPTION_DEFAULT_ENGINE)
> +		pos = mp_encode_str(pos, engine, strlen(engine));
> +	else
> +		pos = mp_encode_uint(pos, limit);
> +	struct tuple *tuple = tuple_new(format, pos_ret, pos_ret + size);
> +	region_truncate(region, svp);
> +	if (tuple == NULL)
> +		return -1;
> +	*result = tuple;
> +	return 0;
> +}
> +
> +int> +sql_options_get(struct index *index, const char *key, uint32_t part_count,
> +		struct tuple **result)
> +{
> +	assert(part_count == 1);
> +	(void)part_count;
> +	struct space *space = space_cache_find(index->def->space_id);
> +	uint32_t option_id = sql_option_id_by_key(key);
> +	if (option_id == SQL_OPTION_max) {
> +		*result = NULL;
> +		return 0;
> +	}
> +	return sql_option_tuple(space->format, option_id, result);
> +}
> +
> +struct sql_options_iterator {
> +	struct iterator base;
> +	struct tuple_format *format;
> +	int option_id;
> +	bool is_eq_type;
> +	size_t svp;
> +};
> +
> +static int
> +sql_options_iterator_next(struct iterator *itr, struct tuple **ret)
> +{
> +	struct sql_options_iterator *it = (struct sql_options_iterator *)itr;
> +	int rc = sql_option_tuple(it->format, it->option_id++, ret);
> +	if (it->is_eq_type)
> +		it->option_id = SQL_OPTION_max;
> +	return rc;
> +}
> +
> +static int
> +sql_options_iterator_prev(struct iterator *itr, struct tuple **ret)
> +{
> +	struct sql_options_iterator *it = (struct sql_options_iterator *)itr;
> +	int rc = sql_option_tuple(it->format, it->option_id--, ret);
> +	if (it->is_eq_type)
> +		it->option_id = -1;
> +	return rc;
> +}
> +
> +static void
> +sql_options_iterator_free(struct iterator *itr)
> +{
> +	struct sql_options_iterator *it = (struct sql_options_iterator *)itr;
> +	region_truncate(&fiber()->gc, it->svp);
> +}
> +
> +struct iterator *
> +sql_options_create_iterator(struct index *index, enum iterator_type type,
> +			    const char *key, uint32_t part_count)
> +{
> +	bool is_eq_type = false;
> +	uint32_t option_id;
> +	if (part_count > 0) {
> +		assert(part_count == 1);
> +		option_id = sql_option_id_by_key(key);
> +		if (type == ITER_EQ || type == ITER_REQ)
> +			is_eq_type = true;
> +		else if (type == ITER_LT)
> +			--option_id;
> +		else if (type == ITER_GT)
> +			++option_id;
> +		if (option_id == SQL_OPTION_max && type == ITER_LE)
> +			--option_id;
> +	} else {
> +		option_id = iterator_type_is_reverse(type) ?
> +			    SQL_OPTION_max - 1 : 0;
> +	}
> +	struct space *space = space_cache_find(index->def->space_id);
> +	struct region *region = &fiber()->gc;
> +	size_t svp = region_used(region);
> +	struct sql_options_iterator *it = region_alloc(region, sizeof(*it));

12. Unfortunately, you can't allocate iterators on a
region - iterators should survive fiber garbage
collection.

> +	if (it == NULL) {
> +		diag_set(OutOfMemory, sizeof(*it), "region_alloc", "it");
> +		return NULL;
> +	}
> +	iterator_create(&it->base, index);
> +	it->base.next = iterator_type_is_reverse(type) ?
> +			sql_options_iterator_prev :
> +			sql_options_iterator_next;
> +	it->base.free = sql_options_iterator_free;
> +	it->option_id = option_id;
> +	it->is_eq_type = is_eq_type;
> +	it->format = space->format;
> +	it->svp = svp;
> +	return (struct iterator *)it;
> +}
> diff --git a/src/box/sql.h b/src/box/sql.h
> index 0fa52fc..5c23748 100644
> --- a/src/box/sql.h
> +++ b/src/box/sql.h
> @@ -33,11 +33,68 @@
>  
>  #include <stdbool.h>
>  #include <stdint.h>
> +#include "iterator_type.h"
>  
>  #if defined(__cplusplus)
>  extern "C" {
>  #endif
>  
> +/** SQL options flags. */
> +/** True to trace VDBE execution */
> +#define SQL_VdbeTrace		0x00000001
> +/** Debug print info about SQL query as it parsed */
> +#define PARSER_TRACE_FLAG	0x00000002
> +/** Show full column names on SELECT */
> +#define SQL_FullColNames	0x00000004
> +/** Debug print SQL as it executes */
> +#define SQL_SqlTrace		0x00000200
> +/** Debug info about select statement */
> +#define SQL_SelectTrace		0x00000800
> +/** Debug info about optimizer's work */
> +#define SQL_WhereTrace		0x00008000
> +/** Debug listings of VDBE programs */
> +#define SQL_VdbeListing		0x00000400
> +/** Trace sqlVdbeAddOp() calls */
> +#define SQL_VdbeAddopTrace	0x00001000
> +/** Reverse unordered SELECTs */
> +#define SQL_ReverseOrder	0x00020000
> +/** Enable recursive triggers */
> +#define SQL_RecTriggers		0x00040000
> +/** Defer all FK constraints */
> +#define SQL_DeferFKs		0x02000000
> +/** Debug EXPLAIN QUERY PLAN */
> +#define SQL_VdbeEQP		0x08000000

13. Why have you moved these macros from their old
place?

> +
> +enum {
> +	SQL_OPTION_DEFER_FOREIGN_KEYS = 0,
> +	SQL_OPTION_FULL_COLUMN_NAMES,
> +	SQL_OPTION_RECURSIVE_TRIGGERS,
> +	SQL_OPTION_REVERSE_UNORDERED_SELECTS,
> +	SQL_OPTION_COMPOUND_SELECT_LIMIT,
> +	SQL_OPTION_DEFAULT_ENGINE,
> +#ifndef NDEBUG> diff --git a/test/box/access_misc.result b/test/box/access_misc.result
> index a1b6435..66469e1 100644
> --- a/test/box/access_misc.result
> +++ b/test/box/access_misc.result
> @@ -835,144 +835,146 @@ box.space._space:select()
>        {'name': 'language', 'type': 'str'}, {'name': 'code', 'type': 'str'}]]
>    - [372, 1, '_func_index', 'memtx', 0, {}, [{'name': 'space_id', 'type': 'unsigned'},
>        {'name': 'index_id', 'type': 'unsigned'}, {'name': 'func_id', 'type': 'unsigned'}]]
> +  - [380, 1, '_vsql_settings', 'sysview', 0, {}, [{'name': 'name', 'type': 'string'},
> +      {'name': 'value', 'type': 'any'}]]
>  ...
>  box.space._func:select()
>  ---
>  - - [1, 1, 'box.schema.user.info', 1, 'LUA', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, ['LUA'], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, ['LUA'], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [2, 1, 'TRIM', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [3, 1, 'TYPEOF', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [4, 1, 'PRINTF', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [5, 1, 'UNICODE', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [6, 1, 'CHAR', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [7, 1, 'HEX', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [8, 1, 'VERSION', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [9, 1, 'QUOTE', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [10, 1, 'REPLACE', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [11, 1, 'SUBSTR', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [12, 1, 'GROUP_CONCAT', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [13, 1, 'JULIANDAY', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [14, 1, 'DATE', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [15, 1, 'TIME', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [16, 1, 'DATETIME', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [17, 1, 'STRFTIME', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [18, 1, 'CURRENT_TIME', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [19, 1, 'CURRENT_TIMESTAMP', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none',
> -    'none', false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    'none', false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [20, 1, 'CURRENT_DATE', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [21, 1, 'LENGTH', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [22, 1, 'POSITION', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [23, 1, 'ROUND', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [24, 1, 'UPPER', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [25, 1, 'LOWER', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [26, 1, 'IFNULL', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [27, 1, 'RANDOM', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [28, 1, 'CEIL', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [29, 1, 'CEILING', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [30, 1, 'CHARACTER_LENGTH', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none',
> -    'none', false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    'none', false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [31, 1, 'CHAR_LENGTH', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [32, 1, 'FLOOR', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [33, 1, 'MOD', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [34, 1, 'OCTET_LENGTH', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [35, 1, 'ROW_COUNT', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [36, 1, 'COUNT', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [37, 1, 'LIKE', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [38, 1, 'ABS', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [39, 1, 'EXP', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [40, 1, 'LN', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [41, 1, 'POWER', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [42, 1, 'SQRT', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [43, 1, 'SUM', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [44, 1, 'TOTAL', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [45, 1, 'AVG', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [46, 1, 'RANDOMBLOB', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [47, 1, 'NULLIF', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [48, 1, 'ZEROBLOB', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [49, 1, 'MIN', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [50, 1, 'MAX', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [51, 1, 'COALESCE', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [52, 1, 'EVERY', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [53, 1, 'EXISTS', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [54, 1, 'EXTRACT', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [55, 1, 'SOME', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none', false,
> -    false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [56, 1, 'GREATER', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [57, 1, 'LESSER', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [58, 1, 'SOUNDEX', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [59, 1, 'LIKELIHOOD', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [60, 1, 'LIKELY', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [61, 1, 'UNLIKELY', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [62, 1, '_sql_stat_get', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none',
> -    'none', false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    'none', false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [63, 1, '_sql_stat_push', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none',
> -    'none', false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    'none', false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [64, 1, '_sql_stat_init', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none',
> -    'none', false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    'none', false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [65, 1, 'LUA', 1, 'LUA', 'function(code) return assert(loadstring(code))() end',
>      'function', ['string'], 'any', 'none', 'none', false, false, true, ['LUA', 'SQL'],
> -    {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [66, 1, 'GREATEST', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>    - [67, 1, 'LEAST', 1, 'SQL_BUILTIN', '', 'function', [], 'any', 'none', 'none',
> -    false, false, true, [], {}, '', '2019-08-14 14:09:37', '2019-08-14 14:09:37']
> +    false, false, true, [], {}, '', '2019-10-16 15:38:07', '2019-10-16 15:38:07']
>  ...

14. Could we somehow refactor that test so as it would not change
so much on each change of the schema? In a separate commit/branch.


More information about the Tarantool-patches mailing list