This is an automated email from the ASF dual-hosted git repository.

binbin pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git


The following commit(s) were added to refs/heads/unstable by this push:
     new 0e28daca Fix ZRANGESTORE not overwrite the dst key (#1609)
0e28daca is described below

commit 0e28daca80f22cd7193c903ff9b8c91bef2c8f28
Author: Binbin <binloveplay1...@qq.com>
AuthorDate: Wed Jul 26 00:01:39 2023 +0800

    Fix ZRANGESTORE not overwrite the dst key (#1609)
    
    When the code is doing `store`, it calls the add method,
    which leads us to perform zadd dst xxx in disguise. And
    this result the following two issues.
    
    The first one is we do a type check against dst:
    ```
    127.0.0.1:6379> set dst value
    OK
    127.0.0.1:6379> zrangestore dst non 0 -1
    (integer) 0
    127.0.0.1:6379> get dst
    (nil)
    
    127.0.0.1:6666> set dst value
    OK
    127.0.0.1:6666> zrangestore dst non 0 -1
    (error) ERR Invalid argument: WRONGTYPE Operation against a key holding
    the wrong kind of value
    ```
    
    The second one is when dst has members, we are doing zadd:
    ```
    127.0.0.1:6379> zadd dst 1 a 2 b
    (integer) 2
    127.0.0.1:6379> zadd src 3 c 4 d
    (integer) 2
    127.0.0.1:6379> zrangestore dst src 0 -1
    (integer) 2
    127.0.0.1:6379> zrange dst 0 -1
    1) "c"
    2) "d"
    
    127.0.0.1:6666> zadd dst 1 a 2 b
    (integer) 2
    127.0.0.1:6666> zadd src 3 c 4 d
    (integer) 2
    127.0.0.1:6666> zrangestore dst src 0 -1
    (integer) 2
    127.0.0.1:6666> zrange dst 0 -1
    1) "a"
    2) "b"
    3) "c"
    4) "d"
    ```
    
    ZRANGESTORE was added in #1482
---
 src/commands/cmd_zset.cc                 |  4 ++--
 tests/gocase/unit/type/zset/zset_test.go | 27 ++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/src/commands/cmd_zset.cc b/src/commands/cmd_zset.cc
index 6ee32dfd..e97ead7a 100644
--- a/src/commands/cmd_zset.cc
+++ b/src/commands/cmd_zset.cc
@@ -770,8 +770,8 @@ class CommandZRangeStore : public Commander {
       return {Status::RedisExecErr, s.ToString()};
     }
 
-    uint64_t ret = 0;
-    s = zset_db.Add(dst_, ZAddFlags(), &member_scores, &ret);
+    uint64_t ret = member_scores.size();
+    s = zset_db.Overwrite(dst_, member_scores);
     if (!s.ok()) {
       return {Status::RedisExecErr, s.ToString()};
     }
diff --git a/tests/gocase/unit/type/zset/zset_test.go 
b/tests/gocase/unit/type/zset/zset_test.go
index 847cb576..1d741364 100644
--- a/tests/gocase/unit/type/zset/zset_test.go
+++ b/tests/gocase/unit/type/zset/zset_test.go
@@ -477,7 +477,7 @@ func basicTests(t *testing.T, rdb *redis.Client, ctx 
context.Context, encoding s
                require.Equal(t, []string{"b", "c", "d"}, rdb.ZRange(ctx, 
"zdst", 0, -1).Val())
 
                rdb.ZRangeStore(ctx, "zdst", redis.ZRangeArgs{Key: "zsrc", 
Start: 0, Stop: 2})
-               require.Equal(t, []string{"a", "b", "c", "d"}, rdb.ZRange(ctx, 
"zdst", 0, -1).Val())
+               require.Equal(t, []string{"a", "b", "c"}, rdb.ZRange(ctx, 
"zdst", 0, -1).Val())
 
                rdb.Del(ctx, "zdst")
                rdb.ZRangeStore(ctx, "zdst", redis.ZRangeArgs{Key: "zsrc", 
Start: 0, Stop: 0})
@@ -514,6 +514,31 @@ func basicTests(t *testing.T, rdb *redis.Client, ctx 
context.Context, encoding s
                require.Equal(t, []string{"c", "d", "f"}, rdb.ZRange(ctx, 
"zdst", 0, -1).Val())
        })
 
+       t.Run(fmt.Sprintf("ZRANGESTORE will overwrite dst - %s", encoding), 
func(t *testing.T) {
+               rdb.Del(ctx, "zsrc")
+               rdb.Del(ctx, "zdst")
+
+               // non-existing src key delete the dst key
+               rdb.ZAdd(ctx, "zdst", redis.Z{Score: 1, Member: "dst_a"})
+               require.Equal(t, int64(0), rdb.Do(ctx, "zrangestore", "zdst", 
"zsrc", 0, -1).Val())
+               require.Equal(t, int64(0), rdb.Exists(ctx, "zdst").Val())
+
+               // non-existing src key delete the dst key (different type)
+               require.Equal(t, "OK", rdb.Set(ctx, "zdst", 100, 0).Val())
+               require.Equal(t, int64(0), rdb.Do(ctx, "zrangestore", "zdst", 
"zsrc", 0, -1).Val())
+               require.Equal(t, int64(0), rdb.Exists(ctx, "zdst").Val())
+
+               // overwrite the dst key with the result zset instead of adding
+               rdb.ZAdd(ctx, "zsrc", redis.Z{Score: 1, Member: "src_a"})
+               rdb.ZAdd(ctx, "zsrc", redis.Z{Score: 2, Member: "src_b"})
+               rdb.ZAdd(ctx, "zdst", redis.Z{Score: 3, Member: "dst_c"})
+               require.Equal(t, int64(2), rdb.Do(ctx, "zrangestore", "zdst", 
"zsrc", 0, -1).Val())
+               require.Equal(t, []redis.Z{
+                       {1, "src_a"},
+                       {2, "src_b"},
+               }, rdb.ZRangeWithScores(ctx, "zdst", 0, -1).Val())
+       })
+
        t.Run(fmt.Sprintf("ZRANGESTORE error - %s", encoding), func(t 
*testing.T) {
                rdb.Del(ctx, "zsrc")
                rdb.Del(ctx, "zdst")

Reply via email to