Skip to content

Commit e7674a4

Browse files
authored
Merge branch 'unstable' into fix-bloom-bug
2 parents 4fcfaf1 + 1639c90 commit e7674a4

File tree

6 files changed

+317
-25
lines changed

6 files changed

+317
-25
lines changed

src/commands/cmd_key.cc

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,32 @@ class CommandSort : public Commander {
553553
SortArgument sort_argument_;
554554
};
555555

556+
class CommandKMetadata : public Commander {
557+
public:
558+
Status Execute(engine::Context &ctx, Server *srv, Connection *conn, std::string *output) override {
559+
redis::Database redis(srv->storage, conn->GetNamespace());
560+
std::string &key = args_[1];
561+
std::string nskey = redis.AppendNamespacePrefix(key);
562+
563+
Metadata metadata(kRedisNone, false);
564+
auto s = redis.GetMetadata(ctx, RedisTypes::All(), nskey, &metadata);
565+
if (!s.ok()) return {Status::RedisExecErr, s.ToString()};
566+
567+
if (metadata.IsSingleKVType()) {
568+
*output = conn->Map({{redis::BulkString("type"), redis::BulkString(metadata.TypeName())},
569+
{redis::BulkString("expire"), redis::Integer(metadata.expire)},
570+
{redis::BulkString("flags"), redis::Integer(metadata.flags)}});
571+
} else {
572+
*output = conn->Map({{redis::BulkString("type"), redis::BulkString(metadata.TypeName())},
573+
{redis::BulkString("size"), redis::Integer(metadata.size)},
574+
{redis::BulkString("expire"), redis::Integer(metadata.expire)},
575+
{redis::BulkString("flags"), redis::Integer(metadata.flags)},
576+
{redis::BulkString("version"), redis::Integer(metadata.version)}});
577+
}
578+
return Status::OK();
579+
}
580+
};
581+
556582
REDIS_REGISTER_COMMANDS(Key, MakeCmdAttr<CommandTTL>("ttl", 2, "read-only", 1, 1, 1),
557583
MakeCmdAttr<CommandPTTL>("pttl", 2, "read-only", 1, 1, 1),
558584
MakeCmdAttr<CommandType>("type", 2, "read-only", 1, 1, 1),
@@ -573,6 +599,7 @@ REDIS_REGISTER_COMMANDS(Key, MakeCmdAttr<CommandTTL>("ttl", 2, "read-only", 1, 1
573599
MakeCmdAttr<CommandRenameNX>("renamenx", 3, "write", 1, 2, 1),
574600
MakeCmdAttr<CommandCopy>("copy", -3, "write", 1, 2, 1),
575601
MakeCmdAttr<CommandSort<false>>("sort", -2, "write slow", 1, 1, 1),
576-
MakeCmdAttr<CommandSort<true>>("sort_ro", -2, "read-only slow", 1, 1, 1))
602+
MakeCmdAttr<CommandSort<true>>("sort_ro", -2, "read-only slow", 1, 1, 1),
603+
MakeCmdAttr<CommandKMetadata>("kmetadata", 2, "read-only", 1, 1, 1))
577604

578605
} // namespace redis

src/server/redis_reply.cc

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,12 @@ std::string StatusToRedisErrorMsg(const Status &s) {
6060
return prefix + " " + s.Msg();
6161
}
6262

63-
std::string BulkString(const std::string &data) { return "$" + std::to_string(data.length()) + CRLF + data + CRLF; }
64-
65-
std::string Array(const std::vector<std::string> &list) {
66-
size_t n = std::accumulate(list.begin(), list.end(), 0, [](size_t n, const std::string &s) { return n + s.size(); });
67-
std::string result = MultiLen(list.size());
68-
std::string::size_type final_size = result.size() + n;
69-
result.reserve(final_size);
70-
for (const auto &i : list) result += i;
71-
return result;
63+
std::string BulkString(std::string_view data) {
64+
std::string res = "$" + std::to_string(data.length()) + CRLF;
65+
res.reserve(res.size() + data.size() + 2);
66+
res += data;
67+
res += CRLF;
68+
return res;
7269
}
7370

7471
std::string ArrayOfBulkStrings(const std::vector<std::string> &elems) {
@@ -131,13 +128,4 @@ std::string MapOfBulkStrings(RESP ver, const std::vector<std::string> &elems) {
131128
return result;
132129
}
133130

134-
std::string Map(RESP ver, const std::map<std::string, std::string> &map) {
135-
std::string result = HeaderOfMap(ver, map.size());
136-
for (const auto &pair : map) {
137-
result += pair.first;
138-
result += pair.second;
139-
}
140-
return result;
141-
}
142-
143131
} // namespace redis

src/server/redis_reply.h

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222

2323
#include <event2/buffer.h>
2424

25+
#include <initializer_list>
2526
#include <map>
27+
#include <numeric>
2628
#include <string>
2729
#include <string_view>
2830
#include <vector>
@@ -59,23 +61,38 @@ inline std::string NilString(RESP ver) {
5961
return "$-1" CRLF;
6062
}
6163

62-
std::string BulkString(const std::string &data);
64+
std::string BulkString(std::string_view data);
6365

6466
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
6567
std::string MultiLen(T len) {
6668
return "*" + std::to_string(len) + CRLF;
6769
}
6870

69-
std::string Array(const std::vector<std::string> &list);
71+
template <typename Con>
72+
std::string Array(const Con &list) {
73+
size_t total_size =
74+
std::accumulate(list.begin(), list.end(), 0, [](size_t n, const auto &s) { return n + s.size(); });
75+
std::string result = MultiLen(list.size());
76+
result.reserve(result.size() + total_size);
77+
for (const auto &i : list) result += i;
78+
return result;
79+
}
80+
template <typename T>
81+
std::string Array(std::initializer_list<T> list) {
82+
return Array<std::initializer_list<T>>(list);
83+
}
7084
std::string ArrayOfBulkStrings(const std::vector<std::string> &elements);
7185

7286
std::string Bool(RESP ver, bool b);
87+
7388
inline std::string BigNumber(RESP ver, const std::string &n) {
7489
return ver == RESP::v3 ? "(" + n + CRLF : BulkString(n);
7590
}
91+
7692
inline std::string Double(RESP ver, double d) {
7793
return ver == RESP::v3 ? "," + util::Float2String(d) + CRLF : BulkString(util::Float2String(d));
7894
}
95+
7996
// ext is the extension of file to send, 'txt' for text file, 'md ' for markdown file
8097
// at most 3 chars, padded with space
8198
// if RESP is V2, treat verbatim string as blob string
@@ -89,6 +106,7 @@ inline std::string VerbatimString(RESP ver, std::string ext, const std::string &
89106
}
90107

91108
inline std::string NilArray(RESP ver) { return ver == RESP::v3 ? "_" CRLF : "*-1" CRLF; }
109+
92110
std::string MultiBulkString(RESP ver, const std::vector<std::string> &values);
93111
std::string MultiBulkString(RESP ver, const std::vector<std::string> &values,
94112
const std::vector<rocksdb::Status> &statuses);
@@ -98,16 +116,27 @@ std::string HeaderOfSet(RESP ver, T len) {
98116
return ver == RESP::v3 ? "~" + std::to_string(len) + CRLF : MultiLen(len);
99117
}
100118
std::string SetOfBulkStrings(RESP ver, const std::vector<std::string> &elems);
119+
101120
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
102121
std::string HeaderOfMap(RESP ver, T len) {
103122
return ver == RESP::v3 ? "%" + std::to_string(len) + CRLF : MultiLen(len * 2);
104123
}
105-
std::string Map(RESP ver, const std::map<std::string, std::string> &map);
124+
template <typename Con>
125+
std::string Map(RESP ver, const Con &map) {
126+
std::string result = HeaderOfMap(ver, map.size());
127+
for (const auto &pair : map) {
128+
result += pair.first;
129+
result += pair.second;
130+
}
131+
return result;
132+
}
106133
std::string MapOfBulkStrings(RESP ver, const std::vector<std::string> &elems);
134+
107135
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
108136
std::string HeaderOfAttribute(T len) {
109137
return "|" + std::to_string(len) + CRLF;
110138
}
139+
111140
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
112141
std::string HeaderOfPush(RESP ver, T len) {
113142
return ver == RESP::v3 ? ">" + std::to_string(len) + CRLF : MultiLen(len);

tests/gocase/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/apache/kvrocks/tests/gocase
33
go 1.23.0
44

55
require (
6-
github.com/redis/go-redis/v9 v9.7.1
6+
github.com/redis/go-redis/v9 v9.7.3
77
github.com/shirou/gopsutil/v4 v4.25.2
88
github.com/stretchr/testify v1.10.0
99
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394

tests/gocase/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
2121
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2222
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
2323
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
24-
github.com/redis/go-redis/v9 v9.7.1 h1:4LhKRCIduqXqtvCUlaq9c8bdHOkICjDMrr1+Zb3osAc=
25-
github.com/redis/go-redis/v9 v9.7.1/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
24+
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
25+
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
2626
github.com/shirou/gopsutil/v4 v4.25.2 h1:NMscG3l2CqtWFS86kj3vP7soOczqrQYIEhO/pMvvQkk=
2727
github.com/shirou/gopsutil/v4 v4.25.2/go.mod h1:34gBYJzyqCDT11b6bMHP0XCvWeU3J61XRT7a2EmCRTA=
2828
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=

0 commit comments

Comments
 (0)