[tarantool-patches] [PATCH v1 1/2] sql: better LUA arguments conversion for UDFs

Kirill Shcherbatov kshcherbatov at tarantool.org
Mon Sep 16 16:23:12 MSK 2019


Start using comprehensive serializer luaL_tofield() to prepare
LUA arguments for UDFs. This allows to support cdata types
returned from Lua function.

Needed for #4387
---
 src/box/sql/func.c            | 40 +++++++++++++++++++++++------------
 test/sql-tap/lua_sql.test.lua | 34 +++++++----------------------
 2 files changed, 35 insertions(+), 39 deletions(-)

diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 1d8f28a51..b530bb961 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -49,6 +49,7 @@
 #include "box/func.h"
 #include "box/port.h"
 #include "box/tuple.h"
+#include "lua/msgpack.h"
 #include "lua/utils.h"
 #include "mpstream.h"
 
@@ -160,7 +161,7 @@ port_vdbemem_get_msgpack(struct port *base, uint32_t *size)
 			FALLTHROUGH;
 		}
 		case MP_UINT: {
-			sql_int64 val = sql_value_int64(param);
+			sql_uint64 val = sql_value_uint64(param);
 			mpstream_encode_uint(&stream, val);
 			break;
 		}
@@ -254,19 +255,32 @@ port_lua_get_vdbemem(struct port *base, uint32_t *size)
 	if (val == NULL)
 		return NULL;
 	for (int i = 0; i < argc; i++) {
-		switch(lua_type(L, -1 - i)) {
-		case LUA_TBOOLEAN:
-			mem_set_bool(&val[i], lua_toboolean(L, -1 - i));
+		struct luaL_field field;
+		if (luaL_tofield(L, luaL_msgpack_default, -1 - i, &field) < 0)
+			goto error;
+		switch (field.type) {
+		case MP_BOOL:
+			mem_set_bool(&val[i], field.bval);
 			break;
-		case LUA_TNUMBER:
-			sqlVdbeMemSetDouble(&val[i], lua_tonumber(L, -1 - i));
+		case MP_FLOAT:
+			sqlVdbeMemSetDouble(&val[i], field.fval);
 			break;
-		case LUA_TSTRING:
-			if (sqlVdbeMemSetStr(&val[i], lua_tostring(L, -1 - i),
-					     -1, 1, SQL_TRANSIENT) != 0)
+		case MP_DOUBLE:
+			sqlVdbeMemSetDouble(&val[i], field.dval);
+			break;
+		case MP_INT:
+			mem_set_i64(&val[i], field.ival);
+			break;
+		case MP_UINT:
+			mem_set_u64(&val[i], field.ival);
+			break;
+		case MP_STR:
+			if (sqlVdbeMemSetStr(&val[i], field.sval.data,
+					     field.sval.len, 1,
+					     SQL_TRANSIENT) != 0)
 				goto error;
 			break;
-		case LUA_TNIL:
+		case MP_NIL:
 			sqlVdbeMemSetNull(&val[i]);
 			break;
 		default:
@@ -321,10 +335,10 @@ port_tuple_get_vdbemem(struct port *base, uint32_t *size)
 			sqlVdbeMemSetDouble(&val[i], mp_decode_double(&data));
 			break;
 		case MP_INT:
-			mem_set_i64(val, mp_decode_int(&data));
+			mem_set_i64(&val[i], mp_decode_int(&data));
 			break;
 		case MP_UINT:
-			mem_set_u64(val, mp_decode_uint(&data));
+			mem_set_u64(&val[i], mp_decode_uint(&data));
 			break;
 		case MP_STR:
 			str = mp_decode_str(&data, &len);
@@ -333,7 +347,7 @@ port_tuple_get_vdbemem(struct port *base, uint32_t *size)
 				goto error;
 			break;
 		case MP_NIL:
-			sqlVdbeMemSetNull(val);
+			sqlVdbeMemSetNull(&val[i]);
 			break;
 		default:
 			diag_set(ClientError, ER_SQL_EXECUTE,
diff --git a/test/sql-tap/lua_sql.test.lua b/test/sql-tap/lua_sql.test.lua
index 67eff2d1b..50397cf2d 100755
--- a/test/sql-tap/lua_sql.test.lua
+++ b/test/sql-tap/lua_sql.test.lua
@@ -1,7 +1,7 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
 NULL = require('msgpack').NULL
-test:plan(22)
+test:plan(24)
 
 test:do_test(
     "lua_sql-1.0",
@@ -23,7 +23,7 @@ test:do_test(
         box.schema.func.create('FUNC1', {language = 'Lua',
                         is_deterministic = true,
                         body = 'function(a) return a end',
-                        param_list = {'scalar'}, returns = 'integer',
+                        param_list = {'any'}, returns = 'scalar',
                         exports = {'LUA', 'SQL'}})
         return test:execsql("select func1(1)")
     end,
@@ -88,6 +88,7 @@ from_lua_to_sql = {
     [3] = {"'1'", "1"},
     [4] = {"true", true},
     [5] = {"false", false},
+    [6] = {12, 12LL},
 }
 
 box.schema.func.create('CHECK_FROM_LUA_TO_SQL', {language = 'Lua',
@@ -97,38 +98,20 @@ box.schema.func.create('CHECK_FROM_LUA_TO_SQL', {language = 'Lua',
                                return from_lua_to_sql[i][2]
                            end
                        ]],
-                       param_list = {'integer'}, returns = 'scalar',
+                       param_list = {'integer'}, returns = 'any',
                        exports = {'LUA', 'SQL'}})
 
 -- check for different types
 for i = 1, #from_lua_to_sql, 1 do
     test:do_execsql_test(
         "lua_sql-2.3."..i,
-        "select "..from_lua_to_sql[i][1].." = check_from_lua_to_sql("..i..")",
+        "select "..tostring(from_lua_to_sql[i][1]).." = check_from_lua_to_sql("..i..")",
         {true})
 end
 
-from_lua_to_sql_bad = {
-    [1] = NULL,
-    [2] = 12LL, -- it is possible to support this type
-}
-
-box.schema.func.create('CHECK_FROM_LUA_TO_SQL_BAD', {language = 'Lua',
-                       is_deterministic = true,
-                       body = [[
-                           function(i)
-                               return from_lua_to_sql_bad[i]
-                           end
-                       ]],
-                       param_list = {'integer'}, returns = 'scalar',
-                       exports = {'LUA', 'SQL'}})
-
-for i = 1, #from_lua_to_sql_bad, 1 do
-    test:do_catchsql_test(
-        "lua_sql-2.5."..i,
-        "select check_from_lua_to_sql_bad("..i..")",
-        {1, "/Unsupported/"})
-end
+test:do_execsql_test("lua_sql-2.4.1", "SELECT LUA('return box.NULL') is NULL", {true})
+test:do_execsql_test("lua_sql-2.4.2", "SELECT LUA('return nil') is NULL", {true})
+test:do_execsql_test("lua_sql-2.4.3", "SELECT LUA('ffi = require(\"ffi\") return ffi.new(\"uint64_t\", (2LLU^64)-1)') = 18446744073709551615", {true})
 
 box.schema.func.create('ALLWAYS_ERROR', {language = 'Lua',
                        is_deterministic = true,
@@ -150,7 +133,6 @@ test:do_catchsql_test(
 box.func.FUNC1:drop()
 box.func.CHECK_FROM_SQL_TO_LUA:drop()
 box.func.CHECK_FROM_LUA_TO_SQL:drop()
-box.func.CHECK_FROM_LUA_TO_SQL_BAD:drop()
 box.func.ALLWAYS_ERROR:drop()
 
 test:finish_test()
-- 
2.23.0





More information about the Tarantool-patches mailing list