mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-23 00:28:26 -05:00
Scripting: redis.NIL to return nil bulk replies.
Lua arrays can't contain nil elements (see http://www.lua.org/pil/19.1.html for more information), so Lua scripts were not able to return a multi-bulk reply containing nil bulk elements inside. This commit introduces a special conversion: a table with just a "nilbulk" field set to a boolean value is converted by Redis as a nil bulk reply, but at the same time for Lua this type is not a "nil" so can be used inside Lua arrays. This type is also assigned to redis.NIL, so the following two forms are equivalent and will be able to return a nil bulk reply as second element of a three elements array: EVAL "return {1,redis.NIL,3}" 0 EVAL "return {1,{nilbulk=true},3}" 0 The result in redis-cli will be: 1) (integer) 1 2) (nil) 3) (integer) 3
This commit is contained in:
parent
db100c4671
commit
6dd1693c0e
@ -516,6 +516,14 @@ void scriptingInit(void) {
|
||||
lua_pushcfunction(lua, luaRedisSha1hexCommand);
|
||||
lua_settable(lua, -3);
|
||||
|
||||
/* redis.NIL */
|
||||
lua_pushstring(lua, "NIL");
|
||||
lua_newtable(lua);
|
||||
lua_pushstring(lua, "nilbulk");
|
||||
lua_pushboolean(lua, 1);
|
||||
lua_settable(lua, -3);
|
||||
lua_settable(lua, -3);
|
||||
|
||||
/* Finally set the table as 'redis' global var. */
|
||||
lua_setglobal(lua,"redis");
|
||||
|
||||
@ -610,9 +618,30 @@ void luaReplyToRedisReply(redisClient *c, lua_State *lua) {
|
||||
addReplyLongLong(c,(long long)lua_tonumber(lua,-1));
|
||||
break;
|
||||
case LUA_TTABLE:
|
||||
/* We need to check if it is an array, an error, or a status reply.
|
||||
* Error are returned as a single element table with 'err' field.
|
||||
* Status replies are returned as single elment table with 'ok' field */
|
||||
/* The table can be an array or it may be in a special format that
|
||||
* Lua uses to return special Redis protocol data types.
|
||||
*
|
||||
* 1) Errors are retuned as a single element table with 'err' field.
|
||||
* 2) Status reply are returned as a single element table with 'ok'
|
||||
* field.
|
||||
* 3) A Redis nil bulk reply is returned as a single element table
|
||||
* with 'nilbulk' field set to true.
|
||||
*
|
||||
* All the rest is considered just an array and is translated into
|
||||
* a Redis multi bulk reply. */
|
||||
|
||||
/* Nil bulk reply */
|
||||
lua_pushstring(lua,"nilbulk");
|
||||
lua_gettable(lua,-2);
|
||||
t = lua_type(lua,-1);
|
||||
if (t == LUA_TBOOLEAN) {
|
||||
addReply(c,shared.nullbulk);
|
||||
lua_pop(lua,2);
|
||||
return;
|
||||
}
|
||||
lua_pop(lua,1);
|
||||
|
||||
/* Error reply */
|
||||
lua_pushstring(lua,"err");
|
||||
lua_gettable(lua,-2);
|
||||
t = lua_type(lua,-1);
|
||||
@ -624,8 +653,9 @@ void luaReplyToRedisReply(redisClient *c, lua_State *lua) {
|
||||
lua_pop(lua,2);
|
||||
return;
|
||||
}
|
||||
|
||||
lua_pop(lua,1);
|
||||
|
||||
/* Status reply */
|
||||
lua_pushstring(lua,"ok");
|
||||
lua_gettable(lua,-2);
|
||||
t = lua_type(lua,-1);
|
||||
@ -636,6 +666,7 @@ void luaReplyToRedisReply(redisClient *c, lua_State *lua) {
|
||||
sdsfree(ok);
|
||||
lua_pop(lua,1);
|
||||
} else {
|
||||
/* Multi bulk reply. */
|
||||
void *replylen = addDeferredMultiBulkLength(c);
|
||||
int j = 1, mbulklen = 0;
|
||||
|
||||
|
@ -30,6 +30,10 @@ start_server {tags {"scripting"}} {
|
||||
set _ $e
|
||||
} {this is an error}
|
||||
|
||||
test {EVAL - Lua nil reply -> Redis protocol type conversion} {
|
||||
r eval {return {1,redis.NIL,{nilbulk=true},4}} 0
|
||||
} {1 {} {} 4}
|
||||
|
||||
test {EVAL - Lua table -> Redis protocol type conversion} {
|
||||
r eval {return {1,2,3,'ciao',{1,2}}} 0
|
||||
} {1 2 3 ciao {1 2}}
|
||||
|
Loading…
Reference in New Issue
Block a user