From 7270aca0e874b79616ff7140ad3190b0e19b7dc5 Mon Sep 17 00:00:00 2001 From: Saubhik Kumar Date: Wed, 4 Dec 2024 21:24:14 +0530 Subject: [PATCH] add tests, comply with redis output --- integration_tests/commands/resp/json_test.go | 4 +-- .../commands/websocket/json_test.go | 4 +-- internal/eval/commands.go | 3 +- internal/eval/store_eval.go | 32 +++++++++++-------- internal/server/cmd_meta.go | 5 +++ 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/integration_tests/commands/resp/json_test.go b/integration_tests/commands/resp/json_test.go index 6e9331bb1..216918ac2 100644 --- a/integration_tests/commands/resp/json_test.go +++ b/integration_tests/commands/resp/json_test.go @@ -1684,13 +1684,13 @@ func TestJSONARRINDEX(t *testing.T) { { name: "should return error if key is not present", commands: []string{"json.set key $ " + normalArray, "json.arrindex nonExistentKey $ 3"}, - expected: []interface{}{"OK", "ERR object with key does not exist"}, + expected: []interface{}{"OK", "ERR could not perform this operation on a key that doesn't exist"}, assertType: []string{"equal", "equal"}, }, { name: "should return error if json path is invalid", commands: []string{"json.set key $ " + normalArray, "json.arrindex key $invalid_path 3"}, - expected: []interface{}{"OK", "ERR invalid JSONPath"}, + expected: []interface{}{"OK", "ERR Path '$invalid_path' does not exist"}, assertType: []string{"equal", "equal"}, }, { diff --git a/integration_tests/commands/websocket/json_test.go b/integration_tests/commands/websocket/json_test.go index ac349f650..007732dcf 100644 --- a/integration_tests/commands/websocket/json_test.go +++ b/integration_tests/commands/websocket/json_test.go @@ -1240,14 +1240,14 @@ func TestJSONARRINDEX(t *testing.T) { { name: "should return error if key is not present", commands: []string{"json.set key $ " + normalArray, "json.arrindex nonExistentKey $ 3"}, - expected: []interface{}{"OK", "ERR object with key does not exist"}, + expected: []interface{}{"OK", "ERR could not perform this operation on a key that doesn't exist"}, assertType: []string{"equal", "equal"}, cleanUp: []string{"DEL key"}, }, { name: "should return error if json path is invalid", commands: []string{"json.set key $ " + normalArray, "json.arrindex key $invalid_path 3"}, - expected: []interface{}{"OK", "ERR invalid JSONPath"}, + expected: []interface{}{"OK", "ERR Path '$invalid_path' does not exist"}, assertType: []string{"equal", "equal"}, cleanUp: []string{"DEL key"}, }, diff --git a/internal/eval/commands.go b/internal/eval/commands.go index 3d10986e7..d9d100ca2 100644 --- a/internal/eval/commands.go +++ b/internal/eval/commands.go @@ -673,9 +673,10 @@ var ( Name: "JSON.ARRINDEX", Info: `JSON.ARRINDEX key path value [start [stop]] Search for the first occurrence of a JSON value in an array`, - Eval: evalJSONARRINDEX, + NewEval: evalJSONARRINDEX, Arity: -3, KeySpecs: KeySpecs{BeginIndex: 1}, + IsMigrated: true, } // Internal command used to spawn request across all shards (works internally with the KEYS command) diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 49d8dbd2c..5d785322c 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -6774,9 +6774,9 @@ func evalCommandDocs(args []string) *EvalResponse { return makeEvalResult(result) } -func evalJSONARRINDEX(args []string, store *dstore.Store) []byte { +func evalJSONARRINDEX(args []string, store *dstore.Store) *EvalResponse { if len(args) < 3 || len(args) > 5 { - return diceerrors.NewErrArity("JSONARRINDEX") + return makeEvalError(diceerrors.ErrWrongArgumentCount("JSON.ARRINDEX")) } key := args[0] @@ -6795,7 +6795,7 @@ func evalJSONARRINDEX(args []string, store *dstore.Store) []byte { value, err = strconv.ParseFloat(args[2], 64) if err != nil { - return diceerrors.NewErrWithFormattedMessage("Couldn't parse as integer") + return makeEvalError(diceerrors.ErrGeneral("Couldn't parse as integer")) } } @@ -6804,7 +6804,7 @@ func evalJSONARRINDEX(args []string, store *dstore.Store) []byte { var err error start, err = strconv.Atoi(args[3]) if err != nil { - return diceerrors.NewErrWithMessage("Couldn't parse as integer") + return makeEvalError(diceerrors.ErrGeneral("Couldn't parse as integer")) } } @@ -6813,27 +6813,32 @@ func evalJSONARRINDEX(args []string, store *dstore.Store) []byte { var err error stop, err = strconv.Atoi(args[4]) if err != nil { - return diceerrors.NewErrWithMessage("Couldn't parse as integer") + return makeEvalError(diceerrors.ErrGeneral("Couldn't parse as integer")) } } + // Check if the path specified is valid + expr, err2 := jp.ParseString(path) + if err2 != nil { + return makeEvalError(diceerrors.ErrJSONPathNotFound(path)) + } + obj := store.Get(key) if obj == nil { - return diceerrors.NewErrWithMessage("object with key does not exist") + return makeEvalError(diceerrors.ErrKeyDoesNotExist) + } + + if err2 := object.AssertType(obj.Type, object.ObjTypeJSON); err2 != nil { + return makeEvalError(diceerrors.ErrGeneral("Existing key has wrong Dice type")) } jsonData := obj.Value // Check if the value stored is JSON type _, err = sonic.Marshal(jsonData) - if err != nil { - return diceerrors.NewErrWithMessage("existing key has wrong Dice type") - } - // Check if the path specified is valid - expr, err := jp.ParseString(path) if err != nil { - return diceerrors.NewErrWithMessage("invalid JSONPath") + return makeEvalError(diceerrors.ErrGeneral("Existing key has wrong Dice type")) } results := expr.Get(jsonData) @@ -6870,7 +6875,7 @@ func evalJSONARRINDEX(args []string, store *dstore.Store) []byte { } } - return clientio.Encode(arrIndexList, false) + return makeEvalResult(arrIndexList) } // adjustIndices adjusts the start and stop indices for array traversal. @@ -6883,7 +6888,6 @@ func adjustIndices(start, stop, length int) (adjustedStart, adjustedStop int) { start += length } - // 0 or -1 means the last element is included. if stop <= 0 { stop += length } diff --git a/internal/server/cmd_meta.go b/internal/server/cmd_meta.go index fc9927d4a..ea4fa30f7 100644 --- a/internal/server/cmd_meta.go +++ b/internal/server/cmd_meta.go @@ -506,6 +506,10 @@ var ( Cmd: "COMMAND|GETKEYSANDFLAGS", Type: SingleShard, } + jsonarrindexCmdMeta = CmdMeta{ + Cmd: "JSON.ARRINDEX", + Type: SingleShard, + } // Metadata for multishard commands would go here. // These commands require both breakup and gather logic. @@ -649,4 +653,5 @@ func init() { CmdMetaMap["COMMAND|DOCS"] = CmdCommandDocs CmdMetaMap["COMMAND|GETKEYS"] = CmdCommandGetKeys CmdMetaMap["COMMAND|GETKEYSANDFLAGS"] = CmdCommandGetKeysFlags + CmdMetaMap["JSON.ARRINDEX"] = jsonarrindexCmdMeta }