]> git.saurik.com Git - redis.git/commitdiff
Fix SINTER/UNIONSTORE to allow for &=/|= style operations (i.e. SINTERSTORE set1...
authorAman Gupta <aman@tmm1.net>
Sun, 17 May 2009 21:16:24 +0000 (14:16 -0700)
committerAman Gupta <aman@tmm1.net>
Sun, 17 May 2009 21:16:24 +0000 (14:16 -0700)
redis.c
test-redis.tcl

diff --git a/redis.c b/redis.c
index a3341f6d84161b916777f121d84de156affe7f91..9587dcdcd3ccd023999aa40673869b8cccb658e4 100644 (file)
--- a/redis.c
+++ b/redis.c
@@ -3013,9 +3013,6 @@ static void sinterGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
         /* If we have a target key where to store the resulting set
          * create this key with an empty set inside */
         dstset = createSetObject();
-        deleteKey(c->db,dstkey);
-        dictAdd(c->db->dict,dstkey,dstset);
-        incrRefCount(dstkey);
     }
 
     /* Iterate all the elements of the first (smallest) set, and test
@@ -3044,6 +3041,13 @@ static void sinterGenericCommand(redisClient *c, robj **setskeys, int setsnum, r
     }
     dictReleaseIterator(di);
 
+    if (dstkey) {
+        /* Store the resulting set into the target */
+        deleteKey(c->db,dstkey);
+        dictAdd(c->db->dict,dstkey,dstset);
+        incrRefCount(dstkey);
+    }
+
     if (!dstkey) {
         lenobj->ptr = sdscatprintf(sdsempty(),"*%d\r\n",cardinality);
     } else {
@@ -3095,20 +3099,6 @@ static void sunionDiffGenericCommand(redisClient *c, robj **setskeys, int setsnu
      * this set object will be the resulting object to set into the target key*/
     dstset = createSetObject();
 
-    /* The first thing we should output is the total number of elements...
-     * since this is a multi-bulk write, but at this stage we don't know
-     * the intersection set size, so we use a trick, append an empty object
-     * to the output list and save the pointer to later modify it with the
-     * right length */
-    if (dstkey) {
-        /* If we have a target key where to store the resulting set
-         * create this key with an empty set inside */
-        deleteKey(c->db,dstkey);
-        dictAdd(c->db->dict,dstkey,dstset);
-        incrRefCount(dstkey);
-        server.dirty++;
-    }
-
     /* Iterate all the elements of all the sets, add every element a single
      * time to the result set */
     for (j = 0; j < setsnum; j++) {
@@ -3154,6 +3144,13 @@ static void sunionDiffGenericCommand(redisClient *c, robj **setskeys, int setsnu
             addReply(c,shared.crlf);
         }
         dictReleaseIterator(di);
+    } else {
+        /* If we have a target key where to store the resulting set
+         * create this key with the result set inside */
+        deleteKey(c->db,dstkey);
+        dictAdd(c->db->dict,dstkey,dstset);
+        incrRefCount(dstkey);
+        server.dirty++;
     }
 
     /* Cleanup */
index bd58cb2e7183bea9fc62334ecad0f474ceeaf7c6..1672390346088270a423f5e33a80e78f558d9470 100644 (file)
@@ -481,6 +481,11 @@ proc main {server port} {
         lsort [$r smembers setres]
     } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
 
+    test {SUNIONSTORE with same src and dest} {
+        $r sunionstore set1 set1 set1
+        $r scard set1
+    } {1000}
+
     test {SINTER against three sets} {
         $r sadd set3 999
         $r sadd set3 995
@@ -494,6 +499,11 @@ proc main {server port} {
         lsort [$r smembers setres]
     } {995 999}
 
+    test {SINTERSTORE with same src and dest} {
+       $r sinterstore set1 set1 set1
+       $r scard set1
+    } {1000}
+
     test {SUNION with non existing keys} {
         lsort [$r sunion nokey1 set1 set2 nokey2]
     } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]