diff --git a/src/db.c b/src/db.c index 69d1a776..36650318 100644 --- a/src/db.c +++ b/src/db.c @@ -688,16 +688,20 @@ void shutdownCommand(redisClient *c) { void renameGenericCommand(redisClient *c, int nx) { robj *o; long long expire; + int samekey = 0; - /* To use the same key as src and dst is probably an error */ - if (sdscmp(c->argv[1]->ptr,c->argv[2]->ptr) == 0) { - addReply(c,shared.sameobjecterr); - return; - } + /* When source and dest key is the same, no operation is performed, + * if the key exists, however we still return an error on unexisting key. */ + if (sdscmp(c->argv[1]->ptr,c->argv[2]->ptr) == 0) samekey = 1; if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr)) == NULL) return; + if (samekey) { + addReply(c,nx ? shared.czero : shared.ok); + return; + } + incrRefCount(o); expire = getExpire(c->db,c->argv[1]); if (lookupKeyWrite(c->db,c->argv[2]) != NULL) { diff --git a/tests/unit/basic.tcl b/tests/unit/basic.tcl index b0b3b9ba..fec0df5e 100644 --- a/tests/unit/basic.tcl +++ b/tests/unit/basic.tcl @@ -368,7 +368,18 @@ start_server {tags {"basic"}} { format $err } {ERR*} - test {RENAME where source and dest key is the same} { + test {RENAME where source and dest key are the same (existing)} { + r set mykey foo + r rename mykey mykey + } {OK} + + test {RENAMENX where source and dest key are the same (existing)} { + r set mykey foo + r renamenx mykey mykey + } {0} + + test {RENAME where source and dest key are the same (non existing)} { + r del mykey catch {r rename mykey mykey} err format $err } {ERR*}