[Tarantool-patches] [PATCH v2 3/6] sql: remove SQL built-in functions from _func
imeevma at tarantool.org
imeevma at tarantool.org
Wed Aug 4 15:58:41 MSK 2021
Hi! Thank you for the review! I did not include diff since there were too many
changes and part of them were moved to the other patches. My answers and new
patch below.
On 02.08.2021 23:12, Vladislav Shpilevoy wrote:
> Hi! Thanks for the patch!
>
> See 11 comments below.
>
> On 30.07.2021 00:48, imeevma at tarantool.org wrote:
>> This patch removes SQL built-in functions from _func. These functions
>> could be called directly from Lua, however all they did was returnd an
>
> 1. returnd -> returned.
>
Fixed.
>> error. After this patch, no SQL built-in functions can be called
>> directly from LUA.
>>
>> Closes #6106
>> ---
>> https://github.com/tarantool/tarantool/issues/6106
>> https://github.com/tarantool/tarantool/tree/imeevma/gh-6106-remove-sql-builtins-from-_func
>>> diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua
>> index 97afc0b4d..d0ca3db97 100644
>> --- a/src/box/lua/upgrade.lua
>> +++ b/src/box/lua/upgrade.lua
>> @@ -1003,19 +1003,19 @@ end
>> --------------------------------------------------------------------------------
>> -- Tarantool 2.9.1
>> --------------------------------------------------------------------------------
>> -local function sql_builtin_function_uuid()
>> +local function remove_sql_builtin_functions_from_func()
>> local _func = box.space._func
>> local _priv = box.space._priv
>> - local datetime = os.date("%Y-%m-%d %H:%M:%S")
>> - local t = _func:auto_increment({ADMIN, 'UUID', 1, 'SQL_BUILTIN', '',
>> - 'function', {}, 'any', 'none', 'none',
>> - false, false, true, {}, setmap({}), '',
>> - datetime, datetime})
>> - _priv:replace{ADMIN, PUBLIC, 'function', t.id, box.priv.X}
>> + for _, v in _func:pairs() do
>> + if (v.language == "SQL_BUILTIN") then
>
> 2. You do not need () around the condition.
>
Fixed.
>> + _priv:delete({2, 'function', v.id})
>> + _func:delete({v.id})
>> + end
>> + end
>> end
>> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
>> index 3772596d6..7c1616a3a 100644
>> --- a/src/box/sql/expr.c
>> +++ b/src/box/sql/expr.c
>> @@ -326,11 +326,13 @@ sql_expr_coll(Parse *parse, Expr *p, bool *is_explicit_coll, uint32_t *coll_id,
>> break;
>> }
>> if (op == TK_FUNCTION) {
>> - uint32_t arg_count = p->x.pList == NULL ? 0 :
>> - p->x.pList->nExpr;
>> + int arg_count = p->x.pList == NULL ? 0 :
>> + p->x.pList->nExpr;
>> struct func *func =
>> - sql_func_by_signature(p->u.zToken, arg_count);
>> - if (func == NULL)
>> + sql_func_by_name(p->u.zToken);
>> + if (func == NULL || !func->def->exports.sql ||
>
> 3. Why don't you filter by !func->def->exports.sql in sql_func_by_name()?
> Is it possible in some places to call a function not exported to SQL?
>
Done, I moved all similar checks to new function sql_func_find().
>> + (func->def->param_count != -1 &&
>> + func->def->param_count != arg_count))
>
> 4. Why is argument count important? Isn't SQL_FUNC_DERIVEDCOLL below
> enough?
>
Fixed. I think here it is not important. Also, in some cases we only need
function flags without function itself. I used this place to introduce it, but
its real usage will be later, during addition of static type checking for SQL
built-in functions.
> The same 2 comments in the next diff block.
>
In these two places and one place in resolve.c I used new function, that have
all needed checks inside of it.
>> break;
>> if (sql_func_flag_is_set(func, SQL_FUNC_DERIVEDCOLL) &&
>> arg_count > 0) {
>> @@ -3979,8 +3981,10 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
>> nFarg = pFarg ? pFarg->nExpr : 0;
>> assert(!ExprHasProperty(pExpr, EP_IntValue));
>> zId = pExpr->u.zToken;
>> - struct func *func = sql_func_by_signature(zId, nFarg);
>> - if (func == NULL) {
>> + struct func *func = sql_func_by_name(zId);
>> + if (func == NULL || !func->def->exports.sql ||
>> + (func->def->param_count != -1 &&
>> + func->def->param_count != nFarg)) {
>> diag_set(ClientError, ER_NO_SUCH_FUNCTION,
>> zId);
>> pParse->is_aborted = true;
>> diff --git a/src/box/sql/func.c b/src/box/sql/func.c
>> index 6ca852dec..b05038e2e 100644
>> --- a/src/box/sql/func.c
>> +++ b/src/box/sql/func.c
>> @@ -47,6 +47,37 @@
>> #include <unicode/ucol.h>
>> #include "box/coll_id_cache.h"
>> #include "box/schema.h"
>> +#include "core/assoc.h"
>
> 5. core/ prefix is not not necessary. Also it might look better if
> you group all box/ includes together.
>
Fixed.
>> +#include "box/user.h"
>> +
>> +static struct mh_strnptr_t *built_in_functions = NULL;
>> +
>> +static struct func *
>> +get_built_in_function(const char *name)
>> +{
>> + uint32_t len = strlen(name);
>> + mh_int_t func = mh_strnptr_find_inp(built_in_functions, name, len);
>> + if (func == mh_end(built_in_functions))
>> + return NULL;
>> + return (struct func *) mh_strnptr_node(built_in_functions, func)->val;
>
> 6. In the new code we do not use whitespaces after unary
> operators like cast. But even better - in C you do not need
> an explicit cast from void * to any other pointer.
>
Thanks, fixed.
>> +}
>> +
>> +static int
>> +built_in_functions_cache_insert(struct func *func)
>
> 7. Please, make the hash methods have the same prefix. For instance,
> sql_builtin_func_get(), sql_builtin_func_put().
>
Thanks, replaced to suggested names.
>> +{
>> + const char *name = func->def->name;
>> + uint32_t len = strlen(name);
>> + assert(get_built_in_function(name) == NULL);
>> +
>> + uint32_t hash = mh_strn_hash(name, len);
>> + const struct mh_strnptr_node_t strnode = {name, len, hash, func};
>> + mh_int_t k = mh_strnptr_put(built_in_functions, &strnode, NULL, NULL);
>> + if (k == mh_end(built_in_functions)) {
>> + diag_set(OutOfMemory, sizeof(strnode), "malloc", "strnode");
>> + return -1;
>> + }
>> + return 0;
>> +}
>> @@ -2657,6 +2685,67 @@ static struct {
>>
>> static struct func_vtab func_sql_builtin_vtab;
>>
>> +int
>> +sql_built_in_functions_cache_init(void)
>> +{
>> + built_in_functions = mh_strnptr_new();
>
> 8. It might make sense to check the result for NULL and call
> panic() if it is.
>
Fixed.
>> + for (uint32_t i = 0; i < nelem(sql_builtins); ++i) {
>> + const char *name = sql_builtins[i].name;
>> + uint32_t len = strlen(name);
>> + uint32_t size = sizeof(struct func_def) + len + 1;
>> + struct func_def *def = malloc(size);
>
> 9. Ditto.
>
Fixed.
>> + def->fid = i;
>> + def->uid = 1;
>> + def->body = NULL;
>> + def->comment = NULL;
>> + def->setuid = true;
>> + def->is_deterministic = sql_builtins[i].is_deterministic;
>> + def->is_sandboxed = false;
>> + def->param_count = sql_builtins[i].param_count;
>> + def->returns = sql_builtins[i].returns;
>> + def->aggregate = sql_builtins[i].aggregate;
>> + def->language = FUNC_LANGUAGE_SQL_BUILTIN;
>> + def->name_len = len;
>> + def->exports.sql = sql_builtins[i].export_to_sql;
>> + func_opts_create(&def->opts);
>> + memcpy(def->name, name, len + 1);
>> +
>> + struct func_sql_builtin *func = malloc(sizeof(*func));
>> + if (func == NULL) {
>> + diag_set(OutOfMemory, sizeof(*func), "malloc", "func");
>> + return -1;
>
> 10. The result of sql_built_in_functions_cache_init() is never checked.
> I would suggest to make it void and panic on all errors.
>
Fixed.
>> + }
>> +
>> + func->base.def = def;
>> + func->base.vtab = &func_sql_builtin_vtab;
>> + credentials_create_empty(&func->base.owner_credentials);
>> + memset(func->base.access, 0, sizeof(func->base.access));
>> +
>> + func->flags = sql_builtins[i].flags;
>> + func->call = sql_builtins[i].call;
>> + func->finalize = sql_builtins[i].finalize;
>> + if (built_in_functions_cache_insert(&func->base) != 0)
>> + return -1;
>> + }
>> + return 0;
>> +}
>> +
>> +void
>> +sql_built_in_functions_cache_free(void)
>> +{
>> + if (built_in_functions == NULL)
>> + return;
>> + for (uint32_t i = 0; i < nelem(sql_builtins); ++i) {
>> + const char *name = sql_builtins[i].name;
>> + uint32_t len = strlen(name);
>> + mh_int_t k = mh_strnptr_find_inp(built_in_functions, name, len);
>> + if (k == mh_end(built_in_functions))
>> + continue;
>> + mh_strnptr_del(built_in_functions, k, NULL);
>
> 11. Perhaps a more 'canonical' way would be like
>
> while (mh_size() > 0) { mh_del(mh_first()); ... }
>
I believe it cannot be implemented on hash table with string key. Added an
assert to check that hash table is empty.
> Also you didn't free the function objects.
>
Fixed.
>> + }
>> + mh_strnptr_delete(built_in_functions);
>> +}
New patch:
commit cd575f0326c6276a0b44470532acff22eb97f694
Author: Mergen Imeev <imeevma at gmail.com>
Date: Thu Jul 29 13:54:53 2021 +0300
sql: remove SQL built-in functions from _func
This patch removes SQL built-in functions from _func. These functions
could be called directly from Lua, however all they did was returned an
error. After this patch, no SQL built-in functions can be called
directly from LUA.
Part of #6106
diff --git a/changelogs/unreleased/gh-6106-remove-sql-built-ins-from-_func.md b/changelogs/unreleased/gh-6106-remove-sql-built-ins-from-_func.md
new file mode 100644
index 000000000..88b458540
--- /dev/null
+++ b/changelogs/unreleased/gh-6106-remove-sql-built-ins-from-_func.md
@@ -0,0 +1,7 @@
+## feature/sql
+
+* SQL built-in functions were removed from \_func system space (gh-6106).
+* After this patch, functions will be looked up first in SQL built-in functions
+ and then in user-defined functions.
+* Fixed incorrect error message in case of misuse of the function used to set
+ the default value.
\ No newline at end of file
diff --git a/src/box/alter.cc b/src/box/alter.cc
index 390199298..935790df4 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -3548,13 +3548,6 @@ on_replace_dd_func(struct trigger * /* trigger */, void *event)
"function has references");
return -1;
}
- /* Can't' drop a builtin function. */
- if (old_func->def->language == FUNC_LANGUAGE_SQL_BUILTIN) {
- diag_set(ClientError, ER_DROP_FUNCTION,
- (unsigned) old_func->def->uid,
- "function is SQL built-in");
- return -1;
- }
struct trigger *on_commit =
txn_alter_trigger_new(on_drop_func_commit, old_func);
struct trigger *on_rollback =
diff --git a/src/box/bootstrap.snap b/src/box/bootstrap.snap
index 57374decc..018670d2a 100644
Binary files a/src/box/bootstrap.snap and b/src/box/bootstrap.snap differ
diff --git a/src/box/box.cc b/src/box/box.cc
index 0ff7ee468..a7eda4214 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -2914,6 +2914,7 @@ box_free(void)
gc_free();
engine_shutdown();
wal_free();
+ sql_built_in_functions_cache_free();
}
}
diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua
index 97afc0b4d..6abce50f4 100644
--- a/src/box/lua/upgrade.lua
+++ b/src/box/lua/upgrade.lua
@@ -1003,19 +1003,19 @@ end
--------------------------------------------------------------------------------
-- Tarantool 2.9.1
--------------------------------------------------------------------------------
-local function sql_builtin_function_uuid()
+local function remove_sql_builtin_functions_from_func()
local _func = box.space._func
local _priv = box.space._priv
- local datetime = os.date("%Y-%m-%d %H:%M:%S")
- local t = _func:auto_increment({ADMIN, 'UUID', 1, 'SQL_BUILTIN', '',
- 'function', {}, 'any', 'none', 'none',
- false, false, true, {}, setmap({}), '',
- datetime, datetime})
- _priv:replace{ADMIN, PUBLIC, 'function', t.id, box.priv.X}
+ for _, v in _func:pairs() do
+ if v.language == "SQL_BUILTIN" then
+ _priv:delete({2, 'function', v.id})
+ _func:delete({v.id})
+ end
+ end
end
local function upgrade_to_2_9_1()
- sql_builtin_function_uuid()
+ remove_sql_builtin_functions_from_func()
end
--------------------------------------------------------------------------------
diff --git a/src/box/sql.c b/src/box/sql.c
index 433264abe..f18dfa063 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -75,6 +75,7 @@ sql_init(void)
panic("failed to initialize SQL subsystem");
sql_stmt_cache_init();
+ sql_built_in_functions_cache_init();
assert(db != NULL);
}
diff --git a/src/box/sql.h b/src/box/sql.h
index 4c364306c..2ac97c762 100644
--- a/src/box/sql.h
+++ b/src/box/sql.h
@@ -56,6 +56,15 @@ sql_init(void);
struct sql *
sql_get(void);
+/** Initialize global cache for built-in functions. */
+void
+sql_built_in_functions_cache_init(void);
+
+/** Free global cache for built-in functions. */
+void
+sql_built_in_functions_cache_free(void);
+
+
struct Expr;
struct Parse;
struct Select;
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 9514d070a..2a3a5d457 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -47,6 +47,10 @@
#include <unicode/ucol.h>
#include "box/coll_id_cache.h"
#include "box/schema.h"
+#include "box/user.h"
+#include "assoc.h"
+
+static struct mh_strnptr_t *built_in_functions = NULL;
static const unsigned char *
mem_as_ustr(struct Mem *mem)
@@ -2643,11 +2647,49 @@ static struct {
},
};
+static struct func *
+built_in_func_get(const char *name)
+{
+ uint32_t len = strlen(name);
+ mh_int_t k = mh_strnptr_find_inp(built_in_functions, name, len);
+ if (k == mh_end(built_in_functions))
+ return NULL;
+ return mh_strnptr_node(built_in_functions, k)->val;
+}
+
+static void
+built_in_func_put(struct func *func)
+{
+ const char *name = func->def->name;
+ uint32_t len = strlen(name);
+ assert(built_in_func_get(name) == NULL);
+
+ uint32_t hash = mh_strn_hash(name, len);
+ const struct mh_strnptr_node_t strnode = {name, len, hash, func};
+ mh_int_t k = mh_strnptr_put(built_in_functions, &strnode, NULL, NULL);
+ if (k == mh_end(built_in_functions)) {
+ panic("Out of memory on insertion into SQL built-in functions "
+ "hash");
+ }
+}
+
struct func *
sql_func_find(struct Expr *expr)
{
const char *name = expr->u.zToken;
- struct func *func = func_by_name(name, strlen(name));
+ int n = expr->x.pList ? expr->x.pList->nExpr : 0;
+ struct func *func = built_in_func_get(name);
+ if (func != NULL) {
+ assert(func->def->exports.sql);
+ int param_count = func->def->param_count;
+ if (param_count != -1 && param_count != n) {
+ diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, name,
+ tt_sprintf("%d", func->def->param_count), n);
+ return NULL;
+ }
+ return func;
+ }
+ func = func_by_name(name, strlen(name));
if (func == NULL) {
diag_set(ClientError, ER_NO_SUCH_FUNCTION, name);
return NULL;
@@ -2658,8 +2700,7 @@ sql_func_find(struct Expr *expr)
name));
return NULL;
}
- int n = expr->x.pList ? expr->x.pList->nExpr : 0;
- if (func->def->param_count != -1 && func->def->param_count != n) {
+ if (func->def->param_count != n) {
diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, name,
tt_sprintf("%d", func->def->param_count), n);
return NULL;
@@ -2670,9 +2711,10 @@ sql_func_find(struct Expr *expr)
uint32_t
sql_func_flags(const char *name)
{
- struct func *func = func_by_name(name, strlen(name));
- if (func == NULL || func->def->language != FUNC_LANGUAGE_SQL_BUILTIN)
+ struct func *func = built_in_func_get(name);
+ if (func == NULL)
return 0;
+ assert(func->def->language == FUNC_LANGUAGE_SQL_BUILTIN);
uint32_t flags = ((struct func_sql_builtin *)func)->flags;
if (func->def->aggregate == FUNC_AGGREGATE_GROUP)
flags |= SQL_FUNC_AGG;
@@ -2681,6 +2723,72 @@ sql_func_flags(const char *name)
static struct func_vtab func_sql_builtin_vtab;
+void
+sql_built_in_functions_cache_init(void)
+{
+ built_in_functions = mh_strnptr_new();
+ if (built_in_functions == NULL)
+ panic("Out of memory on creating SQL built-in functions hash");
+ for (uint32_t i = 0; i < nelem(sql_builtins); ++i) {
+ const char *name = sql_builtins[i].name;
+ if (!sql_builtins[i].export_to_sql)
+ continue;
+ uint32_t len = strlen(name);
+ uint32_t size = sizeof(struct func_def) + len + 1;
+ struct func_def *def = malloc(size);
+ if (def == NULL)
+ panic("Out of memory on creating SQL built-in");
+ def->fid = i;
+ def->uid = 1;
+ def->body = NULL;
+ def->comment = NULL;
+ def->setuid = true;
+ def->is_deterministic = sql_builtins[i].is_deterministic;
+ def->is_sandboxed = false;
+ def->param_count = sql_builtins[i].param_count;
+ def->returns = sql_builtins[i].returns;
+ def->aggregate = sql_builtins[i].aggregate;
+ def->language = FUNC_LANGUAGE_SQL_BUILTIN;
+ def->name_len = len;
+ def->exports.sql = sql_builtins[i].export_to_sql;
+ func_opts_create(&def->opts);
+ memcpy(def->name, name, len + 1);
+
+ struct func_sql_builtin *func = malloc(sizeof(*func));
+ if (func == NULL)
+ panic("Out of memory on creating SQL built-in");
+
+ func->base.def = def;
+ func->base.vtab = &func_sql_builtin_vtab;
+ credentials_create_empty(&func->base.owner_credentials);
+ memset(func->base.access, 0, sizeof(func->base.access));
+
+ func->flags = sql_builtins[i].flags;
+ func->call = sql_builtins[i].call;
+ func->finalize = sql_builtins[i].finalize;
+ built_in_func_put(&func->base);
+ }
+}
+
+void
+sql_built_in_functions_cache_free(void)
+{
+ if (built_in_functions == NULL)
+ return;
+ for (uint32_t i = 0; i < nelem(sql_builtins); ++i) {
+ const char *name = sql_builtins[i].name;
+ uint32_t len = strlen(name);
+ mh_int_t k = mh_strnptr_find_inp(built_in_functions, name, len);
+ if (k == mh_end(built_in_functions))
+ continue;
+ struct func *func = mh_strnptr_node(built_in_functions, k)->val;
+ mh_strnptr_del(built_in_functions, k, NULL);
+ func_delete(func);
+ }
+ assert(mh_size(built_in_functions) == 0);
+ mh_strnptr_delete(built_in_functions);
+}
+
struct func *
func_sql_builtin_new(struct func_def *def)
{
diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result
index b2328487c..cea440c64 100644
--- a/test/box-py/bootstrap.result
+++ b/test/box-py/bootstrap.result
@@ -176,73 +176,7 @@ box.space._priv:select{}
- [1, 0, 'universe', 0, 24]
- [1, 1, 'universe', 0, 4294967295]
- [1, 2, 'function', 1, 4]
- - [1, 2, 'function', 2, 4]
- - [1, 2, 'function', 3, 4]
- - [1, 2, 'function', 4, 4]
- - [1, 2, 'function', 5, 4]
- - [1, 2, 'function', 6, 4]
- - [1, 2, 'function', 7, 4]
- - [1, 2, 'function', 8, 4]
- - [1, 2, 'function', 9, 4]
- - [1, 2, 'function', 10, 4]
- - [1, 2, 'function', 11, 4]
- - [1, 2, 'function', 12, 4]
- - [1, 2, 'function', 13, 4]
- - [1, 2, 'function', 14, 4]
- - [1, 2, 'function', 15, 4]
- - [1, 2, 'function', 16, 4]
- - [1, 2, 'function', 17, 4]
- - [1, 2, 'function', 18, 4]
- - [1, 2, 'function', 19, 4]
- - [1, 2, 'function', 20, 4]
- - [1, 2, 'function', 21, 4]
- - [1, 2, 'function', 22, 4]
- - [1, 2, 'function', 23, 4]
- - [1, 2, 'function', 24, 4]
- - [1, 2, 'function', 25, 4]
- - [1, 2, 'function', 26, 4]
- - [1, 2, 'function', 27, 4]
- - [1, 2, 'function', 28, 4]
- - [1, 2, 'function', 29, 4]
- - [1, 2, 'function', 30, 4]
- - [1, 2, 'function', 31, 4]
- - [1, 2, 'function', 32, 4]
- - [1, 2, 'function', 33, 4]
- - [1, 2, 'function', 34, 4]
- - [1, 2, 'function', 35, 4]
- - [1, 2, 'function', 36, 4]
- - [1, 2, 'function', 37, 4]
- - [1, 2, 'function', 38, 4]
- - [1, 2, 'function', 39, 4]
- - [1, 2, 'function', 40, 4]
- - [1, 2, 'function', 41, 4]
- - [1, 2, 'function', 42, 4]
- - [1, 2, 'function', 43, 4]
- - [1, 2, 'function', 44, 4]
- - [1, 2, 'function', 45, 4]
- - [1, 2, 'function', 46, 4]
- - [1, 2, 'function', 47, 4]
- - [1, 2, 'function', 48, 4]
- - [1, 2, 'function', 49, 4]
- - [1, 2, 'function', 50, 4]
- - [1, 2, 'function', 51, 4]
- - [1, 2, 'function', 52, 4]
- - [1, 2, 'function', 53, 4]
- - [1, 2, 'function', 54, 4]
- - [1, 2, 'function', 55, 4]
- - [1, 2, 'function', 56, 4]
- - [1, 2, 'function', 57, 4]
- - [1, 2, 'function', 58, 4]
- - [1, 2, 'function', 59, 4]
- - [1, 2, 'function', 60, 4]
- - [1, 2, 'function', 61, 4]
- - [1, 2, 'function', 62, 4]
- - [1, 2, 'function', 63, 4]
- - [1, 2, 'function', 64, 4]
- [1, 2, 'function', 65, 4]
- - [1, 2, 'function', 66, 4]
- - [1, 2, 'function', 67, 4]
- - [1, 2, 'function', 68, 4]
- [1, 2, 'space', 276, 2]
- [1, 2, 'space', 277, 1]
- [1, 2, 'space', 281, 1]
diff --git a/test/box/access_bin.result b/test/box/access_bin.result
index aeb8b3bd8..7c720192f 100644
--- a/test/box/access_bin.result
+++ b/test/box/access_bin.result
@@ -295,10 +295,10 @@ test:drop()
box.schema.user.grant('guest', 'execute', 'universe')
---
...
-function f1() return box.space._func:get(1)[4] end
+function f1() return box.space._func.index[2]:get({'f1'})[4] end
---
...
-function f2() return box.space._func:get(69)[4] end
+function f2() return box.space._func.index[2]:get({'f1'})[4] end
---
...
box.schema.func.create('f1')
diff --git a/test/box/access_bin.test.lua b/test/box/access_bin.test.lua
index 954266858..e82ec759c 100644
--- a/test/box/access_bin.test.lua
+++ b/test/box/access_bin.test.lua
@@ -111,8 +111,8 @@ test:drop()
--
-- notice that guest can execute stuff, but can't read space _func
box.schema.user.grant('guest', 'execute', 'universe')
-function f1() return box.space._func:get(1)[4] end
-function f2() return box.space._func:get(69)[4] end
+function f1() return box.space._func.index[2]:get({'f1'})[4] end
+function f2() return box.space._func.index[2]:get({'f1'})[4] end
box.schema.func.create('f1')
box.schema.func.create('f2',{setuid=true})
c = net.connect(box.cfg.listen)
diff --git a/test/box/access_sysview.result b/test/box/access_sysview.result
index d7a7b7534..071fc8de2 100644
--- a/test/box/access_sysview.result
+++ b/test/box/access_sysview.result
@@ -258,11 +258,11 @@ box.session.su('guest')
...
#box.space._vpriv:select{}
---
-- 83
+- 17
...
#box.space._vfunc:select{}
---
-- 68
+- 2
...
#box.space._vcollation:select{}
---
@@ -290,11 +290,11 @@ box.session.su('guest')
...
#box.space._vpriv:select{}
---
-- 83
+- 17
...
#box.space._vfunc:select{}
---
-- 68
+- 2
...
#box.space._vsequence:select{}
---
diff --git a/test/box/function1.result b/test/box/function1.result
index 0166c828f..a49a133f7 100644
--- a/test/box/function1.result
+++ b/test/box/function1.result
@@ -97,7 +97,7 @@ box.func["function1.args"]
exports:
lua: true
sql: false
- id: 69
+ id: 66
setuid: false
is_multikey: false
is_deterministic: false
@@ -593,7 +593,7 @@ func
exports:
lua: true
sql: false
- id: 69
+ id: 66
setuid: false
is_multikey: false
is_deterministic: false
@@ -665,7 +665,7 @@ func
exports:
lua: true
sql: false
- id: 69
+ id: 66
setuid: false
is_multikey: false
is_deterministic: false
@@ -1032,7 +1032,7 @@ box.func.test ~= nil
box.func.test:drop()
---
...
--- Check SQL builtins
+-- Make sure there is no SQL built-in functions in _func.
test_run:cmd("setopt delimiter ';'")
---
- true
@@ -1048,7 +1048,7 @@ sql_builtin_list = {
"RANDOMBLOB", "NULLIF", "ZEROBLOB", "MIN", "MAX", "COALESCE", "EVERY",
"EXISTS", "EXTRACT", "SOME", "GREATER", "LESSER", "SOUNDEX",
"LIKELIHOOD", "LIKELY", "UNLIKELY", "_sql_stat_get", "_sql_stat_push",
- "_sql_stat_init", "GREATEST", "LEAST"
+ "_sql_stat_init", "GREATEST", "LEAST", "UUID"
}
test_run:cmd("setopt delimiter ''");
---
@@ -1056,7 +1056,7 @@ test_run:cmd("setopt delimiter ''");
ok = true
---
...
-for _, v in pairs(sql_builtin_list) do ok = ok and (box.space._func.index.name:get(v) ~= nil) end
+for _, v in pairs(sql_builtin_list) do ok = ok and (box.space._func.index.name:get(v) == nil) end
---
...
ok == true
@@ -1067,26 +1067,6 @@ box.func.LUA:call({"return 1 + 1"})
---
- 2
...
-box.schema.user.grant('guest', 'execute', 'function', 'SUM')
----
-...
-c = net.connect(box.cfg.listen)
----
-...
-c:call("SUM")
----
-- error: sql builtin function does not support Lua frontend
-...
-c:close()
----
-...
-box.schema.user.revoke('guest', 'execute', 'function', 'SUM')
----
-...
-box.schema.func.drop("SUM")
----
-- error: 'Can''t drop function 1: function is SQL built-in'
-...
-- Introduce function options
box.schema.func.create('test', {body = "function(tuple) return tuple end", is_deterministic = true, opts = {is_multikey = true}})
---
diff --git a/test/box/function1.test.lua b/test/box/function1.test.lua
index ab7b586a0..4fdd48520 100644
--- a/test/box/function1.test.lua
+++ b/test/box/function1.test.lua
@@ -363,7 +363,7 @@ f == nil
box.func.test ~= nil
box.func.test:drop()
--- Check SQL builtins
+-- Make sure there is no SQL built-in functions in _func.
test_run:cmd("setopt delimiter ';'")
sql_builtin_list = {
"TRIM", "TYPEOF", "PRINTF", "UNICODE", "CHAR", "HEX", "VERSION",
@@ -376,22 +376,15 @@ sql_builtin_list = {
"RANDOMBLOB", "NULLIF", "ZEROBLOB", "MIN", "MAX", "COALESCE", "EVERY",
"EXISTS", "EXTRACT", "SOME", "GREATER", "LESSER", "SOUNDEX",
"LIKELIHOOD", "LIKELY", "UNLIKELY", "_sql_stat_get", "_sql_stat_push",
- "_sql_stat_init", "GREATEST", "LEAST"
+ "_sql_stat_init", "GREATEST", "LEAST", "UUID"
}
test_run:cmd("setopt delimiter ''");
ok = true
-for _, v in pairs(sql_builtin_list) do ok = ok and (box.space._func.index.name:get(v) ~= nil) end
+for _, v in pairs(sql_builtin_list) do ok = ok and (box.space._func.index.name:get(v) == nil) end
ok == true
box.func.LUA:call({"return 1 + 1"})
-box.schema.user.grant('guest', 'execute', 'function', 'SUM')
-c = net.connect(box.cfg.listen)
-c:call("SUM")
-c:close()
-box.schema.user.revoke('guest', 'execute', 'function', 'SUM')
-box.schema.func.drop("SUM")
-
-- Introduce function options
box.schema.func.create('test', {body = "function(tuple) return tuple end", is_deterministic = true, opts = {is_multikey = true}})
box.func['test'].is_multikey == true
diff --git a/test/sql-tap/func5.test.lua b/test/sql-tap/func5.test.lua
index 13698582b..bd4561afc 100755
--- a/test/sql-tap/func5.test.lua
+++ b/test/sql-tap/func5.test.lua
@@ -1,6 +1,6 @@
#!/usr/bin/env tarantool
local test = require("sqltester")
-test:plan(27)
+test:plan(29)
--!./tcltestrunner.lua
-- 2010 August 27
@@ -346,4 +346,27 @@ box.func.F2:drop()
box.space.T01:drop()
box.space.T02:drop()
+--
+-- gh-6105: Make sure that functions that were described in _func but were not
+-- implemented are now removed.
+--
+test:do_catchsql_test(
+ "func-7.3",
+ [[
+ SELECT SQRT();
+ ]], {
+ 1, "Function 'SQRT' does not exist"
+ })
+
+-- Make sure that functions are looked up in built-in functions first.
+box.schema.func.create('ABS', {language = 'Lua', param_list = {"INTEGER"},
+ body = body, returns = 'number', exports = {'LUA'}});
+test:do_execsql_test(
+ "func-7.4",
+ [[
+ SELECT ABS(-111);
+ ]], {
+ 111
+ })
+
test:finish_test()
diff --git a/test/wal_off/func_max.result b/test/wal_off/func_max.result
index cc5bcc141..a3ab5b431 100644
--- a/test/wal_off/func_max.result
+++ b/test/wal_off/func_max.result
@@ -42,11 +42,11 @@ test_run:cmd("setopt delimiter ''");
...
func_limit()
---
-- error: 'Failed to create function ''func31933'': function id is too big'
+- error: 'Failed to create function ''func31936'': function id is too big'
...
drop_limit_func()
---
-- error: Function 'func31933' does not exist
+- error: Function 'func31936' does not exist
...
box.schema.user.create('testuser')
---
@@ -62,11 +62,11 @@ session.su('testuser')
...
func_limit()
---
-- error: 'Failed to create function ''func31933'': function id is too big'
+- error: 'Failed to create function ''func31936'': function id is too big'
...
drop_limit_func()
---
-- error: Function 'func31933' does not exist
+- error: Function 'func31936' does not exist
...
session.su('admin')
---
More information about the Tarantool-patches
mailing list