]> git.saurik.com Git - redis.git/commitdiff
Redis.call is now split into two variants of the same function. Redis.call will raise...
authorantirez <antirez@gmail.com>
Thu, 20 Oct 2011 14:02:23 +0000 (16:02 +0200)
committerantirez <antirez@gmail.com>
Thu, 20 Oct 2011 14:02:23 +0000 (16:02 +0200)
src/scripting.c
tests/unit/scripting.tcl

index 1f441ae474efef7bf1727730374e4b3b85f71ec5..af22d5015b59f13b8674482f66308c2ae0bd69de 100644 (file)
@@ -128,7 +128,7 @@ void luaPushError(lua_State *lua, char *error) {
     lua_settable(lua,-3);
 }
 
-int luaRedisCommand(lua_State *lua) {
+int luaRedisGenericCommand(lua_State *lua, int raise_error) {
     int j, argc = lua_gettop(lua);
     struct redisCommand *cmd;
     robj **argv;
@@ -205,6 +205,7 @@ int luaRedisCommand(lua_State *lua) {
         reply = sdscatlen(reply,o->ptr,sdslen(o->ptr));
         listDelNode(c->reply,listFirst(c->reply));
     }
+    if (raise_error && reply[0] != '-') raise_error = 0;
     redisProtocolToLuaType(lua,reply);
     sdsfree(reply);
 
@@ -215,9 +216,25 @@ cleanup:
         decrRefCount(c->argv[j]);
     zfree(c->argv);
 
+    if (raise_error) {
+        /* If we are here we should have an error in the stack, in the
+         * form of a table with an "err" field. Extract the string to
+         * return the plain error. */
+        lua_pushstring(lua,"err");
+        lua_gettable(lua,-2);
+        return lua_error(lua);
+    }
     return 1;
 }
 
+int luaRedisCallCommand(lua_State *lua) {
+    return luaRedisGenericCommand(lua,1);
+}
+
+int luaRedisPCallCommand(lua_State *lua) {
+    return luaRedisGenericCommand(lua,0);
+}
+
 int luaLogCommand(lua_State *lua) {
     int j, argc = lua_gettop(lua);
     int level;
@@ -301,7 +318,12 @@ void scriptingInit(void) {
 
     /* redis.call */
     lua_pushstring(lua,"call");
-    lua_pushcfunction(lua,luaRedisCommand);
+    lua_pushcfunction(lua,luaRedisCallCommand);
+    lua_settable(lua,-3);
+
+    /* redis.pcall */
+    lua_pushstring(lua,"pcall");
+    lua_pushcfunction(lua,luaRedisPCallCommand);
     lua_settable(lua,-3);
 
     /* redis.log and log levels. */
index d8a2e023e2216ab664951dabae628ab15d8da211..5bac5687aef84319d34833a4852c5cb5c10010e8 100644 (file)
@@ -54,7 +54,7 @@ start_server {tags {"scripting"}} {
 
     test {EVAL - Redis integer -> Lua type conversion} {
         r eval {
-            local foo = redis.call('incr','x')
+            local foo = redis.pcall('incr','x')
             return {type(foo),foo}
         } 0
     } {number 1}
@@ -62,7 +62,7 @@ start_server {tags {"scripting"}} {
     test {EVAL - Redis bulk -> Lua type conversion} {
         r set mykey myval
         r eval {
-            local foo = redis.call('get','mykey')
+            local foo = redis.pcall('get','mykey')
             return {type(foo),foo}
         } 0
     } {string myval}
@@ -73,14 +73,14 @@ start_server {tags {"scripting"}} {
         r rpush mylist b
         r rpush mylist c
         r eval {
-            local foo = redis.call('lrange','mylist',0,-1)
+            local foo = redis.pcall('lrange','mylist',0,-1)
             return {type(foo),foo[1],foo[2],foo[3],# foo}
         } 0
     } {table a b c 3}
 
     test {EVAL - Redis status reply -> Lua type conversion} {
         r eval {
-            local foo = redis.call('set','mykey','myval')
+            local foo = redis.pcall('set','mykey','myval')
             return {type(foo),foo['ok']}
         } 0
     } {table OK}
@@ -88,7 +88,7 @@ start_server {tags {"scripting"}} {
     test {EVAL - Redis error reply -> Lua type conversion} {
         r set mykey myval
         r eval {
-            local foo = redis.call('incr','mykey')
+            local foo = redis.pcall('incr','mykey')
             return {type(foo),foo['err']}
         } 0
     } {table {ERR value is not an integer or out of range}}
@@ -96,7 +96,7 @@ start_server {tags {"scripting"}} {
     test {EVAL - Redis nil bulk reply -> Lua type conversion} {
         r del mykey
         r eval {
-            local foo = redis.call('get','mykey')
+            local foo = redis.pcall('get','mykey')
             return {type(foo),foo == false}
         } 0
     } {boolean 1}
@@ -105,11 +105,11 @@ start_server {tags {"scripting"}} {
         r set mykey "this is DB 9"
         r select 10
         r set mykey "this is DB 10"
-        r eval {return redis.call('get','mykey')} 0
+        r eval {return redis.pcall('get','mykey')} 0
     } {this is DB 10}
 
     test {EVAL - Is Lua seleced DB retained?} {
-        r eval {return redis.call('select','9')} 0
+        r eval {return redis.pcall('select','9')} 0
         r get mykey
     } {this is DB 9}
 
@@ -126,18 +126,42 @@ start_server {tags {"scripting"}} {
 
     test {EVAL - Scripts can't run certain commands} {
         set e {}
-        catch {r eval {return redis.call('spop','x')} 0} e
+        catch {r eval {return redis.pcall('spop','x')} 0} e
         set e
     } {*not allowed*}
 
     test {EVAL - Scripts can't run certain commands} {
         set e {}
         catch {
-            r eval "redis.call('randomkey'); return redis.call('set','x','ciao')" 0
+            r eval "redis.pcall('randomkey'); return redis.pcall('set','x','ciao')" 0
         } e
         set e
     } {*not allowed after*}
 
+    test {EVAL - redis.call variant raises a Lua error on Redis cmd error (1)} {
+        set e {}
+        catch {
+            r eval "redis.call('nosuchcommand')" 0
+        } e
+        set e
+    } {*Unknown Redis*}
+
+    test {EVAL - redis.call variant raises a Lua error on Redis cmd error (1)} {
+        set e {}
+        catch {
+            r eval "redis.call('get','a','b','c')" 0
+        } e
+        set e
+    } {*number of args*}
+
+    test {EVAL - redis.call variant raises a Lua error on Redis cmd error (1)} {
+        set e {}
+        r set foo bar
+        catch {
+            r eval "redis.call('lpush','foo','val')" 0
+        } e
+        set e
+    } {*against a key*}
 }
 
 start_server {tags {"scripting repl"}} {