From 085ccc322b515bad0cc48adab19474631e0bfab4 Mon Sep 17 00:00:00 2001 From: helios2003 Date: Mon, 25 Nov 2024 19:24:40 +0530 Subject: [PATCH 01/13] add basic support for geopos --- docs/src/content/docs/commands/GEOPOS.md | 58 +++++++++++++++++++++ integration_tests/commands/http/geo_test.go | 45 ++++++++++++++++ integration_tests/commands/resp/geo_test.go | 34 +----------- internal/eval/commands.go | 9 ++++ internal/eval/store_eval.go | 54 ++++++++++++++++++- internal/server/cmd_meta.go | 5 ++ internal/worker/cmd_meta.go | 4 ++ 7 files changed, 175 insertions(+), 34 deletions(-) create mode 100644 docs/src/content/docs/commands/GEOPOS.md diff --git a/docs/src/content/docs/commands/GEOPOS.md b/docs/src/content/docs/commands/GEOPOS.md new file mode 100644 index 000000000..2d2d16ae7 --- /dev/null +++ b/docs/src/content/docs/commands/GEOPOS.md @@ -0,0 +1,58 @@ +--- +title: GEOPOS +description: The `GEOPOS` command in DiceDB is used to return the longitude, latitude to a specified key, as stored in the sorted set. +--- + +The `GEOPOS` command in DiceDB is used to return the longitude, latitude to a specified key which is stored in a sorted set. When elements are added via `GEOADD` then they are stored in 52 bit geohash hence the values returned by `GEOPOS` might have small margins of error. + +## Syntax + +```bash +GEOPOS key [member [member ...]] +``` +## Parameters +| Parameter | Description | Type | Required | +| --------- | --------------------------------------------------------------------------------- | ------ | -------- | +| key | The name of the sorted set key whose member's coordinates are to be returned | string | Yes | +| member | A unique identifier for the location. | string | Yes | +## Return Values +| Condition | Return Value | +| ------------------------------------------------------------ | ----------------------------------------------------------- | +| Coordinates exist for the specified member(s) | Returns an ordered list of coordinates (longitude, latitude) for each specified member | +| Coordinates do not exist for the specified member(s) | Returns `(nil)` for each member without coordinates +| Incorrect Argument Count |`ERR wrong number of arguments for 'geopos' command` | +| Key does not exist in the sorted set |`Error: nil` | +## Behaviour +When the GEOPOS command is issued, DiceDB performs the following steps: +1. It checks if argument count is valid or not. If not an error is thrown. +2. It checks the validity of the key. +3. If the key is invalid then an error is returned. +4. Else it checks the members provided after the key. +5. For each member it checks the coordinates of the member. +6. If the coordinates exist then it is returned in an ordered list of latitude, longitude for the particular member. +7. If the coordinates do not exist then a ``(nil)`` is returned for that member. + +## Errors +1. `Wrong number of arguments for 'GEOPOS' command` + - Error Message: (error) ERR wrong number of arguments for 'geoadd' command. + - Occurs when the command is executed with an incorrect number of arguments. +2. `Wrong key for 'GEOPOS' command` + - Error Message: Error: nil + - Occurs when the command is executed with a key that does not exist in the sorted set. + +## Example Usage + +Here are a few examples demonstrating the usage of the GEOPOS command: +### Example: Fetching the latitude, longitude of an existing member of the set +```bash +127.0.0.1:7379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" +2 +127.0.0.1:7379> GEOPOS Sicily "Palermo" +1) 1) 13.361387 +2) 38.115556 +``` +### Example: Fetching the latitude, longitude of a member not in the set +```bash +127.0.0.1:7379> GEOPOS Sicily "Agrigento" +1) (nil) +``` \ No newline at end of file diff --git a/integration_tests/commands/http/geo_test.go b/integration_tests/commands/http/geo_test.go index a8e5c6e93..a0524c32f 100644 --- a/integration_tests/commands/http/geo_test.go +++ b/integration_tests/commands/http/geo_test.go @@ -84,3 +84,48 @@ func TestGeoDist(t *testing.T) { }) } } + +func TestGeoPos(t *testing.T) { + exec := NewHTTPCommandExecutor() + + testCases := []struct { + name string + commands []HTTPCommand + expected []interface{} + }{ + { + name: "GEOPOS for existing points", + commands: []HTTPCommand{ + {Command: "GEOADD", Body: map[string]interface{}{"key": "index", "values": []interface{}{"13.361389", "38.115556", "Palermo"}}}, + {Command: "GEOPOS", Body: map[string]interface{}{"key": "index", "values": []interface{}{"Palermo"}}}, + }, + expected: []interface{}{ + float64(1), + []interface{}{float64(13.361387), float64(38.115556)}, + }, + }, + { + name: "GEOPOS for non-existing points", + commands: []HTTPCommand{ + {Command: "GEOPOS", Body: map[string]interface{}{"key": "index", "values": []interface{}{"NonExisting"}}}, + }, + expected: []interface{}{[]interface{}{nil}}, + }, + { + name: "GEOPOS for non-existing index", + commands: []HTTPCommand{ + {Command: "GEOPOS", Body: map[string]interface{}{"key": "NonExisting", "values": []interface{}{"Palermo"}}}, + }, + expected: []interface{}{nil}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + for i, cmd := range tc.commands { + result, _ := exec.FireCommand(cmd) + assert.Equal(t, tc.expected[i], result, "Value mismatch for cmd %v", cmd) + } + }) + } +} diff --git a/integration_tests/commands/resp/geo_test.go b/integration_tests/commands/resp/geo_test.go index 57bd2656a..fed288dc1 100644 --- a/integration_tests/commands/resp/geo_test.go +++ b/integration_tests/commands/resp/geo_test.go @@ -51,36 +51,4 @@ func TestGeoAdd(t *testing.T) { } }) } -} - -func TestGeoDist(t *testing.T) { - conn := getLocalConnection() - defer conn.Close() - - testCases := []struct { - name string - cmds []string - expect []interface{} - delays []time.Duration - }{ - { - name: "GEODIST b/w existing points", - cmds: []string{ - "GEOADD points 13.361389 38.115556 Palermo", - "GEOADD points 15.087269 37.502669 Catania", - "GEODIST points Palermo Catania", - "GEODIST points Palermo Catania km", - }, - expect: []interface{}{int64(1), int64(1), "166274.144", "166.2741"}, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - for i, cmd := range tc.cmds { - result := FireCommand(conn, cmd) - assert.Equal(t, tc.expect[i], result, "Value mismatch for cmd %s", cmd) - } - }) - } -} +} \ No newline at end of file diff --git a/internal/eval/commands.go b/internal/eval/commands.go index 787bca20c..b3965a6dc 100644 --- a/internal/eval/commands.go +++ b/internal/eval/commands.go @@ -1301,6 +1301,14 @@ var ( NewEval: evalGEODIST, KeySpecs: KeySpecs{BeginIndex: 1}, } + geoPosCmdMeta = DiceCmdMeta{ + Name: "GEOPOS", + Info: `Returns the latitude and longitude of the members identified by the particular index.`, + Arity: -3, + NewEval: evalGEOPOS, + IsMigrated: true, + KeySpecs: KeySpecs{BeginIndex: 1}, + } jsonstrappendCmdMeta = DiceCmdMeta{ Name: "JSON.STRAPPEND", Info: `JSON.STRAPPEND key [path] value @@ -1444,6 +1452,7 @@ func init() { DiceCmds["FLUSHDB"] = flushdbCmdMeta DiceCmds["GEOADD"] = geoAddCmdMeta DiceCmds["GEODIST"] = geoDistCmdMeta + DiceCmds["GEOPOS"] = geoPosCmdMeta DiceCmds["GET"] = getCmdMeta DiceCmds["GETBIT"] = getBitCmdMeta DiceCmds["GETDEL"] = getDelCmdMeta diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 7c6d9d2dd..0431fec29 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -12,7 +12,7 @@ import ( "strings" "unicode" "unsafe" - + "github.com/axiomhq/hyperloglog" "github.com/bytedance/sonic" "github.com/dicedb/dice/internal/clientio" @@ -6333,6 +6333,58 @@ func evalGEODIST(args []string, store *dstore.Store) *EvalResponse { } } +func evalGEOPOS(args []string, store *dstore.Store) *EvalResponse { + if len(args) < 2 { + return &EvalResponse{ + Result: nil, + Error: diceerrors.ErrWrongArgumentCount("GEOPOS"), + } + } + + key := args[0] + obj := store.Get(key) + + if obj == nil { + return &EvalResponse{ + Result: clientio.NIL, + Error: nil, + } + } + + ss, err := sortedset.FromObject(obj) + + if err != nil { + return &EvalResponse{ + Result: nil, + Error: diceerrors.ErrWrongTypeOperation, + } + } + + results := make([]interface{}, 0) + + for index := 1; index < len(args); index++ { + member := args[index] + hash, ok := ss.Get(member) + + if !ok { + results = append(results, nil) + continue + } + + lat, lon := geo.DecodeHash(hash) + + latFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lat), 64) + lonFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lon), 64) + + results = append(results, lonFloat, latFloat) + } + + return &EvalResponse{ + Result: results, + Error: nil, + } +} + func evalTouch(args []string, store *dstore.Store) *EvalResponse { if len(args) != 1 { return makeEvalError(diceerrors.ErrWrongArgumentCount("TOUCH")) diff --git a/internal/server/cmd_meta.go b/internal/server/cmd_meta.go index 8212d0495..dc2841c5e 100644 --- a/internal/server/cmd_meta.go +++ b/internal/server/cmd_meta.go @@ -458,6 +458,10 @@ var ( Cmd: "GEODIST", CmdType: SingleShard, } + geoposCmdMeta = CmdsMeta{ + Cmd: "GEOPOS", + CmdType: SingleShard, + } clientCmdMeta = CmdsMeta{ Cmd: "CLIENT", CmdType: SingleShard, @@ -637,6 +641,7 @@ func init() { WorkerCmdsMeta["RESTORE"] = restoreCmdMeta WorkerCmdsMeta["GEOADD"] = geoaddCmdMeta WorkerCmdsMeta["GEODIST"] = geodistCmdMeta + WorkerCmdsMeta["GEOPOS"] = geoposCmdMeta WorkerCmdsMeta["CLIENT"] = clientCmdMeta WorkerCmdsMeta["LATENCY"] = latencyCmdMeta WorkerCmdsMeta["FLUSHDB"] = flushDBCmdMeta diff --git a/internal/worker/cmd_meta.go b/internal/worker/cmd_meta.go index 646b222f2..8fd4aa642 100644 --- a/internal/worker/cmd_meta.go +++ b/internal/worker/cmd_meta.go @@ -112,6 +112,7 @@ const ( CmdRestore = "RESTORE" CmdGeoAdd = "GEOADD" CmdGeoDist = "GEODIST" + CmdGeoPos = "GEOPOS" CmdClient = "CLIENT" CmdLatency = "LATENCY" CmdDel = "DEL" @@ -501,6 +502,9 @@ var CommandsMeta = map[string]CmdMeta{ CmdGeoDist: { CmdType: SingleShard, }, + CmdGeoPos: { + CmdType: SingleShard, + }, CmdClient: { CmdType: SingleShard, }, From 9e90ed2919d697747dc494de5464bab0ef342ffb Mon Sep 17 00:00:00 2001 From: helios2003 Date: Mon, 25 Nov 2024 19:31:51 +0530 Subject: [PATCH 02/13] add required tests back --- integration_tests/commands/resp/geo_test.go | 34 ++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/integration_tests/commands/resp/geo_test.go b/integration_tests/commands/resp/geo_test.go index fed288dc1..57bd2656a 100644 --- a/integration_tests/commands/resp/geo_test.go +++ b/integration_tests/commands/resp/geo_test.go @@ -51,4 +51,36 @@ func TestGeoAdd(t *testing.T) { } }) } -} \ No newline at end of file +} + +func TestGeoDist(t *testing.T) { + conn := getLocalConnection() + defer conn.Close() + + testCases := []struct { + name string + cmds []string + expect []interface{} + delays []time.Duration + }{ + { + name: "GEODIST b/w existing points", + cmds: []string{ + "GEOADD points 13.361389 38.115556 Palermo", + "GEOADD points 15.087269 37.502669 Catania", + "GEODIST points Palermo Catania", + "GEODIST points Palermo Catania km", + }, + expect: []interface{}{int64(1), int64(1), "166274.144", "166.2741"}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + for i, cmd := range tc.cmds { + result := FireCommand(conn, cmd) + assert.Equal(t, tc.expect[i], result, "Value mismatch for cmd %s", cmd) + } + }) + } +} From 194519034861343dd3f4c1333f7f4afdac5cb6e1 Mon Sep 17 00:00:00 2001 From: helios2003 Date: Thu, 28 Nov 2024 18:37:23 +0530 Subject: [PATCH 03/13] complete adding integration tests --- integration_tests/commands/resp/geo_test.go | 49 +++++++++++++++++++ .../commands/websocket/geo_test.go | 49 +++++++++++++++++++ internal/eval/store_eval.go | 1 - 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/integration_tests/commands/resp/geo_test.go b/integration_tests/commands/resp/geo_test.go index 57bd2656a..97fa4d960 100644 --- a/integration_tests/commands/resp/geo_test.go +++ b/integration_tests/commands/resp/geo_test.go @@ -84,3 +84,52 @@ func TestGeoDist(t *testing.T) { }) } } + +func TestGeoPos(t *testing.T) { + conn := getLocalConnection() + defer conn.Close() + + testCases := []struct { + name string + cmds []string + expect []interface{} + delays []time.Duration + }{ + { + name: "GEOPOS b/w existing points", + cmds: []string{ + "GEOADD index 13.361389 38.115556 Palermo", + "GEOPOS index Palermo", + }, + expect: []interface{}{ + int64(1), + []interface{}{"13.361387", "38.115556"}, + }, + }, + { + name: "GEOPOS for non existing points", + cmds: []string{ + "GEOPOS index NonExisting", + }, + expect: []interface{}{ + []interface{}{"(nil)"}, + }, + }, + { + name: "GEOPOS for non existing index", + cmds: []string{ + "GEOPOS NonExisting Palermo", + }, + expect: []interface{}{"(nil)"}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + for i, cmd := range tc.cmds { + result := FireCommand(conn, cmd) + assert.Equal(t, tc.expect[i], result, "Value mismatch for cmd %s", cmd) + } + }) + } +} diff --git a/integration_tests/commands/websocket/geo_test.go b/integration_tests/commands/websocket/geo_test.go index e2c5d240b..b3c14ee61 100644 --- a/integration_tests/commands/websocket/geo_test.go +++ b/integration_tests/commands/websocket/geo_test.go @@ -85,3 +85,52 @@ func TestGeoDist(t *testing.T) { }) } } + +func TestGeoPos(t *testing.T) { + exec := NewWebsocketCommandExecutor() + conn := exec.ConnectToServer() + defer conn.Close() + + testCases := []struct { + name string + cmds []string + expect []interface{} + }{ + { + name: "GEOPOS b/w existing points", + cmds: []string{ + "GEOADD index 13.361389 38.115556 Palermo", + "GEOPOS index Palermo", + }, + expect: []interface{}{ + float64(1), + []interface{}{float64(13.361387), float64(38.115556)}, + }, + }, + { + name: "GEOPOS for non existing points", + cmds: []string{ + "GEOPOS index NonExisting", + }, + expect: []interface{}{[]interface{}{nil}}, + }, + { + name: "GEOPOS for non existing index", + cmds: []string{ + "GEOPOS NonExisting Palermo", + }, + expect: []interface{}{nil}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + for i, cmd := range tc.cmds { + result, err := exec.FireCommandAndReadResponse(conn, cmd) + assert.Nil(t, err) + assert.Equal(t, tc.expect[i], result, "Value mismatch for cmd %s", cmd) + } + }) + } +} + diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index be0b4f6cb..3929f6787 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -12,7 +12,6 @@ import ( "strings" "unicode" "unsafe" - "github.com/axiomhq/hyperloglog" "github.com/bytedance/sonic" "github.com/dicedb/dice/internal/clientio" From cd880f53aecb9aab66a07c5cd650e26ddde590ce Mon Sep 17 00:00:00 2001 From: helios2003 Date: Sat, 30 Nov 2024 22:26:39 +0530 Subject: [PATCH 04/13] add unit tests --- internal/eval/eval_test.go | 81 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/internal/eval/eval_test.go b/internal/eval/eval_test.go index fc6028e02..ba2bece59 100644 --- a/internal/eval/eval_test.go +++ b/internal/eval/eval_test.go @@ -132,6 +132,7 @@ func TestEval(t *testing.T) { testEvalBitFieldRO(t, store) testEvalGEOADD(t, store) testEvalGEODIST(t, store) + testEvalGEOPOS(t, store) testEvalSINTER(t, store) testEvalOBJECTENCODING(t, store) testEvalJSONSTRAPPEND(t, store) @@ -8333,6 +8334,86 @@ func testEvalGEODIST(t *testing.T, store *dstore.Store) { runMigratedEvalTests(t, tests, evalGEODIST, store) } +func testEvalGEOPOS(t *testing.T, store *dstore.Store) { + tests := map[string]evalTestCase{ + "GEOPOS for existing single point": { + setup: func() { + evalGEOADD([]string{"index", "13.361387", "38.115556", "Palermo"}, store) + }, + input: []string{"index", "Palermo"}, + migratedOutput: EvalResponse{ + Result: []interface{}{float64(13.361387), float64(38.115556)}, + Error: nil, + }, + }, + "GEOPOS for multiple existing points": { + setup: func() { + evalGEOADD([]string{"points", "13.361387", "38.115556", "Palermo"}, store) + evalGEOADD([]string{"points", "15.087265", "37.502668", "Catania"}, store) + }, + input: []string{"points", "Palermo", "Catania"}, + migratedOutput: EvalResponse{ + Result: []interface{}{ + []interface{}{float64(13.361387), float64(38.115556)}, + []interface{}{float64(15.087265), float64(37.502668)}, + }, + Error: nil, + }, + }, + "GEOPOS for a point that does not exist": { + setup: func() { + evalGEOADD([]string{"index", "13.361387", "38.115556", "Palermo"}, store) + }, + input: []string{"index", "NonExisting"}, + migratedOutput: EvalResponse{ + Result: []interface{}{nil}, + Error: nil, + }, + }, + "GEOPOS for multiple points, one existing and one non-existing": { + setup: func() { + evalGEOADD([]string{"index", "13.361387", "38.115556", "Palermo"}, store) + }, + input: []string{"index", "Palermo", "NonExisting"}, + migratedOutput: EvalResponse{ + Result: []interface{}{ + []interface{}{float64(13.361387), float64(38.115556)}, + nil, + }, + Error: nil, + }, + }, + "GEOPOS for empty index": { + setup: func() { + evalGEOADD([]string{"", "13.361387", "38.115556", "Palermo"}, store) + }, + input: []string{"", "Palermo"}, + migratedOutput: EvalResponse{ + Result: []interface{}{ + []interface{}{float64(13.361387), float64(38.115556)}, + }, + Error: nil, + }, + }, + "GEOPOS with no members in key": { + input: []string{"index", "Palermo"}, + migratedOutput: EvalResponse{ + Result: nil, + Error: nil, + }, + }, + "GEOPOS with invalid number of arguments": { + input: []string{"index"}, + migratedOutput: EvalResponse{ + Result: nil, + Error: diceerrors.ErrWrongArgumentCount("GEOPOS"), + }, + }, + } + + runMigratedEvalTests(t, tests, evalGEOPOS, store) +} + func testEvalSINTER(t *testing.T, store *dstore.Store) { tests := map[string]evalTestCase{ "intersection of two sets": { From e6bc8cf3a1eb17b12ccae0a26d006e6ed289aece Mon Sep 17 00:00:00 2001 From: helios2003 Date: Sat, 30 Nov 2024 22:48:27 +0530 Subject: [PATCH 05/13] revert imports --- internal/eval/store_eval.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 3929f6787..eb3fe6167 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -12,6 +12,7 @@ import ( "strings" "unicode" "unsafe" + "github.com/axiomhq/hyperloglog" "github.com/bytedance/sonic" "github.com/dicedb/dice/internal/clientio" From 78e5506d5604354bd862d41d0752822b1c9bb2a1 Mon Sep 17 00:00:00 2001 From: helios2003 Date: Sun, 1 Dec 2024 00:30:15 +0530 Subject: [PATCH 06/13] fix printing --- integration_tests/commands/http/geo_test.go | 2 +- integration_tests/commands/resp/geo_test.go | 2 +- integration_tests/commands/websocket/geo_test.go | 2 +- internal/eval/store_eval.go | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/integration_tests/commands/http/geo_test.go b/integration_tests/commands/http/geo_test.go index a0524c32f..f8626e085 100644 --- a/integration_tests/commands/http/geo_test.go +++ b/integration_tests/commands/http/geo_test.go @@ -101,7 +101,7 @@ func TestGeoPos(t *testing.T) { }, expected: []interface{}{ float64(1), - []interface{}{float64(13.361387), float64(38.115556)}, + []interface{}{[]interface{}{float64(13.361387), float64(38.115556)}}, }, }, { diff --git a/integration_tests/commands/resp/geo_test.go b/integration_tests/commands/resp/geo_test.go index 97fa4d960..73a11b6e4 100644 --- a/integration_tests/commands/resp/geo_test.go +++ b/integration_tests/commands/resp/geo_test.go @@ -103,7 +103,7 @@ func TestGeoPos(t *testing.T) { }, expect: []interface{}{ int64(1), - []interface{}{"13.361387", "38.115556"}, + []interface{}{[]interface {}{"13.361387", "38.115556"}}, }, }, { diff --git a/integration_tests/commands/websocket/geo_test.go b/integration_tests/commands/websocket/geo_test.go index b3c14ee61..77a92fd80 100644 --- a/integration_tests/commands/websocket/geo_test.go +++ b/integration_tests/commands/websocket/geo_test.go @@ -104,7 +104,7 @@ func TestGeoPos(t *testing.T) { }, expect: []interface{}{ float64(1), - []interface{}{float64(13.361387), float64(38.115556)}, + []interface{}{[]interface {}{float64(13.361387), float64(38.115556)}}, }, }, { diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index eb3fe6167..046d76309 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -6360,23 +6360,23 @@ func evalGEOPOS(args []string, store *dstore.Store) *EvalResponse { } } - results := make([]interface{}, 0) + results := make([]interface{}, len(args) - 1) for index := 1; index < len(args); index++ { member := args[index] hash, ok := ss.Get(member) if !ok { - results = append(results, nil) + results[index - 1] = (nil) continue } lat, lon := geo.DecodeHash(hash) - latFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lat), 64) lonFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lon), 64) + latFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lat), 64) - results = append(results, lonFloat, latFloat) + results[index - 1] = []interface{}{lonFloat, latFloat} } return &EvalResponse{ From 71de30c123d583e2af85da74f5bb615945010a2d Mon Sep 17 00:00:00 2001 From: helios2003 Date: Sun, 1 Dec 2024 22:14:22 +0530 Subject: [PATCH 07/13] revert to commit --- integration_tests/commands/http/geo_test.go | 2 +- integration_tests/commands/resp/geo_test.go | 2 +- integration_tests/commands/websocket/geo_test.go | 2 +- internal/eval/store_eval.go | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/integration_tests/commands/http/geo_test.go b/integration_tests/commands/http/geo_test.go index f8626e085..a0524c32f 100644 --- a/integration_tests/commands/http/geo_test.go +++ b/integration_tests/commands/http/geo_test.go @@ -101,7 +101,7 @@ func TestGeoPos(t *testing.T) { }, expected: []interface{}{ float64(1), - []interface{}{[]interface{}{float64(13.361387), float64(38.115556)}}, + []interface{}{float64(13.361387), float64(38.115556)}, }, }, { diff --git a/integration_tests/commands/resp/geo_test.go b/integration_tests/commands/resp/geo_test.go index 73a11b6e4..97fa4d960 100644 --- a/integration_tests/commands/resp/geo_test.go +++ b/integration_tests/commands/resp/geo_test.go @@ -103,7 +103,7 @@ func TestGeoPos(t *testing.T) { }, expect: []interface{}{ int64(1), - []interface{}{[]interface {}{"13.361387", "38.115556"}}, + []interface{}{"13.361387", "38.115556"}, }, }, { diff --git a/integration_tests/commands/websocket/geo_test.go b/integration_tests/commands/websocket/geo_test.go index 77a92fd80..b3c14ee61 100644 --- a/integration_tests/commands/websocket/geo_test.go +++ b/integration_tests/commands/websocket/geo_test.go @@ -104,7 +104,7 @@ func TestGeoPos(t *testing.T) { }, expect: []interface{}{ float64(1), - []interface{}{[]interface {}{float64(13.361387), float64(38.115556)}}, + []interface{}{float64(13.361387), float64(38.115556)}, }, }, { diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 046d76309..eb3fe6167 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -6360,23 +6360,23 @@ func evalGEOPOS(args []string, store *dstore.Store) *EvalResponse { } } - results := make([]interface{}, len(args) - 1) + results := make([]interface{}, 0) for index := 1; index < len(args); index++ { member := args[index] hash, ok := ss.Get(member) if !ok { - results[index - 1] = (nil) + results = append(results, nil) continue } lat, lon := geo.DecodeHash(hash) - lonFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lon), 64) latFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lat), 64) + lonFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lon), 64) - results[index - 1] = []interface{}{lonFloat, latFloat} + results = append(results, lonFloat, latFloat) } return &EvalResponse{ From 817a60506f64258c9d3e68ee46a11a82beff7a51 Mon Sep 17 00:00:00 2001 From: helios2003 Date: Sun, 1 Dec 2024 22:34:53 +0530 Subject: [PATCH 08/13] fix build and lint --- internal/eval/commands.go | 2 +- internal/eval/store_eval.go | 24 ++++++++++++------------ internal/server/cmd_meta.go | 7 ++++--- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/internal/eval/commands.go b/internal/eval/commands.go index b3965a6dc..0b920f03a 100644 --- a/internal/eval/commands.go +++ b/internal/eval/commands.go @@ -1307,7 +1307,7 @@ var ( Arity: -3, NewEval: evalGEOPOS, IsMigrated: true, - KeySpecs: KeySpecs{BeginIndex: 1}, + KeySpecs: KeySpecs{BeginIndex: 1}, } jsonstrappendCmdMeta = DiceCmdMeta{ Name: "JSON.STRAPPEND", diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index eb3fe6167..8690a6b3f 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -6347,7 +6347,7 @@ func evalGEOPOS(args []string, store *dstore.Store) *EvalResponse { if obj == nil { return &EvalResponse{ Result: clientio.NIL, - Error: nil, + Error: nil, } } @@ -6362,26 +6362,26 @@ func evalGEOPOS(args []string, store *dstore.Store) *EvalResponse { results := make([]interface{}, 0) - for index := 1; index < len(args); index++ { - member := args[index] - hash, ok := ss.Get(member) + for index := 1; index < len(args); index++ { + member := args[index] + hash, ok := ss.Get(member) - if !ok { - results = append(results, nil) - continue - } + if !ok { + results = append(results, nil) + continue + } - lat, lon := geo.DecodeHash(hash) + lat, lon := geo.DecodeHash(hash) latFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lat), 64) - lonFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lon), 64) + lonFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lon), 64) results = append(results, lonFloat, latFloat) - } + } return &EvalResponse{ Result: results, - Error: nil, + Error: nil, } } diff --git a/internal/server/cmd_meta.go b/internal/server/cmd_meta.go index 62c191121..c0c2a64cb 100644 --- a/internal/server/cmd_meta.go +++ b/internal/server/cmd_meta.go @@ -458,9 +458,9 @@ var ( Cmd: "GEODIST", Type: SingleShard, } - geoposCmdMeta = CmdsMeta{ - Cmd: "GEOPOS", - CmdType: SingleShard, + geoposCmdMeta = CmdMeta{ + Cmd: "GEOPOS", + Type: SingleShard, } clientCmdMeta = CmdMeta{ Cmd: "CLIENT", @@ -641,6 +641,7 @@ func init() { CmdMetaMap["RESTORE"] = restoreCmdMeta CmdMetaMap["GEOADD"] = geoaddCmdMeta CmdMetaMap["GEODIST"] = geodistCmdMeta + CmdMetaMap["GEOPOS"] = geoposCmdMeta CmdMetaMap["CLIENT"] = clientCmdMeta CmdMetaMap["LATENCY"] = latencyCmdMeta CmdMetaMap["FLUSHDB"] = flushDBCmdMeta From a47c4468f3e410d37e22781318a16d80a356aa93 Mon Sep 17 00:00:00 2001 From: helios2003 Date: Mon, 2 Dec 2024 09:46:17 +0530 Subject: [PATCH 09/13] fix unit tests --- internal/eval/eval_test.go | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/internal/eval/eval_test.go b/internal/eval/eval_test.go index ba2bece59..d861a7eba 100644 --- a/internal/eval/eval_test.go +++ b/internal/eval/eval_test.go @@ -8353,10 +8353,8 @@ func testEvalGEOPOS(t *testing.T, store *dstore.Store) { }, input: []string{"points", "Palermo", "Catania"}, migratedOutput: EvalResponse{ - Result: []interface{}{ - []interface{}{float64(13.361387), float64(38.115556)}, - []interface{}{float64(15.087265), float64(37.502668)}, - }, + Result: []interface{}{float64(13.361387), float64(38.115556), + float64(15.087265), float64(37.502668)}, Error: nil, }, }, @@ -8376,10 +8374,7 @@ func testEvalGEOPOS(t *testing.T, store *dstore.Store) { }, input: []string{"index", "Palermo", "NonExisting"}, migratedOutput: EvalResponse{ - Result: []interface{}{ - []interface{}{float64(13.361387), float64(38.115556)}, - nil, - }, + Result: []interface{}{float64(13.361387), float64(38.115556), interface{}(nil)}, Error: nil, }, }, @@ -8389,16 +8384,14 @@ func testEvalGEOPOS(t *testing.T, store *dstore.Store) { }, input: []string{"", "Palermo"}, migratedOutput: EvalResponse{ - Result: []interface{}{ - []interface{}{float64(13.361387), float64(38.115556)}, - }, + Result: []interface{}{float64(13.361387), float64(38.115556)}, Error: nil, }, }, "GEOPOS with no members in key": { input: []string{"index", "Palermo"}, migratedOutput: EvalResponse{ - Result: nil, + Result: clientio.NIL, Error: nil, }, }, From 37d537d01e62087236e23597c73bf16aec226a66 Mon Sep 17 00:00:00 2001 From: helios2003 Date: Mon, 2 Dec 2024 10:10:36 +0530 Subject: [PATCH 10/13] some fix --- integration_tests/commands/http/geo_test.go | 4 ++-- integration_tests/commands/resp/geo_test.go | 2 +- .../commands/websocket/geo_test.go | 2 +- internal/eval/eval_test.go | 17 ++++++++++++----- internal/eval/store_eval.go | 6 +++--- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/integration_tests/commands/http/geo_test.go b/integration_tests/commands/http/geo_test.go index a0524c32f..889c91588 100644 --- a/integration_tests/commands/http/geo_test.go +++ b/integration_tests/commands/http/geo_test.go @@ -101,10 +101,10 @@ func TestGeoPos(t *testing.T) { }, expected: []interface{}{ float64(1), - []interface{}{float64(13.361387), float64(38.115556)}, + []interface{}{[]interface{}{float64(13.361387), float64(38.115556)}}, }, }, - { + { name: "GEOPOS for non-existing points", commands: []HTTPCommand{ {Command: "GEOPOS", Body: map[string]interface{}{"key": "index", "values": []interface{}{"NonExisting"}}}, diff --git a/integration_tests/commands/resp/geo_test.go b/integration_tests/commands/resp/geo_test.go index 97fa4d960..bd0e9a67a 100644 --- a/integration_tests/commands/resp/geo_test.go +++ b/integration_tests/commands/resp/geo_test.go @@ -103,7 +103,7 @@ func TestGeoPos(t *testing.T) { }, expect: []interface{}{ int64(1), - []interface{}{"13.361387", "38.115556"}, + []interface{}{[]interface{}{"13.361387", "38.115556"}}, }, }, { diff --git a/integration_tests/commands/websocket/geo_test.go b/integration_tests/commands/websocket/geo_test.go index b3c14ee61..89e57011c 100644 --- a/integration_tests/commands/websocket/geo_test.go +++ b/integration_tests/commands/websocket/geo_test.go @@ -104,7 +104,7 @@ func TestGeoPos(t *testing.T) { }, expect: []interface{}{ float64(1), - []interface{}{float64(13.361387), float64(38.115556)}, + []interface{}{[]interface{}{float64(13.361387), float64(38.115556)}}, }, }, { diff --git a/internal/eval/eval_test.go b/internal/eval/eval_test.go index d861a7eba..12dfc6265 100644 --- a/internal/eval/eval_test.go +++ b/internal/eval/eval_test.go @@ -8342,7 +8342,7 @@ func testEvalGEOPOS(t *testing.T, store *dstore.Store) { }, input: []string{"index", "Palermo"}, migratedOutput: EvalResponse{ - Result: []interface{}{float64(13.361387), float64(38.115556)}, + Result: []interface{}{[]interface{}{float64(13.361387), float64(38.115556)}}, Error: nil, }, }, @@ -8353,8 +8353,10 @@ func testEvalGEOPOS(t *testing.T, store *dstore.Store) { }, input: []string{"points", "Palermo", "Catania"}, migratedOutput: EvalResponse{ - Result: []interface{}{float64(13.361387), float64(38.115556), - float64(15.087265), float64(37.502668)}, + Result: []interface{}{ + []interface{}{float64(13.361387), float64(38.115556)}, + []interface{}{float64(15.087265), float64(37.502668)}, + }, Error: nil, }, }, @@ -8374,7 +8376,10 @@ func testEvalGEOPOS(t *testing.T, store *dstore.Store) { }, input: []string{"index", "Palermo", "NonExisting"}, migratedOutput: EvalResponse{ - Result: []interface{}{float64(13.361387), float64(38.115556), interface{}(nil)}, + Result: []interface{}{ + []interface{}{float64(13.361387), float64(38.115556)}, + nil, + }, Error: nil, }, }, @@ -8384,7 +8389,9 @@ func testEvalGEOPOS(t *testing.T, store *dstore.Store) { }, input: []string{"", "Palermo"}, migratedOutput: EvalResponse{ - Result: []interface{}{float64(13.361387), float64(38.115556)}, + Result: []interface{}{ + []interface{}{float64(13.361387), float64(38.115556)}, + }, Error: nil, }, }, diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 8690a6b3f..426a6eb14 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -6360,14 +6360,14 @@ func evalGEOPOS(args []string, store *dstore.Store) *EvalResponse { } } - results := make([]interface{}, 0) + results := make([]interface{}, len(args) - 1) for index := 1; index < len(args); index++ { member := args[index] hash, ok := ss.Get(member) if !ok { - results = append(results, nil) + results[index - 1] = (nil) continue } @@ -6376,7 +6376,7 @@ func evalGEOPOS(args []string, store *dstore.Store) *EvalResponse { latFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lat), 64) lonFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lon), 64) - results = append(results, lonFloat, latFloat) + results[index - 1] = []interface{}{lonFloat, latFloat} } return &EvalResponse{ From 135b32b964ecfd87ff8faad047ed142667f1c61b Mon Sep 17 00:00:00 2001 From: helios2003 Date: Mon, 2 Dec 2024 10:20:33 +0530 Subject: [PATCH 11/13] fix --- internal/eval/store_eval.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 426a6eb14..32e55c391 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -6360,14 +6360,14 @@ func evalGEOPOS(args []string, store *dstore.Store) *EvalResponse { } } - results := make([]interface{}, len(args) - 1) + results := make([]interface{}, len(args)-1) for index := 1; index < len(args); index++ { member := args[index] hash, ok := ss.Get(member) if !ok { - results[index - 1] = (nil) + results[index-1] = (nil) continue } @@ -6376,7 +6376,7 @@ func evalGEOPOS(args []string, store *dstore.Store) *EvalResponse { latFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lat), 64) lonFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lon), 64) - results[index - 1] = []interface{}{lonFloat, latFloat} + results[index-1] = []interface{}{lonFloat, latFloat} } return &EvalResponse{ From 41086151dc55457735ea566f5a33f62556e89a78 Mon Sep 17 00:00:00 2001 From: pshubham Date: Mon, 9 Dec 2024 16:05:15 +0530 Subject: [PATCH 12/13] Remove unwanted cmd_meta --- internal/server/cmd_meta.go | 657 ------------------------------------ 1 file changed, 657 deletions(-) delete mode 100644 internal/server/cmd_meta.go diff --git a/internal/server/cmd_meta.go b/internal/server/cmd_meta.go deleted file mode 100644 index c0c2a64cb..000000000 --- a/internal/server/cmd_meta.go +++ /dev/null @@ -1,657 +0,0 @@ -package server - -import ( - "github.com/dicedb/dice/internal/cmd" - "github.com/dicedb/dice/internal/comm" - "github.com/dicedb/dice/internal/eval" - "github.com/dicedb/dice/internal/shard" -) - -// Type defines the type of DiceDB command based on how it interacts with shards. -// It uses an integer value to represent different command types. -type Type int - -// Enum values for Type using iota for auto-increment. -// Global commands don't interact with shards, SingleShard commands interact with one shard, -// MultiShard commands interact with multiple shards, and Custom commands require a direct client connection. -const ( - Global Type = iota // Global commands don't need to interact with shards. - SingleShard // Single-shard commands interact with only one shard. - MultiShard // MultiShard commands interact with multiple shards using scatter-gather logic. - Custom // Custom commands involve direct client communication. -) - -// CmdMeta stores metadata about DiceDB commands, including how they are processed across shards. -// Type indicates how the command should be handled, while Breakup and Gather provide logic -// for breaking up multishard commands and gathering their responses. -type CmdMeta struct { - Cmd string // Command name. - Breakup func(mgr *shard.ShardManager, DiceDBCmd *cmd.DiceDBCmd, c *comm.Client) []cmd.DiceDBCmd // Function to break up multishard commands. - Gather func(responses ...eval.EvalResponse) []byte // Function to gather responses from shards. - RespNoShards func(args []string) []byte // Function for commands that don't interact with shards. - Type // Enum indicating the command type. -} - -// CmdMetaMap is a map that associates command names with their corresponding metadata. -var ( - CmdMetaMap = map[string]CmdMeta{} - - // Metadata for global commands that don't interact with shards. - // PING is an example of global command. - pingCmdMeta = CmdMeta{ - Cmd: "PING", - Type: Global, - } - - // Metadata for single-shard commands that only interact with one shard. - // These commands don't require breakup and gather logic. - setCmdMeta = CmdMeta{ - Cmd: "SET", - Type: SingleShard, - } - expireCmdMeta = CmdMeta{ - Cmd: "EXPIRE", - Type: SingleShard, - } - expireAtCmdMeta = CmdMeta{ - Cmd: "EXPIREAT", - Type: SingleShard, - } - expireTimeCmdMeta = CmdMeta{ - Cmd: "EXPIRETIME", - Type: SingleShard, - } - getCmdMeta = CmdMeta{ - Cmd: "GET", - Type: SingleShard, - } - getsetCmdMeta = CmdMeta{ - Cmd: "GETSET", - Type: SingleShard, - } - setexCmdMeta = CmdMeta{ - Cmd: "SETEX", - Type: SingleShard, - } - saddCmdMeta = CmdMeta{ - Cmd: "SADD", - Type: SingleShard, - } - sremCmdMeta = CmdMeta{ - Cmd: "SREM", - Type: SingleShard, - } - scardCmdMeta = CmdMeta{ - Cmd: "SCARD", - Type: SingleShard, - } - smembersCmdMeta = CmdMeta{ - Cmd: "SMEMBERS", - } - - jsonArrAppendCmdMeta = CmdMeta{ - Cmd: "JSON.ARRAPPEND", - Type: SingleShard, - } - jsonArrLenCmdMeta = CmdMeta{ - Cmd: "JSON.ARRLEN", - Type: SingleShard, - } - jsonArrPopCmdMeta = CmdMeta{ - Cmd: "JSON.ARRPOP", - Type: SingleShard, - } - jsonDebugCmdMeta = CmdMeta{ - Cmd: "JSON.DEBUG", - Type: SingleShard, - } - jsonRespCmdMeta = CmdMeta{ - Cmd: "JSON.RESP", - Type: SingleShard, - } - - getrangeCmdMeta = CmdMeta{ - Cmd: "GETRANGE", - Type: SingleShard, - } - hexistsCmdMeta = CmdMeta{ - Cmd: "HEXISTS", - Type: SingleShard, - } - hkeysCmdMeta = CmdMeta{ - Cmd: "HKEYS", - Type: SingleShard, - } - - hvalsCmdMeta = CmdMeta{ - Cmd: "HVALS", - Type: SingleShard, - } - zaddCmdMeta = CmdMeta{ - Cmd: "ZADD", - Type: SingleShard, - } - zcountCmdMeta = CmdMeta{ - Cmd: "ZCOUNT", - Type: SingleShard, - } - zrangeCmdMeta = CmdMeta{ - Cmd: "ZRANGE", - Type: SingleShard, - } - appendCmdMeta = CmdMeta{ - Cmd: "APPEND", - Type: SingleShard, - } - zpopminCmdMeta = CmdMeta{ - Cmd: "ZPOPMIN", - Type: SingleShard, - } - zrankCmdMeta = CmdMeta{ - Cmd: "ZRANK", - Type: SingleShard, - } - zcardCmdMeta = CmdMeta{ - Cmd: "ZCARD", - Type: SingleShard, - } - zremCmdMeta = CmdMeta{ - Cmd: "ZREM", - Type: SingleShard, - } - pfaddCmdMeta = CmdMeta{ - Cmd: "PFADD", - Type: SingleShard, - } - pfcountCmdMeta = CmdMeta{ - Cmd: "PFCOUNT", - Type: SingleShard, - } - pfmergeCmdMeta = CmdMeta{ - Cmd: "PFMERGE", - Type: SingleShard, - } - ttlCmdMeta = CmdMeta{ - Cmd: "TTL", - Type: SingleShard, - } - pttlCmdMeta = CmdMeta{ - Cmd: "PTTL", - Type: SingleShard, - } - setbitCmdMeta = CmdMeta{ - Cmd: "SETBIT", - Type: SingleShard, - } - getbitCmdMeta = CmdMeta{ - Cmd: "GETBIT", - Type: SingleShard, - } - bitcountCmdMeta = CmdMeta{ - Cmd: "BITCOUNT", - Type: SingleShard, - } - bitfieldCmdMeta = CmdMeta{ - Cmd: "BITFIELD", - Type: SingleShard, - } - bitposCmdMeta = CmdMeta{ - Cmd: "BITPOS", - Type: SingleShard, - } - bitfieldroCmdMeta = CmdMeta{ - Cmd: "BITFIELD_RO", - Type: SingleShard, - } - delCmdMeta = CmdMeta{ - Cmd: "DEL", - Type: SingleShard, - } - existsCmdMeta = CmdMeta{ - Cmd: "EXISTS", - Type: SingleShard, - } - persistCmdMeta = CmdMeta{ - Cmd: "PERSIST", - Type: SingleShard, - } - typeCmdMeta = CmdMeta{ - Cmd: "TYPE", - Type: SingleShard, - } - - jsonclearCmdMeta = CmdMeta{ - Cmd: "JSON.CLEAR", - Type: SingleShard, - } - - jsonstrlenCmdMeta = CmdMeta{ - Cmd: "JSON.STRLEN", - Type: SingleShard, - } - - jsonobjlenCmdMeta = CmdMeta{ - Cmd: "JSON.OBJLEN", - Type: SingleShard, - } - hlenCmdMeta = CmdMeta{ - Cmd: "HLEN", - Type: SingleShard, - } - hstrlenCmdMeta = CmdMeta{ - Cmd: "HSTRLEN", - Type: SingleShard, - } - hscanCmdMeta = CmdMeta{ - Cmd: "HSCAN", - Type: SingleShard, - } - - jsonarrinsertCmdMeta = CmdMeta{ - Cmd: "JSON.ARRINSERT", - Type: SingleShard, - } - - jsonarrtrimCmdMeta = CmdMeta{ - Cmd: "JSON.ARRTRIM", - Type: SingleShard, - } - - jsonobjkeystCmdMeta = CmdMeta{ - Cmd: "JSON.OBJKEYS", - Type: SingleShard, - } - - incrCmdMeta = CmdMeta{ - Cmd: "INCR", - Type: SingleShard, - } - incrByCmdMeta = CmdMeta{ - Cmd: "INCRBY", - Type: SingleShard, - } - decrCmdMeta = CmdMeta{ - Cmd: "DECR", - Type: SingleShard, - } - decrByCmdMeta = CmdMeta{ - Cmd: "DECRBY", - Type: SingleShard, - } - incrByFloatCmdMeta = CmdMeta{ - Cmd: "INCRBYFLOAT", - Type: SingleShard, - } - hincrbyCmdMeta = CmdMeta{ - Cmd: "HINCRBY", - Type: SingleShard, - } - hincrbyfloatCmdMeta = CmdMeta{ - Cmd: "HINCRBYFLOAT", - Type: SingleShard, - } - hrandfieldCmdMeta = CmdMeta{ - Cmd: "HRANDFIELD", - Type: SingleShard, - } - zpopmaxCmdMeta = CmdMeta{ - Cmd: "ZPOPMAX", - Type: SingleShard, - } - bfaddCmdMeta = CmdMeta{ - Cmd: "BF.ADD", - Type: SingleShard, - } - bfreserveCmdMeta = CmdMeta{ - Cmd: "BF.RESERVE", - Type: SingleShard, - } - bfexistsCmdMeta = CmdMeta{ - Cmd: "BF.EXISTS", - Type: SingleShard, - } - bfinfoCmdMeta = CmdMeta{ - Cmd: "BF.INFO", - Type: SingleShard, - } - cmsInitByDimCmdMeta = CmdMeta{ - Cmd: "CMS.INITBYDIM", - Type: SingleShard, - } - cmsInitByProbCmdMeta = CmdMeta{ - Cmd: "CMS.INITBYPROB", - Type: SingleShard, - } - cmsInfoCmdMeta = CmdMeta{ - Cmd: "CMS.INFO", - Type: SingleShard, - } - cmsIncrByCmdMeta = CmdMeta{ - Cmd: "CMS.INCRBY", - Type: SingleShard, - } - cmsQueryCmdMeta = CmdMeta{ - Cmd: "CMS.QUERY", - Type: SingleShard, - } - cmsMergeCmdMeta = CmdMeta{ - Cmd: "CMS.MERGE", - Type: SingleShard, - } - getexCmdMeta = CmdMeta{ - Cmd: "GETEX", - Type: SingleShard, - } - getdelCmdMeta = CmdMeta{ - Cmd: "GETDEL", - Type: SingleShard, - } - hsetCmdMeta = CmdMeta{ - Cmd: "HSET", - Type: SingleShard, - } - hgetCmdMeta = CmdMeta{ - Cmd: "HGET", - Type: SingleShard, - } - hsetnxCmdMeta = CmdMeta{ - Cmd: "HSETNX", - Type: SingleShard, - } - hdelCmdMeta = CmdMeta{ - Cmd: "HDEL", - Type: SingleShard, - } - hmsetCmdMeta = CmdMeta{ - Cmd: "HMSET", - Type: SingleShard, - } - hmgetCmdMeta = CmdMeta{ - Cmd: "HMGET", - Type: SingleShard, - } - lrangeCmdMeta = CmdMeta{ - Cmd: "LRANGE", - Type: SingleShard, - } - linsertCmdMeta = CmdMeta{ - Cmd: "LINSERT", - Type: SingleShard, - } - lpushCmdMeta = CmdMeta{ - Cmd: "LPUSH", - Type: SingleShard, - } - rpushCmdMeta = CmdMeta{ - Cmd: "RPUSH", - Type: SingleShard, - } - lpopCmdMeta = CmdMeta{ - Cmd: "LPOP", - Type: SingleShard, - } - rpopCmdMeta = CmdMeta{ - Cmd: "RPOP", - Type: SingleShard, - } - llenCmdMeta = CmdMeta{ - Cmd: "LLEN", - Type: SingleShard, - } - jsonForgetCmdMeta = CmdMeta{ - Cmd: "JSON.FORGET", - Type: SingleShard, - } - jsonDelCmdMeta = CmdMeta{ - Cmd: "JSON.DEL", - Type: SingleShard, - } - jsonToggleCmdMeta = CmdMeta{ - Cmd: "JSON.TOGGLE", - Type: SingleShard, - } - jsonNumIncrByCmdMeta = CmdMeta{ - Cmd: "JSON.NUMINCRBY", - Type: SingleShard, - } - jsonNumMultByCmdMeta = CmdMeta{ - Cmd: "JSON.NUMMULTBY", - Type: SingleShard, - } - jsonSetCmdMeta = CmdMeta{ - Cmd: "JSON.SET", - Type: SingleShard, - } - jsonGetCmdMeta = CmdMeta{ - Cmd: "JSON.GET", - Type: SingleShard, - } - jsonTypeCmdMeta = CmdMeta{ - Cmd: "JSON.TYPE", - Type: SingleShard, - } - jsonIngestCmdMeta = CmdMeta{ - Cmd: "JSON.INGEST", - Type: SingleShard, - } - jsonArrStrAppendCmdMeta = CmdMeta{ - Cmd: "JSON.STRAPPEND", - Type: SingleShard, - } - hGetAllCmdMeta = CmdMeta{ - Cmd: "HGETALL", - Type: SingleShard, - } - dumpCmdMeta = CmdMeta{ - Cmd: "DUMP", - Type: SingleShard, - } - restoreCmdMeta = CmdMeta{ - Cmd: "RESTORE", - Type: SingleShard, - } - geoaddCmdMeta = CmdMeta{ - Cmd: "GEOADD", - Type: SingleShard, - } - geodistCmdMeta = CmdMeta{ - Cmd: "GEODIST", - Type: SingleShard, - } - geoposCmdMeta = CmdMeta{ - Cmd: "GEOPOS", - Type: SingleShard, - } - clientCmdMeta = CmdMeta{ - Cmd: "CLIENT", - Type: SingleShard, - } - latencyCmdMeta = CmdMeta{ - Cmd: "LATENCY", - Type: SingleShard, - } - flushDBCmdMeta = CmdMeta{ - Cmd: "FLUSHDB", - Type: MultiShard, - } - objectCmdMeta = CmdMeta{ - Cmd: "OBJECT", - Type: SingleShard, - } - commandCmdMeta = CmdMeta{ - Cmd: "COMMAND", - Type: SingleShard, - } - CmdCommandCountMeta = CmdMeta{ - Cmd: "COMMAND|COUNT", - Type: SingleShard, - } - CmdCommandHelp = CmdMeta{ - Cmd: "COMMAND|HELP", - Type: SingleShard, - } - CmdCommandInfo = CmdMeta{ - Cmd: "COMMAND|INFO", - Type: SingleShard, - } - CmdCommandList = CmdMeta{ - Cmd: "COMMAND|LIST", - Type: SingleShard, - } - CmdCommandDocs = CmdMeta{ - Cmd: "COMMAND|DOCS", - Type: SingleShard, - } - CmdCommandGetKeys = CmdMeta{ - Cmd: "COMMAND|GETKEYS", - Type: SingleShard, - } - CmdCommandGetKeysFlags = CmdMeta{ - Cmd: "COMMAND|GETKEYSANDFLAGS", - Type: SingleShard, - } - - // Metadata for multishard commands would go here. - // These commands require both breakup and gather logic. - - // Metadata for custom commands requiring specific client-side logic would go here. -) - -// init initializes the CmdMetaMap map by associating each command name with its corresponding metadata. -func init() { - // Global commands. - CmdMetaMap["PING"] = pingCmdMeta - - // Single-shard commands. - CmdMetaMap["SET"] = setCmdMeta - CmdMetaMap["EXPIRE"] = expireCmdMeta - CmdMetaMap["EXPIREAT"] = expireAtCmdMeta - CmdMetaMap["EXPIRETIME"] = expireTimeCmdMeta - CmdMetaMap["GET"] = getCmdMeta - CmdMetaMap["GETSET"] = getsetCmdMeta - CmdMetaMap["SETEX"] = setexCmdMeta - - CmdMetaMap["SADD"] = saddCmdMeta - CmdMetaMap["SREM"] = sremCmdMeta - CmdMetaMap["SCARD"] = scardCmdMeta - CmdMetaMap["SMEMBERS"] = smembersCmdMeta - - CmdMetaMap["JSON.ARRAPPEND"] = jsonArrAppendCmdMeta - CmdMetaMap["JSON.ARRLEN"] = jsonArrLenCmdMeta - CmdMetaMap["JSON.ARRPOP"] = jsonArrPopCmdMeta - CmdMetaMap["JSON.DEBUG"] = jsonDebugCmdMeta - CmdMetaMap["JSON.RESP"] = jsonRespCmdMeta - - CmdMetaMap["GETRANGE"] = getrangeCmdMeta - CmdMetaMap["APPEND"] = appendCmdMeta - CmdMetaMap["JSON.CLEAR"] = jsonclearCmdMeta - CmdMetaMap["JSON.STRLEN"] = jsonstrlenCmdMeta - CmdMetaMap["JSON.OBJLEN"] = jsonobjlenCmdMeta - CmdMetaMap["HEXISTS"] = hexistsCmdMeta - CmdMetaMap["HKEYS"] = hkeysCmdMeta - CmdMetaMap["HVALS"] = hvalsCmdMeta - CmdMetaMap["JSON.ARRINSERT"] = jsonarrinsertCmdMeta - CmdMetaMap["JSON.ARRTRIM"] = jsonarrtrimCmdMeta - CmdMetaMap["JSON.OBJKEYS"] = jsonobjkeystCmdMeta - CmdMetaMap["ZADD"] = zaddCmdMeta - CmdMetaMap["ZCOUNT"] = zcountCmdMeta - CmdMetaMap["ZRANGE"] = zrangeCmdMeta - CmdMetaMap["ZRANK"] = zrankCmdMeta - CmdMetaMap["ZCARD"] = zcardCmdMeta - CmdMetaMap["ZREM"] = zremCmdMeta - CmdMetaMap["PFADD"] = pfaddCmdMeta - CmdMetaMap["ZPOPMIN"] = zpopminCmdMeta - CmdMetaMap["PFCOUNT"] = pfcountCmdMeta - CmdMetaMap["PFMERGE"] = pfmergeCmdMeta - CmdMetaMap["DEL"] = delCmdMeta - CmdMetaMap["EXISTS"] = existsCmdMeta - CmdMetaMap["PERSIST"] = persistCmdMeta - CmdMetaMap["TYPE"] = typeCmdMeta - CmdMetaMap["HLEN"] = hlenCmdMeta - CmdMetaMap["HSTRLEN"] = hstrlenCmdMeta - CmdMetaMap["HSCAN"] = hscanCmdMeta - CmdMetaMap["INCR"] = incrCmdMeta - CmdMetaMap["INCRBY"] = incrByCmdMeta - CmdMetaMap["INCR"] = incrCmdMeta - CmdMetaMap["DECR"] = decrCmdMeta - CmdMetaMap["DECRBY"] = decrByCmdMeta - CmdMetaMap["INCRBYFLOAT"] = incrByFloatCmdMeta - CmdMetaMap["HINCRBY"] = hincrbyCmdMeta - CmdMetaMap["HINCRBYFLOAT"] = hincrbyfloatCmdMeta - CmdMetaMap["HRANDFIELD"] = hrandfieldCmdMeta - CmdMetaMap["PFADD"] = pfaddCmdMeta - CmdMetaMap["ZPOPMIN"] = zpopminCmdMeta - CmdMetaMap["PFCOUNT"] = pfcountCmdMeta - CmdMetaMap["PFMERGE"] = pfmergeCmdMeta - CmdMetaMap["TTL"] = ttlCmdMeta - CmdMetaMap["PTTL"] = pttlCmdMeta - CmdMetaMap["HINCRBY"] = hincrbyCmdMeta - CmdMetaMap["HINCRBYFLOAT"] = hincrbyfloatCmdMeta - CmdMetaMap["HRANDFIELD"] = hrandfieldCmdMeta - CmdMetaMap["PFADD"] = pfaddCmdMeta - CmdMetaMap["PFCOUNT"] = pfcountCmdMeta - CmdMetaMap["PFMERGE"] = pfmergeCmdMeta - CmdMetaMap["HINCRBY"] = hincrbyCmdMeta - CmdMetaMap["HINCRBYFLOAT"] = hincrbyfloatCmdMeta - CmdMetaMap["HRANDFIELD"] = hrandfieldCmdMeta - CmdMetaMap["ZPOPMAX"] = zpopmaxCmdMeta - CmdMetaMap["BF.ADD"] = bfaddCmdMeta - CmdMetaMap["BF.RESERVE"] = bfreserveCmdMeta - CmdMetaMap["BF.EXISTS"] = bfexistsCmdMeta - CmdMetaMap["BF.INFO"] = bfinfoCmdMeta - CmdMetaMap["CMS.INITBYDIM"] = cmsInitByDimCmdMeta - CmdMetaMap["CMS.INITBYPROB"] = cmsInitByProbCmdMeta - CmdMetaMap["CMS.INFO"] = cmsInfoCmdMeta - CmdMetaMap["CMS.INCRBY"] = cmsIncrByCmdMeta - CmdMetaMap["CMS.QUERY"] = cmsQueryCmdMeta - CmdMetaMap["CMS.MERGE"] = cmsMergeCmdMeta - CmdMetaMap["GETEX"] = getexCmdMeta - CmdMetaMap["GETDEL"] = getdelCmdMeta - CmdMetaMap["HSET"] = hsetCmdMeta - CmdMetaMap["HGET"] = hgetCmdMeta - CmdMetaMap["HSETNX"] = hsetnxCmdMeta - CmdMetaMap["HDEL"] = hdelCmdMeta - CmdMetaMap["HMSET"] = hmsetCmdMeta - CmdMetaMap["HMGET"] = hmgetCmdMeta - CmdMetaMap["SETBIT"] = setbitCmdMeta - CmdMetaMap["GETBIT"] = getbitCmdMeta - CmdMetaMap["BITCOUNT"] = bitcountCmdMeta - CmdMetaMap["BITFIELD"] = bitfieldCmdMeta - CmdMetaMap["BITPOS"] = bitposCmdMeta - CmdMetaMap["BITFIELD_RO"] = bitfieldroCmdMeta - CmdMetaMap["LRANGE"] = lrangeCmdMeta - CmdMetaMap["LINSERT"] = linsertCmdMeta - CmdMetaMap["LPUSH"] = lpushCmdMeta - CmdMetaMap["RPUSH"] = rpushCmdMeta - CmdMetaMap["LPOP"] = lpopCmdMeta - CmdMetaMap["RPOP"] = rpopCmdMeta - CmdMetaMap["LLEN"] = llenCmdMeta - CmdMetaMap["JSON.FORGET"] = jsonForgetCmdMeta - CmdMetaMap["JSON.DEL"] = jsonDelCmdMeta - CmdMetaMap["JSON.TOGGLE"] = jsonToggleCmdMeta - CmdMetaMap["JSON.NUMINCRBY"] = jsonNumIncrByCmdMeta - CmdMetaMap["JSON.NUMMULTBY"] = jsonNumMultByCmdMeta - CmdMetaMap["JSON.SET"] = jsonSetCmdMeta - CmdMetaMap["JSON.GET"] = jsonGetCmdMeta - CmdMetaMap["JSON.TYPE"] = jsonTypeCmdMeta - CmdMetaMap["JSON.INGEST"] = jsonIngestCmdMeta - CmdMetaMap["JSON.STRAPPEND"] = jsonArrStrAppendCmdMeta - CmdMetaMap["HGETALL"] = hGetAllCmdMeta - CmdMetaMap["DUMP"] = dumpCmdMeta - CmdMetaMap["RESTORE"] = restoreCmdMeta - CmdMetaMap["GEOADD"] = geoaddCmdMeta - CmdMetaMap["GEODIST"] = geodistCmdMeta - CmdMetaMap["GEOPOS"] = geoposCmdMeta - CmdMetaMap["CLIENT"] = clientCmdMeta - CmdMetaMap["LATENCY"] = latencyCmdMeta - CmdMetaMap["FLUSHDB"] = flushDBCmdMeta - CmdMetaMap["OBJECT"] = objectCmdMeta - CmdMetaMap["COMMAND"] = commandCmdMeta - CmdMetaMap["COMMAND|COUNT"] = CmdCommandCountMeta - CmdMetaMap["COMMAND|HELP"] = CmdCommandHelp - CmdMetaMap["COMMAND|INFO"] = CmdCommandInfo - CmdMetaMap["COMMAND|LIST"] = CmdCommandList - CmdMetaMap["COMMAND|DOCS"] = CmdCommandDocs - CmdMetaMap["COMMAND|GETKEYS"] = CmdCommandGetKeys - CmdMetaMap["COMMAND|GETKEYSANDFLAGS"] = CmdCommandGetKeysFlags -} From 7e66389e87792c7bfaa73323353dc59c7d8bda10 Mon Sep 17 00:00:00 2001 From: helios2003 Date: Tue, 10 Dec 2024 21:18:37 +0530 Subject: [PATCH 13/13] update tests --- integration_tests/commands/http/geo_test.go | 11 +++++++++++ integration_tests/commands/resp/geo_test.go | 11 +++++++++++ integration_tests/commands/websocket/geo_test.go | 11 +++++++++++ internal/eval/eval_test.go | 10 ++++++++++ 4 files changed, 43 insertions(+) diff --git a/integration_tests/commands/http/geo_test.go b/integration_tests/commands/http/geo_test.go index 889c91588..2943c3fa2 100644 --- a/integration_tests/commands/http/geo_test.go +++ b/integration_tests/commands/http/geo_test.go @@ -117,6 +117,17 @@ func TestGeoPos(t *testing.T) { {Command: "GEOPOS", Body: map[string]interface{}{"key": "NonExisting", "values": []interface{}{"Palermo"}}}, }, expected: []interface{}{nil}, + }, + { + name: "GEOPOS for a key not used for setting geospatial values", + commands: []HTTPCommand{ + {Command: "SET", Body: map[string]interface{}{"key": "k", "value": "v"}}, + {Command: "GEOPOS", Body: map[string]interface{}{"key": "k", "values": []interface{}{"v"}}}, + }, + expected: []interface{}{ + "OK", + "WRONGTYPE Operation against a key holding the wrong kind of value", + }, }, } diff --git a/integration_tests/commands/resp/geo_test.go b/integration_tests/commands/resp/geo_test.go index bd0e9a67a..b6eefc927 100644 --- a/integration_tests/commands/resp/geo_test.go +++ b/integration_tests/commands/resp/geo_test.go @@ -122,6 +122,17 @@ func TestGeoPos(t *testing.T) { }, expect: []interface{}{"(nil)"}, }, + { + name: "GEOPOS for a key not used for setting geospatial values", + cmds: []string{ + "SET k v", + "GEOPOS k v", + }, + expect: []interface{}{ + "OK", + "WRONGTYPE Operation against a key holding the wrong kind of value", + }, + }, } for _, tc := range testCases { diff --git a/integration_tests/commands/websocket/geo_test.go b/integration_tests/commands/websocket/geo_test.go index 89e57011c..e7402f7de 100644 --- a/integration_tests/commands/websocket/geo_test.go +++ b/integration_tests/commands/websocket/geo_test.go @@ -121,6 +121,17 @@ func TestGeoPos(t *testing.T) { }, expect: []interface{}{nil}, }, + { + name: "GEOPOS for a key not used for setting geospatial values", + cmds: []string{ + "SET k v", + "GEOPOS k v", + }, + expect: []interface{}{ + "OK", + "WRONGTYPE Operation against a key holding the wrong kind of value", + }, + }, } for _, tc := range testCases { diff --git a/internal/eval/eval_test.go b/internal/eval/eval_test.go index 02ce4c136..284f8431e 100644 --- a/internal/eval/eval_test.go +++ b/internal/eval/eval_test.go @@ -8323,6 +8323,16 @@ func testEvalGEOPOS(t *testing.T, store *dstore.Store) { Error: diceerrors.ErrWrongArgumentCount("GEOPOS"), }, }, + "GEOPOS for a key not used for setting geospatial values": { + setup: func() { + evalSET([]string{"k", "v"}, store) + }, + input: []string{"k", "v"}, + migratedOutput: EvalResponse{ + Result: nil, + Error: errors.New("WRONGTYPE Operation against a key holding the wrong kind of value"), + }, + }, } runMigratedEvalTests(t, tests, evalGEOPOS, store)