This is an automated email from the ASF dual-hosted git repository.
hulk 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 044b6fde Fix crash in zset store getkeys, fix zdiff/bzmpop range, add
tests (#2051)
044b6fde is described below
commit 044b6fde4d34894b5ff0ba3534419b9631a34753
Author: Binbin <[email protected]>
AuthorDate: Thu Jan 25 19:11:03 2024 +0800
Fix crash in zset store getkeys, fix zdiff/bzmpop range, add tests (#2051)
These following cases will crash the server, the reason is that
the index of numkeys is wrong:
```
command getkeys zdiffstore dst 2 src1 src2
command getkeys zinterstore dst 2 src1 src2
command getkeys zunionstore dst 2 src1 src2
```
These following getkeys output is wrong:
```
> command getkeys zdiff 2 key1 key2
1) "key1"
2) "key2"
3) (nil)
> command getkeys bzmpop 0 2 key1 key2
1) "key1"
```
These are ok:
```
command getkeys zinter 2 key1 key2
command getkeys zunion 2 key1 key2
command getkeys sintercard 2 key1 key2
command getkeys zintercard 2 key1 key2
command getkeys zmpop 2 key1 key2
command getkeys lmpop 2 key1 key2
command getkeys blmpop 0 2 key1 key2
```
However, at present, there is still a problem with our zset store.
We do not support returning dst key, but let's do it later...
```
127.0.0.1:6379> command getkeys zinterstore dst 2 src1 src2
1) "dst"
2) "src1"
3) "src2"
127.0.0.1:6666> command getkeys zinterstore dst 2 src1 src2
1) "src1"
2) "src2"
```
---
src/commands/cmd_zset.cc | 10 +--
tests/gocase/unit/command/command_test.go | 108 ++++++++++++++++++++++++++++++
2 files changed, 113 insertions(+), 5 deletions(-)
diff --git a/src/commands/cmd_zset.cc b/src/commands/cmd_zset.cc
index 7d80829d..12927fa6 100644
--- a/src/commands/cmd_zset.cc
+++ b/src/commands/cmd_zset.cc
@@ -561,7 +561,7 @@ class CommandBZMPop : public BlockingCommander {
static CommandKeyRange Range(const std::vector<std::string> &args) {
int num_key = *ParseInt<int>(args[2], 10);
- return {3, 1 + num_key, 1};
+ return {3, 2 + num_key, 1};
}
private:
@@ -1223,7 +1223,7 @@ class CommandZUnionStore : public Commander {
}
static CommandKeyRange Range(const std::vector<std::string> &args) {
- int num_key = *ParseInt<int>(args[1], 10);
+ int num_key = *ParseInt<int>(args[2], 10);
return {3, 2 + num_key, 1};
}
@@ -1250,7 +1250,7 @@ class CommandZInterStore : public CommandZUnionStore {
}
static CommandKeyRange Range(const std::vector<std::string> &args) {
- int num_key = *ParseInt<int>(args[1], 10);
+ int num_key = *ParseInt<int>(args[2], 10);
return {3, 2 + num_key, 1};
}
};
@@ -1464,7 +1464,7 @@ class CommandZDiff : public Commander {
static CommandKeyRange Range(const std::vector<std::string> &args) {
int num_key = *ParseInt<int>(args[1], 10);
- return {2, 2 + num_key, 1};
+ return {2, 1 + num_key, 1};
}
protected:
@@ -1504,7 +1504,7 @@ class CommandZDiffStore : public Commander {
}
static CommandKeyRange Range(const std::vector<std::string> &args) {
- int num_key = *ParseInt<int>(args[1], 10);
+ int num_key = *ParseInt<int>(args[2], 10);
return {3, 2 + num_key, 1};
}
diff --git a/tests/gocase/unit/command/command_test.go
b/tests/gocase/unit/command/command_test.go
index 58b7589a..89d87a58 100644
--- a/tests/gocase/unit/command/command_test.go
+++ b/tests/gocase/unit/command/command_test.go
@@ -65,4 +65,112 @@ func TestCommand(t *testing.T) {
require.Len(t, vs, 1)
require.Equal(t, "test", vs[0])
})
+
+ t.Run("COMMAND GETKEYS SINTERCARD", func(t *testing.T) {
+ r := rdb.Do(ctx, "COMMAND", "GETKEYS", "SINTERCARD", "2",
"key1", "key2")
+ vs, err := r.Slice()
+ require.NoError(t, err)
+ require.Len(t, vs, 2)
+ require.Equal(t, "key1", vs[0])
+ require.Equal(t, "key2", vs[1])
+ })
+
+ t.Run("COMMAND GETKEYS ZINTER", func(t *testing.T) {
+ r := rdb.Do(ctx, "COMMAND", "GETKEYS", "ZINTER", "2", "key1",
"key2")
+ vs, err := r.Slice()
+ require.NoError(t, err)
+ require.Len(t, vs, 2)
+ require.Equal(t, "key1", vs[0])
+ require.Equal(t, "key2", vs[1])
+ })
+
+ t.Run("COMMAND GETKEYS ZINTERSTORE", func(t *testing.T) {
+ r := rdb.Do(ctx, "COMMAND", "GETKEYS", "ZINTERSTORE", "dst",
"2", "src1", "src2")
+ vs, err := r.Slice()
+ require.NoError(t, err)
+ require.Len(t, vs, 2)
+ require.Equal(t, "src1", vs[0])
+ require.Equal(t, "src2", vs[1])
+ })
+
+ t.Run("COMMAND GETKEYS ZINTERCARD", func(t *testing.T) {
+ r := rdb.Do(ctx, "COMMAND", "GETKEYS", "ZINTERCARD", "2",
"key1", "key2")
+ vs, err := r.Slice()
+ require.NoError(t, err)
+ require.Len(t, vs, 2)
+ require.Equal(t, "key1", vs[0])
+ require.Equal(t, "key2", vs[1])
+ })
+
+ t.Run("COMMAND GETKEYS ZUNION", func(t *testing.T) {
+ r := rdb.Do(ctx, "COMMAND", "GETKEYS", "ZUNION", "2", "key1",
"key2")
+ vs, err := r.Slice()
+ require.NoError(t, err)
+ require.Len(t, vs, 2)
+ require.Equal(t, "key1", vs[0])
+ require.Equal(t, "key2", vs[1])
+ })
+
+ t.Run("COMMAND GETKEYS ZUNIONSTORE", func(t *testing.T) {
+ r := rdb.Do(ctx, "COMMAND", "GETKEYS", "ZUNIONSTORE", "dst",
"2", "src1", "src2")
+ vs, err := r.Slice()
+ require.NoError(t, err)
+ require.Len(t, vs, 2)
+ require.Equal(t, "src1", vs[0])
+ require.Equal(t, "src2", vs[1])
+ })
+
+ t.Run("COMMAND GETKEYS ZDIFF", func(t *testing.T) {
+ r := rdb.Do(ctx, "COMMAND", "GETKEYS", "ZDIFF", "2", "key1",
"key2")
+ vs, err := r.Slice()
+ require.NoError(t, err)
+ require.Len(t, vs, 2)
+ require.Equal(t, "key1", vs[0])
+ require.Equal(t, "key2", vs[1])
+ })
+
+ t.Run("COMMAND GETKEYS ZDIFFSTORE", func(t *testing.T) {
+ r := rdb.Do(ctx, "COMMAND", "GETKEYS", "ZDIFFSTORE", "dst",
"2", "src1", "src2")
+ vs, err := r.Slice()
+ require.NoError(t, err)
+ require.Len(t, vs, 2)
+ require.Equal(t, "src1", vs[0])
+ require.Equal(t, "src2", vs[1])
+ })
+
+ t.Run("COMMAND GETKEYS ZMPOP", func(t *testing.T) {
+ r := rdb.Do(ctx, "COMMAND", "GETKEYS", "ZMPOP", "2", "key1",
"key2")
+ vs, err := r.Slice()
+ require.NoError(t, err)
+ require.Len(t, vs, 2)
+ require.Equal(t, "key1", vs[0])
+ require.Equal(t, "key2", vs[1])
+ })
+
+ t.Run("COMMAND GETKEYS BZMPOP", func(t *testing.T) {
+ r := rdb.Do(ctx, "COMMAND", "GETKEYS", "BZMPOP", "0", "2",
"key1", "key2")
+ vs, err := r.Slice()
+ require.NoError(t, err)
+ require.Len(t, vs, 2)
+ require.Equal(t, "key1", vs[0])
+ require.Equal(t, "key2", vs[1])
+ })
+
+ t.Run("COMMAND GETKEYS LMPOP", func(t *testing.T) {
+ r := rdb.Do(ctx, "COMMAND", "GETKEYS", "LMPOP", "2", "key1",
"key2")
+ vs, err := r.Slice()
+ require.NoError(t, err)
+ require.Len(t, vs, 2)
+ require.Equal(t, "key1", vs[0])
+ require.Equal(t, "key2", vs[1])
+ })
+
+ t.Run("COMMAND GETKEYS BLMPOP", func(t *testing.T) {
+ r := rdb.Do(ctx, "COMMAND", "GETKEYS", "BLMPOP", "0", "2",
"key1", "key2")
+ vs, err := r.Slice()
+ require.NoError(t, err)
+ require.Len(t, vs, 2)
+ require.Equal(t, "key1", vs[0])
+ require.Equal(t, "key2", vs[1])
+ })
}