Reverse range for reverse z-commands. Fixes #27

This commit is contained in:
Roman Gershman 2022-04-25 15:38:29 +03:00
parent 69c8658be4
commit 8ae7436a22
3 changed files with 57 additions and 37 deletions

View File

@ -57,7 +57,6 @@ TEST_F(ListFamilyTest, Expire) {
EXPECT_THAT(resp, IntArg(1));
}
TEST_F(ListFamilyTest, BLPopUnblocking) {
auto resp = Run({"lpush", kKey1, "1"});
EXPECT_THAT(resp, IntArg(1));
@ -158,6 +157,20 @@ TEST_F(ListFamilyTest, BLPopTimeout) {
ASSERT_FALSE(service_->IsLocked(0, kKey1));
}
TEST_F(ListFamilyTest, BLPopTimeout2) {
Run({"BLPOP", "blist1", "blist2", "0.1"});
Run({"RPUSH", "blist2", "d"});
Run({"RPUSH", "blist2", "hello"});
auto resp = Run({"BLPOP", "blist1", "blist2", "1"});
ASSERT_THAT(resp, ArrLen(2));
ASSERT_THAT(resp.GetVec(), ElementsAre("blist2", "d"));
Run({"RPUSH", "blist1", "a"});
Run({"DEL", "blist2"});
Run({"RPUSH", "blist2", "d"});
// Run({"BLPOP", "blist1", "blist2", "1"});
}
TEST_F(ListFamilyTest, LRem) {
auto resp = Run({"rpush", kKey1, "a", "b", "a", "c"});
ASSERT_THAT(resp, IntArg(4));
@ -297,9 +310,7 @@ TEST_F(ListFamilyTest, BPopSameKeyTwice) {
this_fiber::sleep_for(30us);
} while (!IsLocked(0, kKey1));
pp_->at(1)->Await([&] {
EXPECT_EQ(1, CheckedInt({"lpush", kKey1, "bar"}));
});
pp_->at(1)->Await([&] { EXPECT_EQ(1, CheckedInt({"lpush", kKey1, "bar"})); });
pop_fb.join();
ASSERT_THAT(blpop_resp, ArrLen(2));
@ -313,9 +324,7 @@ TEST_F(ListFamilyTest, BPopSameKeyTwice) {
this_fiber::sleep_for(30us);
} while (!IsLocked(0, kKey1));
pp_->at(1)->Await([&] {
EXPECT_EQ(1, CheckedInt({"lpush", kKey2, "bar"}));
});
pp_->at(1)->Await([&] { EXPECT_EQ(1, CheckedInt({"lpush", kKey2, "bar"})); });
pop_fb.join();
ASSERT_THAT(blpop_resp, ArrLen(2));

View File

@ -37,38 +37,43 @@ static const char kLexRangeErr[] = "min or max not valid string range item";
constexpr unsigned kMaxListPackValue = 64;
inline zrangespec GetZrangeSpec(const ZSetFamily::ScoreInterval& si) {
inline zrangespec GetZrangeSpec(bool reverse, const ZSetFamily::ScoreInterval& si) {
auto interval = si;
if (reverse)
swap(interval.first, interval.second);
zrangespec range;
range.min = si.first.val;
range.max = si.second.val;
range.minex = si.first.is_open;
range.maxex = si.second.is_open;
range.min = interval.first.val;
range.max = interval.second.val;
range.minex = interval.first.is_open;
range.maxex = interval.second.is_open;
return range;
}
zlexrangespec GetLexRange(const ZSetFamily::LexInterval& li) {
sds GetLexStr(const ZSetFamily::LexBound& bound) {
if (bound.type == ZSetFamily::LexBound::MINUS_INF)
return cminstring;
if (bound.type == ZSetFamily::LexBound::PLUS_INF)
return cmaxstring;
return sdsnewlen(bound.val.data(), bound.val.size());
};
zlexrangespec GetLexRange(bool reverse, const ZSetFamily::LexInterval& li) {
auto interval = li;
if (reverse)
swap(interval.first, interval.second);
zlexrangespec range;
range.minex = 0;
range.maxex = 0;
if (li.first.type == ZSetFamily::LexBound::MINUS_INF) {
range.min = cminstring;
} else if (li.first.type == ZSetFamily::LexBound::PLUS_INF) {
range.min = cmaxstring;
} else {
range.min = sdsnewlen(li.first.val.data(), li.first.val.size());
range.minex = (li.first.type == ZSetFamily::LexBound::OPEN);
}
if (li.second.type == ZSetFamily::LexBound::MINUS_INF) {
range.max = cminstring;
} else if (li.second.type == ZSetFamily::LexBound::PLUS_INF) {
range.max = cmaxstring;
} else {
range.max = sdsnewlen(li.second.val.data(), li.second.val.size());
range.maxex = (li.second.type == ZSetFamily::LexBound::OPEN);
}
range.min = GetLexStr(interval.first);
range.max = GetLexStr(interval.second);
range.minex = (interval.first.type == ZSetFamily::LexBound::OPEN);
range.maxex = (li.second.type == ZSetFamily::LexBound::OPEN);
return range;
}
@ -195,7 +200,7 @@ void IntervalVisitor::operator()(const ZSetFamily::IndexInterval& ii) {
}
void IntervalVisitor::operator()(const ZSetFamily::ScoreInterval& si) {
zrangespec range = GetZrangeSpec(si);
zrangespec range = GetZrangeSpec(params_.reverse, si);
switch (action_) {
case Action::RANGE:
@ -208,7 +213,7 @@ void IntervalVisitor::operator()(const ZSetFamily::ScoreInterval& si) {
}
void IntervalVisitor::operator()(const ZSetFamily::LexInterval& li) {
zlexrangespec range = GetLexRange(li);
zlexrangespec range = GetLexRange(params_.reverse, li);
switch (action_) {
case Action::RANGE:
@ -218,6 +223,7 @@ void IntervalVisitor::operator()(const ZSetFamily::LexInterval& li) {
ActionRem(range);
break;
}
zslFreeLexRange(&range);
}
void IntervalVisitor::ActionRange(unsigned start, unsigned end) {
@ -1136,7 +1142,6 @@ OpResult<StringVec> ZSetFamily::OpScan(const OpArgs& op_args, std::string_view k
ScoredArray arr = iv.PopResult();
res.resize(arr.size() * 2);
for (size_t i = 0; i < arr.size(); ++i) {
StringBuilder sb(buf, sizeof(buf));
CHECK(DoubleToStringConverter::EcmaScriptConverter().ToShortest(arr[i].second, &sb));
@ -1330,7 +1335,7 @@ OpResult<unsigned> ZSetFamily::OpCount(const OpArgs& op_args, std::string_view k
return res_it.status();
robj* zobj = res_it.value()->second.AsRObj();
zrangespec range = GetZrangeSpec(interval);
zrangespec range = GetZrangeSpec(false, interval);
unsigned count = 0;
if (zobj->encoding == OBJ_ENCODING_LISTPACK) {
@ -1401,7 +1406,7 @@ OpResult<unsigned> ZSetFamily::OpLexCount(const OpArgs& op_args, string_view key
return res_it.status();
robj* zobj = res_it.value()->second.AsRObj();
zlexrangespec range = GetLexRange(interval);
zlexrangespec range = GetLexRange(false, interval);
unsigned count = 0;
if (zobj->encoding == OBJ_ENCODING_LISTPACK) {
uint8_t* zl = (uint8_t*)zobj->ptr;

View File

@ -70,7 +70,7 @@ TEST_F(ZSetFamilyTest, ZRangeRank) {
EXPECT_THAT(Run({"zrangebyscore", "x", "0", "(1.1"}), ArrLen(0));
EXPECT_THAT(Run({"zrangebyscore", "x", "-inf", "1.1"}), "a");
auto resp = Run({"zrevrangebyscore", "x", "-inf", "+inf"});
auto resp = Run({"zrevrangebyscore", "x", "+inf", "-inf"});
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
ASSERT_THAT(resp.GetVec(), ElementsAre("b", "a"));
@ -134,8 +134,14 @@ TEST_F(ZSetFamilyTest, ByLex) {
ASSERT_THAT(resp.GetVec(), ElementsAre("alpha", "bar", "cool", "down", "elephant", "foo"));
}
TEST_F(ZSetFamilyTest, ZRevRange) {
Run({"zadd", "key", "-inf", "a", "1", "b", "2", "c"});
auto resp = Run({"zrevrangebyscore", "key", "2", "-inf"});
EXPECT_THAT(resp, ArrLen(3));
}
TEST_F(ZSetFamilyTest, ZScan) {
string prefix(128,'a');
string prefix(128, 'a');
for (unsigned i = 0; i < 100; ++i) {
Run({"zadd", "key", "1", absl::StrCat(prefix, i)});
}