Aarish Ramesh
Aarish Ramesh

Reputation: 7023

Local variable assignments in Lua scripting using eval command

I am a beginner to lua scripting. I tried executing the below command in redis client

eval "print('hello world')" 0

and it works fine returning me

hello
(nil)    

Firstly i don't understand why does the nil is returned/gets printed always?? is it because of the lua-datatype to redis-datatype inter-conversion which returns nil??

Then i used if constructs and executed the below script

eval "local t = 0; if t == 0 then print('hello'); end" 0 0

the above command prints as expected

hello
(nil)

But when i tried assigning the arguments to the local variable using the below code

eval "local t = ARGV[1]; if t == 0 then print('hello'); end" 0 0

the output is only

(nil)

So can someone explain me how should the assignments of the external arguments to the local variable be carried out??

Upvotes: 3

Views: 3104

Answers (2)

dualed
dualed

Reputation: 10502

The redis eval command does nothing more than split your input into tokens, hence your argument 0 is a string, and not a number.

However, the comparison 0 == "0" is false in Lua, so what you need to do is change to either of those variants:

eval "local t = ARGV[1]; if t == '0' then print('hello'); end" 0 0
eval "local t = ARGV[1]; if tonumber(t) == 0 then print('hello'); end" 0 0

Note: Since is was kind of mentioned by Kamiccolo; note that in Lua's eval you never have access to local variables from outside of the eval because code is always evaluated in the global context!

Upvotes: 2

Kamiccolo
Kamiccolo

Reputation: 8507

According to Redis EVAL documentation, global variable access from chunk executed using eval() to global variables is disabled. It's not mentioned, but I suspect that accessing local ones is even bigger violation and possible leakage. So, You should follow official documentation and use Redis keys instead. Or, of course, re-using returned valies.

Relevant chunk from eval() docs:

Global variables protection

Redis scripts are not allowed to create global variables, in order to avoid leaking data into the Lua state. If a script needs to maintain state between calls (a pretty uncommon need) it should use Redis keys instead.

Just realised, that question's body does not match the question's title, so starting again...

Proper eval() usage (from Redis docs):

The first argument of EVAL is a Lua 5.1 script. The script does not need to define a Lua function (and should not). It is just a Lua program that will run in the context of the Redis server.

The second argument of EVAL is the number of arguments that follows the script (starting from the third argument) that represent Redis key names. This arguments can be accessed by Lua using the KEYS global variable in the form of a one-based array (so KEYS[1], KEYS[2], ...).

All the additional arguments should not represent key names and can be accessed by Lua using the ARGV global variable, very similarly to what happens with keys (so ARGV[1], ARGV[2], ...).

In Your example You're setting number of arguments to 0, so, nothing gets passed to Your Lua script. Quick fix:

eval "local t = ARGV[1]; if t == 0 then print('hello'); end" 1 0

Not sure about nil, but that might be just because Your Lua chunk provided does not return anyhing.

Upvotes: 1

Related Questions