From 968551d5f1a202e71808971022d720417ee8430d Mon Sep 17 00:00:00 2001 From: Twice Date: Sat, 21 Oct 2023 15:49:59 +0900 Subject: [PATCH] Add method to read JSON from storage for simplifying code (#1843) --- kvrocks.conf | 5 ++++ src/types/redis_json.cc | 55 ++++++++++++++++++----------------------- src/types/redis_json.h | 2 ++ 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/kvrocks.conf b/kvrocks.conf index 7089cec89eb..be4332543d8 100644 --- a/kvrocks.conf +++ b/kvrocks.conf @@ -312,6 +312,11 @@ max-bitmap-to-string-mb 16 # Default: no redis-cursor-compatible no +# Maximum nesting depth allowed when parsing and serializing +# JSON documents while using JSON commands like JSON.SET. +# Default: 1024 +json-max-nesting-depth 1024 + ################################## TLS ################################### # By default, TLS/SSL is disabled, i.e. `tls-port` is set to 0. diff --git a/src/types/redis_json.cc b/src/types/redis_json.cc index 291d14b591d..cc4fc7681fd 100644 --- a/src/types/redis_json.cc +++ b/src/types/redis_json.cc @@ -45,15 +45,31 @@ rocksdb::Status Json::write(Slice ns_key, JsonMetadata *metadata, const JsonValu return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } +rocksdb::Status Json::read(const Slice &ns_key, JsonMetadata *metadata, JsonValue *value) { + std::string bytes; + Slice rest; + + auto s = GetMetadata(kRedisJson, ns_key, &bytes, metadata, &rest); + if (!s.ok()) return s; + + if (metadata->format != JsonStorageFormat::JSON) + return rocksdb::Status::NotSupported("JSON storage format not supported"); + + auto origin_res = JsonValue::FromString(rest.ToStringView()); + if (!origin_res) return rocksdb::Status::Corruption(origin_res.Msg()); + *value = *std::move(origin_res); + + return rocksdb::Status::OK(); +} + rocksdb::Status Json::Set(const std::string &user_key, const std::string &path, const std::string &value) { auto ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); - std::string bytes; JsonMetadata metadata; - Slice rest; - auto s = GetMetadata(kRedisJson, ns_key, &bytes, &metadata, &rest); + JsonValue origin; + auto s = read(ns_key, &metadata, &origin); if (s.IsNotFound()) { if (path != "$") return rocksdb::Status::InvalidArgument("new objects must be created at the root"); @@ -67,17 +83,10 @@ rocksdb::Status Json::Set(const std::string &user_key, const std::string &path, if (!s.ok()) return s; - if (metadata.format != JsonStorageFormat::JSON) - return rocksdb::Status::NotSupported("JSON storage format not supported"); - auto new_res = JsonValue::FromString(value, storage_->GetConfig()->json_max_nesting_depth); if (!new_res) return rocksdb::Status::InvalidArgument(new_res.Msg()); auto new_val = *std::move(new_res); - auto origin_res = JsonValue::FromString(rest.ToStringView()); - if (!origin_res) return rocksdb::Status::Corruption(origin_res.Msg()); - auto origin = *std::move(origin_res); - auto set_res = origin.Set(path, std::move(new_val)); if (!set_res) return rocksdb::Status::InvalidArgument(set_res.Msg()); @@ -87,19 +96,11 @@ rocksdb::Status Json::Set(const std::string &user_key, const std::string &path, rocksdb::Status Json::Get(const std::string &user_key, const std::vector &paths, JsonValue *result) { auto ns_key = AppendNamespacePrefix(user_key); - std::string bytes; JsonMetadata metadata; - Slice rest; - auto s = GetMetadata(kRedisJson, ns_key, &bytes, &metadata, &rest); + JsonValue json_val; + auto s = read(ns_key, &metadata, &json_val); if (!s.ok()) return s; - if (metadata.format != JsonStorageFormat::JSON) - return rocksdb::Status::NotSupported("JSON storage format not supported"); - - auto json_res = JsonValue::FromString(rest.ToStringView()); - if (!json_res) return rocksdb::Status::Corruption(json_res.Msg()); - auto json_val = *std::move(json_res); - JsonValue res; if (paths.empty()) { @@ -127,7 +128,7 @@ rocksdb::Status Json::ArrAppend(const std::string &user_key, const std::string & std::vector append_values; append_values.reserve(values.size()); for (auto &v : values) { - auto value_res = JsonValue::FromString(v); + auto value_res = JsonValue::FromString(v, storage_->GetConfig()->json_max_nesting_depth); if (!value_res) return rocksdb::Status::InvalidArgument(value_res.Msg()); auto value = *std::move(value_res); append_values.emplace_back(std::move(value.value)); @@ -135,19 +136,11 @@ rocksdb::Status Json::ArrAppend(const std::string &user_key, const std::string & LockGuard guard(storage_->GetLockManager(), ns_key); - std::string bytes; JsonMetadata metadata; - Slice rest; - auto s = GetMetadata(kRedisJson, ns_key, &bytes, &metadata, &rest); + JsonValue value; + auto s = read(ns_key, &metadata, &value); if (!s.ok()) return s; - if (metadata.format != JsonStorageFormat::JSON) - return rocksdb::Status::NotSupported("JSON storage format not supported"); - - auto value_res = JsonValue::FromString(rest.ToStringView()); - if (!value_res) return rocksdb::Status::Corruption(value_res.Msg()); - auto value = *std::move(value_res); - auto append_res = value.ArrAppend(path, append_values, result_count); if (!append_res) return rocksdb::Status::InvalidArgument(append_res.Msg()); diff --git a/src/types/redis_json.h b/src/types/redis_json.h index 33c2625a533..04895be5e47 100644 --- a/src/types/redis_json.h +++ b/src/types/redis_json.h @@ -25,6 +25,7 @@ #include #include "json.h" +#include "storage/redis_metadata.h" namespace redis { @@ -39,6 +40,7 @@ class Json : public Database { private: rocksdb::Status write(Slice ns_key, JsonMetadata *metadata, const JsonValue &json_val); + rocksdb::Status read(const Slice &ns_key, JsonMetadata *metadata, JsonValue *value); }; } // namespace redis