[tarantool-patches] [PATCH 2/6] sql: annotate SQL functions with return type
Nikita Pettik
korablev at tarantool.org
Mon Sep 17 23:32:26 MSK 2018
From: Georgy Kirichenko <georgy at tarantool.org>
Any SQL function should have declared type of returning value.
Lets temporary add affinity to function definition as a type of
returning value.
---
src/box/lua/lua_sql.c | 207 +++++++++++++++++---------------
src/box/sql/analyze.c | 9 +-
src/box/sql/date.c | 16 +--
src/box/sql/func.c | 142 ++++++++++++----------
src/box/sql/main.c | 7 +-
src/box/sql/sqliteInt.h | 36 +++---
src/box/sql/vdbemem.c | 2 +-
test/sql-tap/alias.test.lua | 2 +-
test/sql-tap/analyze5.test.lua | 1 +
test/sql-tap/analyze9.test.lua | 12 +-
test/sql-tap/analyzeF.test.lua | 6 +-
test/sql-tap/check.test.lua | 2 +-
test/sql-tap/date.test.lua | 2 +-
test/sql-tap/e_expr.test.lua | 26 ++--
test/sql-tap/func5.test.lua | 4 +-
test/sql-tap/gh-3350-skip-scan.test.lua | 4 +-
test/sql-tap/lua_sql.test.lua | 22 ++--
test/sql-tap/subquery.test.lua | 2 +-
test/sql-tap/trigger9.test.lua | 2 +-
19 files changed, 271 insertions(+), 233 deletions(-)
diff --git a/src/box/lua/lua_sql.c b/src/box/lua/lua_sql.c
index 9d78679fb..e69e143db 100644
--- a/src/box/lua/lua_sql.c
+++ b/src/box/lua/lua_sql.c
@@ -6,13 +6,13 @@
* conditions are met:
*
* 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
+ * 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.
+ * 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
@@ -33,27 +33,22 @@
#include "lua/utils.h"
#include "box/lua/call.h"
-#include <box/sql/sqliteInt.h>
-#include <box/sql/vdbeInt.h>
-#include <box/sql.h>
+#include "box/sql/sqliteInt.h"
+#include "box/sql/vdbeInt.h"
-#define LUA_WRONG_TYPE_MESG "Unsupported type passed to lua"
-
-struct lua_sql_func_info{
+struct lua_sql_func_info {
int func_ref;
};
-
/**
* This function is callback which is called by sql engine.
*
* Purpose of this function is to call lua func from sql.
- * Lua func should be previously registered in sql (see lbox_sql_create_function).
- *
+ * Lua func should be previously registered in sql
+ * (see lbox_sql_create_function).
*/
-static void lua_sql_call(sqlite3_context *pCtx,
- int nVal,
- sqlite3_value **apVal) {
+static void
+lua_sql_call(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal) {
lua_State *L = lua_newthread(tarantool_L);
int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
struct lua_sql_func_info *func_info = sqlite3_user_data(pCtx);
@@ -62,43 +57,33 @@ static void lua_sql_call(sqlite3_context *pCtx,
for (int i = 0; i < nVal; i++) {
sqlite3_value *param = apVal[i];
switch (sqlite3_value_type(param)) {
- case SQLITE_INTEGER: {
+ case SQLITE_INTEGER:
luaL_pushint64(L, sqlite3_value_int64(param));
break;
- }
- case SQLITE_FLOAT: {
+ case SQLITE_FLOAT:
lua_pushnumber(L, sqlite3_value_double(param));
break;
- }
- case SQLITE_TEXT: {
- lua_pushstring(L,
- (const char *) sqlite3_value_text(param));
+ case SQLITE_TEXT:
+ lua_pushstring(L, (const char *) sqlite3_value_text(param));
break;
- }
- case SQLITE_BLOB: {
- const void *blob = sqlite3_value_blob(param);
- lua_pushlstring(L, blob,
- (size_t) sqlite3_value_bytes(param));
+ case SQLITE_BLOB:
+ lua_pushlstring(L, sqlite3_value_blob(param),
+ (size_t) sqlite3_value_bytes(param));
break;
- }
- case SQLITE_NULL: {
+ case SQLITE_NULL:
lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_nil_ref);
break;
- }
- default: {
- sqlite3_result_error(pCtx,
- LUA_WRONG_TYPE_MESG,
- -1);
- goto lua_sql_call_exit_1;
- }
+ default:
+ sqlite3_result_error(pCtx, "Unsupported type passed "
+ "to Lua", -1);
+ goto error;
}
}
if (lua_pcall(L, lua_gettop(L) - 1, 1, 0) != 0){
sqlite3_result_error(pCtx, lua_tostring(L, -1), -1);
- goto lua_sql_call_exit_1;
+ goto error;
}
-
- switch(lua_type(L, -1)){
+ switch(lua_type(L, -1)) {
case LUA_TBOOLEAN:
sqlite3_result_int(pCtx, lua_toboolean(L, -1));
break;
@@ -106,26 +91,24 @@ static void lua_sql_call(sqlite3_context *pCtx,
sqlite3_result_double(pCtx, lua_tonumber(L, -1));
break;
case LUA_TSTRING:
- sqlite3_result_text(pCtx,
- lua_tostring(L, -1),
- -1,
- SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, lua_tostring(L, -1), -1,
+ SQLITE_TRANSIENT);
break;
case LUA_TNIL:
sqlite3_result_null(pCtx);
break;
default:
- sqlite3_result_error(pCtx,
- "Unsupported type returned from lua",
- -1);
- goto lua_sql_call_exit_1;
+ sqlite3_result_error(pCtx, "Unsupported type returned from Lua",
+ -1);
+ goto error;
}
- lua_sql_call_exit_1:
+error:
luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
return;
}
-static void lua_sql_destroy(void * p)
+static void
+lua_sql_destroy(void *p)
{
struct lua_sql_func_info *func_info = p;
luaL_unref(tarantool_L, LUA_REGISTRYINDEX, func_info->func_ref);
@@ -134,65 +117,89 @@ static void lua_sql_destroy(void * p)
}
/**
- * A helper to register lua function in sql in runtime
+ * A helper to register lua function in SQL during runtime.
* It makes available queries like this: "SELECT lua_func(arg);"
*
- * sqlite3_create_function *p argument is used to store func ref to
- * lua function (it identifies actual lua func to call if there are many of them)
+ * sqlite3_create_function *p argument is used to store func ref
+ * to lua function (it identifies actual lua func to call if there
+ * are many of them). SQL function must have name and type of
+ * returning value. Additionally, it can feature number of
+ * arguments and deterministic flag.
*/
-
-int lbox_sql_create_function(struct lua_State *L)
+int
+lbox_sql_create_function(struct lua_State *L)
{
- int argc = lua_gettop(L);
- int func_arg_num = -1; // -1 is any arg num
- int is_deterministic = 0;
- const char *name;
- size_t name_len;
- char *normalized_name;
- struct lua_sql_func_info *func_info;
- int rc;
- sqlite3 *db = sql_get();
- /**
- * Check args. Three types are possible:
- * sql_create_function("func_name", func)
- * sql_create_function("func_name", func, func_arg_num)
- * sql_create_function("func_name", func, func_arg_num, is_deterministic)
- */
- if ( !(argc == 2 && lua_isstring(L, 1) && lua_isfunction(L, 2)) &&
- !(argc == 3 && lua_isstring(L, 1) && lua_isfunction(L, 2) &&
- lua_isnumber(L, 3)) &&
- !(argc == 4 && lua_isstring(L, 1) && lua_isfunction(L, 2) &&
- lua_isnumber(L, 3) && lua_isboolean(L, 4))) {
- luaL_error(L, "Invalid arguments");
- return 0;
- }
+ struct sqlite3 *db = sql_get();
if (db == NULL) {
luaL_error(L, "Please call box.cfg{} first");
return 0;
}
- if (argc == 3) {
- func_arg_num = (int) lua_tonumber(L, 3);
- // func should be on top of the stack because of luaL_ref api
+ int argc = lua_gettop(L);
+ /*
+ * Three function prototypes are possible:
+ * 1. sql_create_function("func_name", "type", func);
+ * 2. sql_create_function("func_name", "type", func,
+ * func_arg_num);
+ * 3. sql_create_function("func_name", "type", func,
+ * func_arg_num, is_deterministic);
+ */
+ if (!(argc == 3 && lua_isstring(L, 1) && lua_isstring(L, 2) &&
+ lua_isfunction(L, 3)) &&
+ !(argc == 4 && lua_isstring(L, 1) && lua_isstring(L, 2) &&
+ lua_isfunction(L, 3) && lua_isnumber(L, 4)) &&
+ !(argc == 5 && lua_isstring(L, 1) && lua_isstring(L, 2) &&
+ lua_isfunction(L, 3) && lua_isnumber(L, 4) &&
+ lua_isboolean(L, 5))) {
+ luaL_error(L, "Invalid arguments");
+ return 0;
+ }
+ enum affinity_type type = AFFINITY_UNDEFINED;
+ const char *type_arg = lua_tostring(L, 2);
+ if (strcmp(type_arg, "INT") == 0 || strcmp(type_arg, "INTEGER") == 0) {
+ type = AFFINITY_INTEGER;
+ } else if (strcmp(type_arg, "TEXT") == 0) {
+ type = AFFINITY_TEXT;
+ } else if (strcmp(type_arg, "FLOAT") == 0) {
+ type = AFFINITY_REAL;
+ } else if (strcmp(type_arg, "NUM") == 0) {
+ type = AFFINITY_NUMERIC;
+ } else if (strcmp(type_arg, "BLOB") == 0) {
+ type = AFFINITY_BLOB;
+ } else {
+ luaL_error(L, "Unknown type");
+ }
+ /* -1 indicates any number of arguments. */
+ int func_arg_num = -1;
+ bool is_deterministic = false;
+ if (argc == 4) {
+ func_arg_num = (int) lua_tonumber(L, 4);
lua_pop(L, 1);
+ } else if (argc == 5) {
+ is_deterministic = lua_toboolean(L, 5);
+ func_arg_num = (int) lua_tonumber(L, 4);
+ lua_pop(L, 2);
}
- if (argc == 4) {
- if(lua_toboolean(L, 4))
- is_deterministic = SQLITE_DETERMINISTIC;
- func_arg_num = (int) lua_tonumber(L, 3);
- lua_pop(L, 2);
- }
- name = lua_tostring(L, 1);
- name_len = strlen(name);
- normalized_name = (char*) malloc(name_len+1);
- memcpy(normalized_name, name, name_len+1);
+ const char *name = lua_tostring(L, 1);
+ size_t name_len = strlen(name);
+ char *normalized_name = (char *) region_alloc(&fiber()->gc,
+ name_len + 1);
+ if (normalized_name == NULL) {
+ luaL_error(L, "out of memory");
+ return 0;
+ }
+ memcpy(normalized_name, name, name_len);
+ normalized_name[name_len] = '\0';
sqlite3NormalizeName(normalized_name);
- func_info = (struct lua_sql_func_info*)malloc(sizeof(struct lua_sql_func_info));
+ struct lua_sql_func_info *func_info =
+ (struct lua_sql_func_info *) malloc(sizeof(*func_info));
+ if (func_info == NULL) {
+ luaL_error(L, "out of memory");
+ return 0;
+ }
func_info->func_ref = luaL_ref(L, LUA_REGISTRYINDEX);
- rc = sqlite3_create_function_v2(db, normalized_name, func_arg_num,
- is_deterministic, func_info, lua_sql_call,
- NULL, NULL, lua_sql_destroy);
-
- free(normalized_name);
- return rc;
+ sqlite3_create_function_v2(db, normalized_name, type, func_arg_num,
+ is_deterministic ? SQLITE_DETERMINISTIC : 0,
+ func_info, lua_sql_call, NULL, NULL,
+ lua_sql_destroy);
+ return 0;
}
-
diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index 76ae15386..f1aca5b78 100644
--- a/src/box/sql/analyze.c
+++ b/src/box/sql/analyze.c
@@ -375,7 +375,8 @@ static const FuncDef statInitFuncdef = {
statInit, /* xSFunc */
0, /* xFinalize */
"stat_init", /* zName */
- {0}
+ {0},
+ 0
};
/*
@@ -630,7 +631,8 @@ static const FuncDef statPushFuncdef = {
statPush, /* xSFunc */
0, /* xFinalize */
"stat_push", /* zName */
- {0}
+ {0},
+ 0
};
#define STAT_GET_STAT1 0 /* "stat" column of stat1 table */
@@ -757,7 +759,8 @@ static const FuncDef statGetFuncdef = {
statGet, /* xSFunc */
0, /* xFinalize */
"stat_get", /* zName */
- {0}
+ {0},
+ 0
};
static void
diff --git a/src/box/sql/date.c b/src/box/sql/date.c
index 9566cc386..8a3588355 100644
--- a/src/box/sql/date.c
+++ b/src/box/sql/date.c
@@ -1306,14 +1306,14 @@ sqlite3RegisterDateTimeFunctions(void)
{
static FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
- DFUNCTION(julianday, -1, 0, 0, juliandayFunc),
- DFUNCTION(date, -1, 0, 0, dateFunc),
- DFUNCTION(time, -1, 0, 0, timeFunc),
- DFUNCTION(datetime, -1, 0, 0, datetimeFunc),
- DFUNCTION(strftime, -1, 0, 0, strftimeFunc),
- DFUNCTION(current_time, 0, 0, 0, ctimeFunc),
- DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
- DFUNCTION(current_date, 0, 0, 0, cdateFunc),
+ DFUNCTION(julianday, -1, 0, 0, juliandayFunc, AFFINITY_REAL),
+ DFUNCTION(date, -1, 0, 0, dateFunc, AFFINITY_REAL),
+ DFUNCTION(time, -1, 0, 0, timeFunc, AFFINITY_REAL),
+ DFUNCTION(datetime, -1, 0, 0, datetimeFunc, AFFINITY_REAL),
+ DFUNCTION(strftime, -1, 0, 0, strftimeFunc, AFFINITY_REAL),
+ DFUNCTION(current_time, 0, 0, 0, ctimeFunc, AFFINITY_REAL),
+ DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc, AFFINITY_REAL),
+ DFUNCTION(current_date, 0, 0, 0, cdateFunc, AFFINITY_REAL),
#else
STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc),
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 45056a7da..8c34cbb3d 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -1678,7 +1678,8 @@ groupConcatFinalize(sqlite3_context * context)
* a new one that always throws a run-time error.
*/
static inline int
-sqlite3_overload_function(sqlite3 * db, const char *zName, int nArg)
+sqlite3_overload_function(sqlite3 * db, const char *zName,
+ enum affinity_type type, int nArg)
{
int rc = SQLITE_OK;
@@ -1688,7 +1689,8 @@ sqlite3_overload_function(sqlite3 * db, const char *zName, int nArg)
}
#endif
if (sqlite3FindFunction(db, zName, nArg, 0) == 0) {
- rc = sqlite3CreateFunc(db, zName, nArg, 0, 0, sqlite3InvalidFunction, 0, 0, 0);
+ rc = sqlite3CreateFunc(db, zName, type, nArg, 0, 0,
+ sqlite3InvalidFunction, 0, 0, 0);
}
rc = sqlite3ApiExit(db, rc);
return rc;
@@ -1702,7 +1704,7 @@ sqlite3_overload_function(sqlite3 * db, const char *zName, int nArg)
void
sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 * db)
{
- int rc = sqlite3_overload_function(db, "MATCH", 2);
+ int rc = sqlite3_overload_function(db, "MATCH", AFFINITY_UNDEFINED, 2);
assert(rc == SQLITE_NOMEM || rc == SQLITE_OK);
if (rc == SQLITE_NOMEM) {
sqlite3OomFault(db);
@@ -1736,9 +1738,17 @@ sqlite3RegisterLikeFunctions(sqlite3 * db, int caseSensitive)
} else {
pInfo = (struct compareInfo *)&likeInfoNorm;
}
- sqlite3CreateFunc(db, "LIKE", 2, 0, pInfo, likeFunc, 0, 0, 0);
- sqlite3CreateFunc(db, "LIKE", 3, 0, pInfo, likeFunc, 0, 0, 0);
- sqlite3CreateFunc(db, "GLOB", 2, 0, (struct compareInfo *)&globInfo, likeFunc, 0, 0, 0);
+ /*
+ * FIXME: after introducing type <BOOLEAN> LIKE must
+ * return that type: TRUE if the string matches the
+ * supplied pattern and FALSE otherwise.
+ */
+ sqlite3CreateFunc(db, "LIKE", AFFINITY_INTEGER, 2, 0, pInfo,
+ likeFunc, 0, 0, 0);
+ sqlite3CreateFunc(db, "LIKE", AFFINITY_INTEGER, 3, 0, pInfo,
+ likeFunc, 0, 0, 0);
+ sqlite3CreateFunc(db, "GLOB", AFFINITY_INTEGER, 2, 0,
+ (struct compareInfo *) &globInfo, likeFunc, 0, 0, 0);
setLikeOptFlag(db, "GLOB", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
setLikeOptFlag(db, "LIKE",
caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) :
@@ -1815,77 +1825,87 @@ sqlite3RegisterBuiltinFunctions(void)
#ifdef SQLITE_SOUNDEX
FUNCTION(soundex, 1, 0, 0, soundexFunc),
#endif
- FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
- FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
- FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
- FUNCTION(ltrim, 1, 1, 0, trimFunc),
- FUNCTION(ltrim, 2, 1, 0, trimFunc),
- FUNCTION(rtrim, 1, 2, 0, trimFunc),
- FUNCTION(rtrim, 2, 2, 0, trimFunc),
- FUNCTION(trim, 1, 3, 0, trimFunc),
- FUNCTION(trim, 2, 3, 0, trimFunc),
- FUNCTION(min, -1, 0, 1, minmaxFunc),
- FUNCTION(min, 0, 0, 1, 0),
+ FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY,
+ AFFINITY_INTEGER),
+ FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY,
+ AFFINITY_INTEGER),
+ FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY,
+ AFFINITY_INTEGER),
+ FUNCTION(ltrim, 1, 1, 0, trimFunc, AFFINITY_TEXT),
+ FUNCTION(ltrim, 2, 1, 0, trimFunc, AFFINITY_TEXT),
+ FUNCTION(rtrim, 1, 2, 0, trimFunc, AFFINITY_TEXT),
+ FUNCTION(rtrim, 2, 2, 0, trimFunc, AFFINITY_TEXT),
+ FUNCTION(trim, 1, 3, 0, trimFunc, AFFINITY_TEXT),
+ FUNCTION(trim, 2, 3, 0, trimFunc, AFFINITY_TEXT),
+ FUNCTION(min, -1, 0, 1, minmaxFunc, 0),
+ FUNCTION(min, 0, 0, 1, 0, 0),
AGGREGATE2(min, 1, 0, 1, minmaxStep, minMaxFinalize,
- SQLITE_FUNC_MINMAX),
- FUNCTION(max, -1, 1, 1, minmaxFunc),
- FUNCTION(max, 0, 1, 1, 0),
+ SQLITE_FUNC_MINMAX, 0),
+ FUNCTION(max, -1, 1, 1, minmaxFunc, 0),
+ FUNCTION(max, 0, 1, 1, 0, 0),
AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize,
- SQLITE_FUNC_MINMAX),
- FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
- FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
- FUNCTION(instr, 2, 0, 0, instrFunc),
- FUNCTION(printf, -1, 0, 0, printfFunc),
- FUNCTION(unicode, 1, 0, 0, unicodeFunc),
- FUNCTION(char, -1, 0, 0, charFunc),
- FUNCTION(abs, 1, 0, 0, absFunc),
+ SQLITE_FUNC_MINMAX, 0),
+ FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF,
+ AFFINITY_TEXT),
+ FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH,
+ AFFINITY_INTEGER),
+ FUNCTION(instr, 2, 0, 0, instrFunc, AFFINITY_INTEGER),
+ FUNCTION(printf, -1, 0, 0, printfFunc, AFFINITY_TEXT),
+ FUNCTION(unicode, 1, 0, 0, unicodeFunc, AFFINITY_TEXT),
+ FUNCTION(char, -1, 0, 0, charFunc, AFFINITY_TEXT),
+ FUNCTION(abs, 1, 0, 0, absFunc, AFFINITY_REAL),
#ifndef SQLITE_OMIT_FLOATING_POINT
- FUNCTION(round, 1, 0, 0, roundFunc),
- FUNCTION(round, 2, 0, 0, roundFunc),
+ FUNCTION(round, 1, 0, 0, roundFunc, AFFINITY_INTEGER),
+ FUNCTION(round, 2, 0, 0, roundFunc, AFFINITY_INTEGER),
#endif
- FUNCTION(upper, 1, 0, 1, UpperICUFunc),
- FUNCTION(lower, 1, 0, 1, LowerICUFunc),
- FUNCTION(hex, 1, 0, 0, hexFunc),
- FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
- VFUNCTION(random, 0, 0, 0, randomFunc),
- VFUNCTION(randomblob, 1, 0, 0, randomBlob),
- FUNCTION(nullif, 2, 0, 1, nullifFunc),
- FUNCTION(version, 0, 0, 0, sql_func_version),
- FUNCTION(quote, 1, 0, 0, quoteFunc),
- VFUNCTION(changes, 0, 0, 0, changes),
- VFUNCTION(total_changes, 0, 0, 0, total_changes),
- FUNCTION(replace, 3, 0, 0, replaceFunc),
- FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc),
- FUNCTION(substr, 2, 0, 0, substrFunc),
- FUNCTION(substr, 3, 0, 0, substrFunc),
- AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize),
- AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize),
- AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize),
+ FUNCTION(upper, 1, 0, 1, UpperICUFunc, AFFINITY_TEXT),
+ FUNCTION(lower, 1, 0, 1, LowerICUFunc, AFFINITY_TEXT),
+ FUNCTION(hex, 1, 0, 0, hexFunc, AFFINITY_TEXT),
+ FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE,
+ AFFINITY_INTEGER),
+ VFUNCTION(random, 0, 0, 0, randomFunc, AFFINITY_REAL),
+ VFUNCTION(randomblob, 1, 0, 0, randomBlob, AFFINITY_BLOB),
+ FUNCTION(nullif, 2, 0, 1, nullifFunc, 0),
+ FUNCTION(version, 0, 0, 0, sql_func_version, AFFINITY_TEXT),
+ FUNCTION(quote, 1, 0, 0, quoteFunc, AFFINITY_TEXT),
+ VFUNCTION(changes, 0, 0, 0, changes, AFFINITY_INTEGER),
+ VFUNCTION(total_changes, 0, 0, 0, total_changes,
+ AFFINITY_INTEGER),
+ FUNCTION(replace, 3, 0, 0, replaceFunc, AFFINITY_TEXT),
+ FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc, AFFINITY_BLOB),
+ FUNCTION(substr, 2, 0, 0, substrFunc, AFFINITY_TEXT),
+ FUNCTION(substr, 3, 0, 0, substrFunc, AFFINITY_TEXT),
+ AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize, 0),
+ AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize, 0),
+ AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize, 0),
AGGREGATE2(count, 0, 0, 0, countStep, countFinalize,
- SQLITE_FUNC_COUNT),
- AGGREGATE(count, 1, 0, 0, countStep, countFinalize),
+ SQLITE_FUNC_COUNT, AFFINITY_INTEGER),
+ AGGREGATE(count, 1, 0, 0, countStep, countFinalize,
+ AFFINITY_INTEGER),
AGGREGATE(group_concat, 1, 0, 0, groupConcatStep,
- groupConcatFinalize),
+ groupConcatFinalize, AFFINITY_TEXT),
AGGREGATE(group_concat, 2, 0, 0, groupConcatStep,
- groupConcatFinalize),
+ groupConcatFinalize, AFFINITY_TEXT),
LIKEFUNC(glob, 2, &globInfo,
- SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE),
+ SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE, AFFINITY_INTEGER),
#ifdef SQLITE_CASE_SENSITIVE_LIKE
LIKEFUNC(like, 2, &likeInfoAlt,
- SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE),
+ SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE, AFFINITY_INTEGER),
LIKEFUNC(like, 3, &likeInfoAlt,
- SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE),
+ SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE, AFFINITY_INTEGER),
#else
- LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
- LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
+ LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE,
+ AFFINITY_INTEGER),
+ LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE,
+ AFFINITY_INTEGER),
#endif
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
- FUNCTION(unknown, -1, 0, 0, unknownFunc),
+ FUNCTION(unknown, -1, 0, 0, unknownFunc, 0),
#endif
- FUNCTION(coalesce, 1, 0, 0, 0),
- FUNCTION(coalesce, 0, 0, 0, 0),
- FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
+ FUNCTION(coalesce, 1, 0, 0, 0, 0),
+ FUNCTION(coalesce, 0, 0, 0, 0, 0),
+ FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE, 0),
};
sqlite3AnalyzeFunctions();
sqlite3RegisterDateTimeFunctions();
diff --git a/src/box/sql/main.c b/src/box/sql/main.c
index 69b2fec80..e2b55647d 100644
--- a/src/box/sql/main.c
+++ b/src/box/sql/main.c
@@ -1075,6 +1075,7 @@ sqlite3_interrupt(sqlite3 * db)
int
sqlite3CreateFunc(sqlite3 * db,
const char *zFunctionName,
+ enum affinity_type type,
int nArg,
int flags,
void *pUserData,
@@ -1137,12 +1138,14 @@ sqlite3CreateFunc(sqlite3 * db,
p->xFinalize = xFinal;
p->pUserData = pUserData;
p->nArg = (u16) nArg;
+ p->ret_type = type;
return SQLITE_OK;
}
int
sqlite3_create_function_v2(sqlite3 * db,
const char *zFunc,
+ enum affinity_type type,
int nArg,
int flags,
void *p,
@@ -1173,8 +1176,8 @@ sqlite3_create_function_v2(sqlite3 * db,
pArg->xDestroy = xDestroy;
pArg->pUserData = p;
}
- rc = sqlite3CreateFunc(db, zFunc, nArg, flags, p, xSFunc, xStep, xFinal,
- pArg);
+ rc = sqlite3CreateFunc(db, zFunc, type, nArg, flags, p, xSFunc, xStep,
+ xFinal, pArg);
if (pArg && pArg->nRef == 0) {
assert(rc != SQLITE_OK);
xDestroy(p);
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 5ca628aac..100777a28 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -737,6 +737,7 @@ sqlite3_memory_used(void);
int
sqlite3_create_function_v2(sqlite3 * db,
const char *zFunctionName,
+ enum affinity_type type,
int nArg,
int flags,
void *pApp,
@@ -1659,6 +1660,8 @@ struct FuncDef {
FuncDef *pHash; /* Next with a different name but the same hash */
FuncDestructor *pDestructor; /* Reference counted destructor function */
} u;
+ /* Return type. */
+ enum affinity_type ret_type;
};
/*
@@ -1741,30 +1744,30 @@ struct FuncDestructor {
* FuncDef.flags variable is set to the value passed as the flags
* parameter.
*/
-#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
+#define FUNCTION(zName, nArg, iArg, bNC, xFunc, type) \
{nArg, SQLITE_FUNC_CONSTANT|(bNC*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
-#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0}, type }
+#define VFUNCTION(zName, nArg, iArg, bNC, xFunc, type) \
{nArg, (bNC*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
-#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0}, type }
+#define DFUNCTION(zName, nArg, iArg, bNC, xFunc, type) \
{nArg, SQLITE_FUNC_SLOCHNG|(bNC*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
-#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0}, type }
+#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags, type) \
{nArg,SQLITE_FUNC_CONSTANT|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0}, type }
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_SLOCHNG|(bNC*SQLITE_FUNC_NEEDCOLL), \
- pArg, 0, xFunc, 0, #zName, }
-#define LIKEFUNC(zName, nArg, arg, flags) \
+ pArg, 0, xFunc, 0, #zName, {SQLITE_AFF_STRING, {0}}}
+#define LIKEFUNC(zName, nArg, arg, flags, type) \
{nArg, SQLITE_FUNC_CONSTANT|flags, \
- (void *)arg, 0, likeFunc, 0, #zName, {0} }
-#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
+ (void *)arg, 0, likeFunc, 0, #zName, {0}, type }
+#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal, type) \
{nArg, (nc*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}}
-#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
+ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}, type}
+#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags, type) \
{nArg, (nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}}
+ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}, type}
/*
* All current savepoints are stored in a linked list starting at
@@ -4530,7 +4533,8 @@ void sqlite3RegisterLikeFunctions(sqlite3 *, int);
int sqlite3IsLikeFunction(sqlite3 *, Expr *, int *, char *);
void sqlite3SchemaClear(sqlite3 *);
Schema *sqlite3SchemaCreate(sqlite3 *);
-int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
+int sqlite3CreateFunc(sqlite3 *, const char *, enum affinity_type,
+ int, int, void *,
void (*)(sqlite3_context *, int, sqlite3_value **),
void (*)(sqlite3_context *, int, sqlite3_value **),
void (*)(sqlite3_context *),
diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index 65bb67d8f..27b83a0df 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -1422,7 +1422,7 @@ void
sqlite3AnalyzeFunctions(void)
{
static FuncDef aAnalyzeTableFuncs[] = {
- FUNCTION(sqlite_record, 1, 0, 0, recordFunc),
+ FUNCTION(sqlite_record, 1, 0, 0, recordFunc, 0),
};
sqlite3InsertBuiltinFuncs(aAnalyzeTableFuncs,
ArraySize(aAnalyzeTableFuncs));
diff --git a/test/sql-tap/alias.test.lua b/test/sql-tap/alias.test.lua
index 4321413cb..df082b699 100755
--- a/test/sql-tap/alias.test.lua
+++ b/test/sql-tap/alias.test.lua
@@ -32,7 +32,7 @@ end
-- Function is declared as deterministic deliberately.
-- Otherwise it would be called as much as it occurs in a query.
-box.internal.sql_create_function("sequence", sequence, 0, true)
+box.internal.sql_create_function("sequence", "INT", sequence, 0, true)
test:do_test(
"alias-1.1",
diff --git a/test/sql-tap/analyze5.test.lua b/test/sql-tap/analyze5.test.lua
index d68bd3c5b..67229e78f 100755
--- a/test/sql-tap/analyze5.test.lua
+++ b/test/sql-tap/analyze5.test.lua
@@ -46,6 +46,7 @@ test:do_test(
function()
box.internal.sql_create_function(
"msgpack_decode",
+ "BLOB",
function(txt)
-- MsgPack, must contain single-element array w/ string
return require('msgpack').decode(txt)[1]
diff --git a/test/sql-tap/analyze9.test.lua b/test/sql-tap/analyze9.test.lua
index 1dbfe5d2b..9d60214cb 100755
--- a/test/sql-tap/analyze9.test.lua
+++ b/test/sql-tap/analyze9.test.lua
@@ -61,7 +61,7 @@ msgpack_decode_sample = function(txt)
return decoded_str
end
-box.internal.sql_create_function("msgpack_decode_sample", msgpack_decode_sample)
+box.internal.sql_create_function("msgpack_decode_sample", "TEXT", msgpack_decode_sample)
test:do_execsql_test(
1.2,
@@ -135,7 +135,7 @@ lindex = function(str, pos)
return string.sub(str, pos+1, pos+1)
end
-box.internal.sql_create_function("lindex", lindex)
+box.internal.sql_create_function("lindex", "TEXT", lindex)
-- Analogue of function from tcl
lrange = function(str, first, last)
@@ -154,7 +154,7 @@ lrange = function(str, first, last)
return res_tokens
end
-box.internal.sql_create_function("lrange", lrange)
+box.internal.sql_create_function("lrange", "TEXT", lrange)
generate_tens = function(n)
tens = {}
@@ -242,7 +242,7 @@ insert_filler_rows_n = function(iStart, nCopy, nVal)
end
end
-box.internal.sql_create_function("insert_filler_rows_n", insert_filler_rows_n)
+box.internal.sql_create_function("insert_filler_rows_n", "INT", insert_filler_rows_n)
test:do_test(
4.1,
@@ -1210,7 +1210,7 @@ r = function()
return math.random(1, 15)
end
-box.internal.sql_create_function("r", r)
+box.internal.sql_create_function("r", "NUM", r)
test:do_test(
20.1,
@@ -1346,7 +1346,7 @@ int_to_char = function(i)
return ret
end
-box.internal.sql_create_function("int_to_char", int_to_char)
+box.internal.sql_create_function("int_to_char", "TEXT", int_to_char)
-- These tests are commented until query planer will be stable.
--test:do_execsql_test(
diff --git a/test/sql-tap/analyzeF.test.lua b/test/sql-tap/analyzeF.test.lua
index 10cb574bd..0f67881af 100755
--- a/test/sql-tap/analyzeF.test.lua
+++ b/test/sql-tap/analyzeF.test.lua
@@ -22,7 +22,7 @@ local function isqrt(i)
return math.floor(math.sqrt(i))
end
-box.internal.sql_create_function("isqrt", isqrt)
+box.internal.sql_create_function("isqrt", "FLOAT", isqrt)
test:do_execsql_test(
1.0,
@@ -109,9 +109,9 @@ local function det19()
end
-box.internal.sql_create_function("det4", det4)
+box.internal.sql_create_function("det4", "NUM", det4)
-box.internal.sql_create_function("det19", det19)
+box.internal.sql_create_function("det19", "NUM", det19)
where_clause_x = {"x = det4() AND y = det19()"}
where_clauses_y = {"x = det19() AND y = det4()"}
diff --git a/test/sql-tap/check.test.lua b/test/sql-tap/check.test.lua
index ff36552de..cb5cfa32b 100755
--- a/test/sql-tap/check.test.lua
+++ b/test/sql-tap/check.test.lua
@@ -721,7 +721,7 @@ test:do_execsql_test(
local function myfunc(x)
return x < 10
end
-box.internal.sql_create_function("myfunc", myfunc)
+box.internal.sql_create_function("myfunc", "INT", myfunc)
test:do_execsql_test(
7.1,
diff --git a/test/sql-tap/date.test.lua b/test/sql-tap/date.test.lua
index 5c22bf606..624437641 100755
--- a/test/sql-tap/date.test.lua
+++ b/test/sql-tap/date.test.lua
@@ -451,7 +451,7 @@ local function sleeper()
-- after 100 ms
os.execute("sleep 0.1")
end
-box.internal.sql_create_function("sleeper", sleeper)
+box.internal.sql_create_function("sleeper", "INT", sleeper)
-- db("func", "sleeper", "sleeper")
test:do_test(
"date-15.1",
diff --git a/test/sql-tap/e_expr.test.lua b/test/sql-tap/e_expr.test.lua
index e04431685..9a9a5faae 100755
--- a/test/sql-tap/e_expr.test.lua
+++ b/test/sql-tap/e_expr.test.lua
@@ -43,8 +43,8 @@ end
local function regexfunc(a, b)
return (a == b)
end
-box.internal.sql_create_function("MATCH", matchfunc)
-box.internal.sql_create_function("REGEXP", regexfunc)
+box.internal.sql_create_function("MATCH", "INT", matchfunc)
+box.internal.sql_create_function("REGEXP", "INT", regexfunc)
-- Set up three global variables:
--
@@ -653,7 +653,7 @@ end
local function reverse_collate(zLeft, zRight)
return reverse_str(zLeft) > reverse_str(zRight)
end
-box.internal.sql_create_function("REVERSE", reverse_collate)
+box.internal.sql_create_function("REVERSE", "INT", reverse_collate)
--db("collate", "reverse", "reverse_collate")
-- EVIDENCE-OF: R-59577-33471 The COLLATE operator is a unary postfix
-- operator that assigns a collating sequence to an expression.
@@ -1277,9 +1277,9 @@ local function glob(args)
return 1
end
-box.internal.sql_create_function("GLOB", glob)
-box.internal.sql_create_function("MATCH", glob)
-box.internal.sql_create_function("REGEXP", glob)
+box.internal.sql_create_function("GLOB", "INT", glob)
+box.internal.sql_create_function("MATCH", "INT", glob)
+box.internal.sql_create_function("REGEXP", "INT", glob)
local test_cases12 ={
{1, 123},
{2, 123.4e05},
@@ -1438,7 +1438,7 @@ local function func_x()
xcount = xcount + 1
return x
end
-box.internal.sql_create_function("X", func_x)
+box.internal.sql_create_function("X", "INT", func_x)
local test_cases13 = {
{1, 10, "x() >= 5 AND x() <= 15", 1, 2},
{2, 10, "x() BETWEEN 5 AND 15", 1, 1},
@@ -2126,7 +2126,7 @@ function likefunc(...)
return 1
end
-box.internal.sql_create_function("LIKE", likefunc)
+box.internal.sql_create_function("LIKE", "INT", likefunc)
--db("func", "like", "-argcount", 2, "likefunc")
--db("func", "like", "-argcount", 3, "likefunc")
test:do_execsql_test(
@@ -2430,7 +2430,7 @@ local function globfunc(...)
end
return 1
end
-box.internal.sql_create_function("GLOB", globfunc, 2)
+box.internal.sql_create_function("GLOB", "INT", globfunc, 2)
--db("func", "glob", "-argcount", 2, "globfunc")
test:do_execsql_test(
@@ -2498,7 +2498,7 @@ local function regexpfunc(...)
end
return 1
end
-box.internal.sql_create_function("REGEXP", regexpfunc, 2)
+box.internal.sql_create_function("REGEXP", "INT", regexpfunc, 2)
--db("func", "regexp", "-argcount", 2, "regexpfunc")
test:do_execsql_test(
@@ -2581,7 +2581,7 @@ local function matchfunc(...)
end
return 1
end
-box.internal.sql_create_function("MATCH", matchfunc, 2)
+box.internal.sql_create_function("MATCH", "INT", matchfunc, 2)
test:do_execsql_test(
"e_expr-19.2.1",
@@ -2659,7 +2659,7 @@ local function var(nm)
local result = loadstring("return "..nm)()
return result
end
-box.internal.sql_create_function("VAR", var)
+box.internal.sql_create_function("VAR", "BLOB", var)
--db("func", "var", "var")
-- EVIDENCE-OF: R-30638-59954 In a CASE without a base expression, each
-- WHEN expression is evaluated and the result treated as a boolean,
@@ -3070,7 +3070,7 @@ local function ceval(x)
evalcount = evalcount + 1
return x
end
-box.internal.sql_create_function("CEVAL", ceval)
+box.internal.sql_create_function("CEVAL", "BLOB", ceval)
evalcount = 0
test:do_execsql_test(
"e_expr-26.1.1",
diff --git a/test/sql-tap/func5.test.lua b/test/sql-tap/func5.test.lua
index c8aa4f135..493b50552 100755
--- a/test/sql-tap/func5.test.lua
+++ b/test/sql-tap/func5.test.lua
@@ -76,8 +76,8 @@ counter = function(str)
return global_counter
end
-box.internal.sql_create_function("counter1", counter, -1, false)
-box.internal.sql_create_function("counter2", counter, -1, true)
+box.internal.sql_create_function("counter1", "INT", counter, -1, false)
+box.internal.sql_create_function("counter2", "INT", counter, -1, true)
test:do_execsql_test(
"func5-2.2",
diff --git a/test/sql-tap/gh-3350-skip-scan.test.lua b/test/sql-tap/gh-3350-skip-scan.test.lua
index 301b04a13..4cecfe081 100755
--- a/test/sql-tap/gh-3350-skip-scan.test.lua
+++ b/test/sql-tap/gh-3350-skip-scan.test.lua
@@ -19,8 +19,8 @@ local function int_to_char(i)
return res
end
-box.internal.sql_create_function("lindex", lindex)
-box.internal.sql_create_function("int_to_char", int_to_char)
+box.internal.sql_create_function("lindex", "TEXT", lindex)
+box.internal.sql_create_function("int_to_char", "TEXT", int_to_char)
test:do_execsql_test(
"skip-scan-1.1",
diff --git a/test/sql-tap/lua_sql.test.lua b/test/sql-tap/lua_sql.test.lua
index 394922a2f..68bb24ff2 100755
--- a/test/sql-tap/lua_sql.test.lua
+++ b/test/sql-tap/lua_sql.test.lua
@@ -13,7 +13,7 @@ end
test:do_test(
"lua_sql-1.0",
function ()
- box.internal.sql_create_function("func1", allways_2)
+ box.internal.sql_create_function("func1", "INT", allways_2)
return test:execsql("select func1(1)")
end,
{2})
@@ -22,7 +22,7 @@ test:do_test(
test:do_test(
"lua_sql-1.1",
function ()
- box.internal.sql_create_function("func1", func1)
+ box.internal.sql_create_function("func1", "INT", func1)
return test:execsql("select func1(1)")
end,
{1})
@@ -32,7 +32,7 @@ test:do_test(
"lua_sql-1.2",
function ()
for i = 1, 1000000, 1 do
- box.internal.sql_create_function("func1", func1)
+ box.internal.sql_create_function("func1", "INT", func1)
end
return test:execsql("select func1(1)")
end,
@@ -42,10 +42,10 @@ test:do_test(
test:do_test(
"lua_sql-1.3",
function ()
- box.internal.sql_create_function("allways_2", allways_2, 1) -- specify 1 arg
- box.internal.sql_create_function("allways_2", func1)
- box.internal.sql_create_function("allways_2", func1, 2)
- box.internal.sql_create_function("allways_2", func1, 3)
+ box.internal.sql_create_function("allways_2", "INT", allways_2, 1) -- specify 1 arg
+ box.internal.sql_create_function("allways_2", "INT", func1)
+ box.internal.sql_create_function("allways_2", "INT", func1, 2)
+ box.internal.sql_create_function("allways_2", "INT", func1, 3)
return test:execsql("select allways_2(1)")
end,
{2})
@@ -88,7 +88,7 @@ local function check_from_sql_to_lua(i, arg)
end
return 0
end
-box.internal.sql_create_function("check_from_sql_to_lua", check_from_sql_to_lua)
+box.internal.sql_create_function("check_from_sql_to_lua", "INT", check_from_sql_to_lua)
-- check for different types
for i = 1, #from_sql_to_lua, 1 do
@@ -108,7 +108,7 @@ local from_lua_to_sql = {
local function check_from_lua_to_sql(i)
return from_lua_to_sql[i][2]
end
-box.internal.sql_create_function("check_from_lua_to_sql", check_from_lua_to_sql)
+box.internal.sql_create_function("check_from_lua_to_sql", "BLOB", check_from_lua_to_sql)
-- check for different types
for i = 1, #from_lua_to_sql, 1 do
@@ -125,7 +125,7 @@ local from_lua_to_sql_bad = {
local function check_from_lua_to_sql_bad(i)
return from_lua_to_sql_bad[i]
end
-box.internal.sql_create_function("check_from_lua_to_sql_bad", check_from_lua_to_sql_bad)
+box.internal.sql_create_function("check_from_lua_to_sql_bad", "BLOB", check_from_lua_to_sql_bad)
for i = 1, #from_lua_to_sql_bad, 1 do
test:do_catchsql_test(
@@ -138,7 +138,7 @@ local function allways_error()
error("my_error123")
return 1
end
-box.internal.sql_create_function("allways_error", allways_error)
+box.internal.sql_create_function("allways_error", "INT", allways_error)
test:do_catchsql_test(
"lua_sql-2.6",
diff --git a/test/sql-tap/subquery.test.lua b/test/sql-tap/subquery.test.lua
index 0e63f2e3e..fb1c23c0b 100755
--- a/test/sql-tap/subquery.test.lua
+++ b/test/sql-tap/subquery.test.lua
@@ -720,7 +720,7 @@ test:do_test(
end
callcnt = 0
- box.internal.sql_create_function("callcnt", callcntproc)
+ box.internal.sql_create_function("callcnt", "INT", callcntproc)
return test:execsql [[
CREATE TABLE t4(x,y PRIMARY KEY);
INSERT INTO t4 VALUES('one',1);
diff --git a/test/sql-tap/trigger9.test.lua b/test/sql-tap/trigger9.test.lua
index 30409582c..0dfd07ac3 100755
--- a/test/sql-tap/trigger9.test.lua
+++ b/test/sql-tap/trigger9.test.lua
@@ -46,7 +46,7 @@ local function has_rowdata(sql)
-- X(41, "X!cmd", [=[["expr","[lsearch [execsql \"explain $sql\"] RowData]>=0"]]=])
end
-box.internal.sql_create_function('randstr', test.randstr, 1)
+box.internal.sql_create_function('randstr', 'TEXT', test.randstr, 1)
-- MUST_WORK_TEST
test:do_execsql_test(
--
2.15.1
More information about the Tarantool-patches
mailing list