Skip to content

Commit

Permalink
Merge branch 'unstable' into bitfield-command
Browse files Browse the repository at this point in the history
  • Loading branch information
git-hulk authored Dec 1, 2023
2 parents 289d25b + 155f3d9 commit ac8a4fd
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 3 deletions.
25 changes: 24 additions & 1 deletion src/commands/cmd_json.cc
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,28 @@ class CommanderJsonArrIndex : public Commander {
ssize_t end_;
};

class CommandJsonDel : public Commander {
public:
Status Execute(Server *svr, Connection *conn, std::string *output) override {
redis::Json json(svr->storage, conn->GetNamespace());
size_t result = 0;
std::string path = "$";
if (args_.size() == 3) {
path = args_[2];
} else if (args_.size() > 3) {
return {Status::RedisExecErr, "The number of arguments is more than expected"};
}
auto s = json.Del(args_[1], path, &result);
if (s.IsNotFound()) {
*output = redis::NilString();
return Status::OK();
}
if (!s.ok()) return {Status::RedisExecErr, s.ToString()};
*output = redis::Integer(result);
return Status::OK();
}
};

REDIS_REGISTER_COMMANDS(MakeCmdAttr<CommandJsonSet>("json.set", 4, "write", 1, 1, 1),
MakeCmdAttr<CommandJsonGet>("json.get", -2, "read-only", 1, 1, 1),
MakeCmdAttr<CommandJsonInfo>("json.info", 2, "read-only", 1, 1, 1),
Expand All @@ -491,6 +513,7 @@ REDIS_REGISTER_COMMANDS(MakeCmdAttr<CommandJsonSet>("json.set", 4, "write", 1, 1
MakeCmdAttr<CommandJsonMerge>("json.merge", 4, "write", 1, 1, 1),
MakeCmdAttr<CommandJsonObjkeys>("json.objkeys", -2, "read-only", 1, 1, 1),
MakeCmdAttr<CommandJsonArrPop>("json.arrpop", -2, "write", 1, 1, 1),
MakeCmdAttr<CommanderJsonArrIndex>("json.arrindex", -4, "read-only", 1, 1, 1), );
MakeCmdAttr<CommanderJsonArrIndex>("json.arrindex", -4, "read-only", 1, 1, 1),
MakeCmdAttr<CommandJsonDel>("json.del", -2, "write", 1, 1, 1), );

} // namespace redis
11 changes: 11 additions & 0 deletions src/types/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#pragma once

#include <algorithm>
#include <cstddef>
#include <jsoncons/json.hpp>
#include <jsoncons/json_error.hpp>
#include <jsoncons/json_options.hpp>
Expand Down Expand Up @@ -475,6 +476,16 @@ struct JsonValue {
return Status::OK();
}

StatusOr<size_t> Del(const std::string &path) {
size_t count = 0;
try {
count = jsoncons::jsonpath::remove(value, path);
} catch (const jsoncons::jsonpath::jsonpath_error &e) {
return {Status::NotOK, e.what()};
}
return count;
}

JsonValue(const JsonValue &) = default;
JsonValue(JsonValue &&) = default;

Expand Down
35 changes: 35 additions & 0 deletions src/types/redis_json.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ rocksdb::Status Json::create(const std::string &ns_key, JsonMetadata &metadata,
return write(ns_key, &metadata, json_val);
}

rocksdb::Status Json::del(const Slice &ns_key) {
auto batch = storage_->GetWriteBatchBase();
WriteBatchLogData log_data(kRedisJson);
batch->PutLogData(log_data.Encode());

batch->Delete(metadata_cf_handle_, ns_key);

return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch());
}

rocksdb::Status Json::Info(const std::string &user_key, JsonStorageFormat *storage_format) {
auto ns_key = AppendNamespacePrefix(user_key);

Expand Down Expand Up @@ -390,4 +400,29 @@ rocksdb::Status Json::ArrTrim(const std::string &user_key, const std::string &pa
return write(ns_key, &metadata, json_val);
}

rocksdb::Status Json::Del(const std::string &user_key, const std::string &path, size_t *result) {
auto ns_key = AppendNamespacePrefix(user_key);

LockGuard guard(storage_->GetLockManager(), ns_key);
if (path == "$") {
*result = 1;
return del(ns_key);
}
JsonValue json_val;
JsonMetadata metadata;
auto s = read(ns_key, &metadata, &json_val);

if (!s.ok()) return s;

auto res = json_val.Del(path);
if (!res) return rocksdb::Status::InvalidArgument(res.Msg());

*result = *res;
if (*result == 0) {
return rocksdb::Status::OK();
}

return write(ns_key, &metadata, json_val);
}

} // namespace redis
2 changes: 2 additions & 0 deletions src/types/redis_json.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@ class Json : public Database {

rocksdb::Status ArrTrim(const std::string &user_key, const std::string &path, int64_t start, int64_t stop,
std::vector<std::optional<uint64_t>> &results);
rocksdb::Status Del(const std::string &user_key, const std::string &path, size_t *result);

private:
rocksdb::Status write(Slice ns_key, JsonMetadata *metadata, const JsonValue &json_val);
rocksdb::Status read(const Slice &ns_key, JsonMetadata *metadata, JsonValue *value);
rocksdb::Status create(const std::string &ns_key, JsonMetadata &metadata, const std::string &value);
rocksdb::Status del(const Slice &ns_key);
};

} // namespace redis
54 changes: 52 additions & 2 deletions tests/cppunit/types/json_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,13 @@ TEST_F(RedisJsonTest, Set) {
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(), R"([{},[{},4]])");

ASSERT_TRUE(json_->Del(key_).ok());
size_t result = 0;
ASSERT_TRUE(json_->Del(key_, "$", &result).ok());
ASSERT_TRUE(json_->Set(key_, "$", "[{ }, [ ]]").ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(), "[{},[]]");
ASSERT_THAT(json_->Set(key_, "$[1]", "invalid").ToString(), MatchesRegex(".*syntax_error.*"));
ASSERT_TRUE(json_->Del(key_).ok());
ASSERT_TRUE(json_->Del(key_, "$", &result).ok());
}

TEST_F(RedisJsonTest, Get) {
Expand Down Expand Up @@ -485,3 +486,52 @@ TEST_F(RedisJsonTest, ArrIndex) {
ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "3", 0, 2, &res).ok() && res.size() == 1);
ASSERT_EQ(res[0], -1);
}

TEST_F(RedisJsonTest, Del) {
size_t result = 0;

ASSERT_TRUE(
json_
->Set(key_, "$",
R"({"obj":{"a":1, "b":2}, "arr":[1,2,3], "str": "foo", "bool": true, "int": 42, "float": 3.14})")
.ok());

ASSERT_TRUE(json_->Del(key_, "$", &result).ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).IsNotFound());
ASSERT_EQ(result, 1);

ASSERT_TRUE(
json_
->Set(key_, "$",
R"({"obj":{"a":1, "b":2}, "arr":[1,2,3], "str": "foo", "bool": true, "int": 42, "float": 3.14})")
.ok());

ASSERT_TRUE(json_->Del(key_, "$.obj", &result).ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(), R"({"arr":[1,2,3],"bool":true,"float":3.14,"int":42,"str":"foo"})");
ASSERT_EQ(result, 1);

ASSERT_TRUE(json_->Del(key_, "$.arr", &result).ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(), R"({"bool":true,"float":3.14,"int":42,"str":"foo"})");
ASSERT_EQ(result, 1);

ASSERT_TRUE(
json_
->Set(key_, "$",
R"({"obj":{"a":1, "b":2}, "arr":[1,2,3], "str": "foo", "bool": true, "int": 42, "float": 3.14})")
.ok());
ASSERT_TRUE(json_->Del(key_, "$.*", &result).ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(), R"({})");
ASSERT_EQ(result, 6);

ASSERT_TRUE(json_->Del(key_, "$.some", &result).ok());
ASSERT_EQ(result, 0);

ASSERT_TRUE(json_->Set(key_, "$", R"({"a": 1, "nested": {"a": 2, "b": 3}})").ok());
ASSERT_TRUE(json_->Del(key_, "$..a", &result).ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(), R"({"nested":{"b":3}})");
ASSERT_EQ(result, 2);
}

0 comments on commit ac8a4fd

Please sign in to comment.