From 38ca643d05e46c695cab964761ffeb1e7f4f687f Mon Sep 17 00:00:00 2001 From: Sahil Date: Tue, 25 Jun 2024 18:23:54 +0530 Subject: [PATCH] feat: added RENAME command --- echovault/api_generic.go | 22 ++++++++++++ internal/modules/generic/commands.go | 48 ++++++++++++++++++++++++--- internal/modules/generic/key_funcs.go | 9 +++++ 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/echovault/api_generic.go b/echovault/api_generic.go index 2116d1b6..dac2754b 100644 --- a/echovault/api_generic.go +++ b/echovault/api_generic.go @@ -507,3 +507,25 @@ func (server *EchoVault) DecrBy(key string, value string) (int, error) { // Parse the integer response return internal.ParseIntegerResponse(b) } + +// Rename renames the key from oldKey to newKey. +// If the oldKey does not exist, an error is returned. +// +// Parameters: +// +// `oldKey` - string - The key to be renamed. +// +// `newKey` - string - The new name for the key. +// +// Returns: A string indicating the success of the operation. +func (server *EchoVault) Rename(oldKey string, newKey string) (string, error) { + // Construct the command + cmd := []string{"RENAME", oldKey, newKey} + // Execute the command + b, err := server.handleCommand(server.context, internal.EncodeCommand(cmd), nil, false, true) + if err != nil { + return "", err + } + // Parse the simple string response + return internal.ParseStringResponse(b) +} diff --git a/internal/modules/generic/commands.go b/internal/modules/generic/commands.go index 5bb5bd17..e8e3c368 100644 --- a/internal/modules/generic/commands.go +++ b/internal/modules/generic/commands.go @@ -581,6 +581,35 @@ func handleDecrBy(params internal.HandlerFuncParams) ([]byte, error) { return []byte(fmt.Sprintf(":%d\r\n", newValue)), nil } +func handleRename(params internal.HandlerFuncParams) ([]byte, error) { + if len(params.Command) != 3 { + return nil, errors.New("wrong number of arguments for RENAME") + } + + oldKey := params.Command[1] + newKey := params.Command[2] + + // Get the current value for the old key + values := params.GetValues(params.Context, []string{oldKey}) + oldValue, ok := values[oldKey] + + if !ok || oldValue == nil { + return nil, errors.New("no such key") + } + + // Set the new key with the old value + if err := params.SetValues(params.Context, map[string]interface{}{newKey: oldValue}); err != nil { + return nil, err + } + + // Delete the old key + if err := params.DeleteKey(oldKey); err != nil { + return nil, err + } + + return []byte("+OK\r\n"), nil +} + func Commands() []internal.Command { return []internal.Command{ { @@ -778,8 +807,8 @@ This operation is limited to 64 bit signed integers.`, Command: "incrby", Module: constants.GenericModule, Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory}, - Description: `(INCRBY key increment) -Increments the number stored at key by increment. If the key does not exist, it is set to 0 before performing the operation. + Description: `(INCRBY key increment) +Increments the number stored at key by increment. If the key does not exist, it is set to 0 before performing the operation. An error is returned if the key contains a value of the wrong type or contains a string that can not be represented as integer.`, Sync: true, KeyExtractionFunc: incrByKeyFunc, @@ -789,13 +818,22 @@ An error is returned if the key contains a value of the wrong type or contains a Command: "decrby", Module: constants.GenericModule, Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory}, - Description: `(DECRBY key decrement) -The DECRBY command reduces the value stored at the specified key by the specified decrement. -If the key does not exist, it is initialized with a value of 0 before performing the operation. + Description: `(DECRBY key decrement) +The DECRBY command reduces the value stored at the specified key by the specified decrement. +If the key does not exist, it is initialized with a value of 0 before performing the operation. If the key's value is not of the correct type or cannot be represented as an integer, an error is returned.`, Sync: true, KeyExtractionFunc: decrByKeyFunc, HandlerFunc: handleDecrBy, }, + { + Command: "rename", + Module: constants.GenericModule, + Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory}, + Description: `(RENAME key newkey) Renames key to newkey. If newkey already exists, it is overwritten. If key does not exist, an error is returned.`, + Sync: true, + KeyExtractionFunc: renameKeyFunc, + HandlerFunc: handleRename, + }, } } diff --git a/internal/modules/generic/key_funcs.go b/internal/modules/generic/key_funcs.go index 9c5de68f..150d0ea6 100644 --- a/internal/modules/generic/key_funcs.go +++ b/internal/modules/generic/key_funcs.go @@ -172,3 +172,12 @@ func decrByKeyFunc(cmd []string) (internal.KeyExtractionFuncResult, error) { WriteKeys: []string{cmd[1]}, }, nil } + +func renameKeyFunc(cmd []string) (internal.KeyExtractionFuncResult, error) { + if len(cmd) != 3 { + return internal.KeyExtractionFuncResult{}, errors.New(constants.WrongArgsResponse) + } + return internal.KeyExtractionFuncResult{ + WriteKeys: cmd[1:3], + }, nil +}