chore(hset_family): Support resp3 format for hrandfield (#4978)

* chore(hset_family): Support resp3 format for hrandfield

Return nested arrays if hrandfield is used with values.

Signed-off-by: Abhijat Malviya <abhijat@dragonflydb.io>
This commit is contained in:
Abhijat Malviya 2025-04-23 18:22:02 +05:30 committed by GitHub
parent 9e3fb79225
commit 30a98c4fac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 43 additions and 3 deletions

View file

@ -1271,10 +1271,23 @@ void HSetFamily::HRandField(CmdArgList args, const CommandContext& cmd_cntx) {
auto* rb = static_cast<RedisReplyBuilder*>(cmd_cntx.rb); auto* rb = static_cast<RedisReplyBuilder*>(cmd_cntx.rb);
OpResult<StringVec> result = cmd_cntx.tx->ScheduleSingleHopT(std::move(cb)); OpResult<StringVec> result = cmd_cntx.tx->ScheduleSingleHopT(std::move(cb));
if (result) { if (result) {
if ((result->size() == 1) && (args.size() == 1)) if (result->size() == 1 && args.size() == 1)
rb->SendBulkString(result->front()); rb->SendBulkString(result->front());
else else if (with_values) {
rb->SendBulkStrArr(*result, facade::RedisReplyBuilder::ARRAY); const auto result_size = result->size();
DCHECK(result_size % 2 == 0)
<< "unexpected size of strings " << result_size << ", expected pairs";
SinkReplyBuilder::ReplyScope scope{rb};
const bool is_resp3 = rb->IsResp3();
rb->StartArray(is_resp3 ? result_size / 2 : result_size);
for (size_t i = 0; i < result_size; i += 2) {
if (is_resp3)
rb->StartArray(2);
rb->SendBulkString((*result)[i]);
rb->SendBulkString((*result)[i + 1]);
}
} else
rb->SendBulkStrArr(*result, RedisReplyBuilder::ARRAY);
} else if (result.status() == OpStatus::KEY_NOTFOUND) { } else if (result.status() == OpStatus::KEY_NOTFOUND) {
if (args.size() == 1) if (args.size() == 1)
rb->SendNull(); rb->SendNull();

View file

@ -541,4 +541,31 @@ TEST_F(HSetFamilyTest, KeyRemovedWhenEmpty) {
test_cmd([&] { EXPECT_THAT(Run({"HSTRLEN", "a", "afield"}), IntArg(0)); }, "HSTRLEN"); test_cmd([&] { EXPECT_THAT(Run({"HSTRLEN", "a", "afield"}), IntArg(0)); }, "HSTRLEN");
} }
TEST_F(HSetFamilyTest, HRandFieldRespFormat) {
absl::flat_hash_map<std::string, std::string> expected{
{"a", "1"},
{"b", "2"},
{"c", "3"},
};
Run({"HELLO", "3"});
EXPECT_THAT(Run({"HSET", "key", "a", "1", "b", "2", "c", "3"}), IntArg(3));
auto resp = Run({"HRANDFIELD", "key", "3", "WITHVALUES"});
EXPECT_THAT(resp, ArrLen(3));
for (const auto& v : resp.GetVec()) {
EXPECT_THAT(v, ArrLen(2));
const auto& kv = v.GetVec();
EXPECT_THAT(kv[0], AnyOf("a", "b", "c"));
EXPECT_THAT(kv[1], expected[kv[0].GetView()]);
}
Run({"HELLO", "2"});
resp = Run({"HRANDFIELD", "key", "3", "WITHVALUES"});
EXPECT_THAT(resp, ArrLen(6));
const auto& vec = resp.GetVec();
for (size_t i = 0; i < vec.size(); i += 2) {
EXPECT_THAT(vec[i], AnyOf("a", "b", "c"));
EXPECT_THAT(vec[i + 1], expected[vec[i].GetView()]);
}
}
} // namespace dfly } // namespace dfly