mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-11 18:35:46 +02:00
fix(json_family): Fix the JSON.SET bug if the path is in legacy mode and is not the root (#3693)
Signed-off-by: Stepan Bagritsevich <stefan@dragonflydb.io>
This commit is contained in:
parent
9b8aa8eab4
commit
3ece1725a1
2 changed files with 49 additions and 17 deletions
|
@ -391,14 +391,21 @@ string ConvertToJsonPointer(string_view json_path) {
|
|||
return result;
|
||||
}
|
||||
|
||||
string ConvertExpressionToJsonPointer(string_view json_path) {
|
||||
if (json_path.empty() || !absl::StartsWith(json_path, "$.")) {
|
||||
std::optional<std::string> ConvertExpressionToJsonPointer(string_view json_path) {
|
||||
if (json_path.empty()) {
|
||||
VLOG(1) << "retrieved malformed JSON path expression: " << json_path;
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// remove prefix
|
||||
json_path.remove_prefix(2);
|
||||
// Remove prefix
|
||||
if (json_path.front() == '$') {
|
||||
json_path.remove_prefix(1);
|
||||
}
|
||||
if (json_path.front() == '.') {
|
||||
json_path.remove_prefix(1);
|
||||
}
|
||||
|
||||
DCHECK(json_path.length());
|
||||
|
||||
std::string pointer;
|
||||
vector<string> splitted = absl::StrSplit(json_path, '.');
|
||||
|
@ -406,12 +413,12 @@ string ConvertExpressionToJsonPointer(string_view json_path) {
|
|||
if (it.front() == '[' && it.back() == ']') {
|
||||
std::string index = it.substr(1, it.size() - 2);
|
||||
if (index.empty()) {
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
for (char ch : index) {
|
||||
if (!std::isdigit(ch)) {
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1186,17 +1193,17 @@ OpResult<bool> OpSet(const OpArgs& op_args, string_view key, string_view path,
|
|||
};
|
||||
|
||||
auto inserter = [&](JsonType& json) {
|
||||
// Set a new value if the path doesn't exist and the nx condition is not set.
|
||||
// Set a new value if the path doesn't exist and the xx condition is not set.
|
||||
if (!path_exists && !is_xx_condition) {
|
||||
string pointer = ConvertExpressionToJsonPointer(path);
|
||||
if (pointer.empty()) {
|
||||
auto pointer = ConvertExpressionToJsonPointer(path);
|
||||
if (!pointer) {
|
||||
VLOG(1) << "Failed to convert the following expression path to a valid JSON pointer: "
|
||||
<< path;
|
||||
return OpStatus::SYNTAX_ERR;
|
||||
}
|
||||
|
||||
error_code ec;
|
||||
jsoncons::jsonpointer::add(json, pointer, new_json, ec);
|
||||
jsoncons::jsonpointer::add(json, pointer.value(), new_json, ec);
|
||||
if (ec) {
|
||||
VLOG(1) << "Failed to add a JSON value to the following path: " << path
|
||||
<< " with the error: " << ec.message();
|
||||
|
|
|
@ -2402,23 +2402,48 @@ TEST_F(JsonFamilyTest, SetLegacy) {
|
|||
{"a": 2}
|
||||
)";
|
||||
|
||||
resp = Run({"JSON.SET", "json3", "$", json});
|
||||
resp = Run({"JSON.SET", "json3", ".", json});
|
||||
EXPECT_THAT(resp, "OK");
|
||||
|
||||
resp = Run({"JSON.SET", "json3", "$.b", "8"});
|
||||
resp = Run({"JSON.SET", "json3", ".b", "8"});
|
||||
EXPECT_THAT(resp, "OK");
|
||||
|
||||
resp = Run({"JSON.SET", "json3", "$.c", "[1,2,3]"});
|
||||
resp = Run({"JSON.SET", "json3", ".c", "[1,2,3]"});
|
||||
EXPECT_THAT(resp, "OK");
|
||||
|
||||
resp = Run({"JSON.SET", "json3", "$.z", "3", "XX"});
|
||||
resp = Run({"JSON.SET", "json3", ".z", "3", "XX"});
|
||||
EXPECT_THAT(resp, ArgType(RespExpr::NIL));
|
||||
|
||||
resp = Run({"JSON.SET", "json3", "$.b", "4", "NX"});
|
||||
resp = Run({"JSON.SET", "json3", ".z", "3"});
|
||||
EXPECT_THAT(resp, "OK");
|
||||
|
||||
resp = Run({"JSON.SET", "json3", ".z", "4", "XX"});
|
||||
EXPECT_THAT(resp, "OK");
|
||||
|
||||
resp = Run({"JSON.SET", "json3", ".b", "4", "NX"});
|
||||
EXPECT_THAT(resp, ArgType(RespExpr::NIL));
|
||||
|
||||
resp = Run({"JSON.SET", "json3", ".b", "5"});
|
||||
EXPECT_THAT(resp, "OK");
|
||||
|
||||
resp = Run({"JSON.SET", "json3", ".", "[]", "NX"});
|
||||
EXPECT_THAT(resp, ArgType(RespExpr::NIL));
|
||||
|
||||
resp = Run({"JSON.GET", "json3"});
|
||||
EXPECT_EQ(resp, R"({"a":2,"b":8,"c":[1,2,3]})");
|
||||
EXPECT_EQ(resp, R"({"a":2,"b":5,"c":[1,2,3],"z":4})");
|
||||
|
||||
json = R"(
|
||||
{"foo": "bar"}
|
||||
)";
|
||||
|
||||
resp = Run({"JSON.SET", "json4", ".", json});
|
||||
EXPECT_THAT(resp, "OK");
|
||||
|
||||
resp = Run({"JSON.SET", "json4", "foo", "\"baz\"", "XX"});
|
||||
EXPECT_THAT(resp, "OK");
|
||||
|
||||
resp = Run({"JSON.SET", "json4", "foo2", "\"qaz\"", "NX"});
|
||||
EXPECT_THAT(resp, "OK");
|
||||
}
|
||||
|
||||
TEST_F(JsonFamilyTest, MSet) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue