Feat:Add "copy" command

Add "copy" command,also fixes the out of range error of select when the number is negative.

Move execCopy to "keys.go" ,
Add test in "keys_test.go",
Add "copy.go" and "copy_test.go" file.
This commit is contained in:
Eriri
2022-06-23 15:20:07 +08:00
committed by finley
parent 7a9cbb7c11
commit f327000d3a
9 changed files with 395 additions and 3 deletions

View File

@@ -11,6 +11,7 @@ import (
"github.com/hdt3213/godis/lib/wildcard"
"github.com/hdt3213/godis/redis/protocol"
"strconv"
"strings"
"time"
)
@@ -308,6 +309,68 @@ func undoExpire(db *DB, args [][]byte) []CmdLine {
}
}
// execCopy usage: COPY source destination [DB destination-db] [REPLACE]
// This command copies the value stored at the source key to the destination key.
func execCopy(mdb *MultiDB, conn redis.Connection, args [][]byte) redis.Reply {
dbIndex := conn.GetDBIndex()
db := mdb.dbSet[dbIndex] // Current DB
replaceFlag := false
srcKey := string(args[0])
destKey := string(args[1])
// Parse options
if len(args) > 2 {
for i := 2; i < len(args); i++ {
arg := strings.ToLower(string(args[i]))
if arg == "db" {
if i+1 >= len(args) {
return &protocol.SyntaxErrReply{}
}
idx, err := strconv.Atoi(string(args[i+1]))
if err != nil {
return &protocol.SyntaxErrReply{}
}
if idx >= len(mdb.dbSet) || idx < 0 {
return protocol.MakeErrReply("ERR DB index is out of range")
}
dbIndex = idx
i++
} else if arg == "replace" {
replaceFlag = true
} else {
return &protocol.SyntaxErrReply{}
}
}
}
if srcKey == destKey && dbIndex == conn.GetDBIndex() {
return protocol.MakeErrReply("ERR source and destination objects are the same")
}
// source key does not exist
src, exists := db.GetEntity(srcKey)
if !exists {
return protocol.MakeIntReply(0)
}
destDB := mdb.dbSet[dbIndex]
if _, exists = destDB.GetEntity(destKey); exists != false {
// If destKey exists and there is no "replace" option
if replaceFlag == false {
return protocol.MakeIntReply(0)
}
}
destDB.PutEntity(destKey, src)
raw, exists := db.ttlMap.Get(srcKey)
if exists {
expire := raw.(time.Time)
destDB.Expire(destKey, expire)
}
mdb.aofHandler.AddAof(conn.GetDBIndex(), utils.ToCmdLine3("copy", args...))
return protocol.MakeIntReply(1)
}
func init() {
RegisterCommand("Del", execDel, writeAllKeys, undoDel, -2)
RegisterCommand("Expire", execExpire, writeFirstKey, undoExpire, 3)