Skip to content
This repository has been archived by the owner on May 14, 2024. It is now read-only.
Josh Baker edited this page Oct 11, 2016 · 9 revisions

EVAL script numkeys key [key ...] arg [arg ...]

EVAL and EVALSHA are used to evaluate scripts using Javascript.

The first argument of EVAL is a Javascript script.

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

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

The following example should clarify what stated above:

> eval "return [KEYS[0],KEYS[1],ARGV[2],ARGV[3]]" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"

It is possible to call SummitDB commands from a script using two different functions:

  • sdb.call()
  • sdb.pcall()

sdb.call() is similar to sdb.pcall(), the only difference is that if a SummitDB command call will result in an error, sdb.call() will raise a Javascript error that in turn will force EVAL to return an error to the command caller, while sdb.pcall will trap the error and return a Lua table representing the error.

The arguments of the sdb.call() and sdb.pcall() functions are all the arguments of a well formed SummitDB command:

> eval "return sdb.call('set','foo','bar')" 0
OK

The above script sets the key foo to the string bar. However it violates the EVAL command semantics as all the keys that the script uses should be passed using the KEYS array:

> eval "return sdb.call('set',KEYS[0],'bar')" 1 foo
OK

All SummitDB commands must be analyzed before execution to determine which keys the command will operate on. In order for this to be true for EVAL, keys must be passed explicitly.

Bandwidth and EVALSHA

The EVAL command forces you to send the script body again and again. SummitDB does not need to recompile the script every time as it uses an internal caching mechanism, however paying the cost of the additional bandwidth may not be optimal in many contexts.

In order to avoid the bandwidth penalty, SummitDB implements the EVALSHA command.

EVALSHA works exactly like EVAL, but instead of having a script as the first argument it has the SHA1 digest of a script. The behavior is the following:

  • If the server still remembers a script with a matching SHA1 digest, the script is executed.
  • If the server does not remember a script with this SHA1 digest, a special error is returned telling the client to use EVAL instead.

Example:

> set foo bar
OK
> eval "return sdb.call('get','foo')" 0
"bar"
> script load "return sdb.call('get','foo')"
"0d441febfdce5898f0ef48634670b02af9fd3f73"
> evalsha "0d441febfdce5898f0ef48634670b02af9fd3f73" 0
"bar"
> evalsha ffffffffffffffffffffffffffffffffffffffff 0
(error) `NOSCRIPT` No matching script. Please use EVAL.

The client library implementation can always optimistically send EVALSHA under the hood even when the client actually calls EVAL, in the hope the script was already seen by the server. If the NOSCRIPT error is returned EVAL will be used instead. Passing keys and arguments as additional EVAL arguments is also very useful in this context as the script string remains constant and can be efficiently cached by Redis.

Clone this wiki locally