Compare commits
2 Commits
master
...
MG-pmr-pro
Author | SHA1 | Date | |
---|---|---|---|
|
16245d7ec8 | ||
|
49ad114366 |
@ -238,7 +238,7 @@ Value ToBoltValue(const storage::PropertyValue &value) {
|
||||
case storage::PropertyValue::Type::Double:
|
||||
return Value(value.ValueDouble());
|
||||
case storage::PropertyValue::Type::String:
|
||||
return Value(value.ValueString());
|
||||
return Value(std::string{value.ValueString()});
|
||||
case storage::PropertyValue::Type::List: {
|
||||
const auto &values = value.ValueList();
|
||||
std::vector<Value> vec;
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
|
||||
#include <jemalloc/jemalloc.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <gflags/gflags.h>
|
||||
#include <spdlog/common.h>
|
||||
@ -44,6 +46,7 @@
|
||||
#include "query/procedure/py_module.hpp"
|
||||
#include "requests/requests.hpp"
|
||||
#include "storage/v2/isolation_level.hpp"
|
||||
#include "storage/v2/property_value.hpp"
|
||||
#include "storage/v2/storage.hpp"
|
||||
#include "storage/v2/view.hpp"
|
||||
#include "telemetry/telemetry.hpp"
|
||||
@ -817,7 +820,7 @@ class BoltSession final : public communication::bolt::Session<communication::Inp
|
||||
|
||||
std::pair<std::vector<std::string>, std::optional<int>> Interpret(
|
||||
const std::string &query, const std::map<std::string, communication::bolt::Value> ¶ms) override {
|
||||
std::map<std::string, storage::PropertyValue> params_pv;
|
||||
storage::PropertyValue::TMap params_pv{utils::NewDeleteResource()};
|
||||
for (const auto &kv : params) params_pv.emplace(kv.first, glue::ToPropertyValue(kv.second));
|
||||
const std::string *username{nullptr};
|
||||
if (user_) {
|
||||
|
@ -11,6 +11,9 @@
|
||||
|
||||
#include "query/cypher_query_interpreter.hpp"
|
||||
|
||||
#include "utils/memory.hpp"
|
||||
#include "utils/pmr/string.hpp"
|
||||
|
||||
// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)
|
||||
DEFINE_HIDDEN_bool(query_cost_planner, true, "Use the cost-estimating query planner.");
|
||||
// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)
|
||||
@ -20,7 +23,7 @@ DEFINE_VALIDATED_int32(query_plan_cache_ttl, 60, "Time to live for cached query
|
||||
namespace query {
|
||||
CachedPlan::CachedPlan(std::unique_ptr<LogicalPlan> plan) : plan_(std::move(plan)) {}
|
||||
|
||||
ParsedQuery ParseQuery(const std::string &query_string, const std::map<std::string, storage::PropertyValue> ¶ms,
|
||||
ParsedQuery ParseQuery(const std::string &query_string, const storage::PropertyValue::TMap ¶ms,
|
||||
utils::SkipList<QueryCacheEntry> *cache, utils::SpinLock *antlr_lock,
|
||||
const InterpreterConfig::Query &query_config) {
|
||||
// Strip the query for caching purposes. The process of stripping a query
|
||||
@ -34,7 +37,7 @@ ParsedQuery ParseQuery(const std::string &query_string, const std::map<std::stri
|
||||
|
||||
// Check that all user-specified parameters are provided.
|
||||
for (const auto ¶m_pair : stripped_query.parameters()) {
|
||||
auto it = params.find(param_pair.second);
|
||||
auto it = params.find(utils::pmr::string{param_pair.second, utils::NewDeleteResource()});
|
||||
|
||||
if (it == params.end()) {
|
||||
throw query::UnprovidedParameterError("Parameter ${} not provided.", param_pair.second);
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "query/frontend/semantic/symbol_generator.hpp"
|
||||
#include "query/frontend/stripped.hpp"
|
||||
#include "query/plan/planner.hpp"
|
||||
#include "storage/v2/property_value.hpp"
|
||||
#include "utils/flag_validation.hpp"
|
||||
#include "utils/timer.hpp"
|
||||
|
||||
@ -101,7 +102,7 @@ struct PlanCacheEntry {
|
||||
*/
|
||||
struct ParsedQuery {
|
||||
std::string query_string;
|
||||
std::map<std::string, storage::PropertyValue> user_parameters;
|
||||
storage::PropertyValue::TMap user_parameters;
|
||||
Parameters parameters;
|
||||
frontend::StrippedQuery stripped_query;
|
||||
AstStorage ast_storage;
|
||||
@ -110,7 +111,7 @@ struct ParsedQuery {
|
||||
bool is_cacheable{true};
|
||||
};
|
||||
|
||||
ParsedQuery ParseQuery(const std::string &query_string, const std::map<std::string, storage::PropertyValue> ¶ms,
|
||||
ParsedQuery ParseQuery(const std::string &query_string, const storage::PropertyValue::TMap ¶ms,
|
||||
utils::SkipList<QueryCacheEntry> *cache, utils::SpinLock *antlr_lock,
|
||||
const InterpreterConfig::Query &query_config);
|
||||
|
||||
|
@ -83,6 +83,7 @@ template <typename T>
|
||||
void PrintObject(std::ostream *out, const T &arg);
|
||||
|
||||
void PrintObject(std::ostream *out, const std::string &str);
|
||||
void PrintObject(std::ostream *out, const utils::pmr::string &str);
|
||||
|
||||
void PrintObject(std::ostream *out, Aggregation::Op op);
|
||||
|
||||
@ -95,9 +96,15 @@ void PrintObject(std::ostream *out, const storage::PropertyValue &value);
|
||||
template <typename T>
|
||||
void PrintObject(std::ostream *out, const std::vector<T> &vec);
|
||||
|
||||
template <typename T>
|
||||
void PrintObject(std::ostream *out, const utils::pmr::vector<T> &vec);
|
||||
|
||||
template <typename K, typename V>
|
||||
void PrintObject(std::ostream *out, const std::map<K, V> &map);
|
||||
|
||||
template <typename K, typename V>
|
||||
void PrintObject(std::ostream *out, const utils::pmr::map<K, V> &map);
|
||||
|
||||
template <typename T>
|
||||
void PrintObject(std::ostream *out, const T &arg) {
|
||||
static_assert(!std::is_convertible<T, Expression *>::value,
|
||||
@ -109,6 +116,7 @@ void PrintObject(std::ostream *out, const T &arg) {
|
||||
}
|
||||
|
||||
void PrintObject(std::ostream *out, const std::string &str) { *out << utils::Escape(str); }
|
||||
void PrintObject(std::ostream *out, const utils::pmr::string &str) { *out << utils::Escape(str); }
|
||||
|
||||
void PrintObject(std::ostream *out, Aggregation::Op op) { *out << Aggregation::OpToString(op); }
|
||||
|
||||
@ -165,6 +173,13 @@ void PrintObject(std::ostream *out, const std::vector<T> &vec) {
|
||||
*out << "]";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PrintObject(std::ostream *out, const utils::pmr::vector<T> &vec) {
|
||||
*out << "[";
|
||||
utils::PrintIterable(*out, vec, ", ", [](auto &stream, const auto &item) { PrintObject(&stream, item); });
|
||||
*out << "]";
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
void PrintObject(std::ostream *out, const std::map<K, V> &map) {
|
||||
*out << "{";
|
||||
@ -176,6 +191,17 @@ void PrintObject(std::ostream *out, const std::map<K, V> &map) {
|
||||
*out << "}";
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
void PrintObject(std::ostream *out, const utils::pmr::map<K, V> &map) {
|
||||
*out << "{";
|
||||
utils::PrintIterable(*out, map, ", ", [](auto &stream, const auto &item) {
|
||||
PrintObject(&stream, item.first);
|
||||
stream << ": ";
|
||||
PrintObject(&stream, item.second);
|
||||
});
|
||||
*out << "}";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PrintOperatorArgs(std::ostream *out, const T &arg) {
|
||||
*out << " ";
|
||||
|
@ -1503,8 +1503,7 @@ TriggerEventType ToTriggerEventType(const TriggerQuery::EventType event_type) {
|
||||
}
|
||||
}
|
||||
|
||||
Callback CreateTrigger(TriggerQuery *trigger_query,
|
||||
const std::map<std::string, storage::PropertyValue> &user_parameters,
|
||||
Callback CreateTrigger(TriggerQuery *trigger_query, const storage::PropertyValue::TMap &user_parameters,
|
||||
InterpreterContext *interpreter_context, DbAccessor *dba, std::optional<std::string> owner) {
|
||||
return {
|
||||
{},
|
||||
@ -1554,7 +1553,7 @@ Callback ShowTriggers(InterpreterContext *interpreter_context) {
|
||||
|
||||
PreparedQuery PrepareTriggerQuery(ParsedQuery parsed_query, const bool in_explicit_transaction,
|
||||
std::vector<Notification> *notifications, InterpreterContext *interpreter_context,
|
||||
DbAccessor *dba, const std::map<std::string, storage::PropertyValue> &user_parameters,
|
||||
DbAccessor *dba, const storage::PropertyValue::TMap &user_parameters,
|
||||
const std::string *username) {
|
||||
if (in_explicit_transaction) {
|
||||
throw TriggerModificationInMulticommandTxException();
|
||||
@ -1604,8 +1603,7 @@ PreparedQuery PrepareTriggerQuery(ParsedQuery parsed_query, const bool in_explic
|
||||
|
||||
PreparedQuery PrepareStreamQuery(ParsedQuery parsed_query, const bool in_explicit_transaction,
|
||||
std::vector<Notification> *notifications, InterpreterContext *interpreter_context,
|
||||
DbAccessor *dba,
|
||||
const std::map<std::string, storage::PropertyValue> & /*user_parameters*/,
|
||||
DbAccessor *dba, const storage::PropertyValue::TMap & /*user_parameters*/,
|
||||
const std::string *username) {
|
||||
if (in_explicit_transaction) {
|
||||
throw StreamQueryInMulticommandTxException();
|
||||
@ -2033,7 +2031,7 @@ void Interpreter::RollbackTransaction() {
|
||||
}
|
||||
|
||||
Interpreter::PrepareResult Interpreter::Prepare(const std::string &query_string,
|
||||
const std::map<std::string, storage::PropertyValue> ¶ms,
|
||||
const storage::PropertyValue::TMap ¶ms,
|
||||
const std::string *username) {
|
||||
if (!in_explicit_transaction_) {
|
||||
query_executions_.clear();
|
||||
|
@ -220,7 +220,7 @@ class Interpreter final {
|
||||
*
|
||||
* @throw query::QueryException
|
||||
*/
|
||||
PrepareResult Prepare(const std::string &query, const std::map<std::string, storage::PropertyValue> ¶ms,
|
||||
PrepareResult Prepare(const std::string &query, const storage::PropertyValue::TMap ¶ms,
|
||||
const std::string *username);
|
||||
|
||||
/**
|
||||
|
@ -1520,7 +1520,7 @@ storage::PropertyValue ToPropertyValue(const mgp_map &map) {
|
||||
storage::PropertyValue result{std::map<std::string, storage::PropertyValue>{}};
|
||||
auto &result_map = result.ValueMap();
|
||||
for (const auto &[key, value] : map.items) {
|
||||
result_map.insert_or_assign(std::string{key}, ToPropertyValue(value));
|
||||
result_map.insert_or_assign(utils::pmr::string{key}, ToPropertyValue(value));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "query/serialization/property_value.hpp"
|
||||
#include "storage/v2/property_value.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
|
||||
namespace query::serialization {
|
||||
|
||||
@ -46,7 +47,7 @@ nlohmann::json SerializePropertyValue(const storage::PropertyValue &property_val
|
||||
}
|
||||
}
|
||||
|
||||
nlohmann::json SerializePropertyValueVector(const std::vector<storage::PropertyValue> &values) {
|
||||
nlohmann::json SerializePropertyValueVector(const storage::PropertyValue::TVector &values) {
|
||||
nlohmann::json array = nlohmann::json::array();
|
||||
for (const auto &value : values) {
|
||||
array.push_back(SerializePropertyValue(value));
|
||||
@ -54,6 +55,18 @@ nlohmann::json SerializePropertyValueVector(const std::vector<storage::PropertyV
|
||||
return array;
|
||||
}
|
||||
|
||||
nlohmann::json SerializePropertyValueMap(const storage::PropertyValue::TMap ¶meters) {
|
||||
nlohmann::json data = nlohmann::json::object();
|
||||
data.emplace("type", static_cast<uint64_t>(ObjectType::MAP));
|
||||
data.emplace("value", nlohmann::json::object());
|
||||
|
||||
for (const auto &[key, value] : parameters) {
|
||||
data["value"][std::string{key}] = SerializePropertyValue(value);
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
nlohmann::json SerializePropertyValueMap(const std::map<std::string, storage::PropertyValue> ¶meters) {
|
||||
nlohmann::json data = nlohmann::json::object();
|
||||
data.emplace("type", static_cast<uint64_t>(ObjectType::MAP));
|
||||
@ -112,9 +125,9 @@ std::vector<storage::PropertyValue> DeserializePropertyValueList(const nlohmann:
|
||||
return property_values;
|
||||
}
|
||||
|
||||
std::map<std::string, storage::PropertyValue> DeserializePropertyValueMap(const nlohmann::json::object_t &data) {
|
||||
storage::PropertyValue::TMap DeserializePropertyValueMap(const nlohmann::json::object_t &data) {
|
||||
MG_ASSERT(data.at("type").get<ObjectType>() == ObjectType::MAP, "Invalid map serialization");
|
||||
std::map<std::string, storage::PropertyValue> property_values;
|
||||
storage::PropertyValue::TMap property_values{utils::NewDeleteResource()};
|
||||
|
||||
const nlohmann::json::object_t &values = data.at("value");
|
||||
for (const auto &[key, value] : values) {
|
||||
|
@ -19,7 +19,9 @@ namespace query::serialization {
|
||||
|
||||
nlohmann::json SerializePropertyValue(const storage::PropertyValue &property_value);
|
||||
|
||||
nlohmann::json SerializePropertyValueVector(const std::vector<storage::PropertyValue> &values);
|
||||
nlohmann::json SerializePropertyValueVector(const storage::PropertyValue::TVector &values);
|
||||
|
||||
nlohmann::json SerializePropertyValueMap(const storage::PropertyValue::TMap ¶meters);
|
||||
|
||||
nlohmann::json SerializePropertyValueMap(const std::map<std::string, storage::PropertyValue> ¶meters);
|
||||
|
||||
@ -27,6 +29,6 @@ storage::PropertyValue DeserializePropertyValue(const nlohmann::json &data);
|
||||
|
||||
std::vector<storage::PropertyValue> DeserializePropertyValueList(const nlohmann::json::array_t &data);
|
||||
|
||||
std::map<std::string, storage::PropertyValue> DeserializePropertyValueMap(const nlohmann::json::object_t &data);
|
||||
storage::PropertyValue::TMap DeserializePropertyValueMap(const nlohmann::json::object_t &data);
|
||||
|
||||
} // namespace query::serialization
|
||||
|
@ -523,7 +523,7 @@ Streams::StreamsMap::iterator Streams::CreateConsumer(StreamsMap &map, const std
|
||||
interpreter->Abort();
|
||||
}};
|
||||
|
||||
const static std::map<std::string, storage::PropertyValue> empty_parameters{};
|
||||
const static storage::PropertyValue::TMap empty_parameters{utils::NewDeleteResource()};
|
||||
uint32_t i = 0;
|
||||
while (true) {
|
||||
try {
|
||||
|
@ -150,8 +150,7 @@ std::vector<std::pair<Identifier, TriggerIdentifierTag>> GetPredefinedIdentifier
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Trigger::Trigger(std::string name, const std::string &query,
|
||||
const std::map<std::string, storage::PropertyValue> &user_parameters,
|
||||
Trigger::Trigger(std::string name, const std::string &query, const storage::PropertyValue::TMap &user_parameters,
|
||||
const TriggerEventType event_type, utils::SkipList<QueryCacheEntry> *query_cache,
|
||||
DbAccessor *db_accessor, utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config,
|
||||
std::optional<std::string> owner, const query::AuthChecker *auth_checker)
|
||||
@ -333,11 +332,11 @@ void TriggerStore::RestoreTriggers(utils::SkipList<QueryCacheEntry> *query_cache
|
||||
}
|
||||
|
||||
void TriggerStore::AddTrigger(std::string name, const std::string &query,
|
||||
const std::map<std::string, storage::PropertyValue> &user_parameters,
|
||||
TriggerEventType event_type, TriggerPhase phase,
|
||||
utils::SkipList<QueryCacheEntry> *query_cache, DbAccessor *db_accessor,
|
||||
utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config,
|
||||
std::optional<std::string> owner, const query::AuthChecker *auth_checker) {
|
||||
const storage::PropertyValue::TMap &user_parameters, TriggerEventType event_type,
|
||||
TriggerPhase phase, utils::SkipList<QueryCacheEntry> *query_cache,
|
||||
DbAccessor *db_accessor, utils::SpinLock *antlr_lock,
|
||||
const InterpreterConfig::Query &query_config, std::optional<std::string> owner,
|
||||
const query::AuthChecker *auth_checker) {
|
||||
std::unique_lock store_guard{store_lock_};
|
||||
if (storage_.Get(name)) {
|
||||
throw utils::BasicException("Trigger with the same name already exists.");
|
||||
|
@ -32,11 +32,10 @@
|
||||
|
||||
namespace query {
|
||||
struct Trigger {
|
||||
explicit Trigger(std::string name, const std::string &query,
|
||||
const std::map<std::string, storage::PropertyValue> &user_parameters, TriggerEventType event_type,
|
||||
utils::SkipList<QueryCacheEntry> *query_cache, DbAccessor *db_accessor, utils::SpinLock *antlr_lock,
|
||||
const InterpreterConfig::Query &query_config, std::optional<std::string> owner,
|
||||
const query::AuthChecker *auth_checker);
|
||||
explicit Trigger(std::string name, const std::string &query, const storage::PropertyValue::TMap &user_parameters,
|
||||
TriggerEventType event_type, utils::SkipList<QueryCacheEntry> *query_cache, DbAccessor *db_accessor,
|
||||
utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config,
|
||||
std::optional<std::string> owner, const query::AuthChecker *auth_checker);
|
||||
|
||||
void Execute(DbAccessor *dba, utils::MonotonicBufferResource *execution_memory, double max_execution_time_sec,
|
||||
std::atomic<bool> *is_shutting_down, const TriggerContext &context,
|
||||
@ -84,10 +83,9 @@ struct TriggerStore {
|
||||
utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config,
|
||||
const query::AuthChecker *auth_checker);
|
||||
|
||||
void AddTrigger(std::string name, const std::string &query,
|
||||
const std::map<std::string, storage::PropertyValue> &user_parameters, TriggerEventType event_type,
|
||||
TriggerPhase phase, utils::SkipList<QueryCacheEntry> *query_cache, DbAccessor *db_accessor,
|
||||
utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config,
|
||||
void AddTrigger(std::string name, const std::string &query, const storage::PropertyValue::TMap &user_parameters,
|
||||
TriggerEventType event_type, TriggerPhase phase, utils::SkipList<QueryCacheEntry> *query_cache,
|
||||
DbAccessor *db_accessor, utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config,
|
||||
std::optional<std::string> owner, const query::AuthChecker *auth_checker);
|
||||
|
||||
void DropTrigger(const std::string &name);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "storage/v2/property_value.hpp"
|
||||
#include "storage/v2/temporal.hpp"
|
||||
#include "utils/exceptions.hpp"
|
||||
#include "utils/fnv.hpp"
|
||||
@ -278,12 +279,18 @@ TypedValue::operator storage::PropertyValue() const {
|
||||
case TypedValue::Type::Double:
|
||||
return storage::PropertyValue(double_v);
|
||||
case TypedValue::Type::String:
|
||||
return storage::PropertyValue(std::string(string_v));
|
||||
case TypedValue::Type::List:
|
||||
return storage::PropertyValue(std::vector<storage::PropertyValue>(list_v.begin(), list_v.end()));
|
||||
return storage::PropertyValue(string_v, memory_);
|
||||
case TypedValue::Type::List: {
|
||||
storage::PropertyValue::TVector list{memory_};
|
||||
list.reserve(list_v.size());
|
||||
for (const auto &tv : list_v) {
|
||||
list.emplace_back(storage::PropertyValue(tv));
|
||||
}
|
||||
return storage::PropertyValue(std::move(list));
|
||||
}
|
||||
case TypedValue::Type::Map: {
|
||||
std::map<std::string, storage::PropertyValue> map;
|
||||
for (const auto &kv : map_v) map.emplace(kv.first, kv.second);
|
||||
storage::PropertyValue::TMap map{memory_};
|
||||
for (const auto &kv : map_v) map.emplace(kv.first, storage::PropertyValue(kv.second));
|
||||
return storage::PropertyValue(std::move(map));
|
||||
}
|
||||
case Type::Date:
|
||||
|
@ -19,6 +19,10 @@
|
||||
#include "storage/v2/temporal.hpp"
|
||||
#include "utils/algorithm.hpp"
|
||||
#include "utils/exceptions.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
#include "utils/pmr/map.hpp"
|
||||
#include "utils/pmr/string.hpp"
|
||||
#include "utils/pmr/vector.hpp"
|
||||
|
||||
namespace storage {
|
||||
|
||||
@ -48,6 +52,12 @@ class PropertyValue {
|
||||
TemporalData = 7
|
||||
};
|
||||
|
||||
using TString = utils::pmr::string;
|
||||
using TVector = utils::pmr::vector<PropertyValue>;
|
||||
using TMap = utils::pmr::map<utils::pmr::string, PropertyValue>;
|
||||
|
||||
using allocator_type = utils::Allocator<PropertyValue>;
|
||||
|
||||
static bool AreComparableTypes(Type a, Type b) {
|
||||
return (a == b) || (a == Type::Int && b == Type::Double) || (a == Type::Double && b == Type::Int);
|
||||
}
|
||||
@ -56,45 +66,204 @@ class PropertyValue {
|
||||
PropertyValue() : type_(Type::Null) {}
|
||||
|
||||
// constructors for primitive types
|
||||
explicit PropertyValue(const bool value) : type_(Type::Bool) { bool_v = value; }
|
||||
explicit PropertyValue(const int value) : type_(Type::Int) { int_v = value; }
|
||||
explicit PropertyValue(const int64_t value) : type_(Type::Int) { int_v = value; }
|
||||
explicit PropertyValue(const double value) : type_(Type::Double) { double_v = value; }
|
||||
explicit PropertyValue(const TemporalData value) : type_{Type::TemporalData} { temporal_data_v = value; }
|
||||
explicit PropertyValue(const bool value, utils::MemoryResource *memory = utils::NewDeleteResource())
|
||||
: type_(Type::Bool), memory_{memory} {
|
||||
bool_v = value;
|
||||
}
|
||||
explicit PropertyValue(const int value, utils::MemoryResource *memory = utils::NewDeleteResource())
|
||||
: type_(Type::Int), memory_{memory} {
|
||||
int_v = value;
|
||||
}
|
||||
explicit PropertyValue(const int64_t value, utils::MemoryResource *memory = utils::NewDeleteResource())
|
||||
: type_(Type::Int), memory_{memory} {
|
||||
int_v = value;
|
||||
}
|
||||
explicit PropertyValue(const double value, utils::MemoryResource *memory = utils::NewDeleteResource())
|
||||
: type_(Type::Double), memory_{memory} {
|
||||
double_v = value;
|
||||
}
|
||||
explicit PropertyValue(const TemporalData value, utils::MemoryResource *memory = utils::NewDeleteResource())
|
||||
: type_{Type::TemporalData}, memory_{memory} {
|
||||
temporal_data_v = value;
|
||||
}
|
||||
|
||||
// copy constructors for non-primitive types
|
||||
/// @throw std::bad_alloc
|
||||
explicit PropertyValue(const std::string &value) : type_(Type::String) { new (&string_v) std::string(value); }
|
||||
explicit PropertyValue(const std::string &value, utils::MemoryResource *memory = utils::NewDeleteResource())
|
||||
: type_(Type::String), memory_{memory} {
|
||||
new (&string_v) TString(value, memory);
|
||||
}
|
||||
/// @throw std::bad_alloc
|
||||
/// @throw std::length_error if length of value exceeds
|
||||
/// std::string::max_length().
|
||||
explicit PropertyValue(const char *value) : type_(Type::String) { new (&string_v) std::string(value); }
|
||||
/// @throw std::bad_alloc
|
||||
explicit PropertyValue(const std::vector<PropertyValue> &value) : type_(Type::List) {
|
||||
new (&list_v) std::vector<PropertyValue>(value);
|
||||
}
|
||||
/// @throw std::bad_alloc
|
||||
explicit PropertyValue(const std::map<std::string, PropertyValue> &value) : type_(Type::Map) {
|
||||
new (&map_v) std::map<std::string, PropertyValue>(value);
|
||||
explicit PropertyValue(const char *value, utils::MemoryResource *memory = utils::NewDeleteResource())
|
||||
: type_(Type::String), memory_{memory} {
|
||||
new (&string_v) TString(value, memory);
|
||||
}
|
||||
|
||||
// move constructors for non-primitive types
|
||||
explicit PropertyValue(std::string &&value) noexcept : type_(Type::String) {
|
||||
new (&string_v) std::string(std::move(value));
|
||||
/**
|
||||
* Construct a copy of other.
|
||||
* utils::MemoryResource is obtained by calling
|
||||
* std::allocator_traits<>::
|
||||
* select_on_container_copy_construction(other.get_allocator()).
|
||||
* Since we use utils::Allocator, which does not propagate, this means that
|
||||
* memory_ will be the default utils::NewDeleteResource().
|
||||
*/
|
||||
explicit PropertyValue(const TString &other)
|
||||
: PropertyValue(other,
|
||||
std::allocator_traits<utils::Allocator<PropertyValue>>::select_on_container_copy_construction(
|
||||
other.get_allocator())
|
||||
.GetMemoryResource()) {}
|
||||
|
||||
/** Construct a copy using the given utils::MemoryResource */
|
||||
PropertyValue(const TString &other, utils::MemoryResource *memory) : type_(Type::String), memory_{memory} {
|
||||
new (&string_v) TString(other, memory_);
|
||||
}
|
||||
explicit PropertyValue(std::vector<PropertyValue> &&value) noexcept : type_(Type::List) {
|
||||
new (&list_v) std::vector<PropertyValue>(std::move(value));
|
||||
|
||||
/** Construct a copy using the given utils::MemoryResource */
|
||||
explicit PropertyValue(const std::vector<PropertyValue> &value,
|
||||
utils::MemoryResource *memory = utils::NewDeleteResource())
|
||||
: type_(Type::List), memory_(memory) {
|
||||
new (&list_v) TVector(memory_);
|
||||
list_v.reserve(value.size());
|
||||
list_v.assign(value.begin(), value.end());
|
||||
}
|
||||
explicit PropertyValue(std::map<std::string, PropertyValue> &&value) noexcept : type_(Type::Map) {
|
||||
new (&map_v) std::map<std::string, PropertyValue>(std::move(value));
|
||||
|
||||
/**
|
||||
* Construct a copy of other.
|
||||
* utils::MemoryResource is obtained by calling
|
||||
* std::allocator_traits<>::
|
||||
* select_on_container_copy_construction(other.get_allocator()).
|
||||
* Since we use utils::Allocator, which does not propagate, this means that
|
||||
* memory_ will be the default utils::NewDeleteResource().
|
||||
*/
|
||||
explicit PropertyValue(const TVector &other)
|
||||
: PropertyValue(other,
|
||||
std::allocator_traits<utils::Allocator<PropertyValue>>::select_on_container_copy_construction(
|
||||
other.get_allocator())
|
||||
.GetMemoryResource()) {}
|
||||
|
||||
/** Construct a copy using the given utils::MemoryResource */
|
||||
PropertyValue(const TVector &value, utils::MemoryResource *memory) : type_(Type::List), memory_(memory) {
|
||||
new (&list_v) TVector(value, memory_);
|
||||
}
|
||||
|
||||
/** Construct a copy using the given utils::MemoryResource */
|
||||
explicit PropertyValue(const std::map<std::string, PropertyValue> &value,
|
||||
utils::MemoryResource *memory = utils::NewDeleteResource())
|
||||
: type_(Type::Map), memory_{memory} {
|
||||
new (&map_v) TMap(memory_);
|
||||
for (const auto &kv : value) map_v.emplace(kv.first, kv.second);
|
||||
}
|
||||
/**
|
||||
* Construct a copy of other.
|
||||
* utils::MemoryResource is obtained by calling
|
||||
* std::allocator_traits<>::
|
||||
* select_on_container_copy_construction(other.get_allocator()).
|
||||
* Since we use utils::Allocator, which does not propagate, this means that
|
||||
* memory_ will be the default utils::NewDeleteResource().
|
||||
*/
|
||||
explicit PropertyValue(const TMap &other)
|
||||
: PropertyValue(other,
|
||||
std::allocator_traits<utils::Allocator<PropertyValue>>::select_on_container_copy_construction(
|
||||
other.get_allocator())
|
||||
.GetMemoryResource()) {}
|
||||
|
||||
/** Construct a copy using the given utils::MemoryResource */
|
||||
PropertyValue(const TMap &value, utils::MemoryResource *memory) : type_(Type::Map), memory_{memory} {
|
||||
new (&map_v) TMap(value, memory_);
|
||||
}
|
||||
/**
|
||||
* Construct with the value of other.
|
||||
* utils::MemoryResource is obtained from other. After the move, other will be
|
||||
* left in unspecified state.
|
||||
*/
|
||||
explicit PropertyValue(TString &&other) noexcept
|
||||
: PropertyValue(std::move(other), other.get_allocator().GetMemoryResource()) {}
|
||||
|
||||
/**
|
||||
* Construct with the value of other and use the given MemoryResource
|
||||
* After the move, other will be left in unspecified state.
|
||||
*/
|
||||
PropertyValue(TString &&other, utils::MemoryResource *memory) : type_(Type::String), memory_{memory} {
|
||||
new (&string_v) TString(std::move(other), memory_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an element-wise move using default utils::NewDeleteResource().
|
||||
* Other will be not be empty, though elements may be Null.
|
||||
*/
|
||||
explicit PropertyValue(std::vector<PropertyValue> &&other)
|
||||
: PropertyValue(std::move(other), utils::NewDeleteResource()) {}
|
||||
|
||||
/**
|
||||
* Perform an element-wise move of the other and use the given MemoryResource.
|
||||
* Other will be not be left empty, though elements may be Null.
|
||||
*/
|
||||
PropertyValue(std::vector<PropertyValue> &&other, utils::MemoryResource *memory)
|
||||
: type_(Type::List), memory_{memory} {
|
||||
new (&list_v) TVector(memory_);
|
||||
list_v.reserve(other.size());
|
||||
// std::vector<PropertyValue> has std::allocator and there's no move
|
||||
// constructor for std::vector using different allocator types. Since
|
||||
// std::allocator is not propagated to elements, it is possible that some
|
||||
// PropertyValue elements have a MemoryResource that is the same as the one we
|
||||
// are given. In such a case we would like to move those PropertyValue
|
||||
// instances, so we use move_iterator.
|
||||
list_v.assign(std::make_move_iterator(other.begin()), std::make_move_iterator(other.end()));
|
||||
}
|
||||
/**
|
||||
* Construct with the value of other.
|
||||
* utils::MemoryResource is obtained from other. After the move, other will be
|
||||
* left empty.
|
||||
*/
|
||||
explicit PropertyValue(TVector &&other) noexcept
|
||||
: PropertyValue(std::move(other), other.get_allocator().GetMemoryResource()) {}
|
||||
|
||||
/**
|
||||
* Construct with the value of other and use the given MemoryResource.
|
||||
* If `other.get_allocator() != *memory`, this call will perform an
|
||||
* element-wise move and other is not guaranteed to be empty.
|
||||
*/
|
||||
PropertyValue(TVector &&other, utils::MemoryResource *memory) : type_(Type::List), memory_{memory} {
|
||||
new (&list_v) TVector(std::move(other), memory_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an element-wise move using default utils::NewDeleteResource().
|
||||
* Other will not be left empty, i.e. keys will exist but their values may
|
||||
* be Null.
|
||||
*/
|
||||
explicit PropertyValue(std::map<std::string, PropertyValue> &&other)
|
||||
: PropertyValue(std::move(other), utils::NewDeleteResource()) {}
|
||||
|
||||
/**
|
||||
* Perform an element-wise move using the given MemoryResource.
|
||||
* Other will not be left empty, i.e. keys will exist but their values may
|
||||
* be Null.
|
||||
*/
|
||||
PropertyValue(std::map<std::string, PropertyValue> &&other, utils::MemoryResource *memory)
|
||||
: type_(Type::Map), memory_{memory} {
|
||||
new (&map_v) TMap(memory_);
|
||||
for (auto &kv : other) map_v.emplace(kv.first, std::move(kv.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with the value of other.
|
||||
* utils::MemoryResource is obtained from other. After the move, other will be
|
||||
* left empty.
|
||||
*/
|
||||
explicit PropertyValue(TMap &&other) noexcept
|
||||
: PropertyValue(std::move(other), other.get_allocator().GetMemoryResource()) {}
|
||||
|
||||
// copy constructor
|
||||
/// @throw std::bad_alloc
|
||||
PropertyValue(const PropertyValue &other);
|
||||
PropertyValue(const PropertyValue &other, utils::MemoryResource *memory);
|
||||
|
||||
// move constructor
|
||||
PropertyValue(PropertyValue &&other) noexcept;
|
||||
PropertyValue(PropertyValue &&other, utils::MemoryResource *memory) noexcept;
|
||||
|
||||
// copy assignment
|
||||
/// @throw std::bad_alloc
|
||||
@ -153,7 +322,7 @@ class PropertyValue {
|
||||
|
||||
// const value getters for non-primitive types
|
||||
/// @throw PropertyValueException if value isn't of correct type.
|
||||
const std::string &ValueString() const {
|
||||
const TString &ValueString() const {
|
||||
if (type_ != Type::String) {
|
||||
throw PropertyValueException("The value isn't a string!");
|
||||
}
|
||||
@ -161,7 +330,7 @@ class PropertyValue {
|
||||
}
|
||||
|
||||
/// @throw PropertyValueException if value isn't of correct type.
|
||||
const std::vector<PropertyValue> &ValueList() const {
|
||||
const TVector &ValueList() const {
|
||||
if (type_ != Type::List) {
|
||||
throw PropertyValueException("The value isn't a list!");
|
||||
}
|
||||
@ -169,7 +338,7 @@ class PropertyValue {
|
||||
}
|
||||
|
||||
/// @throw PropertyValueException if value isn't of correct type.
|
||||
const std::map<std::string, PropertyValue> &ValueMap() const {
|
||||
const TMap &ValueMap() const {
|
||||
if (type_ != Type::Map) {
|
||||
throw PropertyValueException("The value isn't a map!");
|
||||
}
|
||||
@ -178,7 +347,7 @@ class PropertyValue {
|
||||
|
||||
// reference value getters for non-primitive types
|
||||
/// @throw PropertyValueException if value isn't of correct type.
|
||||
std::string &ValueString() {
|
||||
TString &ValueString() {
|
||||
if (type_ != Type::String) {
|
||||
throw PropertyValueException("The value isn't a string!");
|
||||
}
|
||||
@ -186,7 +355,7 @@ class PropertyValue {
|
||||
}
|
||||
|
||||
/// @throw PropertyValueException if value isn't of correct type.
|
||||
std::vector<PropertyValue> &ValueList() {
|
||||
TVector &ValueList() {
|
||||
if (type_ != Type::List) {
|
||||
throw PropertyValueException("The value isn't a list!");
|
||||
}
|
||||
@ -194,7 +363,7 @@ class PropertyValue {
|
||||
}
|
||||
|
||||
/// @throw PropertyValueException if value isn't of correct type.
|
||||
std::map<std::string, PropertyValue> &ValueMap() {
|
||||
TMap &ValueMap() {
|
||||
if (type_ != Type::Map) {
|
||||
throw PropertyValueException("The value isn't a map!");
|
||||
}
|
||||
@ -208,13 +377,14 @@ class PropertyValue {
|
||||
bool bool_v;
|
||||
int64_t int_v;
|
||||
double double_v;
|
||||
std::string string_v;
|
||||
std::vector<PropertyValue> list_v;
|
||||
std::map<std::string, PropertyValue> map_v;
|
||||
TString string_v;
|
||||
TVector list_v;
|
||||
TMap map_v;
|
||||
TemporalData temporal_data_v;
|
||||
};
|
||||
|
||||
Type type_;
|
||||
utils::MemoryResource *memory_{utils::NewDeleteResource()};
|
||||
};
|
||||
|
||||
// stream output
|
||||
@ -329,8 +499,14 @@ inline bool operator<(const PropertyValue &first, const PropertyValue &second) n
|
||||
return first.ValueTemporalData() < second.ValueTemporalData();
|
||||
}
|
||||
}
|
||||
inline PropertyValue::PropertyValue(const PropertyValue &other)
|
||||
: PropertyValue(
|
||||
other,
|
||||
std::allocator_traits<utils::Allocator<PropertyValue>>::select_on_container_copy_construction(other.memory_)
|
||||
.GetMemoryResource()) {}
|
||||
|
||||
inline PropertyValue::PropertyValue(const PropertyValue &other) : type_(other.type_) {
|
||||
inline PropertyValue::PropertyValue(const PropertyValue &other, utils::MemoryResource *memory)
|
||||
: type_(other.type_), memory_{memory} {
|
||||
switch (other.type_) {
|
||||
case Type::Null:
|
||||
return;
|
||||
@ -344,13 +520,13 @@ inline PropertyValue::PropertyValue(const PropertyValue &other) : type_(other.ty
|
||||
this->double_v = other.double_v;
|
||||
return;
|
||||
case Type::String:
|
||||
new (&string_v) std::string(other.string_v);
|
||||
new (&string_v) TString(other.string_v, memory_);
|
||||
return;
|
||||
case Type::List:
|
||||
new (&list_v) std::vector<PropertyValue>(other.list_v);
|
||||
new (&list_v) TVector(other.list_v, memory_);
|
||||
return;
|
||||
case Type::Map:
|
||||
new (&map_v) std::map<std::string, PropertyValue>(other.map_v);
|
||||
new (&map_v) TMap(other.map_v, memory_);
|
||||
return;
|
||||
case Type::TemporalData:
|
||||
this->temporal_data_v = other.temporal_data_v;
|
||||
@ -358,7 +534,10 @@ inline PropertyValue::PropertyValue(const PropertyValue &other) : type_(other.ty
|
||||
}
|
||||
}
|
||||
|
||||
inline PropertyValue::PropertyValue(PropertyValue &&other) noexcept : type_(other.type_) {
|
||||
inline PropertyValue::PropertyValue(PropertyValue &&other) noexcept : PropertyValue(std::move(other), other.memory_) {}
|
||||
|
||||
inline PropertyValue::PropertyValue(PropertyValue &&other, utils::MemoryResource *memory) noexcept
|
||||
: type_(other.type_), memory_{memory} {
|
||||
switch (other.type_) {
|
||||
case Type::Null:
|
||||
break;
|
||||
@ -372,13 +551,13 @@ inline PropertyValue::PropertyValue(PropertyValue &&other) noexcept : type_(othe
|
||||
this->double_v = other.double_v;
|
||||
break;
|
||||
case Type::String:
|
||||
new (&string_v) std::string(std::move(other.string_v));
|
||||
new (&string_v) TString(std::move(other.string_v), memory_);
|
||||
break;
|
||||
case Type::List:
|
||||
new (&list_v) std::vector<PropertyValue>(std::move(other.list_v));
|
||||
new (&list_v) TVector(std::move(other.list_v), memory_);
|
||||
break;
|
||||
case Type::Map:
|
||||
new (&map_v) std::map<std::string, PropertyValue>(std::move(other.map_v));
|
||||
new (&map_v) TMap(std::move(other.map_v), memory_);
|
||||
break;
|
||||
case Type::TemporalData:
|
||||
this->temporal_data_v = other.temporal_data_v;
|
||||
@ -409,13 +588,13 @@ inline PropertyValue &PropertyValue::operator=(const PropertyValue &other) {
|
||||
this->double_v = other.double_v;
|
||||
break;
|
||||
case Type::String:
|
||||
new (&string_v) std::string(other.string_v);
|
||||
new (&string_v) TString(other.string_v, memory_);
|
||||
break;
|
||||
case Type::List:
|
||||
new (&list_v) std::vector<PropertyValue>(other.list_v);
|
||||
new (&list_v) TVector(other.list_v, memory_);
|
||||
break;
|
||||
case Type::Map:
|
||||
new (&map_v) std::map<std::string, PropertyValue>(other.map_v);
|
||||
new (&map_v) TMap(other.map_v, memory_);
|
||||
break;
|
||||
case Type::TemporalData:
|
||||
this->temporal_data_v = other.temporal_data_v;
|
||||
@ -444,13 +623,13 @@ inline PropertyValue &PropertyValue::operator=(PropertyValue &&other) noexcept {
|
||||
this->double_v = other.double_v;
|
||||
break;
|
||||
case Type::String:
|
||||
new (&string_v) std::string(std::move(other.string_v));
|
||||
new (&string_v) TString(std::move(other.string_v), memory_);
|
||||
break;
|
||||
case Type::List:
|
||||
new (&list_v) std::vector<PropertyValue>(std::move(other.list_v));
|
||||
new (&list_v) TVector(std::move(other.list_v), memory_);
|
||||
break;
|
||||
case Type::Map:
|
||||
new (&map_v) std::map<std::string, PropertyValue>(std::move(other.map_v));
|
||||
new (&map_v) TMap(std::move(other.map_v), memory_);
|
||||
break;
|
||||
case Type::TemporalData:
|
||||
this->temporal_data_v = other.temporal_data_v;
|
||||
|
@ -16,7 +16,9 @@
|
||||
#include "query/interpreter.hpp"
|
||||
#include "query/typed_value.hpp"
|
||||
#include "storage/v2/isolation_level.hpp"
|
||||
#include "storage/v2/property_value.hpp"
|
||||
#include "storage/v2/storage.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
|
||||
class ExpansionBenchFixture : public benchmark::Fixture {
|
||||
protected:
|
||||
@ -64,7 +66,7 @@ BENCHMARK_DEFINE_F(ExpansionBenchFixture, Match)(benchmark::State &state) {
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
ResultStreamFaker results(&*db);
|
||||
interpreter->Prepare(query, {}, nullptr);
|
||||
interpreter->Prepare(query, storage::PropertyValue::TMap{utils::NewDeleteResource()}, nullptr);
|
||||
interpreter->PullAll(&results);
|
||||
}
|
||||
}
|
||||
@ -79,7 +81,7 @@ BENCHMARK_DEFINE_F(ExpansionBenchFixture, Expand)(benchmark::State &state) {
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
ResultStreamFaker results(&*db);
|
||||
interpreter->Prepare(query, {}, nullptr);
|
||||
interpreter->Prepare(query, storage::PropertyValue::TMap{utils::NewDeleteResource()}, nullptr);
|
||||
interpreter->PullAll(&results);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "storage/v2/isolation_level.hpp"
|
||||
#include "storage/v2/storage.hpp"
|
||||
#include "utils/license.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
#include "utils/on_scope_exit.hpp"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
@ -35,7 +36,8 @@ int main(int argc, char *argv[]) {
|
||||
query::Interpreter interpreter{&interpreter_context};
|
||||
|
||||
ResultStreamFaker stream(&db);
|
||||
auto [header, _, qid] = interpreter.Prepare(argv[1], {}, nullptr);
|
||||
auto [header, _, qid] =
|
||||
interpreter.Prepare(argv[1], storage::PropertyValue::TMap{utils::NewDeleteResource()}, nullptr);
|
||||
stream.Header(header);
|
||||
auto summary = interpreter.PullAll(&stream);
|
||||
stream.Summary(summary);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "storage/v2/property_value.hpp"
|
||||
#include "utils/csv_parsing.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -40,6 +41,14 @@ auto ToEdgeList(const communication::bolt::Value &v) {
|
||||
return list;
|
||||
};
|
||||
|
||||
auto ToPropertyValueMap(const std::map<std::string, storage::PropertyValue> &map) {
|
||||
storage::PropertyValue::TMap property_value_map{utils::NewDeleteResource()};
|
||||
for (const auto &[key, value] : map) {
|
||||
property_value_map.emplace(utils::pmr::string{key, utils::NewDeleteResource()}, std::move(value));
|
||||
}
|
||||
return property_value_map;
|
||||
}
|
||||
|
||||
struct InterpreterFaker {
|
||||
InterpreterFaker(storage::Storage *db, const query::InterpreterConfig config,
|
||||
const std::filesystem::path &data_directory)
|
||||
@ -50,7 +59,7 @@ struct InterpreterFaker {
|
||||
auto Prepare(const std::string &query, const std::map<std::string, storage::PropertyValue> ¶ms = {}) {
|
||||
ResultStreamFaker stream(interpreter_context.db);
|
||||
|
||||
const auto [header, _, qid] = interpreter.Prepare(query, params, nullptr);
|
||||
const auto [header, _, qid] = interpreter.Prepare(query, ToPropertyValueMap(params), nullptr);
|
||||
stream.Header(header);
|
||||
return std::make_pair(std::move(stream), qid);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "storage/v2/property_value.hpp"
|
||||
#include "storage/v2/temporal.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
||||
TEST(PropertyValue, Null) {
|
||||
@ -423,7 +424,7 @@ TEST(PropertyValue, MapCopy) {
|
||||
{
|
||||
const auto &ret = pv.ValueMap();
|
||||
ASSERT_EQ(ret.size(), 1);
|
||||
ASSERT_EQ(ret.at("nandare").ValueInt(), 123);
|
||||
ASSERT_EQ(ret.at({"nandare", utils::NewDeleteResource()}).ValueInt(), 123);
|
||||
}
|
||||
|
||||
const auto &cpv = pv;
|
||||
@ -436,7 +437,7 @@ TEST(PropertyValue, MapCopy) {
|
||||
{
|
||||
const auto &ret = cpv.ValueMap();
|
||||
ASSERT_EQ(ret.size(), 1);
|
||||
ASSERT_EQ(ret.at("nandare").ValueInt(), 123);
|
||||
ASSERT_EQ(ret.at({"nandare", utils::NewDeleteResource()}).ValueInt(), 123);
|
||||
}
|
||||
|
||||
{
|
||||
@ -476,7 +477,7 @@ TEST(PropertyValue, MapMove) {
|
||||
{
|
||||
const auto &ret = pv.ValueMap();
|
||||
ASSERT_EQ(ret.size(), 1);
|
||||
ASSERT_EQ(ret.at("nandare").ValueInt(), 123);
|
||||
ASSERT_EQ(ret.at({"nandare", utils::NewDeleteResource()}).ValueInt(), 123);
|
||||
}
|
||||
|
||||
const auto &cpv = pv;
|
||||
@ -489,7 +490,7 @@ TEST(PropertyValue, MapMove) {
|
||||
{
|
||||
const auto &ret = cpv.ValueMap();
|
||||
ASSERT_EQ(ret.size(), 1);
|
||||
ASSERT_EQ(ret.at("nandare").ValueInt(), 123);
|
||||
ASSERT_EQ(ret.at({"nandare", utils::NewDeleteResource()}).ValueInt(), 123);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -21,8 +21,10 @@
|
||||
#include "query/dump.hpp"
|
||||
#include "query/interpreter.hpp"
|
||||
#include "query/typed_value.hpp"
|
||||
#include "storage/v2/property_value.hpp"
|
||||
#include "storage/v2/storage.hpp"
|
||||
#include "storage/v2/temporal.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
#include "utils/temporal.hpp"
|
||||
|
||||
const char *kPropertyId = "property_id";
|
||||
@ -207,7 +209,7 @@ auto Execute(storage::Storage *db, const std::string &query) {
|
||||
query::Interpreter interpreter(&context);
|
||||
ResultStreamFaker stream(db);
|
||||
|
||||
auto [header, _, qid] = interpreter.Prepare(query, {}, nullptr);
|
||||
auto [header, _, qid] = interpreter.Prepare(query, storage::PropertyValue::TMap{utils::NewDeleteResource()}, nullptr);
|
||||
stream.Header(header);
|
||||
auto summary = interpreter.PullAll(&stream);
|
||||
stream.Summary(summary);
|
||||
@ -399,7 +401,12 @@ TEST(DumpTest, PropertyValue) {
|
||||
auto bool_value = storage::PropertyValue(true);
|
||||
auto double_value = storage::PropertyValue(-1.2);
|
||||
auto str_value = storage::PropertyValue("hello 'world'");
|
||||
auto map_value = storage::PropertyValue({{"prop 1", int_value}, {"prop`2`", bool_value}});
|
||||
storage::PropertyValue map_value = storage::PropertyValue(std::invoke([&] {
|
||||
storage::PropertyValue::TMap map_value{utils::NewDeleteResource()};
|
||||
map_value.emplace(storage::PropertyValue::TString{"prop 1", utils::NewDeleteResource()}, int_value);
|
||||
map_value.emplace(storage::PropertyValue::TString{"prop 2", utils::NewDeleteResource()}, bool_value);
|
||||
return map_value;
|
||||
}));
|
||||
auto dt = storage::PropertyValue(
|
||||
storage::TemporalData(storage::TemporalType::Date, utils::Date({1994, 12, 7}).MicrosecondsSinceEpoch()));
|
||||
auto lt = storage::PropertyValue(storage::TemporalData(
|
||||
@ -409,7 +416,8 @@ TEST(DumpTest, PropertyValue) {
|
||||
utils::LocalDateTime({1994, 12, 7}, {14, 10, 44, 99, 99}).MicrosecondsSinceEpoch()));
|
||||
auto dur = storage::PropertyValue(
|
||||
storage::TemporalData(storage::TemporalType::Duration, utils::Duration({3, 4, 5, 6, 10, 11}).microseconds));
|
||||
auto list_value = storage::PropertyValue({map_value, null_value, double_value, dt, lt, ldt, dur});
|
||||
auto list_value = storage::PropertyValue(storage::PropertyValue::TVector{
|
||||
{map_value, null_value, double_value, dt, lt, ldt, dur}, utils::NewDeleteResource()});
|
||||
CreateVertex(&dba, {}, {{"p1", list_value}, {"p2", str_value}}, false);
|
||||
ASSERT_FALSE(dba.Commit().HasError());
|
||||
}
|
||||
@ -751,7 +759,8 @@ class StatefulInterpreter {
|
||||
auto Execute(const std::string &query) {
|
||||
ResultStreamFaker stream(db_);
|
||||
|
||||
auto [header, _, qid] = interpreter_.Prepare(query, {}, nullptr);
|
||||
auto [header, _, qid] =
|
||||
interpreter_.Prepare(query, storage::PropertyValue::TMap{utils::NewDeleteResource()}, nullptr);
|
||||
stream.Header(header);
|
||||
auto summary = interpreter_.PullAll(&stream);
|
||||
stream.Summary(summary);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "communication/result_stream_faker.hpp"
|
||||
#include "query/interpreter.hpp"
|
||||
#include "storage/v2/storage.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
|
||||
DECLARE_bool(query_cost_planner);
|
||||
|
||||
@ -53,7 +54,8 @@ class QueryExecution : public testing::Test {
|
||||
auto Execute(const std::string &query) {
|
||||
ResultStreamFaker stream(&*db_);
|
||||
|
||||
auto [header, _, qid] = interpreter_->Prepare(query, {}, nullptr);
|
||||
auto [header, _, qid] =
|
||||
interpreter_->Prepare(query, storage::PropertyValue::TMap{utils::NewDeleteResource()}, nullptr);
|
||||
stream.Header(header);
|
||||
auto summary = interpreter_->PullAll(&stream);
|
||||
stream.Summary(summary);
|
||||
|
@ -877,11 +877,15 @@ TEST_F(TriggerStoreTest, Restore) {
|
||||
const auto event_type = query::TriggerEventType::VERTEX_CREATE;
|
||||
const std::string owner{"owner"};
|
||||
store->AddTrigger(trigger_name_before, trigger_statement,
|
||||
std::map<std::string, storage::PropertyValue>{{"parameter", storage::PropertyValue{1}}}, event_type,
|
||||
query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
storage::PropertyValue::TMap{
|
||||
{{utils::pmr::string{"parameter", utils::NewDeleteResource()}, storage::PropertyValue{1}}},
|
||||
utils::NewDeleteResource()},
|
||||
event_type, query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
query::InterpreterConfig::Query{}, std::nullopt, &auth_checker);
|
||||
store->AddTrigger(trigger_name_after, trigger_statement,
|
||||
std::map<std::string, storage::PropertyValue>{{"parameter", storage::PropertyValue{"value"}}},
|
||||
storage::PropertyValue::TMap{
|
||||
{{utils::pmr::string{"parameter", utils::NewDeleteResource()}, storage::PropertyValue{1}}},
|
||||
utils::NewDeleteResource()},
|
||||
event_type, query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
query::InterpreterConfig::Query{}, {owner}, &auth_checker);
|
||||
|
||||
@ -932,34 +936,38 @@ TEST_F(TriggerStoreTest, AddTrigger) {
|
||||
query::TriggerStore store{testing_directory};
|
||||
|
||||
// Invalid query in statements
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETUR 1", {}, query::TriggerEventType::VERTEX_CREATE,
|
||||
query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
utils::BasicException);
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN createdEdges", {}, query::TriggerEventType::VERTEX_CREATE,
|
||||
query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETUR 1", storage::PropertyValue::TMap{utils::NewDeleteResource()},
|
||||
query::TriggerEventType::VERTEX_CREATE, query::TriggerPhase::BEFORE_COMMIT, &ast_cache,
|
||||
&*dba, &antlr_lock, query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
utils::BasicException);
|
||||
ASSERT_THROW(
|
||||
store.AddTrigger("trigger", "RETURN createdEdges", storage::PropertyValue::TMap{utils::NewDeleteResource()},
|
||||
query::TriggerEventType::VERTEX_CREATE, query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
&antlr_lock, query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
utils::BasicException);
|
||||
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN $parameter", {}, query::TriggerEventType::VERTEX_CREATE,
|
||||
query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
utils::BasicException);
|
||||
ASSERT_THROW(
|
||||
store.AddTrigger("trigger", "RETURN $parameter", storage::PropertyValue::TMap{utils::NewDeleteResource()},
|
||||
query::TriggerEventType::VERTEX_CREATE, query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
&antlr_lock, query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
utils::BasicException);
|
||||
|
||||
ASSERT_NO_THROW(
|
||||
store.AddTrigger("trigger", "RETURN $parameter",
|
||||
std::map<std::string, storage::PropertyValue>{{"parameter", storage::PropertyValue{1}}},
|
||||
storage::PropertyValue::TMap{
|
||||
{{utils::pmr::string{"parameter", utils::NewDeleteResource()}, storage::PropertyValue{1}}},
|
||||
utils::NewDeleteResource()},
|
||||
query::TriggerEventType::VERTEX_CREATE, query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
&antlr_lock, query::InterpreterConfig::Query{}, std::nullopt, &auth_checker));
|
||||
|
||||
// Inserting with the same name
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN 1", {}, query::TriggerEventType::VERTEX_CREATE,
|
||||
query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN 1", storage::PropertyValue::TMap{utils::NewDeleteResource()},
|
||||
query::TriggerEventType::VERTEX_CREATE, query::TriggerPhase::BEFORE_COMMIT, &ast_cache,
|
||||
&*dba, &antlr_lock, query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
utils::BasicException);
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN 1", {}, query::TriggerEventType::VERTEX_CREATE,
|
||||
query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN 1", storage::PropertyValue::TMap{utils::NewDeleteResource()},
|
||||
query::TriggerEventType::VERTEX_CREATE, query::TriggerPhase::AFTER_COMMIT, &ast_cache,
|
||||
&*dba, &antlr_lock, query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
utils::BasicException);
|
||||
|
||||
ASSERT_EQ(store.GetTriggerInfo().size(), 1);
|
||||
@ -973,9 +981,9 @@ TEST_F(TriggerStoreTest, DropTrigger) {
|
||||
ASSERT_THROW(store.DropTrigger("Unknown"), utils::BasicException);
|
||||
|
||||
const auto *trigger_name = "trigger";
|
||||
store.AddTrigger(trigger_name, "RETURN 1", {}, query::TriggerEventType::VERTEX_CREATE,
|
||||
query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
query::InterpreterConfig::Query{}, std::nullopt, &auth_checker);
|
||||
store.AddTrigger(trigger_name, "RETURN 1", storage::PropertyValue::TMap{utils::NewDeleteResource()},
|
||||
query::TriggerEventType::VERTEX_CREATE, query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
&antlr_lock, query::InterpreterConfig::Query{}, std::nullopt, &auth_checker);
|
||||
|
||||
ASSERT_THROW(store.DropTrigger("Unknown"), utils::BasicException);
|
||||
ASSERT_NO_THROW(store.DropTrigger(trigger_name));
|
||||
@ -986,9 +994,9 @@ TEST_F(TriggerStoreTest, TriggerInfo) {
|
||||
query::TriggerStore store{testing_directory};
|
||||
|
||||
std::vector<query::TriggerStore::TriggerInfo> expected_info;
|
||||
store.AddTrigger("trigger", "RETURN 1", {}, query::TriggerEventType::VERTEX_CREATE,
|
||||
query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
query::InterpreterConfig::Query{}, std::nullopt, &auth_checker);
|
||||
store.AddTrigger("trigger", "RETURN 1", storage::PropertyValue::TMap{utils::NewDeleteResource()},
|
||||
query::TriggerEventType::VERTEX_CREATE, query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
&antlr_lock, query::InterpreterConfig::Query{}, std::nullopt, &auth_checker);
|
||||
expected_info.push_back(
|
||||
{"trigger", "RETURN 1", query::TriggerEventType::VERTEX_CREATE, query::TriggerPhase::BEFORE_COMMIT});
|
||||
|
||||
@ -1006,9 +1014,9 @@ TEST_F(TriggerStoreTest, TriggerInfo) {
|
||||
|
||||
check_trigger_info();
|
||||
|
||||
store.AddTrigger("edge_update_trigger", "RETURN 1", {}, query::TriggerEventType::EDGE_UPDATE,
|
||||
query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock, query::InterpreterConfig::Query{},
|
||||
std::nullopt, &auth_checker);
|
||||
store.AddTrigger("edge_update_trigger", "RETURN 1", storage::PropertyValue::TMap{utils::NewDeleteResource()},
|
||||
query::TriggerEventType::EDGE_UPDATE, query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba,
|
||||
&antlr_lock, query::InterpreterConfig::Query{}, std::nullopt, &auth_checker);
|
||||
expected_info.push_back(
|
||||
{"edge_update_trigger", "RETURN 1", query::TriggerEventType::EDGE_UPDATE, query::TriggerPhase::AFTER_COMMIT});
|
||||
|
||||
@ -1119,7 +1127,8 @@ TEST_F(TriggerStoreTest, AnyTriggerAllKeywords) {
|
||||
SCOPED_TRACE(query::TriggerEventTypeToString(event_type));
|
||||
for (const auto keyword : keywords) {
|
||||
SCOPED_TRACE(keyword);
|
||||
EXPECT_NO_THROW(store.AddTrigger(trigger_name, fmt::format("RETURN {}", keyword), {}, event_type,
|
||||
EXPECT_NO_THROW(store.AddTrigger(trigger_name, fmt::format("RETURN {}", keyword),
|
||||
storage::PropertyValue::TMap{utils::NewDeleteResource()}, event_type,
|
||||
query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
query::InterpreterConfig::Query{}, std::nullopt, &auth_checker));
|
||||
store.DropTrigger(trigger_name);
|
||||
@ -1143,12 +1152,13 @@ TEST_F(TriggerStoreTest, AuthCheckerUsage) {
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(mock_checker, IsUserAuthorized(owner, ElementsAre(Privilege::CREATE))).Times(1).WillOnce(Return(true));
|
||||
|
||||
ASSERT_NO_THROW(store->AddTrigger("successfull_trigger_1", "CREATE (n:VERTEX) RETURN n", {},
|
||||
query::TriggerEventType::EDGE_UPDATE, query::TriggerPhase::AFTER_COMMIT, &ast_cache,
|
||||
&*dba, &antlr_lock, query::InterpreterConfig::Query{}, std::nullopt,
|
||||
&mock_checker));
|
||||
ASSERT_NO_THROW(store->AddTrigger(
|
||||
"successfull_trigger_1", "CREATE (n:VERTEX) RETURN n", storage::PropertyValue::TMap{utils::NewDeleteResource()},
|
||||
query::TriggerEventType::EDGE_UPDATE, query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
query::InterpreterConfig::Query{}, std::nullopt, &mock_checker));
|
||||
|
||||
ASSERT_NO_THROW(store->AddTrigger("successfull_trigger_2", "CREATE (n:VERTEX) RETURN n", {},
|
||||
ASSERT_NO_THROW(store->AddTrigger("successfull_trigger_2", "CREATE (n:VERTEX) RETURN n",
|
||||
storage::PropertyValue::TMap{utils::NewDeleteResource()},
|
||||
query::TriggerEventType::EDGE_UPDATE, query::TriggerPhase::AFTER_COMMIT, &ast_cache,
|
||||
&*dba, &antlr_lock, query::InterpreterConfig::Query{}, owner, &mock_checker));
|
||||
|
||||
@ -1156,7 +1166,8 @@ TEST_F(TriggerStoreTest, AuthCheckerUsage) {
|
||||
.Times(1)
|
||||
.WillOnce(Return(false));
|
||||
|
||||
ASSERT_THROW(store->AddTrigger("unprivileged_trigger", "MATCH (n:VERTEX) RETURN n", {},
|
||||
ASSERT_THROW(store->AddTrigger("unprivileged_trigger", "MATCH (n:VERTEX) RETURN n",
|
||||
storage::PropertyValue::TMap{utils::NewDeleteResource()},
|
||||
query::TriggerEventType::EDGE_UPDATE, query::TriggerPhase::AFTER_COMMIT, &ast_cache,
|
||||
&*dba, &antlr_lock, query::InterpreterConfig::Query{}, std::nullopt, &mock_checker);
|
||||
, utils::BasicException);
|
||||
|
Loading…
Reference in New Issue
Block a user