]> git.saurik.com Git - redis.git/commitdiff
REPLACE option for RESTORE.
authorantirez <antirez@gmail.com>
Wed, 7 Nov 2012 09:57:23 +0000 (10:57 +0100)
committerantirez <antirez@gmail.com>
Wed, 7 Nov 2012 09:57:23 +0000 (10:57 +0100)
The REPLACE option deletes an existing key with the same name (if any)
and materializes the new one. The default behavior without RESTORE is to
return an error if a key already exists.

src/cluster.c
src/redis.c
tests/unit/dump.tcl

index 57243132d0da6656655d59c63b7bd0614b89f852..33a267589ff945d589c64d508323de8d41e9183f 100644 (file)
@@ -1539,15 +1539,25 @@ void dumpCommand(redisClient *c) {
     return;
 }
 
     return;
 }
 
-/* RESTORE key ttl serialized-value */
+/* RESTORE key ttl serialized-value [REPLACE] */
 void restoreCommand(redisClient *c) {
     long ttl;
     rio payload;
 void restoreCommand(redisClient *c) {
     long ttl;
     rio payload;
-    int type;
+    int j, type, replace = 0;
     robj *obj;
 
     robj *obj;
 
+    /* Parse additional options */
+    for (j = 4; j < c->argc; j++) {
+        if (!strcasecmp(c->argv[j]->ptr,"replace")) {
+            replace = 1;
+        } else {
+            addReply(c,shared.syntaxerr);
+            return;
+        }
+    }
+
     /* Make sure this key does not already exist here... */
     /* Make sure this key does not already exist here... */
-    if (lookupKeyWrite(c->db,c->argv[1]) != NULL) {
+    if (!replace && lookupKeyWrite(c->db,c->argv[1]) != NULL) {
         addReplyError(c,"Target key name is busy.");
         return;
     }
         addReplyError(c,"Target key name is busy.");
         return;
     }
@@ -1574,6 +1584,9 @@ void restoreCommand(redisClient *c) {
         return;
     }
 
         return;
     }
 
+    /* Remove the old key if needed. */
+    if (replace) dbDelete(c->db,c->argv[1]);
+
     /* Create the key and set the TTL if any */
     dbAdd(c->db,c->argv[1],obj);
     if (ttl) setExpire(c->db,c->argv[1],mstime()+ttl);
     /* Create the key and set the TTL if any */
     dbAdd(c->db,c->argv[1],obj);
     if (ttl) setExpire(c->db,c->argv[1],mstime()+ttl);
index 5ac025e75996f5b0fafc33693d84985ddabb4f31..0780e8876b4f5bbb2e618d1de50709106f8988f6 100644 (file)
@@ -240,7 +240,7 @@ struct redisCommand redisCommandTable[] = {
     {"watch",watchCommand,-2,"rs",0,noPreloadGetKeys,1,-1,1,0,0},
     {"unwatch",unwatchCommand,1,"rs",0,NULL,0,0,0,0,0},
     {"cluster",clusterCommand,-2,"ar",0,NULL,0,0,0,0,0},
     {"watch",watchCommand,-2,"rs",0,noPreloadGetKeys,1,-1,1,0,0},
     {"unwatch",unwatchCommand,1,"rs",0,NULL,0,0,0,0,0},
     {"cluster",clusterCommand,-2,"ar",0,NULL,0,0,0,0,0},
-    {"restore",restoreCommand,4,"awm",0,NULL,1,1,1,0,0},
+    {"restore",restoreCommand,-4,"awm",0,NULL,1,1,1,0,0},
     {"migrate",migrateCommand,6,"aw",0,NULL,0,0,0,0,0},
     {"asking",askingCommand,1,"r",0,NULL,0,0,0,0,0},
     {"dump",dumpCommand,2,"ar",0,NULL,1,1,1,0,0},
     {"migrate",migrateCommand,6,"aw",0,NULL,0,0,0,0,0},
     {"asking",askingCommand,1,"r",0,NULL,0,0,0,0,0},
     {"dump",dumpCommand,2,"ar",0,NULL,1,1,1,0,0},
index be891a96f958cdc4bf84742cafc5c7746e0e3703..1eb91eb21842571067e84474cbd817d9d94efe96 100644 (file)
@@ -23,6 +23,22 @@ start_server {tags {"dump"}} {
         set e
     } {*is busy*}
 
         set e
     } {*is busy*}
 
+    test {RESTORE can overwrite an existing key with REPLACE} {
+        r set foo bar1
+        set encoded1 [r dump foo]
+        r set foo bar2
+        set encoded2 [r dump foo]
+        r del foo
+        r restore foo 0 $encoded1
+        r restore foo 0 $encoded2 replace
+        r get foo
+    } {bar2}
+
+    test {RESTORE can detect a syntax error for unrecongized options} {
+        catch {r restore foo 0 "..." invalid-option} e
+        set e
+    } {*syntax*}
+
     test {DUMP of non existing key returns nil} {
         r dump nonexisting_key
     } {}
     test {DUMP of non existing key returns nil} {
         r dump nonexisting_key
     } {}