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

Nikita Pettik korablev at tarantool.org
Wed Sep 25 18:51:56 MSK 2019


On 16 Sep 16:23, Kirill Shcherbatov wrote:
> 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);

If this is a bug, please move it to a separate patch and provide
test case.

>  			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));
> @@ -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]);
>
These two places also look like bugs as well...

> 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',

Why did you have to change types? What is the difference between them,
if the base type is not map or array?

>                          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})

Btw, is this documented fact that nil is converted to NULL?
So box.NULL and nil means the same in SQL..





More information about the Tarantool-patches mailing list