diff --git a/src/scripting.c b/src/scripting.c index 6beb6cdbf..a75871ad3 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -410,9 +410,9 @@ void luaReplyToRedisReply(client *c, lua_State *lua) { lua_pushnil(lua); /* Use nil to start iteration. */ while (lua_next(lua,-2)) { /* Stack now: table, key, value */ - luaReplyToRedisReply(c, lua); /* Return value. */ - lua_pushvalue(lua,-1); /* Dup key before consuming. */ + lua_pushvalue(lua,-2); /* Dup key before consuming. */ luaReplyToRedisReply(c, lua); /* Return key. */ + luaReplyToRedisReply(c, lua); /* Return value. */ /* Stack now: table, key. */ maplen++; } diff --git a/tests/support/redis.tcl b/tests/support/redis.tcl index a90ac7f29..566750c0d 100644 --- a/tests/support/redis.tcl +++ b/tests/support/redis.tcl @@ -210,6 +210,24 @@ proc ::redis::redis_multi_bulk_read {id fd} { return $l } +proc ::redis::redis_read_map {id fd} { + set count [redis_read_line $fd] + if {$count == -1} return {} + set d {} + set err {} + for {set i 0} {$i < $count} {incr i} { + if {[catch { + set k [redis_read_reply $id $fd] ; # key + set v [redis_read_reply $id $fd] ; # value + dict set d $k $v + } e] && $err eq {}} { + set err $e + } + } + if {$err ne {}} {return -code error $err} + return $d +} + proc ::redis::redis_read_line fd { string trim [gets $fd] } @@ -222,6 +240,7 @@ proc ::redis::redis_read_reply {id fd} { - {return -code error [redis_read_line $fd]} $ {redis_bulk_read $fd} * {redis_multi_bulk_read $id $fd} + % {redis_read_map $id $fd} default { if {$type eq {}} { set ::redis::fd($id) {} diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl index 6bcba4c3f..e3cd2f87f 100644 --- a/tests/unit/scripting.tcl +++ b/tests/unit/scripting.tcl @@ -533,6 +533,30 @@ start_server {tags {"scripting"}} { } e set e } {*wrong number*} + + test {Script with RESP3 map} { + set expected_dict [dict create field value] + set expected_list [list field value] + + # Sanity test for RESP3 without scripts + r HELLO 3 + r hset hash field value + set res [r hgetall hash] + assert_equal $res $expected_dict + + # Test RESP3 client with script in both RESP2 and RESP3 modes + set res [r eval {redis.setresp(3); return redis.call('hgetall', KEYS[1])} 1 hash] + assert_equal $res $expected_dict + set res [r eval {redis.setresp(2); return redis.call('hgetall', KEYS[1])} 1 hash] + assert_equal $res $expected_list + + # Test RESP2 client with script in both RESP2 and RESP3 modes + r HELLO 2 + set res [r eval {redis.setresp(3); return redis.call('hgetall', KEYS[1])} 1 hash] + assert_equal $res $expected_list + set res [r eval {redis.setresp(2); return redis.call('hgetall', KEYS[1])} 1 hash] + assert_equal $res $expected_list + } } # Start a new server since the last test in this stanza will kill the