diff --git a/src/base_cmd.h b/src/base_cmd.h index 14295f3ad..92a623e6a 100644 --- a/src/base_cmd.h +++ b/src/base_cmd.h @@ -77,6 +77,7 @@ const std::string kCmdNameHVals = "hvals"; const std::string kCmdNameSIsMember = "sismember"; const std::string kCmdNameSAdd = "sadd"; const std::string kCmdNameSUnionStore = "sunionstore"; +const std::string kCmdNameSInter = "sinter"; const std::string kCmdNameSRem = "srem"; const std::string kCmdNameSUnion = "sunion"; diff --git a/src/cmd_set.cc b/src/cmd_set.cc index 6a659fd7e..2cc14982b 100644 --- a/src/cmd_set.cc +++ b/src/cmd_set.cc @@ -21,15 +21,10 @@ bool SIsMemberCmd::DoInitial(PClient* client) { } void SIsMemberCmd::DoCmd(PClient* client) { PObject* value = nullptr; - auto replyNum = 0; // only change to 1 if ismember . key not exist it is 0 - PError err = PSTORE.GetValueByType(client->Key(), value, kPTypeSet); - if (err == kPErrorOK && value->CastSet()->contains(client->argv_[2])) { - // only key exist and set has key , set 1 + int32_t reply_Num = 0; // only change to 1 if ismember . key not exist it is 0 + PSTORE.GetBackend()->SIsmember(client->Key(), client->argv_[2], &reply_Num); - replyNum = 1; - } - - client->AppendInteger(replyNum); + client->AppendInteger(reply_Num); } SAddCmd::SAddCmd(const std::string& name, int16_t arity) @@ -43,75 +38,52 @@ bool SAddCmd::DoInitial(PClient* client) { // not including all the elements already present in the set. void SAddCmd::DoCmd(PClient* client) { PObject* value = nullptr; - PError err = PSTORE.GetValueByType(client->Key(), value, kPTypeSet); - if (err != kPErrorOK) { - if (err == kPErrorNotExist) { - value = PSTORE.SetValue(client->Key(), PObject::CreateSet()); - } else { - client->SetRes(CmdRes::kSyntaxErr, "sadd cmd error"); - return; - } - } - auto set = value->CastSet(); - const auto oldSize = set->size(); - for (int i = 2; i < client->argv_.size(); ++i) { - set->insert(client->argv_[i]); + const std::vector members(client->argv_.begin() + 2, client->argv_.end()); + int32_t ret = 0; + storage::Status s = PSTORE.GetBackend()->SAdd(client->Key(), members, &ret); + if (s.ok()) { + client->AppendInteger(ret); + } else { + client->SetRes(CmdRes::kSyntaxErr, "sadd cmd error"); } - // new size is bigger than old size , avoid the risk - client->AppendInteger(set->size() - oldSize); } SUnionStoreCmd::SUnionStoreCmd(const std::string& name, int16_t arity) : BaseCmd(name, arity, kCmdFlagsWrite, kAclCategoryWrite | kAclCategorySet) {} bool SUnionStoreCmd::DoInitial(PClient* client) { - std::vector keys(client->argv_.begin(), client->argv_.end()); - keys.erase(keys.begin()); + std::vector keys(client->argv_.begin() + 1, client->argv_.end()); client->SetKey(keys); return true; } void SUnionStoreCmd::DoCmd(PClient* client) { - std::unordered_set unionSet; - std::string destKey = client->Keys().at(0); std::vector keys(client->Keys().begin() + 1, client->Keys().end()); - - PObject* value = nullptr; - for (auto key : keys) { - PError err = PSTORE.GetValueByType(key, value, kPTypeSet); - if (err == kPErrorOK) { - const auto set = value->CastSet(); - auto it = set->cbegin(); - for (; it != set->cend(); ++it) { - std::string sv(it->data(), it->size()); - if (unionSet.find(sv) == unionSet.end()) { - unionSet.insert(sv); - } - } - } else if (err != kPErrorNotExist) { - client->SetRes(CmdRes::kErrOther); - return; - } + std::vector value_to_dest; + int32_t ret = 0; + storage::Status s = PSTORE.GetBackend()->SUnionstore(client->Keys().at(0), keys, value_to_dest, &ret); + if (!s.ok()) { + client->SetRes(CmdRes::kSyntaxErr, "sunionstore cmd error"); } + client->AppendInteger(ret); +} +SInterCmd::SInterCmd(const std::string& name, int16_t arity) + : BaseCmd(name, arity, kCmdFlagsReadonly, kAclCategoryRead | kAclCategorySet) {} - PError err = PSTORE.GetValueByType(destKey, value, kPTypeSet); - if (err == kPErrorOK) { - auto updateSet = value->CastSet(); - updateSet->clear(); - for (auto it : unionSet) { - updateSet->emplace(it); - } - client->AppendInteger(updateSet->size()); - } else if (err == kPErrorNotExist) { - value = PSTORE.SetValue(destKey, PObject::CreateSet()); - auto updateSet = value->CastSet(); - for (auto it : unionSet) { - updateSet->emplace(it); - } - client->AppendInteger(updateSet->size()); - } else { - client->SetRes(CmdRes::kErrOther); +bool SInterCmd::DoInitial(PClient* client) { + std::vector keys(client->argv_.begin() + 1, client->argv_.end()); + + client->SetKey(keys); + return true; +} + +void SInterCmd::DoCmd(PClient* client) { + std::vector res_vt; + storage::Status s = PSTORE.GetBackend()->SInter(client->Keys(), &res_vt); + if (!s.ok()) { + client->SetRes(CmdRes::kErrOther, "sinter cmd error"); } + client->AppendStringVector(res_vt); } SRemCmd::SRemCmd(const std::string& name, int16_t arity) @@ -123,23 +95,13 @@ bool SRemCmd::DoInitial(PClient* client) { } void SRemCmd::DoCmd(PClient* client) { - PObject* value = nullptr; - PError err = PSTORE.GetValueByType(client->Key(), value, kPTypeSet); - int retVal = 0; - if (err != kPErrorOK) { - if (err == kPErrorNotExist) { - client->AppendInteger(0); - } else { - client->SetRes(CmdRes::kSyntaxErr, "srem cmd error"); - } - return; + std::vector to_delete_members(client->argv_.begin() + 2, client->argv_.end()); + int32_t reply_num = 0; + storage::Status s = PSTORE.GetBackend()->SRem(client->Key(), to_delete_members, &reply_num); + if (!s.ok()) { + client->SetRes(CmdRes::kErrOther, "srem cmd error"); } - auto unset = value->CastSet(); - const auto oldSize = unset->size(); - for (int i = 2; i < client->argv_.size(); ++i) { - unset->erase(client->argv_[i]); - } - client->AppendInteger(oldSize - unset->size()); + client->AppendInteger(reply_num); } SUnionCmd::SUnionCmd(const std::string& name, int16_t arity) @@ -152,24 +114,11 @@ bool SUnionCmd::DoInitial(PClient* client) { } void SUnionCmd::DoCmd(PClient* client) { - std::unordered_set unionSet; - for (auto key : client->Keys()) { - PObject* value = nullptr; - PError err = PSTORE.GetValueByType(key, value, kPTypeSet); - if (err == kPErrorOK) { - const auto set = value->CastSet(); - for (const auto& it : *set) { - unionSet.insert(it); - } - } else if (err != kPErrorNotExist) { - client->SetRes(CmdRes::kErrOther); - return; - } - } - client->AppendArrayLenUint64(unionSet.size()); - for (const auto& member : unionSet) { - client->AppendStringLenUint64(member.size()); - client->AppendContent(member); + std::vector res_vt; + storage::Status s = PSTORE.GetBackend()->SUnion(client->Keys(), &res_vt); + if (!s.ok()) { + client->SetRes(CmdRes::kErrOther, "sunion cmd error"); } + client->AppendStringVector(res_vt); } -} // namespace pikiwidb \ No newline at end of file +} // namespace pikiwidb diff --git a/src/cmd_set.h b/src/cmd_set.h index b0b2f4dc2..f95751910 100644 --- a/src/cmd_set.h +++ b/src/cmd_set.h @@ -64,4 +64,15 @@ class SUnionCmd : public BaseCmd { private: void DoCmd(PClient *client) override; }; +class SInterCmd : public BaseCmd { + public: + SInterCmd(const std::string &name, int16_t arity); + + protected: + bool DoInitial(PClient *client) override; + + private: + void DoCmd(PClient *client) override; +}; + } // namespace pikiwidb diff --git a/src/cmd_table_manager.cc b/src/cmd_table_manager.cc index 08b639aa8..370f1597a 100644 --- a/src/cmd_table_manager.cc +++ b/src/cmd_table_manager.cc @@ -82,6 +82,7 @@ void CmdTableManager::InitCmdTable() { ADD_COMMAND(SAdd, -3); ADD_COMMAND(SUnionStore, -3); ADD_COMMAND(SRem, -3); + ADD_COMMAND(SInter, -2); ADD_COMMAND(SUnion, -2); } diff --git a/tests/set_test.go b/tests/set_test.go index f75b8cd42..b6ca88b50 100644 --- a/tests/set_test.go +++ b/tests/set_test.go @@ -110,4 +110,59 @@ var _ = Describe("Set", Ordered, func() { //Expect(sMembers.Err()).NotTo(HaveOccurred()) //Expect(sMembers.Val()).To(HaveLen(5)) }) + It("Cmd SADD", func() { + log.Println("Cmd SADD Begin") + Expect(client.SAdd(ctx, "myset", "one", "two").Val()).NotTo(Equal("FooBar")) + }) + It("should SAdd", func() { + sAdd := client.SAdd(ctx, "setSAdd1", "Hello") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(1))) + + sAdd = client.SAdd(ctx, "setSAdd1", "World") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(1))) + + sAdd = client.SAdd(ctx, "setSAdd1", "World") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(0))) + + // sMembers := client.SMembers(ctx, "set") After the smember command is developed, uncomment it to test smember command. + // Expect(sMembers.Err()).NotTo(HaveOccurred()) + // Expect(sMembers.Val()).To(ConsistOf([]string{"Hello", "World"})) + }) + + It("should SAdd strings", func() { + set := []string{"Hello", "World", "World"} + sAdd := client.SAdd(ctx, "setSAdd2", set) + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(2))) + + // sMembers := client.SMembers(ctx, "set") After the smember command is developed, uncomment it to test smember command. + // Expect(sMembers.Err()).NotTo(HaveOccurred()) + // Expect(sMembers.Val()).To(ConsistOf([]string{"Hello", "World"})) + }) + It("should SInter", func() { + sAdd := client.SAdd(ctx, "set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd(ctx, "set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sInter := client.SInter(ctx, "set1", "set2") + Expect(sInter.Err()).NotTo(HaveOccurred()) + Expect(sInter.Val()).To(Equal([]string{"c"})) + + sInter = client.SInter(ctx, "nonexistent_set1", "nonexistent_set2") + Expect(sInter.Err()).NotTo(HaveOccurred()) + Expect(sInter.Val()).To(HaveLen(0)) + }) })