This is an automated email from the ASF dual-hosted git repository.

hulk pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git


The following commit(s) were added to refs/heads/unstable by this push:
     new 03ceb6e8 Fix GEOHASH / GEOPOS should return nil array instead of error 
for non-existing key (#1573)
03ceb6e8 is described below

commit 03ceb6e8105656c2fc08ae47a820e3e37d3c56f3
Author: Binbin <[email protected]>
AuthorDate: Wed Jul 12 12:12:50 2023 +0800

    Fix GEOHASH / GEOPOS should return nil array instead of error for 
non-existing key (#1573)
    
    The current code GETHASH returns an error for a key
    that doesn't exist:
    ```
    127.0.0.1:6666> geohash mykey a b c
    (error) ERR NotFound:
    ```
    
    In Redis, this would return:
    ```
    127.0.0.1:6379> geohash mykey a b c
    1) (nil)
    2) (nil)
    3) (nil)
    ```
    
    GEOPOS also has the same issue, this PR fixes these inconsistencies in this 
case.
---
 src/commands/cmd_geo.cc           | 15 +++++++++++++--
 tests/gocase/unit/geo/geo_test.go | 10 ++++++++++
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/src/commands/cmd_geo.cc b/src/commands/cmd_geo.cc
index 49cc99ad..62dab23c 100644
--- a/src/commands/cmd_geo.cc
+++ b/src/commands/cmd_geo.cc
@@ -163,10 +163,14 @@ class CommandGeoHash : public Commander {
     std::vector<std::string> hashes;
     redis::Geo geo_db(svr->storage, conn->GetNamespace());
     auto s = geo_db.Hash(args_[1], members_, &hashes);
-    if (!s.ok()) {
+    if (!s.ok() && !s.IsNotFound()) {
       return {Status::RedisExecErr, s.ToString()};
     }
 
+    if (s.IsNotFound()) {
+      hashes.resize(members_.size(), "");
+    }
+
     *output = redis::MultiBulkString(hashes);
     return Status::OK();
   }
@@ -188,11 +192,18 @@ class CommandGeoPos : public Commander {
     std::map<std::string, GeoPoint> geo_points;
     redis::Geo geo_db(svr->storage, conn->GetNamespace());
     auto s = geo_db.Pos(args_[1], members_, &geo_points);
-    if (!s.ok()) {
+    if (!s.ok() && !s.IsNotFound()) {
       return {Status::RedisExecErr, s.ToString()};
     }
 
     std::vector<std::string> list;
+
+    if (s.IsNotFound()) {
+      list.resize(members_.size(), "");
+      *output = redis::MultiBulkString(list);
+      return Status::OK();
+    }
+
     for (const auto &member : members_) {
       auto iter = geo_points.find(member.ToString());
       if (iter == geo_points.end()) {
diff --git a/tests/gocase/unit/geo/geo_test.go 
b/tests/gocase/unit/geo/geo_test.go
index 173ae67c..c34dee86 100644
--- a/tests/gocase/unit/geo/geo_test.go
+++ b/tests/gocase/unit/geo/geo_test.go
@@ -134,12 +134,22 @@ func TestGeo(t *testing.T) {
                require.EqualValues(t, 
[]redis.GeoLocation([]redis.GeoLocation{{Name: "wtc one", Longitude: 0, 
Latitude: 0, Dist: 0, GeoHash: 0}, {Name: "union square", Longitude: 0, 
Latitude: 0, Dist: 0, GeoHash: 0}, {Name: "central park n/q/r", Longitude: 0, 
Latitude: 0, Dist: 0, GeoHash: 0}, {Name: "4545", Longitude: 0, Latitude: 0, 
Dist: 0, GeoHash: 0}, {Name: "lic market", Longitude: 0, Latitude: 0, Dist: 0, 
GeoHash: 0}}), rdb.GeoRadiusByMember(ctx, "nyc", "wtc one", 
&redis.GeoRadiusQuery{Radius: [...]
        })
 
+       t.Run("GEOHASH against non existing key", func(t *testing.T) {
+               require.NoError(t, rdb.Del(ctx, "points").Err())
+               require.EqualValues(t, []interface{}{nil, nil, nil}, 
rdb.Do(ctx, "GEOHASH", "points", "a", "b", "c").Val())
+       })
+
        t.Run("GEOHASH is able to return geohash strings", func(t *testing.T) {
                require.NoError(t, rdb.Del(ctx, "points").Err())
                require.NoError(t, rdb.GeoAdd(ctx, "points", 
&redis.GeoLocation{Name: "test", Longitude: -5.6, Latitude: 42.6}).Err())
                require.EqualValues(t, []string([]string{"ezs42e44yx0"}), 
rdb.GeoHash(ctx, "points", "test").Val())
        })
 
+       t.Run("GEOPOS against non existing key", func(t *testing.T) {
+               require.NoError(t, rdb.Del(ctx, "points").Err())
+               require.EqualValues(t, []interface{}{nil, nil, nil}, 
rdb.Do(ctx, "GEOPOS", "points", "a", "b", "c").Val())
+       })
+
        t.Run("GEOPOS simple", func(t *testing.T) {
                require.NoError(t, rdb.Del(ctx, "points").Err())
                require.NoError(t, rdb.GeoAdd(ctx, "points", 
&redis.GeoLocation{Name: "a", Longitude: 10, Latitude: 20}, 
&redis.GeoLocation{Name: "b", Longitude: 30, Latitude: 40}).Err())

Reply via email to