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 <[email protected]>
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")