Add StrLen and GetRange commands

This commit is contained in:
Roman Gershman 2022-03-24 14:16:00 +02:00
parent fd220ea621
commit 0ce043e7a4
5 changed files with 85 additions and 9 deletions

View File

@ -498,11 +498,14 @@ size_t CompactObj::Size() const {
return taglen_;
}
if (taglen_ == SMALL_TAG) {
switch (taglen_) {
case SMALL_TAG:
return u_.small_str.size();
case INT_TAG: {
absl::AlphaNum an(u_.ival);
return an.size();
}
if (taglen_ == ROBJ_TAG) {
case ROBJ_TAG:
return u_.r_obj.Size();
}

View File

@ -106,12 +106,15 @@ TEST_F(CompactObjectTest, InlineAsciiEncoded) {
TEST_F(CompactObjectTest, Int) {
cobj_.SetString("0");
EXPECT_EQ(0, cobj_.TryGetInt());
EXPECT_EQ(1, cobj_.Size());
EXPECT_EQ(cobj_, "0");
EXPECT_EQ("0", cobj_.GetSlice(&tmp_));
EXPECT_EQ(OBJ_STRING, cobj_.ObjType());
cobj_.SetString("42");
EXPECT_EQ(8181779779123079347, cobj_.HashCode());
EXPECT_EQ(OBJ_ENCODING_INT, cobj_.Encoding());
EXPECT_EQ(2, cobj_.Size());
}
TEST_F(CompactObjectTest, MediumString) {

View File

@ -72,7 +72,6 @@ int main(int argc, char* argv[]) {
}
mi_option_enable(mi_option_show_errors);
mi_option_set(mi_option_max_warnings, 0);
_mi_options_init();
uring::UringPool pp{1024};
pp.Run();

View File

@ -432,6 +432,73 @@ void StringFamily::MSet(CmdArgList args, ConnectionContext* cntx) {
return (*cntx)->SendOk();
}
void StringFamily::StrLen(CmdArgList args, ConnectionContext* cntx) {
string_view key = ArgS(args, 1);
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<size_t> {
OpResult<MainIterator> it_res = shard->db_slice().Find(t->db_index(), key, OBJ_STRING);
if (!it_res.ok())
return it_res.status();
return it_res.value()->second.Size();
};
Transaction* trans = cntx->transaction;
OpResult<size_t> result = trans->ScheduleSingleHopT(std::move(cb));
if (result.status() == OpStatus::WRONG_TYPE) {
(*cntx)->SendError(result.status());
} else {
(*cntx)->SendLong(result.value());
}
}
void StringFamily::GetRange(CmdArgList args, ConnectionContext* cntx) {
string_view key = ArgS(args, 1);
string_view from = ArgS(args, 2);
string_view to = ArgS(args, 3);
int32_t start, end;
if (!absl::SimpleAtoi(from, &start) || !absl::SimpleAtoi(to, &end)) {
return (*cntx)->SendError(kInvalidIntErr);
}
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<string> {
OpResult<MainIterator> it_res = shard->db_slice().Find(t->db_index(), key, OBJ_STRING);
if (!it_res.ok())
return it_res.status();
if (start < 0 && end < 0 && start > end) {
return OpStatus::OK;
}
const CompactObj& co = it_res.value()->second;
size_t strlen = co.Size();
if (start < 0)
start = strlen + start;
if (end < 0)
end = strlen + end;
if (start < 0)
start = 0;
if (end < 0)
end = 0;
if (size_t(end) >= strlen)
end = strlen - 1;
string tmp;
string_view slice = co.GetSlice(&tmp);
return string(slice.substr(start, end - start + 1));
};
Transaction* trans = cntx->transaction;
OpResult<string> result = trans->ScheduleSingleHopT(std::move(cb));
if (result.status() == OpStatus::WRONG_TYPE) {
(*cntx)->SendError(result.status());
} else {
(*cntx)->SendBulkString(result.value());
}
}
auto StringFamily::OpMGet(bool fetch_mcflag, bool fetch_mcver, const Transaction* t,
EngineShard* shard) -> MGetResponse {
auto args = t->ShardArgsInShard(shard->shard_id());
@ -587,7 +654,9 @@ void StringFamily::Register(CommandRegistry* registry) {
<< CI{"GET", CO::READONLY | CO::FAST, 2, 1, 1, 1}.HFUNC(Get)
<< CI{"GETSET", CO::WRITE | CO::DENYOOM | CO::FAST, 3, 1, 1, 1}.HFUNC(GetSet)
<< CI{"MGET", CO::READONLY | CO::FAST, -2, 1, -1, 1}.HFUNC(MGet)
<< CI{"MSET", CO::WRITE | CO::DENYOOM, -3, 1, -1, 2}.HFUNC(MSet);
<< CI{"MSET", CO::WRITE | CO::DENYOOM, -3, 1, -1, 2}.HFUNC(MSet)
<< CI{"STRLEN", CO::READONLY | CO::FAST, 2, 1, 1, 1}.HFUNC(StrLen)
<< CI{"GETRANGE", CO::READONLY | CO::FAST, 4, 1, 1, 1}.HFUNC(GetRange);
}
} // namespace dfly

View File

@ -61,6 +61,8 @@ class StringFamily {
static void DecrBy(CmdArgList args, ConnectionContext* cntx);
static void Append(CmdArgList args, ConnectionContext* cntx);
static void Prepend(CmdArgList args, ConnectionContext* cntx);
static void StrLen(CmdArgList args, ConnectionContext* cntx);
static void GetRange(CmdArgList args, ConnectionContext* cntx);
static void IncrByGeneric(std::string_view key, int64_t val, ConnectionContext* cntx);
static void ExtendGeneric(CmdArgList args, bool prepend, ConnectionContext* cntx);