Compare commits

...

2 Commits

Author SHA1 Message Date
Antonio Andelic
16245d7ec8 Fix tests 2022-02-11 12:42:40 +01:00
Antonio Andelic
49ad114366 PMR property value 2022-02-11 11:32:11 +01:00
22 changed files with 400 additions and 135 deletions

View File

@ -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;

View File

@ -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> &params) 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_) {

View File

@ -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> &params,
ParsedQuery ParseQuery(const std::string &query_string, const storage::PropertyValue::TMap &params,
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 &param_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);

View File

@ -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> &params,
ParsedQuery ParseQuery(const std::string &query_string, const storage::PropertyValue::TMap &params,
utils::SkipList<QueryCacheEntry> *cache, utils::SpinLock *antlr_lock,
const InterpreterConfig::Query &query_config);

View File

@ -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 << " ";

View File

@ -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> &params,
const storage::PropertyValue::TMap &params,
const std::string *username) {
if (!in_explicit_transaction_) {
query_executions_.clear();

View File

@ -220,7 +220,7 @@ class Interpreter final {
*
* @throw query::QueryException
*/
PrepareResult Prepare(const std::string &query, const std::map<std::string, storage::PropertyValue> &params,
PrepareResult Prepare(const std::string &query, const storage::PropertyValue::TMap &params,
const std::string *username);
/**

View File

@ -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;
}

View File

@ -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 &parameters) {
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> &parameters) {
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) {

View File

@ -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 &parameters);
nlohmann::json SerializePropertyValueMap(const std::map<std::string, storage::PropertyValue> &parameters);
@ -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

View File

@ -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 {

View File

@ -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.");

View File

@ -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);

View File

@ -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:

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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> &params = {}) {
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);
}

View File

@ -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);
}
{

View File

@ -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);

View File

@ -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);

View File

@ -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);