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 3df90b37 Add RESP3 big number (#2034)
3df90b37 is described below

commit 3df90b3764da1767c5227969d14a7264de7efe4d
Author: hulk <[email protected]>
AuthorDate: Mon Jan 22 00:12:50 2024 +0800

    Add RESP3 big number (#2034)
---
 src/commands/cmd_server.cc                  |  4 ++-
 src/server/redis_connection.h               |  3 +++
 src/storage/scripting.cc                    | 42 +++++++++++++++++++----------
 tests/gocase/unit/debug/debug_test.go       |  4 +++
 tests/gocase/unit/protocol/protocol_test.go |  2 ++
 5 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/src/commands/cmd_server.cc b/src/commands/cmd_server.cc
index d34c5595..fb6ca8a4 100644
--- a/src/commands/cmd_server.cc
+++ b/src/commands/cmd_server.cc
@@ -623,6 +623,8 @@ class CommandDebug : public Commander {
           *output += redis::Integer(i);
           *output += conn->Bool(i == 1);
         }
+      } else if (protocol_type_ == "bignum") {
+        *output = conn->BigNumber("1234567999999999999999999999999999999");
       } else if (protocol_type_ == "true") {
         *output = conn->Bool(true);
       } else if (protocol_type_ == "false") {
@@ -631,7 +633,7 @@ class CommandDebug : public Commander {
         *output = conn->NilString();
       } else {
         *output = redis::Error(
-            "Wrong protocol type name. Please use one of the following: 
string|int|array|set|true|false|null");
+            "Wrong protocol type name. Please use one of the following: 
string|int|array|set|bignum|true|false|null");
       }
     } else {
       return {Status::RedisInvalidCmd, "Unknown subcommand, should be DEBUG or 
PROTOCOL"};
diff --git a/src/server/redis_connection.h b/src/server/redis_connection.h
index 7f622fe5..47b694a0 100644
--- a/src/server/redis_connection.h
+++ b/src/server/redis_connection.h
@@ -65,6 +65,9 @@ class Connection : public EvbufCallbackBase<Connection> {
   RESP GetProtocolVersion() const { return protocol_version_; }
   void SetProtocolVersion(RESP version) { protocol_version_ = version; }
   std::string Bool(bool b) const;
+  std::string BigNumber(const std::string &n) const {
+    return protocol_version_ == RESP::v3 ? "(" + n + CRLF : BulkString(n);
+  }
   std::string NilString() const { return redis::NilString(protocol_version_); }
   std::string NilArray() const { return protocol_version_ == RESP::v3 ? "_" 
CRLF : "*-1" CRLF; }
   std::string MultiBulkString(const std::vector<std::string> &values, bool 
output_nil_for_empty_string = true) const;
diff --git a/src/storage/scripting.cc b/src/storage/scripting.cc
index 4d94cd4a..8105d321 100644
--- a/src/storage/scripting.cc
+++ b/src/storage/scripting.cc
@@ -1080,6 +1080,7 @@ std::string ReplyToRedisReply(redis::Connection *conn, 
lua_State *lua) {
   std::string output;
   const char *obj_s = nullptr;
   size_t obj_len = 0;
+  int j = 0, mbulklen = 0;
 
   int t = lua_type(lua, -1);
   switch (t) {
@@ -1113,6 +1114,7 @@ std::string ReplyToRedisReply(redis::Connection *conn, 
lua_State *lua) {
         return output;
       }
       lua_pop(lua, 1); /* Discard field name pushed before. */
+
       /* Handle status reply. */
       lua_pushstring(lua, "ok");
       lua_gettable(lua, -2);
@@ -1122,23 +1124,35 @@ std::string ReplyToRedisReply(redis::Connection *conn, 
lua_State *lua) {
         output = redis::BulkString(std::string(obj_s, obj_len));
         lua_pop(lua, 1);
         return output;
-      } else {
-        int j = 1, mbulklen = 0;
-        lua_pop(lua, 1); /* Discard the 'ok' field value we popped */
-        while (true) {
-          lua_pushnumber(lua, j++);
-          lua_gettable(lua, -2);
-          t = lua_type(lua, -1);
-          if (t == LUA_TNIL) {
-            lua_pop(lua, 1);
-            break;
-          }
-          mbulklen++;
-          output += ReplyToRedisReply(conn, lua);
+      }
+      lua_pop(lua, 1); /* Discard the 'ok' field value we pushed */
+
+      /* Handle big number reply. */
+      lua_pushstring(lua, "big_number");
+      lua_gettable(lua, -2);
+      t = lua_type(lua, -1);
+      if (t == LUA_TSTRING) {
+        obj_s = lua_tolstring(lua, -1, &obj_len);
+        output = conn->BigNumber(std::string(obj_s, obj_len));
+        lua_pop(lua, 1);
+        return output;
+      }
+      lua_pop(lua, 1); /* Discard the 'big_number' field value we pushed */
+
+      j = 1, mbulklen = 0;
+      while (true) {
+        lua_pushnumber(lua, j++);
+        lua_gettable(lua, -2);
+        t = lua_type(lua, -1);
+        if (t == LUA_TNIL) {
           lua_pop(lua, 1);
+          break;
         }
-        output = redis::MultiLen(mbulklen) + output;
+        mbulklen++;
+        output += ReplyToRedisReply(conn, lua);
+        lua_pop(lua, 1);
       }
+      output = redis::MultiLen(mbulklen) + output;
       break;
     default:
       output = conn->NilString();
diff --git a/tests/gocase/unit/debug/debug_test.go 
b/tests/gocase/unit/debug/debug_test.go
index faa29811..1aae088f 100644
--- a/tests/gocase/unit/debug/debug_test.go
+++ b/tests/gocase/unit/debug/debug_test.go
@@ -21,6 +21,7 @@ package debug
 
 import (
        "context"
+       "math/big"
        "testing"
 
        "github.com/redis/go-redis/v9"
@@ -46,6 +47,7 @@ func TestDebugProtocolV2(t *testing.T) {
                        "array":   []interface{}{int64(0), int64(1), int64(2)},
                        "set":     []interface{}{int64(0), int64(1), int64(2)},
                        "map":     []interface{}{int64(0), int64(0), int64(1), 
int64(1), int64(2), int64(0)},
+                       "bignum":  "1234567999999999999999999999999999999",
                        "true":    int64(1),
                        "false":   int64(0),
                }
@@ -83,12 +85,14 @@ func TestDebugProtocolV3(t *testing.T) {
        defer func() { require.NoError(t, rdb.Close()) }()
 
        t.Run("debug protocol type", func(t *testing.T) {
+               bignum, _ := 
big.NewInt(0).SetString("1234567999999999999999999999999999999", 10)
                types := map[string]interface{}{
                        "string":  "Hello World",
                        "integer": int64(12345),
                        "array":   []interface{}{int64(0), int64(1), int64(2)},
                        "set":     []interface{}{int64(0), int64(1), int64(2)},
                        "map":     map[interface{}]interface{}{int64(0): false, 
int64(1): true, int64(2): false},
+                       "bignum":  bignum,
                        "true":    true,
                        "false":   false,
                }
diff --git a/tests/gocase/unit/protocol/protocol_test.go 
b/tests/gocase/unit/protocol/protocol_test.go
index 7919bf77..33202c90 100644
--- a/tests/gocase/unit/protocol/protocol_test.go
+++ b/tests/gocase/unit/protocol/protocol_test.go
@@ -156,6 +156,7 @@ func TestProtocolRESP2(t *testing.T) {
                        "array":   {"*3", ":0", ":1", ":2"},
                        "set":     {"*3", ":0", ":1", ":2"},
                        "map":     {"*6", ":0", ":0", ":1", ":1", ":2", ":0"},
+                       "bignum":  {"$37", 
"1234567999999999999999999999999999999"},
                        "true":    {":1"},
                        "false":   {":0"},
                        "null":    {"$-1"},
@@ -210,6 +211,7 @@ func TestProtocolRESP3(t *testing.T) {
                        "array":   {"*3", ":0", ":1", ":2"},
                        "set":     {"~3", ":0", ":1", ":2"},
                        "map":     {"%3", ":0", "#f", ":1", "#t", ":2", "#f"},
+                       "bignum":  {"(1234567999999999999999999999999999999"},
                        "true":    {"#t"},
                        "false":   {"#f"},
                        "null":    {"_"},

Reply via email to