From d1c7b8c6cec16e9227c5db80adb001f352e90ff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Szara=C5=84ski?= <67064139+wszaranski@users.noreply.github.com> Date: Thu, 10 Jun 2021 17:20:29 +0200 Subject: [PATCH] Add GETDEL command Redis 6.2.0 added GETDEL command. See: https://redis.io/commands/getdel --- README.md | 1 + cmd_string.go | 36 ++++++++++++++++++++++++++++++++++++ cmd_string_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/README.md b/README.md index ba959bd4..5b498c4a 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Implemented commands: - GETBIT - GETRANGE - GETSET + - GETDEL - INCR - INCRBY - INCRBYFLOAT diff --git a/cmd_string.go b/cmd_string.go index 09d4577a..f21be84d 100644 --- a/cmd_string.go +++ b/cmd_string.go @@ -23,6 +23,7 @@ func commandsString(m *Miniredis) { m.srv.Register("GET", m.cmdGet) m.srv.Register("GETRANGE", m.cmdGetrange) m.srv.Register("GETSET", m.cmdGetset) + m.srv.Register("GETDEL", m.cmdGetdel) m.srv.Register("INCRBYFLOAT", m.cmdIncrbyfloat) m.srv.Register("INCRBY", m.cmdIncrby) m.srv.Register("INCR", m.cmdIncr) @@ -394,6 +395,41 @@ func (m *Miniredis) cmdGetset(c *server.Peer, cmd string, args []string) { }) } +// GETDEL +func (m *Miniredis) cmdGetdel(c *server.Peer, cmd string, args []string) { + if len(args) != 1 { + setDirty(c) + c.WriteError(errWrongNumber(cmd)) + return + } + if !m.handleAuth(c) { + return + } + if m.checkPubsub(c, cmd) { + return + } + + withTx(m, c, func(c *server.Peer, ctx *connCtx) { + db := m.db(ctx.selectedDB) + + key := args[0] + + if !db.exists(key) { + c.WriteNull() + return + } + + if db.t(key) != "string" { + c.WriteError(msgWrongType) + return + } + + v := db.stringGet(key) + db.del(key, true) + c.WriteBulk(v) + }) +} + // MGET func (m *Miniredis) cmdMget(c *server.Peer, cmd string, args []string) { if len(args) < 1 { diff --git a/cmd_string_test.go b/cmd_string_test.go index ee43873e..28ee523e 100644 --- a/cmd_string_test.go +++ b/cmd_string_test.go @@ -787,6 +787,51 @@ func TestGetSet(t *testing.T) { } } +func TestGetdel(t *testing.T) { + s, err := Run() + ok(t, err) + defer s.Close() + c, err := proto.Dial(s.Addr()) + ok(t, err) + defer c.Close() + + // Missing key + { + mustNil(t, c, "GETDEL", "foo") + } + + // Existing key + { + s.Set("foo", "bar") + mustDo(t, c, + "GETDEL", "foo", + proto.String("bar"), + ) + must0(t, c, "EXISTS", "foo") + } + + // Wrong type of existing key + { + s.HSet("wrong", "foo", "bar") + mustDo(t, c, + "GETDEL", "wrong", + proto.Error(msgWrongType), + ) + } + + // Wrong usage + { + mustDo(t, c, + "GETDEL", + proto.Error(errWrongNumber("getdel")), + ) + mustDo(t, c, + "GETDEL", "foo", "bar", + proto.Error(errWrongNumber("getdel")), + ) + } +} + func TestStrlen(t *testing.T) { s, err := Run() ok(t, err)