Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using the TYPE command inside a Redis / Lua Script

Tags:

redis

lua

I am attempting to use the Redis TYPE command inside a Lua script (executed via EVAL)

local key_type = redis.call("TYPE", key)

According to the Redis documentation, this should return a string of "none", "zset" etc.

However the type of the returned value is a lua table. Comparing the value to a string always returns false.

I've managed to get around the problem by changing the call to

local key_type = redis.call("TYPE", key)["ok"]

This value is indeed a string and does work in string comparison commands. I am worried that this is a bug in my particular version of Redis and it will break in future versions when I upgrade.

Does anyone know if this is expected behaviour, or a bug?

like image 422
Andrew Newdigate Avatar asked Jan 29 '14 15:01

Andrew Newdigate


People also ask

Is Redis written in Lua?

The first argument is the script's source code. Scripts are written in Lua and executed by the embedded Lua 5.1 interpreter in Redis.

What type of digest is returned by the script load command?

Bulk string reply This command returns the SHA1 digest of the script added into the script cache.


1 Answers

The TYPE command returns a status reply (a.k.a simple string), e.g "+list\r\n".

On Redis scripting side, call is implemented by luaRedisCallCommand which performs the real Redis command behind the scenes.

Once successfully executed, this function converts the command result with redisProtocolToLuaType.

When a status reply is encountered, this function creates a Lua table with "ok" as key, and the status reply as value (see redisProtocolToLuaType_Status). So:

  • there is no bug,
  • this is why redis.call("TYPE", key) is a table (and thus you need to get the value for the "ok" key as you did, to get key's type as a string).

Note: when you directly return the table, Redis takes care to get the value associated to the "ok" key, and returns it as a status reply, e.g:

> EVAL 'return redis.call("TYPE", "foo")' 
set

See this code section for more details.

like image 90
deltheil Avatar answered Sep 27 '22 22:09

deltheil