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/incubator-kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new 8ffdfaf Add GETDEL command (#771)
8ffdfaf is described below
commit 8ffdfaf2d5caf73977a9855066d7e06ecc93c76f
Author: ran <[email protected]>
AuthorDate: Sun Aug 7 23:45:07 2022 +0800
Add GETDEL command (#771)
---
README.md | 2 +-
src/redis_cmd.cc | 19 +++++++++++++++++++
src/redis_string.cc | 10 ++++++++++
src/redis_string.h | 1 +
tests/cppunit/t_string_test.cc | 14 ++++++++++++++
tests/tcl/tests/unit/command.tcl | 4 ++--
tests/tcl/tests/unit/type/string.tcl | 12 ++++++------
7 files changed, 53 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index ace584b..d2f75b6 100644
--- a/README.md
+++ b/README.md
@@ -114,7 +114,7 @@ $ redis-cli -p 6666
### Running test cases
```shell
-$ ./build.sh build --unittest
+$ ./x.py build --unittest
$ cd build
$ ./unittest
```
diff --git a/src/redis_cmd.cc b/src/redis_cmd.cc
index 886613b..aa8f84e 100644
--- a/src/redis_cmd.cc
+++ b/src/redis_cmd.cc
@@ -325,6 +325,24 @@ class CommandGetSet : public Commander {
}
};
+class CommandGetDel : public Commander {
+ public:
+ Status Execute(Server *svr, Connection *conn, std::string *output) override {
+ Redis::String string_db(svr->storage_, conn->GetNamespace());
+ std::string value;
+ rocksdb::Status s = string_db.GetDel(args_[1], &value);
+ if (!s.ok() && !s.IsNotFound()) {
+ return Status(Status::RedisExecErr, s.ToString());
+ }
+ if (s.IsNotFound()) {
+ *output = Redis::NilString();
+ } else {
+ *output = Redis::BulkString(value);
+ }
+ return Status::OK();
+ }
+};
+
class CommandGetRange: public Commander {
public:
Status Parse(const std::vector<std::string> &args) override {
@@ -4778,6 +4796,7 @@ CommandAttributes redisCommandTable[] = {
ADD_CMD("strlen", 2, "read-only", 1, 1, 1, CommandStrlen),
ADD_CMD("getset", 3, "write", 1, 1, 1, CommandGetSet),
ADD_CMD("getrange", 4, "read-only", 1, 1, 1, CommandGetRange),
+ ADD_CMD("getdel", 2, "write", 1, 1, 1, CommandGetDel),
ADD_CMD("setrange", 4, "write", 1, 1, 1, CommandSetRange),
ADD_CMD("mget", -2, "read-only", 1, -1, 1, CommandMGet),
ADD_CMD("append", 3, "write", 1, 1, 1, CommandAppend),
diff --git a/src/redis_string.cc b/src/redis_string.cc
index 1a288d5..20ea14c 100644
--- a/src/redis_string.cc
+++ b/src/redis_string.cc
@@ -165,6 +165,16 @@ rocksdb::Status String::GetSet(const std::string
&user_key, const std::string &n
// prev status was used to tell whether old value was empty or not
return !write_status.ok() ? write_status : s;
}
+rocksdb::Status String::GetDel(const std::string &user_key, std::string
*value) {
+ std::string ns_key;
+ AppendNamespacePrefix(user_key, &ns_key);
+
+ LockGuard guard(storage_->GetLockManager(), ns_key);
+ rocksdb::Status s = getValue(ns_key, value);
+ if (!s.ok()) return s;
+
+ return storage_->Delete(rocksdb::WriteOptions(), metadata_cf_handle_,
ns_key);
+}
rocksdb::Status String::Set(const std::string &user_key, const std::string
&value) {
std::vector<StringPair> pairs{StringPair{user_key, value}};
diff --git a/src/redis_string.h b/src/redis_string.h
index 0403070..37d66d2 100644
--- a/src/redis_string.h
+++ b/src/redis_string.h
@@ -41,6 +41,7 @@ class String : public Database {
rocksdb::Status Append(const std::string &user_key, const std::string
&value, int *ret);
rocksdb::Status Get(const std::string &user_key, std::string *value);
rocksdb::Status GetSet(const std::string &user_key, const std::string
&new_value, std::string *old_value);
+ rocksdb::Status GetDel(const std::string &user_key, std::string *value);
rocksdb::Status Set(const std::string &user_key, const std::string &value);
rocksdb::Status SetEX(const std::string &user_key, const std::string &value,
int ttl);
rocksdb::Status SetNX(const std::string &user_key, const std::string &value,
int ttl, int *ret);
diff --git a/tests/cppunit/t_string_test.cc b/tests/cppunit/t_string_test.cc
index c612bfa..5d01f0b 100644
--- a/tests/cppunit/t_string_test.cc
+++ b/tests/cppunit/t_string_test.cc
@@ -157,6 +157,20 @@ TEST_F(RedisStringTest, GetSet) {
}
string->Del(key_);
}
+TEST_F(RedisStringTest, GetDel) {
+ for (size_t i = 0; i < pairs_.size(); i++) {
+ string->Set(pairs_[i].key.ToString(), pairs_[i].value.ToString());
+ }
+ for (size_t i = 0; i < pairs_.size(); i++) {
+ std::string got_value;
+ string->GetDel(pairs_[i].key.ToString(), &got_value);
+ EXPECT_EQ(pairs_[i].value, got_value);
+
+ std::string second_got_value;
+ auto s = string->GetDel(pairs_[i].key.ToString(), &second_got_value);
+ EXPECT_TRUE(!s.ok() && s.IsNotFound());
+ }
+}
TEST_F(RedisStringTest, MSetXX) {
int ret;
diff --git a/tests/tcl/tests/unit/command.tcl b/tests/tcl/tests/unit/command.tcl
index d6aba67..70f20e0 100644
--- a/tests/tcl/tests/unit/command.tcl
+++ b/tests/tcl/tests/unit/command.tcl
@@ -16,9 +16,9 @@
# under the License.
start_server {tags {"command"}} {
- test {kvrocks has 170 commands currently} {
+ test {kvrocks has 171 commands currently} {
r command count
- } {170}
+ } {171}
test {acquire GET command info by COMMAND INFO} {
set e [lindex [r command info get] 0]
diff --git a/tests/tcl/tests/unit/type/string.tcl
b/tests/tcl/tests/unit/type/string.tcl
index b1ab480..7db12af 100644
--- a/tests/tcl/tests/unit/type/string.tcl
+++ b/tests/tcl/tests/unit/type/string.tcl
@@ -180,12 +180,12 @@ start_server {tags {"string"}} {
# set ex
# } {*wrong number of arguments*}
- # test "GETDEL command" {
- # r del foo
- # r set foo bar
- # assert_equal bar [r getdel foo ]
- # assert_equal {} [r getdel foo ]
- # }
+ test "GETDEL command" {
+ r del foo
+ r set foo bar
+ assert_equal bar [r getdel foo ]
+ assert_equal {} [r getdel foo ]
+ }
# test {GETDEL propagate as DEL command to replica} {
# set repl [attach_to_replication_stream]