This is an automated email from the ASF dual-hosted git repository.
hulk pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new 6cb5b3aa Minor refactor the return value of JSON methods (#1920)
6cb5b3aa is described below
commit 6cb5b3aa57805299359e73e903212b2e25dbfcad
Author: hulk <[email protected]>
AuthorDate: Wed Dec 6 09:43:45 2023 +0800
Minor refactor the return value of JSON methods (#1920)
---
src/commands/cmd_json.cc | 144 ++++++++++++---------------------------
src/types/json.h | 131 ++++++++++++++++++-----------------
src/types/redis_json.cc | 73 ++++++++++----------
src/types/redis_json.h | 23 +++----
tests/cppunit/types/json_test.cc | 90 ++++++++++++------------
5 files changed, 203 insertions(+), 258 deletions(-)
diff --git a/src/commands/cmd_json.cc b/src/commands/cmd_json.cc
index 6602cc9f..41763bdb 100644
--- a/src/commands/cmd_json.cc
+++ b/src/commands/cmd_json.cc
@@ -32,6 +32,19 @@
namespace redis {
+template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
+std::string OptionalsToString(Optionals<T> &opts) {
+ std::string str = MultiLen(opts.size());
+ for (const auto &opt : opts) {
+ if (opt.has_value()) {
+ str += redis::Integer(opt.value());
+ } else {
+ str += redis::NilString();
+ }
+ }
+ return str;
+}
+
class CommandJsonSet : public Commander {
public:
Status Execute(Server *srv, Connection *conn, std::string *output) override {
@@ -126,20 +139,12 @@ class CommandJsonArrAppend : public Commander {
Status Execute(Server *srv, Connection *conn, std::string *output) override {
redis::Json json(srv->storage, conn->GetNamespace());
- std::vector<size_t> result_count;
+ Optionals<size_t> results;
- auto s = json.ArrAppend(args_[1], args_[2], {args_.begin() + 3,
args_.end()}, &result_count);
+ auto s = json.ArrAppend(args_[1], args_[2], {args_.begin() + 3,
args_.end()}, &results);
if (!s.ok()) return {Status::RedisExecErr, s.ToString()};
- *output = redis::MultiLen(result_count.size());
- for (size_t c : result_count) {
- if (c != 0) {
- *output += redis::Integer(c);
- } else {
- *output += redis::NilString();
- }
- }
-
+ *output = OptionalsToString(results);
return Status::OK();
}
};
@@ -159,25 +164,17 @@ class CommandJsonArrInsert : public Commander {
Status Execute(Server *srv, Connection *conn, std::string *output) override {
redis::Json json(srv->storage, conn->GetNamespace());
- std::vector<std::optional<uint64_t>> result_count;
+ Optionals<uint64_t> results;
auto parse_result = ParseInt<int>(args_[3], 10);
- auto s = json.ArrInsert(args_[1], args_[2], index_, {args_.begin() + 4,
args_.end()}, &result_count);
+ auto s = json.ArrInsert(args_[1], args_[2], index_, {args_.begin() + 4,
args_.end()}, &results);
if (s.IsNotFound()) {
*output = redis::NilString();
return Status::OK();
}
if (!s.ok()) return {Status::RedisExecErr, s.ToString()};
- *output = redis::MultiLen(result_count.size());
- for (auto c : result_count) {
- if (c.has_value()) {
- *output += redis::Integer(c.value());
- } else {
- *output += redis::NilString();
- }
- }
-
+ *output = OptionalsToString(results);
return Status::OK();
}
@@ -215,11 +212,11 @@ class CommandJsonObjkeys : public Commander {
Status Execute(Server *srv, Connection *conn, std::string *output) override {
redis::Json json(srv->storage, conn->GetNamespace());
- std::vector<std::optional<std::vector<std::string>>> results;
+ Optionals<std::vector<std::string>> results;
// If path not specified set it to $
std::string path = (args_.size() > 2) ? args_[2] : "$";
- auto s = json.ObjKeys(args_[1], path, results);
+ auto s = json.ObjKeys(args_[1], path, &results);
if (!s.ok() && !s.IsNotFound()) return {Status::RedisExecErr,
s.ToString()};
if (s.IsNotFound()) {
*output = redis::NilString();
@@ -268,25 +265,15 @@ class CommandJsonToggle : public Commander {
redis::Json json(svr->storage, conn->GetNamespace());
std::string path = (args_.size() > 2) ? args_[2] : "$";
- std::vector<std::optional<bool>> results;
- auto s = json.Toggle(args_[1], path, results);
-
+ Optionals<bool> results;
+ auto s = json.Toggle(args_[1], path, &results);
+ if (!s.ok() && !s.IsNotFound()) return {Status::RedisExecErr,
s.ToString()};
if (s.IsNotFound()) {
*output = redis::NilString();
return Status::OK();
}
- *output = redis::MultiLen(results.size());
- for (auto it = results.rbegin(); it != results.rend(); ++it) {
- if (it->has_value()) {
- *output += redis::Integer(it->value());
- } else {
- *output += redis::NilString();
- }
- }
-
- if (!s.ok()) return {Status::RedisExecErr, s.ToString()};
-
+ *output = OptionalsToString(results);
return Status::OK();
}
};
@@ -303,23 +290,15 @@ class CommandJsonArrLen : public Commander {
return {Status::RedisExecErr, "The number of arguments is more than
expected"};
}
- std::vector<std::optional<uint64_t>> results;
- auto s = json.ArrLen(args_[1], path, results);
+ Optionals<uint64_t> results;
+ auto s = json.ArrLen(args_[1], path, &results);
if (s.IsNotFound()) {
*output = redis::NilString();
return Status::OK();
}
if (!s.ok()) return {Status::RedisExecErr, s.ToString()};
- *output = redis::MultiLen(results.size());
- for (const auto &len : results) {
- if (len.has_value()) {
- *output += redis::Integer(len.value());
- } else {
- *output += redis::NilString();
- }
- }
-
+ *output = OptionalsToString(results);
return Status::OK();
}
};
@@ -367,7 +346,7 @@ class CommandJsonArrPop : public Commander {
Status Execute(Server *srv, Connection *conn, std::string *output) override {
redis::Json json(srv->storage, conn->GetNamespace());
- std::vector<std::optional<JsonValue>> results;
+ Optionals<JsonValue> results;
auto s = json.ArrPop(args_[1], path_, index_, &results);
if (!s.ok()) return {Status::RedisExecErr, s.ToString()};
@@ -401,23 +380,15 @@ class CommandJsonObjLen : public Commander {
return {Status::RedisExecErr, "The number of arguments is more than
expected"};
}
- std::vector<std::optional<uint64_t>> results;
- auto s = json.ObjLen(args_[1], path, results);
+ Optionals<uint64_t> results;
+ auto s = json.ObjLen(args_[1], path, &results);
if (s.IsNotFound()) {
*output = redis::NilString();
return Status::OK();
}
if (!s.ok()) return {Status::RedisExecErr, s.ToString()};
- *output = redis::MultiLen(results.size());
- for (const auto &len : results) {
- if (len.has_value()) {
- *output += redis::Integer(len.value());
- } else {
- *output += redis::NilString();
- }
- }
-
+ *output = OptionalsToString(results);
return Status::OK();
}
};
@@ -435,9 +406,9 @@ class CommandJsonArrTrim : public Commander {
Status Execute(Server *srv, Connection *conn, std::string *output) override {
redis::Json json(srv->storage, conn->GetNamespace());
- std::vector<std::optional<uint64_t>> results;
+ Optionals<uint64_t> results;
- auto s = json.ArrTrim(args_[1], path_, start_, stop_, results);
+ auto s = json.ArrTrim(args_[1], path_, start_, stop_, &results);
if (s.IsNotFound()) {
*output = redis::NilString();
@@ -445,15 +416,7 @@ class CommandJsonArrTrim : public Commander {
}
if (!s.ok()) return {Status::RedisExecErr, s.ToString()};
- *output = redis::MultiLen(results.size());
- for (const auto &len : results) {
- if (len.has_value()) {
- *output += redis::Integer(len.value());
- } else {
- *output += redis::NilString();
- }
- }
-
+ *output = OptionalsToString(results);
return Status::OK();
}
@@ -484,9 +447,9 @@ class CommanderJsonArrIndex : public Commander {
Status Execute(Server *svr, Connection *conn, std::string *output) override {
redis::Json json(svr->storage, conn->GetNamespace());
- std::vector<ssize_t> result;
+ Optionals<ssize_t> results;
- auto s = json.ArrIndex(args_[1], args_[2], args_[3], start_, end_,
&result);
+ auto s = json.ArrIndex(args_[1], args_[2], args_[3], start_, end_,
&results);
if (s.IsNotFound()) {
*output = redis::NilString();
@@ -495,14 +458,7 @@ class CommanderJsonArrIndex : public Commander {
if (!s.ok()) return {Status::RedisExecErr, s.ToString()};
- *output = redis::MultiLen(result.size());
- for (const auto &found_index : result) {
- if (found_index == NOT_ARRAY) {
- *output += redis::NilString();
- continue;
- }
- *output += redis::Integer(found_index);
- }
+ *output = OptionalsToString(results);
return Status::OK();
}
@@ -580,25 +536,13 @@ class CommandJsonStrAppend : public Commander {
return {Status::RedisExecErr, "The number of arguments is more than
expected"};
}
- std::vector<uint64_t> results;
- auto s = json.StrAppend(args_[1], path, args_[3], results);
+ Optionals<uint64_t> results;
+ auto s = json.StrAppend(args_[1], path, args_[3], &results);
if (!s.ok()) return {Status::RedisExecErr, s.ToString()};
- *output = IntegerArray(results);
+ *output = OptionalsToString(results);
return Status::OK();
}
-
- static std::string IntegerArray(const std::vector<uint64_t> &values) {
- std::string result = "*" + std::to_string(values.size()) + CRLF;
- for (const auto &value : values) {
- if (value == std::numeric_limits<uint64_t>::max()) {
- result += NilString();
- } else {
- result += Integer(value);
- }
- }
- return result;
- }
};
class CommandJsonStrLen : public Commander {
@@ -613,11 +557,11 @@ class CommandJsonStrLen : public Commander {
return {Status::RedisExecErr, "The number of arguments is more than
expected"};
}
- std::vector<uint64_t> results;
- auto s = json.StrLen(args_[1], path, results);
+ Optionals<uint64_t> results;
+ auto s = json.StrLen(args_[1], path, &results);
if (!s.ok()) return {Status::RedisExecErr, s.ToString()};
- *output = CommandJsonStrAppend::IntegerArray(results);
+ *output = OptionalsToString(results);
return Status::OK();
}
};
diff --git a/src/types/json.h b/src/types/json.h
index 0163c07a..4b786834 100644
--- a/src/types/json.h
+++ b/src/types/json.h
@@ -41,8 +41,8 @@
#include "jsoncons_ext/jsonpath/jsonpath_error.hpp"
#include "status.h"
-constexpr ssize_t NOT_FOUND_INDEX = -1;
-constexpr ssize_t NOT_ARRAY = -2;
+template <class T>
+using Optionals = std::vector<std::optional<T>>;
struct JsonValue {
enum class NumOpEnum : uint8_t {
@@ -161,7 +161,8 @@ struct JsonValue {
return Status::OK();
}
- Status StrAppend(std::string_view path, const std::string &append_value,
std::vector<uint64_t> &append_cnt) {
+ StatusOr<Optionals<uint64_t>> StrAppend(std::string_view path, const
std::string &append_value) {
+ Optionals<uint64_t> results;
try {
std::string append_str;
jsoncons::json append_json = jsoncons::json::parse(append_value);
@@ -171,37 +172,39 @@ struct JsonValue {
return {Status::NotOK, "STRAPPEND need input a string to append"};
}
- jsoncons::jsonpath::json_replace(
- value, path, [&append_str, &append_cnt](const std::string &
/*path*/, jsoncons::json &origin) {
- if (origin.is_string()) {
- auto origin_str = origin.as_string();
- append_cnt.push_back(origin_str.length() + append_str.length());
- origin = origin_str + append_str;
- } else {
- append_cnt.push_back(std::numeric_limits<uint64_t>::max());
- }
- });
+ jsoncons::jsonpath::json_replace(value, path,
+ [&append_str, &results](const
std::string & /*path*/, jsoncons::json &origin) {
+ if (origin.is_string()) {
+ auto origin_str =
origin.as_string();
+
results.emplace_back(origin_str.length() + append_str.length());
+ origin = origin_str + append_str;
+ } else {
+ results.emplace_back(std::nullopt);
+ }
+ });
} catch (const jsoncons::jsonpath::jsonpath_error &e) {
return {Status::NotOK, e.what()};
}
- return Status::OK();
+ std::reverse(results.begin(), results.end());
+ return results;
}
- Status StrLen(std::string_view path, std::vector<uint64_t> &str_lens) const {
+ StatusOr<Optionals<uint64_t>> StrLen(std::string_view path) const {
+ Optionals<uint64_t> results;
try {
jsoncons::jsonpath::json_query(value, path,
- [&str_lens](const std::string & /*path*/,
const jsoncons::json &origin) {
+ [&results](const std::string & /*path*/,
const jsoncons::json &origin) {
if (origin.is_string()) {
-
str_lens.push_back(origin.as_string().length());
+
results.emplace_back(origin.as_string().length());
} else {
-
str_lens.push_back(std::numeric_limits<uint64_t>::max());
+ results.emplace_back(std::nullopt);
}
});
} catch (const jsoncons::jsonpath::jsonpath_error &e) {
return {Status::NotOK, e.what()};
}
- return Status::OK();
+ return results;
}
StatusOr<JsonValue> Get(std::string_view path) const {
@@ -212,53 +215,52 @@ struct JsonValue {
}
}
- StatusOr<std::vector<size_t>> ArrAppend(std::string_view path, const
std::vector<jsoncons::json> &append_values) {
- std::vector<size_t> result_count;
+ StatusOr<Optionals<size_t>> ArrAppend(std::string_view path, const
std::vector<jsoncons::json> &append_values) {
+ Optionals<size_t> results;
try {
jsoncons::jsonpath::json_replace(
- value, path, [&append_values, &result_count](const std::string &
/*path*/, jsoncons::json &val) {
+ value, path, [&append_values, &results](const std::string &
/*path*/, jsoncons::json &val) {
if (val.is_array()) {
val.insert(val.array_range().end(), append_values.begin(),
append_values.end());
- result_count.emplace_back(val.size());
+ results.emplace_back(val.size());
} else {
- result_count.emplace_back(0);
+ results.emplace_back(std::nullopt);
}
});
} catch (const jsoncons::jsonpath::jsonpath_error &e) {
return {Status::NotOK, e.what()};
}
- return result_count;
+ return results;
}
- StatusOr<std::vector<std::optional<uint64_t>>> ArrInsert(std::string_view
path, const int64_t &index,
- const
std::vector<jsoncons::json> &insert_values) {
- std::vector<std::optional<uint64_t>> result_count;
-
+ StatusOr<Optionals<uint64_t>> ArrInsert(std::string_view path, const int64_t
&index,
+ const std::vector<jsoncons::json>
&insert_values) {
+ Optionals<uint64_t> results;
try {
jsoncons::jsonpath::json_replace(
- value, path, [&insert_values, &result_count, index](const
std::string & /*path*/, jsoncons::json &val) {
+ value, path, [&insert_values, &results, index](const std::string &
/*path*/, jsoncons::json &val) {
if (val.is_array()) {
auto len = static_cast<int64_t>(val.size());
// When index > 0, we need index < len
// when index < 0, we need index >= -len.
if (index >= len || index < -len) {
- result_count.emplace_back(std::nullopt);
+ results.emplace_back(std::nullopt);
return;
}
auto base_iter = index >= 0 ? val.array_range().begin() :
val.array_range().end();
val.insert(base_iter + index, insert_values.begin(),
insert_values.end());
- result_count.emplace_back(val.size());
+ results.emplace_back(val.size());
} else {
- result_count.emplace_back(std::nullopt);
+ results.emplace_back(std::nullopt);
}
});
} catch (const jsoncons::jsonpath::jsonpath_error &e) {
return {Status::NotOK, e.what()};
}
- return result_count;
+ return results;
}
static std::pair<ssize_t, ssize_t> NormalizeArrIndices(ssize_t start,
ssize_t end, ssize_t len) {
@@ -276,13 +278,13 @@ struct JsonValue {
return {start, end};
}
- StatusOr<std::vector<ssize_t>> ArrIndex(std::string_view path, const
jsoncons::json &needle, ssize_t start,
- ssize_t end) const {
- std::vector<ssize_t> result;
+ StatusOr<Optionals<ssize_t>> ArrIndex(std::string_view path, const
jsoncons::json &needle, ssize_t start,
+ ssize_t end) const {
+ Optionals<ssize_t> results;
try {
jsoncons::jsonpath::json_query(value, path, [&](const std::string &
/*path*/, const jsoncons::json &val) {
if (!val.is_array()) {
- result.emplace_back(NOT_ARRAY);
+ results.emplace_back(std::nullopt);
return;
}
auto [pstart, pend] = NormalizeArrIndices(start, end,
static_cast<ssize_t>(val.size()));
@@ -292,15 +294,16 @@ struct JsonValue {
auto end_it = arr_begin + pend;
auto it = std::find(begin_it, end_it, needle);
if (it != end_it) {
- result.emplace_back(it - arr_begin);
+ results.emplace_back(it - arr_begin);
return;
}
- result.emplace_back(NOT_FOUND_INDEX);
+ // index not found
+ results.emplace_back(-1);
});
} catch (const jsoncons::jsonpath::jsonpath_error &e) {
return {Status::NotOK, e.what()};
}
- return result;
+ return results;
}
StatusOr<std::vector<std::string>> Type(std::string_view path) const {
@@ -342,21 +345,22 @@ struct JsonValue {
return types;
}
- StatusOr<std::vector<std::optional<bool>>> Toggle(std::string_view path) {
- std::vector<std::optional<bool>> result;
+ StatusOr<Optionals<bool>> Toggle(std::string_view path) {
+ Optionals<bool> results;
try {
- jsoncons::jsonpath::json_replace(value, path, [&result](const
std::string & /*path*/, jsoncons::json &val) {
+ jsoncons::jsonpath::json_replace(value, path, [&results](const
std::string & /*path*/, jsoncons::json &val) {
if (val.is_bool()) {
val = !val.as_bool();
- result.emplace_back(val.as_bool());
+ results.emplace_back(val.as_bool());
} else {
- result.emplace_back(std::nullopt);
+ results.emplace_back(std::nullopt);
}
});
} catch (const jsoncons::jsonpath::jsonpath_error &e) {
return {Status::NotOK, e.what()};
}
- return result;
+ std::reverse(results.begin(), results.end());
+ return results;
}
StatusOr<size_t> Clear(std::string_view path) {
@@ -384,21 +388,21 @@ struct JsonValue {
return count;
}
- Status ArrLen(std::string_view path, std::vector<std::optional<uint64_t>>
&arr_lens) const {
+ StatusOr<Optionals<uint64_t>> ArrLen(std::string_view path) const {
+ Optionals<uint64_t> results;
try {
jsoncons::jsonpath::json_query(value, path,
- [&arr_lens](const std::string & /*path*/,
const jsoncons::json &basic_json) {
+ [&results](const std::string & /*path*/,
const jsoncons::json &basic_json) {
if (basic_json.is_array()) {
-
arr_lens.emplace_back(static_cast<uint64_t>(basic_json.size()));
+
results.emplace_back(static_cast<uint64_t>(basic_json.size()));
} else {
- arr_lens.emplace_back(std::nullopt);
+ results.emplace_back(std::nullopt);
}
});
} catch (const jsoncons::jsonpath::jsonpath_error &e) {
return {Status::NotOK, e.what()};
}
-
- return Status::OK();
+ return results;
}
StatusOr<bool> Merge(const std::string_view path, const std::string
&merge_value) {
@@ -449,7 +453,8 @@ struct JsonValue {
return is_updated;
}
- Status ObjKeys(std::string_view path,
std::vector<std::optional<std::vector<std::string>>> &keys) const {
+ StatusOr<Optionals<std::vector<std::string>>> ObjKeys(std::string_view path)
const {
+ Optionals<std::vector<std::string>> keys;
try {
jsoncons::jsonpath::json_query(value, path,
[&keys](const std::string & /*path*/,
const jsoncons::json &basic_json) {
@@ -466,10 +471,12 @@ struct JsonValue {
} catch (const jsoncons::jsonpath::jsonpath_error &e) {
return {Status::NotOK, e.what()};
}
- return Status::OK();
+
+ return keys;
}
- Status ObjLen(std::string_view path, std::vector<std::optional<uint64_t>>
&obj_lens) const {
+ StatusOr<Optionals<uint64_t>> ObjLen(std::string_view path) const {
+ Optionals<uint64_t> obj_lens;
try {
jsoncons::jsonpath::json_query(value, path,
[&obj_lens](const std::string & /*path*/,
const jsoncons::json &basic_json) {
@@ -482,11 +489,11 @@ struct JsonValue {
} catch (const jsoncons::jsonpath::jsonpath_error &e) {
return {Status::NotOK, e.what()};
}
- return Status::OK();
+ return obj_lens;
}
- StatusOr<std::vector<std::optional<JsonValue>>> ArrPop(std::string_view
path, int64_t index = -1) {
- std::vector<std::optional<JsonValue>> popped_values;
+ StatusOr<Optionals<JsonValue>> ArrPop(std::string_view path, int64_t index =
-1) {
+ Optionals<JsonValue> popped_values;
try {
jsoncons::jsonpath::json_replace(value, path,
@@ -512,7 +519,8 @@ struct JsonValue {
return popped_values;
}
- Status ArrTrim(std::string_view path, int64_t start, int64_t stop,
std::vector<std::optional<uint64_t>> &results) {
+ StatusOr<Optionals<uint64_t>> ArrTrim(std::string_view path, int64_t start,
int64_t stop) {
+ Optionals<uint64_t> results;
try {
jsoncons::jsonpath::json_replace(
value, path, [&results, start, stop](const std::string & /*path*/,
jsoncons::json &val) {
@@ -540,8 +548,7 @@ struct JsonValue {
} catch (const jsoncons::jsonpath::jsonpath_error &e) {
return {Status::NotOK, e.what()};
}
-
- return Status::OK();
+ return results;
}
StatusOr<size_t> Del(const std::string &path) {
diff --git a/src/types/redis_json.cc b/src/types/redis_json.cc
index f3532b17..8c0f28bf 100644
--- a/src/types/redis_json.cc
+++ b/src/types/redis_json.cc
@@ -165,7 +165,7 @@ rocksdb::Status Json::Get(const std::string &user_key,
const std::vector<std::st
}
rocksdb::Status Json::ArrAppend(const std::string &user_key, const std::string
&path,
- const std::vector<std::string> &values,
std::vector<size_t> *result_count) {
+ const std::vector<std::string> &values,
Optionals<size_t> *results) {
auto ns_key = AppendNamespacePrefix(user_key);
std::vector<jsoncons::json> append_values;
@@ -186,16 +186,17 @@ rocksdb::Status Json::ArrAppend(const std::string
&user_key, const std::string &
auto append_res = value.ArrAppend(path, append_values);
if (!append_res) return rocksdb::Status::InvalidArgument(append_res.Msg());
- *result_count = *append_res;
+ *results = std::move(*append_res);
- bool is_write = std::any_of(result_count->begin(), result_count->end(),
[](uint64_t c) { return c > 0; });
+ bool is_write =
+ std::any_of(results->begin(), results->end(), [](std::optional<uint64_t>
c) { return c.has_value(); });
if (!is_write) return rocksdb::Status::OK();
return write(ns_key, &metadata, value);
}
rocksdb::Status Json::ArrIndex(const std::string &user_key, const std::string
&path, const std::string &needle,
- ssize_t start, ssize_t end,
std::vector<ssize_t> *result) {
+ ssize_t start, ssize_t end, Optionals<ssize_t>
*results) {
auto ns_key = AppendNamespacePrefix(user_key);
auto needle_res = JsonValue::FromString(needle,
storage_->GetConfig()->json_max_nesting_depth);
@@ -209,8 +210,8 @@ rocksdb::Status Json::ArrIndex(const std::string &user_key,
const std::string &p
auto index_res = value.ArrIndex(path, needle_value.value, start, end);
if (!index_res) return rocksdb::Status::InvalidArgument(index_res.Msg());
- *result = *index_res;
+ *results = std::move(*index_res);
return rocksdb::Status::OK();
}
@@ -282,23 +283,22 @@ rocksdb::Status Json::Clear(const std::string &user_key,
const std::string &path
return write(ns_key, &metadata, json_val);
}
-rocksdb::Status Json::ArrLen(const std::string &user_key, const std::string
&path,
- std::vector<std::optional<uint64_t>> &arr_lens) {
+rocksdb::Status Json::ArrLen(const std::string &user_key, const std::string
&path, Optionals<uint64_t> *results) {
auto ns_key = AppendNamespacePrefix(user_key);
JsonMetadata metadata;
JsonValue json_val;
auto s = read(ns_key, &metadata, &json_val);
if (!s.ok()) return s;
- auto len_res = json_val.ArrLen(path, arr_lens);
+ auto len_res = json_val.ArrLen(path);
if (!len_res) return rocksdb::Status::InvalidArgument(len_res.Msg());
+ *results = std::move(*len_res);
return rocksdb::Status::OK();
}
rocksdb::Status Json::ArrInsert(const std::string &user_key, const std::string
&path, const int64_t &index,
- const std::vector<std::string> &values,
- std::vector<std::optional<uint64_t>>
*result_count) {
+ const std::vector<std::string> &values,
Optionals<uint64_t> *results) {
auto ns_key = AppendNamespacePrefix(user_key);
std::vector<jsoncons::json> insert_values;
@@ -319,17 +319,16 @@ rocksdb::Status Json::ArrInsert(const std::string
&user_key, const std::string &
auto insert_res = value.ArrInsert(path, index, insert_values);
if (!insert_res) return rocksdb::Status::InvalidArgument(insert_res.Msg());
- *result_count = *insert_res;
+ *results = std::move(*insert_res);
bool is_write =
- std::any_of(result_count->begin(), result_count->end(),
[](std::optional<uint64_t> c) { return c.has_value(); });
+ std::any_of(results->begin(), results->end(), [](std::optional<uint64_t>
c) { return c.has_value(); });
if (!is_write) return rocksdb::Status::OK();
return write(ns_key, &metadata, value);
}
-rocksdb::Status Json::Toggle(const std::string &user_key, const std::string
&path,
- std::vector<std::optional<bool>> &result) {
+rocksdb::Status Json::Toggle(const std::string &user_key, const std::string
&path, Optionals<bool> *results) {
auto ns_key = AppendNamespacePrefix(user_key);
LockGuard guard(storage_->GetLockManager(), ns_key);
@@ -341,7 +340,7 @@ rocksdb::Status Json::Toggle(const std::string &user_key,
const std::string &pat
auto toggle_res = origin.Toggle(path);
if (!toggle_res) return rocksdb::Status::InvalidArgument(toggle_res.Msg());
- result = *toggle_res;
+ *results = std::move(*toggle_res);
return write(ns_key, &metadata, origin);
}
@@ -369,20 +368,21 @@ rocksdb::Status Json::ArrPop(const std::string &user_key,
const std::string &pat
}
rocksdb::Status Json::ObjKeys(const std::string &user_key, const std::string
&path,
-
std::vector<std::optional<std::vector<std::string>>> &keys) {
+ Optionals<std::vector<std::string>> *keys) {
auto ns_key = AppendNamespacePrefix(user_key);
JsonMetadata metadata;
JsonValue json_val;
auto s = read(ns_key, &metadata, &json_val);
if (!s.ok()) return s;
- auto keys_res = json_val.ObjKeys(path, keys);
+ auto keys_res = json_val.ObjKeys(path);
if (!keys_res) return rocksdb::Status::InvalidArgument(keys_res.Msg());
+ *keys = std::move(*keys_res);
return rocksdb::Status::OK();
}
rocksdb::Status Json::ArrTrim(const std::string &user_key, const std::string
&path, int64_t start, int64_t stop,
- std::vector<std::optional<uint64_t>> &results) {
+ Optionals<uint64_t> *results) {
auto ns_key = AppendNamespacePrefix(user_key);
LockGuard guard(storage_->GetLockManager(), ns_key);
@@ -392,10 +392,12 @@ rocksdb::Status Json::ArrTrim(const std::string
&user_key, const std::string &pa
auto s = read(ns_key, &metadata, &json_val);
if (!s.ok()) return s;
- auto len_res = json_val.ArrTrim(path, start, stop, results);
+ auto len_res = json_val.ArrTrim(path, start, stop);
if (!len_res) return rocksdb::Status::InvalidArgument(len_res.Msg());
+
+ *results = std::move(*len_res);
bool is_write =
- std::any_of(results.begin(), results.end(), [](const
std::optional<uint64_t> &val) { return val.has_value(); });
+ std::any_of(results->begin(), results->end(), [](const
std::optional<uint64_t> &val) { return val.has_value(); });
if (!is_write) return rocksdb::Status::OK();
return write(ns_key, &metadata, json_val);
}
@@ -464,24 +466,19 @@ rocksdb::Status Json::numop(JsonValue::NumOpEnum op,
const std::string &user_key
}
rocksdb::Status Json::StrAppend(const std::string &user_key, const std::string
&path, const std::string &value,
- std::vector<uint64_t> &append_cnt) {
+ Optionals<uint64_t> *results) {
auto ns_key = AppendNamespacePrefix(user_key);
JsonMetadata metadata;
JsonValue json_val;
auto s = read(ns_key, &metadata, &json_val);
if (!s.ok()) return s;
- auto append_res = json_val.StrAppend(path, value, append_cnt);
+ auto append_res = json_val.StrAppend(path, value);
if (!append_res) return rocksdb::Status::InvalidArgument(append_res.Msg());
- // need reverse order
- std::reverse(append_cnt.begin(), append_cnt.end());
+ *results = std::move(*append_res);
- bool need_overwrite = false;
- for (auto append : append_cnt) {
- if (append != std::numeric_limits<uint64_t>::max()) {
- need_overwrite = true;
- }
- }
+ bool need_overwrite =
+ std::any_of(results->begin(), results->end(), [](const
std::optional<uint64_t> &val) { return val.has_value(); });
if (!need_overwrite) {
return rocksdb::Status::OK();
}
@@ -489,29 +486,29 @@ rocksdb::Status Json::StrAppend(const std::string
&user_key, const std::string &
return write(ns_key, &metadata, json_val);
}
-rocksdb::Status Json::StrLen(const std::string &user_key, const std::string
&path, std::vector<uint64_t> &str_lens) {
+rocksdb::Status Json::StrLen(const std::string &user_key, const std::string
&path, Optionals<uint64_t> *results) {
auto ns_key = AppendNamespacePrefix(user_key);
JsonMetadata metadata;
JsonValue json_val;
auto s = read(ns_key, &metadata, &json_val);
if (!s.ok()) return s;
- auto append_res = json_val.StrLen(path, str_lens);
- if (!append_res) return rocksdb::Status::InvalidArgument(append_res.Msg());
+ auto str_lens = json_val.StrLen(path);
+ if (!str_lens) return rocksdb::Status::InvalidArgument(str_lens.Msg());
+ *results = std::move(*str_lens);
return rocksdb::Status::OK();
}
-rocksdb::Status Json::ObjLen(const std::string &user_key, const std::string
&path,
- std::vector<std::optional<uint64_t>> &obj_lens) {
+rocksdb::Status Json::ObjLen(const std::string &user_key, const std::string
&path, Optionals<uint64_t> *results) {
auto ns_key = AppendNamespacePrefix(user_key);
JsonMetadata metadata;
JsonValue json_val;
auto s = read(ns_key, &metadata, &json_val);
if (!s.ok()) return s;
- auto len_res = json_val.ObjLen(path, obj_lens);
- if (!len_res) return rocksdb::Status::InvalidArgument(len_res.Msg());
-
+ auto obj_lens = json_val.ObjLen(path);
+ if (!obj_lens) return rocksdb::Status::InvalidArgument(obj_lens.Msg());
+ *results = std::move(*obj_lens);
return rocksdb::Status::OK();
}
diff --git a/src/types/redis_json.h b/src/types/redis_json.h
index bf5e21b5..e0e5ec31 100644
--- a/src/types/redis_json.h
+++ b/src/types/redis_json.h
@@ -38,34 +38,31 @@ class Json : public Database {
rocksdb::Status Info(const std::string &user_key, JsonStorageFormat
*storage_format);
rocksdb::Status Type(const std::string &user_key, const std::string &path,
std::vector<std::string> *results);
rocksdb::Status ArrAppend(const std::string &user_key, const std::string
&path,
- const std::vector<std::string> &values,
std::vector<size_t> *result_count);
+ const std::vector<std::string> &values,
Optionals<size_t> *results);
rocksdb::Status Merge(const std::string &user_key, const std::string &path,
const std::string &value, bool &result);
rocksdb::Status Clear(const std::string &user_key, const std::string &path,
size_t *result);
- rocksdb::Status ArrLen(const std::string &user_key, const std::string &path,
- std::vector<std::optional<uint64_t>> &arr_lens);
+ rocksdb::Status ArrLen(const std::string &user_key, const std::string &path,
Optionals<uint64_t> *results);
rocksdb::Status ArrInsert(const std::string &user_key, const std::string
&path, const int64_t &index,
- const std::vector<std::string> &values,
std::vector<std::optional<uint64_t>> *result_count);
- rocksdb::Status Toggle(const std::string &user_key, const std::string &path,
- std::vector<std::optional<bool>> &result);
+ const std::vector<std::string> &values,
Optionals<uint64_t> *results);
+ rocksdb::Status Toggle(const std::string &user_key, const std::string &path,
Optionals<bool> *results);
rocksdb::Status ObjKeys(const std::string &user_key, const std::string &path,
- std::vector<std::optional<std::vector<std::string>>>
&keys);
+ Optionals<std::vector<std::string>> *keys);
rocksdb::Status ArrPop(const std::string &user_key, const std::string &path,
int64_t index,
std::vector<std::optional<JsonValue>> *results);
rocksdb::Status ArrIndex(const std::string &user_key, const std::string
&path, const std::string &needle,
- ssize_t start, ssize_t end, std::vector<ssize_t>
*result);
+ ssize_t start, ssize_t end, Optionals<ssize_t>
*results);
rocksdb::Status NumIncrBy(const std::string &user_key, const std::string
&path, const std::string &value,
JsonValue *result);
rocksdb::Status NumMultBy(const std::string &user_key, const std::string
&path, const std::string &value,
JsonValue *result);
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);
+ Optionals<uint64_t> *results);
rocksdb::Status Del(const std::string &user_key, const std::string &path,
size_t *result);
rocksdb::Status StrAppend(const std::string &user_key, const std::string
&path, const std::string &value,
- std::vector<uint64_t> &append_cnt);
- rocksdb::Status StrLen(const std::string &user_key, const std::string &path,
std::vector<uint64_t> &lens);
- rocksdb::Status ObjLen(const std::string &user_key, const std::string &path,
- std::vector<std::optional<uint64_t>> &obj_lens);
+ Optionals<uint64_t> *results);
+ rocksdb::Status StrLen(const std::string &user_key, const std::string &path,
Optionals<uint64_t> *results);
+ rocksdb::Status ObjLen(const std::string &user_key, const std::string &path,
Optionals<uint64_t> *results);
private:
rocksdb::Status write(Slice ns_key, JsonMetadata *metadata, const JsonValue
&json_val);
diff --git a/tests/cppunit/types/json_test.cc b/tests/cppunit/types/json_test.cc
index 196bff44..ee76a65c 100644
--- a/tests/cppunit/types/json_test.cc
+++ b/tests/cppunit/types/json_test.cc
@@ -36,7 +36,6 @@ class RedisJsonTest : public TestBase {
std::unique_ptr<redis::Json> json_;
JsonValue json_val_;
- std::vector<uint64_t> append_cnt_;
};
using ::testing::MatchesRegex;
@@ -143,14 +142,14 @@ TEST_F(RedisJsonTest, Print) {
}
TEST_F(RedisJsonTest, ArrAppend) {
- std::vector<size_t> res;
+ Optionals<size_t> res;
ASSERT_FALSE(json_->ArrAppend(key_, "$", {"1"}, &res).ok());
ASSERT_TRUE(json_->Set(key_, "$", R"({"x":1,"y":[]})").ok());
ASSERT_TRUE(json_->ArrAppend(key_, "$.x", {"1"}, &res).ok());
ASSERT_EQ(res.size(), 1);
- ASSERT_EQ(res[0], 0);
+ ASSERT_EQ(res[0], std::nullopt);
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(), R"({"x":1,"y":[]})");
res.clear();
@@ -174,7 +173,7 @@ TEST_F(RedisJsonTest, ArrAppend) {
ASSERT_TRUE(json_->ArrAppend(key_, "$..y", {"1", "2", "3"}, &res).ok());
ASSERT_EQ(res.size(), 4);
std::sort(res.begin(), res.end());
- ASSERT_EQ(res[0], 0);
+ ASSERT_EQ(res[0], std::nullopt);
ASSERT_EQ(res[1], 3);
ASSERT_EQ(res[2], 4);
ASSERT_EQ(res[3], 6);
@@ -269,52 +268,52 @@ TEST_F(RedisJsonTest, ArrLen) {
json_->Set(key_, "$",
R"({"a1":[1,2],"a2":[[1,5,7],[8],[9]],"i":1,"d":1.0,"s":"string","o":{"a3":[1,1,1]}})")
.ok());
// 1. simple array
- std::vector<std::optional<uint64_t>> res;
- ASSERT_TRUE(json_->ArrLen(key_, "$.a1", res).ok());
+ Optionals<uint64_t> res;
+ ASSERT_TRUE(json_->ArrLen(key_, "$.a1", &res).ok());
ASSERT_EQ(res.size(), 1);
ASSERT_EQ(res[0], 2);
res.clear();
// 2. nested array
- ASSERT_TRUE(json_->ArrLen(key_, "$.a2", res).ok());
+ ASSERT_TRUE(json_->ArrLen(key_, "$.a2", &res).ok());
ASSERT_EQ(res.size(), 1);
ASSERT_EQ(res[0], 3);
res.clear();
- ASSERT_TRUE(json_->ArrLen(key_, "$.a2[0]", res).ok());
+ ASSERT_TRUE(json_->ArrLen(key_, "$.a2[0]", &res).ok());
ASSERT_EQ(res.size(), 1);
ASSERT_EQ(res[0], 3);
res.clear();
// 3.non-array type
- ASSERT_TRUE(json_->ArrLen(key_, "$.i", res).ok());
+ ASSERT_TRUE(json_->ArrLen(key_, "$.i", &res).ok());
ASSERT_EQ(res.size(), 1);
ASSERT_EQ(res[0], std::nullopt);
res.clear();
- ASSERT_TRUE(json_->ArrLen(key_, "$.d", res).ok());
+ ASSERT_TRUE(json_->ArrLen(key_, "$.d", &res).ok());
ASSERT_EQ(res.size(), 1);
ASSERT_EQ(res[0], std::nullopt);
res.clear();
- ASSERT_TRUE(json_->ArrLen(key_, "$.s", res).ok());
+ ASSERT_TRUE(json_->ArrLen(key_, "$.s", &res).ok());
ASSERT_EQ(res.size(), 1);
ASSERT_EQ(res[0], std::nullopt);
res.clear();
// 4. object
- ASSERT_TRUE(json_->ArrLen(key_, "$.o", res).ok());
+ ASSERT_TRUE(json_->ArrLen(key_, "$.o", &res).ok());
ASSERT_EQ(res.size(), 1);
ASSERT_EQ(res[0], std::nullopt);
res.clear();
- ASSERT_TRUE(json_->ArrLen(key_, "$.o.a3", res).ok());
+ ASSERT_TRUE(json_->ArrLen(key_, "$.o.a3", &res).ok());
ASSERT_EQ(res.size(), 1);
ASSERT_EQ(res[0], 3);
res.clear();
// 5. key/path is not found
- ASSERT_FALSE(json_->ArrLen("not_exists", "$.*", res).ok());
- ASSERT_TRUE(json_->ArrLen(key_, "$.not_exists", res).ok());
+ ASSERT_FALSE(json_->ArrLen("not_exists", "$.*", &res).ok());
+ ASSERT_TRUE(json_->ArrLen(key_, "$.not_exists", &res).ok());
ASSERT_TRUE(res.empty());
}
TEST_F(RedisJsonTest, Toggle) {
- std::vector<std::optional<bool>> res;
+ Optionals<bool> res;
ASSERT_TRUE(json_->Set(key_, "$", "true").ok());
- ASSERT_TRUE(json_->Toggle(key_, "$", res).ok());
+ ASSERT_TRUE(json_->Toggle(key_, "$", &res).ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(), "false");
ASSERT_EQ(res.size(), 1);
@@ -322,7 +321,7 @@ TEST_F(RedisJsonTest, Toggle) {
res.clear();
ASSERT_TRUE(json_->Set(key_, "$", R"({"bool":true})").ok());
- ASSERT_TRUE(json_->Toggle(key_, "$.bool", res).ok());
+ ASSERT_TRUE(json_->Toggle(key_, "$.bool", &res).ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(), R"({"bool":false})");
ASSERT_EQ(res.size(), 1);
@@ -330,7 +329,7 @@ TEST_F(RedisJsonTest, Toggle) {
res.clear();
ASSERT_TRUE(json_->Set(key_, "$",
R"({"bool":true,"bools":{"bool":true}})").ok());
- ASSERT_TRUE(json_->Toggle(key_, "$.bool", res).ok());
+ ASSERT_TRUE(json_->Toggle(key_, "$.bool", &res).ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(),
R"({"bool":false,"bools":{"bool":true}})");
ASSERT_EQ(res.size(), 1);
@@ -338,7 +337,7 @@ TEST_F(RedisJsonTest, Toggle) {
res.clear();
ASSERT_TRUE(json_->Set(key_, "$",
R"({"bool":true,"bools":{"bool":true}})").ok());
- ASSERT_TRUE(json_->Toggle(key_, "$..bool", res).ok());
+ ASSERT_TRUE(json_->Toggle(key_, "$..bool", &res).ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(),
R"({"bool":false,"bools":{"bool":false}})");
ASSERT_EQ(res.size(), 2);
@@ -346,31 +345,31 @@ TEST_F(RedisJsonTest, Toggle) {
res.clear();
ASSERT_TRUE(json_->Set(key_, "$",
R"({"bool":false,"bools":{"bool":true}})").ok());
- ASSERT_TRUE(json_->Toggle(key_, "$..bool", res).ok());
+ ASSERT_TRUE(json_->Toggle(key_, "$..bool", &res).ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(),
R"({"bool":true,"bools":{"bool":false}})");
ASSERT_EQ(res.size(), 2);
- ASSERT_THAT(res, testing::ElementsAre(false, true));
+ ASSERT_THAT(res, testing::ElementsAre(true, false));
res.clear();
ASSERT_TRUE(json_->Set(key_, "$",
R"({"bool":false,"bools":{"bool":true},"incorrectbool":{"bool":88}})").ok());
- ASSERT_TRUE(json_->Toggle(key_, "$..bool", res).ok());
+ ASSERT_TRUE(json_->Toggle(key_, "$..bool", &res).ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(),
R"({"bool":true,"bools":{"bool":false},"incorrectbool":{"bool":88}})");
ASSERT_EQ(res.size(), 3);
- ASSERT_THAT(res, testing::ElementsAre(std::nullopt, false, true));
+ ASSERT_THAT(res, testing::ElementsAre(true, false, std::nullopt));
res.clear();
ASSERT_TRUE(json_->Set(key_, "$", "[true,true,99]").ok());
- ASSERT_TRUE(json_->Toggle(key_, "$..*", res).ok());
+ ASSERT_TRUE(json_->Toggle(key_, "$..*", &res).ok());
ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok());
ASSERT_EQ(json_val_.Dump().GetValue(), "[false,false,99]");
ASSERT_EQ(res.size(), 3);
- ASSERT_THAT(res, testing::ElementsAre(std::nullopt, false, false));
+ ASSERT_THAT(res, testing::ElementsAre(false, false, std::nullopt));
}
TEST_F(RedisJsonTest, ArrPop) {
- std::vector<std::optional<JsonValue>> res;
+ Optionals<JsonValue> res;
// Array
ASSERT_TRUE(json_->Set(key_, "$", R"([3,"str",2.1,{},[5,6]])").ok());
@@ -438,7 +437,7 @@ TEST_F(RedisJsonTest, ArrPop) {
}
TEST_F(RedisJsonTest, ArrIndex) {
- std::vector<ssize_t> res;
+ Optionals<ssize_t> res;
int max_end = std::numeric_limits<int>::max();
ASSERT_TRUE(json_->Set(key_, "$", R"({"arr":[0, 1, 2, 3, 2, 1, 0]})").ok());
@@ -661,34 +660,35 @@ TEST_F(RedisJsonTest, NumMultBy) {
}
TEST_F(RedisJsonTest, StrAppend) {
+ Optionals<uint64_t> results;
ASSERT_TRUE(json_->Set(key_, "$", R"({"a":"foo", "nested": {"a": "hello"},
"nested2": {"a": 31}})").ok());
- ASSERT_TRUE(json_->StrAppend(key_, "$.a", "\"be\"", append_cnt_).ok());
- ASSERT_EQ(append_cnt_.size(), 1);
- ASSERT_EQ(append_cnt_[0], 5);
+ ASSERT_TRUE(json_->StrAppend(key_, "$.a", "\"be\"", &results).ok());
+ ASSERT_EQ(results.size(), 1);
+ ASSERT_EQ(results[0], 5);
- append_cnt_.clear();
+ results.clear();
ASSERT_TRUE(json_->Set(key_, "$", R"({"a":"foo", "nested": {"a": "hello"},
"nested2": {"a": 31}})").ok());
- ASSERT_TRUE(json_->StrAppend(key_, "$..a", "\"be\"", append_cnt_).ok());
- ASSERT_EQ(append_cnt_.size(), 3);
- std::vector<int64_t> result1 = {5, 7, -1};
+ ASSERT_TRUE(json_->StrAppend(key_, "$..a", "\"be\"", &results).ok());
+ ASSERT_EQ(results.size(), 3);
+ Optionals<int64_t> result1 = {5, 7, std::nullopt};
for (int i = 0; i < 3; ++i) {
- ASSERT_EQ(append_cnt_[i], result1[i]);
+ ASSERT_EQ(results[i], result1[i]);
}
}
TEST_F(RedisJsonTest, StrLen) {
- append_cnt_.clear();
+ Optionals<uint64_t> results;
ASSERT_TRUE(json_->Set(key_, "$", R"({"a":"foo", "nested": {"a": "hello"},
"nested2": {"a": 31}})").ok());
- ASSERT_TRUE(json_->StrLen(key_, "$.a", append_cnt_).ok());
- ASSERT_EQ(append_cnt_.size(), 1);
- ASSERT_EQ(append_cnt_[0], 3);
+ ASSERT_TRUE(json_->StrLen(key_, "$.a", &results).ok());
+ ASSERT_EQ(results.size(), 1);
+ ASSERT_EQ(results[0], 3);
- append_cnt_.clear();
+ results.clear();
ASSERT_TRUE(json_->Set(key_, "$", R"({"a":"foo", "nested": {"a": "hello"},
"nested2": {"a": 31}})").ok());
- ASSERT_TRUE(json_->StrLen(key_, "$..a", append_cnt_).ok());
- ASSERT_EQ(append_cnt_.size(), 3);
- std::vector<int64_t> result1 = {3, 5, -1};
+ ASSERT_TRUE(json_->StrLen(key_, "$..a", &results).ok());
+ ASSERT_EQ(results.size(), 3);
+ Optionals<int64_t> result1 = {3, 5, std::nullopt};
for (int i = 0; i < 3; ++i) {
- ASSERT_EQ(append_cnt_[i], result1[i]);
+ ASSERT_EQ(results[i], result1[i]);
}
}