Integrated new accessors with TypedValue and temporary disabled
procedures, streams, triggers. Additionally, small changes to ExpressionEvaluator and commented out parts of the operators that used old accessors
This commit is contained in:
parent
ced3b7db06
commit
b5f8060c1f
@ -17,6 +17,7 @@
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <regex>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "expr/ast.hpp"
|
||||
@ -27,8 +28,11 @@
|
||||
|
||||
namespace memgraph::expr {
|
||||
|
||||
struct StorageTag {};
|
||||
struct QueryEngineTag {};
|
||||
|
||||
template <typename TypedValue, typename EvaluationContext, typename DbAccessor, typename StorageView, typename LabelId,
|
||||
typename PropertyValue, typename ConvFunction, typename Error>
|
||||
typename PropertyValue, typename ConvFunction, typename Error, typename Tag = StorageTag>
|
||||
class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
|
||||
public:
|
||||
ExpressionEvaluator(Frame<TypedValue> *frame, const SymbolTable &symbol_table, const EvaluationContext &ctx,
|
||||
@ -377,6 +381,46 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VertexAccessor, typename TTag = Tag,
|
||||
typename TReturnType = std::enable_if_t<std::is_same_v<TTag, StorageTag>, bool>>
|
||||
TReturnType HasLabelImpl(const VertexAccessor &vertex, StorageTag tag, const LabelIx &label) {
|
||||
auto has_label = vertex.HasLabel(view_, GetLabel(label));
|
||||
if (has_label.HasError() && has_label.GetError() == Error::NONEXISTENT_OBJECT) {
|
||||
// This is a very nasty and temporary hack in order to make MERGE
|
||||
// work. The old storage had the following logic when returning an
|
||||
// `OLD` view: `return old ? old : new`. That means that if the
|
||||
// `OLD` view didn't exist, it returned the NEW view. With this hack
|
||||
// we simulate that behavior.
|
||||
// TODO (mferencevic, teon.banek): Remove once MERGE is
|
||||
// reimplemented.
|
||||
has_label = vertex.HasLabel(StorageView::NEW, GetLabel(label));
|
||||
}
|
||||
if (has_label.HasError()) {
|
||||
switch (has_label.GetError()) {
|
||||
case Error::DELETED_OBJECT:
|
||||
throw ExpressionRuntimeException("Trying to access labels on a deleted node.");
|
||||
case Error::NONEXISTENT_OBJECT:
|
||||
throw ExpressionRuntimeException("Trying to access labels from a node that doesn't exist.");
|
||||
case Error::SERIALIZATION_ERROR:
|
||||
case Error::VERTEX_HAS_EDGES:
|
||||
case Error::PROPERTIES_DISABLED:
|
||||
throw ExpressionRuntimeException("Unexpected error when accessing labels.");
|
||||
}
|
||||
}
|
||||
if (!*has_label) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename VertexAccessor, typename TTag = Tag,
|
||||
typename TReturnType = std::enable_if_t<std::is_same_v<TTag, QueryEngineTag>, bool>>
|
||||
TReturnType HasLabelImpl(const VertexAccessor &vertex, QueryEngineTag tag, const LabelIx &label_ix) {
|
||||
auto label = requests::Label{.id = LabelId::FromUint(label_ix.ix)};
|
||||
auto has_label = vertex.HasLabel(label);
|
||||
return !has_label;
|
||||
}
|
||||
|
||||
TypedValue Visit(LabelsTest &labels_test) override {
|
||||
auto expression_result = labels_test.expression_->Accept(*this);
|
||||
switch (expression_result.type()) {
|
||||
@ -385,30 +429,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
|
||||
case TypedValue::Type::Vertex: {
|
||||
const auto &vertex = expression_result.ValueVertex();
|
||||
for (const auto &label : labels_test.labels_) {
|
||||
auto has_label = vertex.HasLabel(view_, GetLabel(label));
|
||||
if (has_label.HasError() && has_label.GetError() == Error::NONEXISTENT_OBJECT) {
|
||||
// This is a very nasty and temporary hack in order to make MERGE
|
||||
// work. The old storage had the following logic when returning an
|
||||
// `OLD` view: `return old ? old : new`. That means that if the
|
||||
// `OLD` view didn't exist, it returned the NEW view. With this hack
|
||||
// we simulate that behavior.
|
||||
// TODO (mferencevic, teon.banek): Remove once MERGE is
|
||||
// reimplemented.
|
||||
has_label = vertex.HasLabel(StorageView::NEW, GetLabel(label));
|
||||
}
|
||||
if (has_label.HasError()) {
|
||||
switch (has_label.GetError()) {
|
||||
case Error::DELETED_OBJECT:
|
||||
throw ExpressionRuntimeException("Trying to access labels on a deleted node.");
|
||||
case Error::NONEXISTENT_OBJECT:
|
||||
throw ExpressionRuntimeException("Trying to access labels from a node that doesn't exist.");
|
||||
case Error::SERIALIZATION_ERROR:
|
||||
case Error::VERTEX_HAS_EDGES:
|
||||
case Error::PROPERTIES_DISABLED:
|
||||
throw ExpressionRuntimeException("Unexpected error when accessing labels.");
|
||||
}
|
||||
}
|
||||
if (!*has_label) {
|
||||
if (HasLabelImpl(vertex, Tag{}, label)) {
|
||||
return TypedValue(false, ctx_->memory);
|
||||
}
|
||||
}
|
||||
@ -695,58 +716,20 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
|
||||
}
|
||||
|
||||
private:
|
||||
template <class TRecordAccessor>
|
||||
TypedValue GetProperty(const TRecordAccessor &record_accessor, PropertyIx prop) {
|
||||
auto maybe_prop = record_accessor.GetProperty(view_, ctx_->properties[prop.ix]);
|
||||
if (maybe_prop.HasError() && maybe_prop.GetError() == Error::NONEXISTENT_OBJECT) {
|
||||
// This is a very nasty and temporary hack in order to make MERGE work.
|
||||
// The old storage had the following logic when returning an `OLD` view:
|
||||
// `return old ? old : new`. That means that if the `OLD` view didn't
|
||||
// exist, it returned the NEW view. With this hack we simulate that
|
||||
// behavior.
|
||||
// TODO (mferencevic, teon.banek): Remove once MERGE is reimplemented.
|
||||
maybe_prop = record_accessor.GetProperty(StorageView::NEW, ctx_->properties[prop.ix]);
|
||||
}
|
||||
if (maybe_prop.HasError()) {
|
||||
switch (maybe_prop.GetError()) {
|
||||
case Error::DELETED_OBJECT:
|
||||
throw ExpressionRuntimeException("Trying to get a property from a deleted object.");
|
||||
case Error::NONEXISTENT_OBJECT:
|
||||
throw ExpressionRuntimeException("Trying to get a property from an object that doesn't exist.");
|
||||
case Error::SERIALIZATION_ERROR:
|
||||
case Error::VERTEX_HAS_EDGES:
|
||||
case Error::PROPERTIES_DISABLED:
|
||||
throw ExpressionRuntimeException("Unexpected error when getting a property.");
|
||||
}
|
||||
}
|
||||
return conv_(*maybe_prop);
|
||||
template <class TRecordAccessor, class TTag = Tag,
|
||||
class TReturnType = std::enable_if_t<std::is_same_v<TTag, QueryEngineTag>, TypedValue>>
|
||||
TReturnType GetProperty(const TRecordAccessor &record_accessor, PropertyIx prop) {
|
||||
auto maybe_prop = record_accessor.GetProperty(prop.name);
|
||||
// Handler non existent property
|
||||
return conv_(maybe_prop);
|
||||
}
|
||||
|
||||
template <class TRecordAccessor>
|
||||
TypedValue GetProperty(const TRecordAccessor &record_accessor, const std::string_view name) {
|
||||
auto maybe_prop = record_accessor.GetProperty(view_, dba_->NameToProperty(name));
|
||||
if (maybe_prop.HasError() && maybe_prop.GetError() == Error::NONEXISTENT_OBJECT) {
|
||||
// This is a very nasty and temporary hack in order to make MERGE work.
|
||||
// The old storage had the following logic when returning an `OLD` view:
|
||||
// `return old ? old : new`. That means that if the `OLD` view didn't
|
||||
// exist, it returned the NEW view. With this hack we simulate that
|
||||
// behavior.
|
||||
// TODO (mferencevic, teon.banek): Remove once MERGE is reimplemented.
|
||||
maybe_prop = record_accessor.GetProperty(view_, dba_->NameToProperty(name));
|
||||
}
|
||||
if (maybe_prop.HasError()) {
|
||||
switch (maybe_prop.GetError()) {
|
||||
case Error::DELETED_OBJECT:
|
||||
throw ExpressionRuntimeException("Trying to get a property from a deleted object.");
|
||||
case Error::NONEXISTENT_OBJECT:
|
||||
throw ExpressionRuntimeException("Trying to get a property from an object that doesn't exist.");
|
||||
case Error::SERIALIZATION_ERROR:
|
||||
case Error::VERTEX_HAS_EDGES:
|
||||
case Error::PROPERTIES_DISABLED:
|
||||
throw ExpressionRuntimeException("Unexpected error when getting a property.");
|
||||
}
|
||||
}
|
||||
return conv_(*maybe_prop);
|
||||
template <class TRecordAccessor, class TTag = Tag,
|
||||
class TReturnType = std::enable_if_t<std::is_same_v<TTag, QueryEngineTag>, TypedValue>>
|
||||
TReturnType GetProperty(const TRecordAccessor &record_accessor, const std::string_view name) {
|
||||
auto maybe_prop = record_accessor.GetProperty(std::string(name));
|
||||
// Handler non existent property
|
||||
return conv_(maybe_prop);
|
||||
}
|
||||
|
||||
LabelId GetLabel(LabelIx label) { return ctx_->labels[label.ix]; }
|
||||
|
@ -23,16 +23,16 @@ set(mg_query_v2_sources
|
||||
plan/rewrite/index_lookup.cpp
|
||||
plan/rule_based_planner.cpp
|
||||
plan/variable_start_planner.cpp
|
||||
procedure/mg_procedure_impl.cpp
|
||||
procedure/mg_procedure_helpers.cpp
|
||||
procedure/module.cpp
|
||||
procedure/py_module.cpp
|
||||
# procedure/mg_procedure_impl.cpp
|
||||
# procedure/mg_procedure_helpers.cpp
|
||||
# procedure/module.cpp
|
||||
# procedure/py_module.cpp
|
||||
serialization/property_value.cpp
|
||||
stream/streams.cpp
|
||||
stream/sources.cpp
|
||||
stream/common.cpp
|
||||
trigger.cpp
|
||||
trigger_context.cpp
|
||||
# stream/streams.cpp
|
||||
# stream/sources.cpp
|
||||
# stream/common.cpp
|
||||
# trigger.cpp
|
||||
# trigger_context.cpp
|
||||
bindings/typed_value.cpp
|
||||
accessors.cpp)
|
||||
|
||||
|
@ -26,7 +26,7 @@ std::map<std::string, Value> EdgeAccessor::Properties() const {
|
||||
// return res;
|
||||
}
|
||||
|
||||
Value EdgeAccessor::GetProperty(const std::string &prop_name) {
|
||||
Value EdgeAccessor::GetProperty(const std::string &prop_name) const {
|
||||
MG_ASSERT(properties.contains(prop_name));
|
||||
return properties[prop_name];
|
||||
}
|
||||
@ -54,7 +54,7 @@ std::map<std::string, Value> VertexAccessor::Properties() const {
|
||||
return properties;
|
||||
}
|
||||
|
||||
Value VertexAccessor::GetProperty(const std::string &prop_name) {
|
||||
Value VertexAccessor::GetProperty(const std::string &prop_name) const {
|
||||
MG_ASSERT(properties.contains(prop_name));
|
||||
return Value(properties[prop_name]);
|
||||
// return ValueToTypedValue(properties[prop_name]);
|
||||
|
@ -38,7 +38,10 @@ class EdgeAccessor final {
|
||||
|
||||
std::map<std::string, Value> Properties() const;
|
||||
|
||||
Value GetProperty(const std::string &prop_name);
|
||||
Value GetProperty(const std::string &prop_name) const;
|
||||
|
||||
// Dummy function
|
||||
inline size_t CypherId() const { return 10; }
|
||||
|
||||
// bool HasSrcAccessor const { return src == nullptr; }
|
||||
// bool HasDstAccessor const { return dst == nullptr; }
|
||||
@ -54,7 +57,7 @@ class EdgeAccessor final {
|
||||
|
||||
private:
|
||||
Edge edge;
|
||||
std::map<std::string, Value> properties;
|
||||
mutable std::map<std::string, Value> properties;
|
||||
};
|
||||
|
||||
class VertexAccessor final {
|
||||
@ -67,7 +70,10 @@ class VertexAccessor final {
|
||||
|
||||
std::map<std::string, Value> Properties() const;
|
||||
|
||||
Value GetProperty(const std::string &prop_name);
|
||||
Value GetProperty(const std::string &prop_name) const;
|
||||
|
||||
// Dummy function
|
||||
inline size_t CypherId() const { return 10; }
|
||||
|
||||
// auto InEdges(storage::View view, const std::vector<storage::EdgeTypeId> &edge_types) const
|
||||
// -> storage::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.InEdges(view)))> {
|
||||
@ -116,7 +122,7 @@ class VertexAccessor final {
|
||||
|
||||
private:
|
||||
Vertex vertex;
|
||||
std::map<std::string, Value> properties;
|
||||
mutable std::map<std::string, Value> properties;
|
||||
};
|
||||
|
||||
// inline VertexAccessor EdgeAccessor::To() const { return VertexAccessor(impl_.ToVertex()); }
|
||||
|
@ -16,19 +16,31 @@
|
||||
#include "expr/interpret/eval.hpp"
|
||||
#include "query/v2/bindings/typed_value.hpp"
|
||||
#include "query/v2/context.hpp"
|
||||
#include "query/v2/conversions.hpp"
|
||||
#include "query/v2/db_accessor.hpp"
|
||||
#include "query/v2/requests.hpp"
|
||||
#include "storage/v3/conversions.hpp"
|
||||
#include "storage/v3/id_types.hpp"
|
||||
#include "storage/v3/property_store.hpp"
|
||||
#include "storage/v3/property_value.hpp"
|
||||
#include "storage/v3/view.hpp"
|
||||
#include "storage/v3/conversions.hpp"
|
||||
|
||||
namespace memgraph::query::v2 {
|
||||
|
||||
inline const auto lam = [](const auto &val) { return memgraph::storage::v3::PropertyToTypedValue<TypedValue>(val); };
|
||||
inline const auto lam = [](const auto &val) { return ValueToTypedValue(val); };
|
||||
namespace detail {
|
||||
class Callable {
|
||||
public:
|
||||
auto operator()(const memgraph::storage::v3::PropertyValue &val) const {
|
||||
return memgraph::storage::v3::PropertyToTypedValue<TypedValue>(val);
|
||||
};
|
||||
auto operator()(const requests::Value &val) const { return ValueToTypedValue(val); };
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
using ExpressionEvaluator =
|
||||
memgraph::expr::ExpressionEvaluator<TypedValue, EvaluationContext, DbAccessor, storage::v3::View,
|
||||
storage::v3::LabelId, storage::v3::PropertyStore, decltype(lam),
|
||||
memgraph::storage::v3::Error>;
|
||||
storage::v3::LabelId, requests::Value, detail::Callable,
|
||||
memgraph::storage::v3::Error, memgraph::expr::QueryEngineTag>;
|
||||
|
||||
} // namespace memgraph::query::v2
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "query/v2/metadata.hpp"
|
||||
#include "query/v2/parameters.hpp"
|
||||
#include "query/v2/plan/profile.hpp"
|
||||
#include "query/v2/trigger.hpp"
|
||||
//#include "query/v2/trigger.hpp"
|
||||
#include "utils/async_timer.hpp"
|
||||
|
||||
namespace memgraph::query::v2 {
|
||||
@ -70,7 +70,7 @@ struct ExecutionContext {
|
||||
plan::ProfilingStats stats;
|
||||
plan::ProfilingStats *stats_root{nullptr};
|
||||
ExecutionStats execution_stats;
|
||||
TriggerContextCollector *trigger_context_collector{nullptr};
|
||||
// TriggerContextCollector *trigger_context_collector{nullptr};
|
||||
utils::AsyncTimer timer;
|
||||
};
|
||||
|
||||
|
@ -35,9 +35,9 @@ inline TypedValue ValueToTypedValue(const Value &value) {
|
||||
case Value::MAP:
|
||||
// return TypedValue(value.map_v);
|
||||
case Value::VERTEX:
|
||||
// return TypedValue(accessors::VertexAccessor(value.vertex_v, {}));
|
||||
return TypedValue(accessors::VertexAccessor(value.vertex_v, {}));
|
||||
case Value::EDGE:
|
||||
// return TypedValue(accessors::EdgeAccessor(value.edge_v, {}));
|
||||
return TypedValue(accessors::EdgeAccessor(value.edge_v, {}));
|
||||
case Value::PATH:
|
||||
break;
|
||||
}
|
||||
|
@ -21,11 +21,12 @@
|
||||
#include <type_traits>
|
||||
|
||||
#include "query/v2/bindings/typed_value.hpp"
|
||||
#include "query/v2/conversions.hpp"
|
||||
#include "query/v2/db_accessor.hpp"
|
||||
#include "query/v2/exceptions.hpp"
|
||||
#include "query/v2/procedure/cypher_types.hpp"
|
||||
#include "query/v2/procedure/mg_procedure_impl.hpp"
|
||||
#include "query/v2/procedure/module.hpp"
|
||||
//#include "query/v2/procedure/mg_procedure_impl.hpp"
|
||||
//#include "query/v2/procedure/module.hpp"
|
||||
#include "storage/v3/conversions.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/temporal.hpp"
|
||||
@ -392,22 +393,21 @@ TypedValue Properties(const TypedValue *args, int64_t nargs, const FunctionConte
|
||||
auto *dba = ctx.db_accessor;
|
||||
auto get_properties = [&](const auto &record_accessor) {
|
||||
TypedValue::TMap properties(ctx.memory);
|
||||
auto maybe_props = record_accessor.Properties(ctx.view);
|
||||
if (maybe_props.HasError()) {
|
||||
switch (maybe_props.GetError()) {
|
||||
case storage::v3::Error::DELETED_OBJECT:
|
||||
throw QueryRuntimeException("Trying to get properties from a deleted object.");
|
||||
case storage::v3::Error::NONEXISTENT_OBJECT:
|
||||
throw query::v2::QueryRuntimeException("Trying to get properties from an object that doesn't exist.");
|
||||
case storage::v3::Error::SERIALIZATION_ERROR:
|
||||
case storage::v3::Error::VERTEX_HAS_EDGES:
|
||||
case storage::v3::Error::PROPERTIES_DISABLED:
|
||||
throw QueryRuntimeException("Unexpected error when getting properties.");
|
||||
}
|
||||
}
|
||||
for (const auto &property : *maybe_props) {
|
||||
properties.emplace(dba->PropertyToName(property.first),
|
||||
storage::v3::PropertyToTypedValue<TypedValue>(property.second));
|
||||
auto props = record_accessor.Properties();
|
||||
// add error handling
|
||||
// if (maybe_props.HasError()) {
|
||||
// switch (maybe_props.GetError()) {
|
||||
// case storage::v3::Error::DELETED_OBJECT:
|
||||
// throw QueryRuntimeException("Trying to get properties from a deleted object.");
|
||||
// case storage::v3::Error::NONEXISTENT_OBJECT:
|
||||
// throw query::v2::QueryRuntimeException("Trying to get properties from an object that doesn't exist.");
|
||||
// case storage::v3::Error::SERIALIZATION_ERROR:
|
||||
// case storage::v3::Error::VERTEX_HAS_EDGES:
|
||||
// case storage::v3::Error::PROPERTIES_DISABLED:
|
||||
// throw QueryRuntimeException("Unexpected error when getting properties.");
|
||||
// }
|
||||
for (const auto &property : props) {
|
||||
properties.emplace(property.first, ValueToTypedValue(property.second));
|
||||
}
|
||||
return TypedValue(std::move(properties));
|
||||
};
|
||||
@ -435,7 +435,8 @@ TypedValue Size(const TypedValue *args, int64_t nargs, const FunctionContext &ct
|
||||
// to do it.
|
||||
return TypedValue(static_cast<int64_t>(value.ValueMap().size()), ctx.memory);
|
||||
} else {
|
||||
return TypedValue(static_cast<int64_t>(value.ValuePath().edges().size()), ctx.memory);
|
||||
// TODO(kostasrim) Fix the dummy return
|
||||
return TypedValue(int64_t(0), ctx.memory);
|
||||
}
|
||||
}
|
||||
|
||||
@ -469,25 +470,26 @@ TypedValue Degree(const TypedValue *args, int64_t nargs, const FunctionContext &
|
||||
FType<Or<Null, Vertex>>("degree", args, nargs);
|
||||
if (args[0].IsNull()) return TypedValue(ctx.memory);
|
||||
const auto &vertex = args[0].ValueVertex();
|
||||
size_t out_degree = UnwrapDegreeResult(vertex.OutDegree(ctx.view));
|
||||
size_t in_degree = UnwrapDegreeResult(vertex.InDegree(ctx.view));
|
||||
return TypedValue(static_cast<int64_t>(out_degree + in_degree), ctx.memory);
|
||||
// size_t out_degree = UnwrapDegreeResult(vertex.OutDegree(ctx.view));
|
||||
// size_t in_degree = UnwrapDegreeResult(vertex.InDegree(ctx.view));
|
||||
// TODO(kostasrim) Fix dummy values
|
||||
return TypedValue(int64_t(0), ctx.memory);
|
||||
}
|
||||
|
||||
TypedValue InDegree(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
|
||||
FType<Or<Null, Vertex>>("inDegree", args, nargs);
|
||||
if (args[0].IsNull()) return TypedValue(ctx.memory);
|
||||
const auto &vertex = args[0].ValueVertex();
|
||||
size_t in_degree = UnwrapDegreeResult(vertex.InDegree(ctx.view));
|
||||
return TypedValue(static_cast<int64_t>(in_degree), ctx.memory);
|
||||
// size_t in_degree = UnwrapDegreeResult(vertex.InDegree(ctx.view));
|
||||
return TypedValue(int64_t(0), ctx.memory);
|
||||
}
|
||||
|
||||
TypedValue OutDegree(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
|
||||
FType<Or<Null, Vertex>>("outDegree", args, nargs);
|
||||
if (args[0].IsNull()) return TypedValue(ctx.memory);
|
||||
const auto &vertex = args[0].ValueVertex();
|
||||
size_t out_degree = UnwrapDegreeResult(vertex.OutDegree(ctx.view));
|
||||
return TypedValue(static_cast<int64_t>(out_degree), ctx.memory);
|
||||
// size_t out_degree = UnwrapDegreeResult(vertex.OutDegree(ctx.view));
|
||||
return TypedValue(int64_t(0), ctx.memory);
|
||||
}
|
||||
|
||||
TypedValue ToBoolean(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
|
||||
@ -553,7 +555,7 @@ TypedValue Type(const TypedValue *args, int64_t nargs, const FunctionContext &ct
|
||||
FType<Or<Null, Edge>>("type", args, nargs);
|
||||
auto *dba = ctx.db_accessor;
|
||||
if (args[0].IsNull()) return TypedValue(ctx.memory);
|
||||
return TypedValue(dba->EdgeTypeToName(args[0].ValueEdge().EdgeType()), ctx.memory);
|
||||
return TypedValue(args[0].ValueEdge().EdgeType(), ctx.memory);
|
||||
}
|
||||
|
||||
TypedValue ValueType(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
|
||||
@ -598,21 +600,21 @@ TypedValue Keys(const TypedValue *args, int64_t nargs, const FunctionContext &ct
|
||||
auto *dba = ctx.db_accessor;
|
||||
auto get_keys = [&](const auto &record_accessor) {
|
||||
TypedValue::TVector keys(ctx.memory);
|
||||
auto maybe_props = record_accessor.Properties(ctx.view);
|
||||
if (maybe_props.HasError()) {
|
||||
switch (maybe_props.GetError()) {
|
||||
case storage::v3::Error::DELETED_OBJECT:
|
||||
throw QueryRuntimeException("Trying to get keys from a deleted object.");
|
||||
case storage::v3::Error::NONEXISTENT_OBJECT:
|
||||
throw query::v2::QueryRuntimeException("Trying to get keys from an object that doesn't exist.");
|
||||
case storage::v3::Error::SERIALIZATION_ERROR:
|
||||
case storage::v3::Error::VERTEX_HAS_EDGES:
|
||||
case storage::v3::Error::PROPERTIES_DISABLED:
|
||||
throw QueryRuntimeException("Unexpected error when getting keys.");
|
||||
}
|
||||
}
|
||||
for (const auto &property : *maybe_props) {
|
||||
keys.emplace_back(dba->PropertyToName(property.first));
|
||||
auto maybe_props = record_accessor.Properties();
|
||||
// if (maybe_props.HasError()) {
|
||||
// switch (maybe_props.GetError()) {
|
||||
// case storage::v3::Error::DELETED_OBJECT:
|
||||
// throw QueryRuntimeException("Trying to get keys from a deleted object.");
|
||||
// case storage::v3::Error::NONEXISTENT_OBJECT:
|
||||
// throw query::v2::QueryRuntimeException("Trying to get keys from an object that doesn't exist.");
|
||||
// case storage::v3::Error::SERIALIZATION_ERROR:
|
||||
// case storage::v3::Error::VERTEX_HAS_EDGES:
|
||||
// case storage::v3::Error::PROPERTIES_DISABLED:
|
||||
// throw QueryRuntimeException("Unexpected error when getting keys.");
|
||||
// }
|
||||
// }
|
||||
for (const auto &property : maybe_props) {
|
||||
keys.emplace_back(property.first);
|
||||
}
|
||||
return TypedValue(std::move(keys));
|
||||
};
|
||||
@ -630,44 +632,47 @@ TypedValue Labels(const TypedValue *args, int64_t nargs, const FunctionContext &
|
||||
FType<Or<Null, Vertex>>("labels", args, nargs);
|
||||
auto *dba = ctx.db_accessor;
|
||||
if (args[0].IsNull()) return TypedValue(ctx.memory);
|
||||
TypedValue::TVector labels(ctx.memory);
|
||||
auto maybe_labels = args[0].ValueVertex().Labels(ctx.view);
|
||||
if (maybe_labels.HasError()) {
|
||||
switch (maybe_labels.GetError()) {
|
||||
case storage::v3::Error::DELETED_OBJECT:
|
||||
throw QueryRuntimeException("Trying to get labels from a deleted node.");
|
||||
case storage::v3::Error::NONEXISTENT_OBJECT:
|
||||
throw query::v2::QueryRuntimeException("Trying to get labels from a node that doesn't exist.");
|
||||
case storage::v3::Error::SERIALIZATION_ERROR:
|
||||
case storage::v3::Error::VERTEX_HAS_EDGES:
|
||||
case storage::v3::Error::PROPERTIES_DISABLED:
|
||||
throw QueryRuntimeException("Unexpected error when getting labels.");
|
||||
}
|
||||
}
|
||||
for (const auto &label : *maybe_labels) {
|
||||
labels.emplace_back(dba->LabelToName(label));
|
||||
}
|
||||
return TypedValue(std::move(labels));
|
||||
// TypedValue::TVector labels(ctx.memory);
|
||||
return TypedValue();
|
||||
// auto maybe_labels = args[0].ValueVertex().Labels();
|
||||
// if (maybe_labels.HasError()) {
|
||||
// switch (maybe_labels.GetError()) {
|
||||
// case storage::v3::Error::DELETED_OBJECT:
|
||||
// throw QueryRuntimeException("Trying to get labels from a deleted node.");
|
||||
// case storage::v3::Error::NONEXISTENT_OBJECT:
|
||||
// throw query::v2::QueryRuntimeException("Trying to get labels from a node that doesn't exist.");
|
||||
// case storage::v3::Error::SERIALIZATION_ERROR:
|
||||
// case storage::v3::Error::VERTEX_HAS_EDGES:
|
||||
// case storage::v3::Error::PROPERTIES_DISABLED:
|
||||
// throw QueryRuntimeException("Unexpected error when getting labels.");
|
||||
// }
|
||||
// }
|
||||
// for (const auto &label : maybe_labels) {
|
||||
// labels.emplace_back(label);
|
||||
// }
|
||||
// return TypedValue(std::move(labels));
|
||||
}
|
||||
|
||||
TypedValue Nodes(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
|
||||
FType<Or<Null, Path>>("nodes", args, nargs);
|
||||
if (args[0].IsNull()) return TypedValue(ctx.memory);
|
||||
const auto &vertices = args[0].ValuePath().vertices();
|
||||
TypedValue::TVector values(ctx.memory);
|
||||
values.reserve(vertices.size());
|
||||
for (const auto &v : vertices) values.emplace_back(v);
|
||||
return TypedValue(std::move(values));
|
||||
// const auto &vertices = args[0].ValuePath().vertices();
|
||||
return TypedValue();
|
||||
// TypedValue::TVector values(ctx.memory);
|
||||
// values.reserve(vertices.size());
|
||||
// for (const auto &v : vertices) values.emplace_back(v);
|
||||
// return TypedValue(std::move(values));
|
||||
}
|
||||
|
||||
TypedValue Relationships(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
|
||||
FType<Or<Null, Path>>("relationships", args, nargs);
|
||||
if (args[0].IsNull()) return TypedValue(ctx.memory);
|
||||
const auto &edges = args[0].ValuePath().edges();
|
||||
TypedValue::TVector values(ctx.memory);
|
||||
values.reserve(edges.size());
|
||||
for (const auto &e : edges) values.emplace_back(e);
|
||||
return TypedValue(std::move(values));
|
||||
// const auto &edges = args[0].ValuePath().edges();
|
||||
return TypedValue();
|
||||
// TypedValue::TVector values(ctx.memory);
|
||||
// values.reserve(edges.size());
|
||||
// for (const auto &e : edges) values.emplace_back(e);
|
||||
// return TypedValue(std::move(values));
|
||||
}
|
||||
|
||||
TypedValue Range(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
|
||||
@ -877,9 +882,9 @@ TypedValue Id(const TypedValue *args, int64_t nargs, const FunctionContext &ctx)
|
||||
if (arg.IsNull()) {
|
||||
return TypedValue(ctx.memory);
|
||||
} else if (arg.IsVertex()) {
|
||||
return TypedValue(arg.ValueVertex().CypherId(), ctx.memory);
|
||||
return TypedValue(int64_t(arg.ValueVertex().CypherId()), ctx.memory);
|
||||
} else {
|
||||
return TypedValue(arg.ValueEdge().CypherId(), ctx.memory);
|
||||
return TypedValue(int64_t(arg.ValueEdge().CypherId()), ctx.memory);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1180,48 +1185,49 @@ TypedValue Duration(const TypedValue *args, int64_t nargs, const FunctionContext
|
||||
return TypedValue(utils::Duration(duration_parameters), ctx.memory);
|
||||
}
|
||||
|
||||
std::function<TypedValue(const TypedValue *, const int64_t, const FunctionContext &)> UserFunction(
|
||||
const mgp_func &func, const std::string &fully_qualified_name) {
|
||||
return [func, fully_qualified_name](const TypedValue *args, int64_t nargs, const FunctionContext &ctx) -> TypedValue {
|
||||
/// Find function is called to aquire the lock on Module pointer while user-defined function is executed
|
||||
const auto &maybe_found =
|
||||
procedure::FindFunction(procedure::gModuleRegistry, fully_qualified_name, utils::NewDeleteResource());
|
||||
if (!maybe_found) {
|
||||
throw QueryRuntimeException(
|
||||
"Function '{}' has been unloaded. Please check query modules to confirm that function is loaded in Memgraph.",
|
||||
fully_qualified_name);
|
||||
}
|
||||
|
||||
const auto &func_cb = func.cb;
|
||||
mgp_memory memory{ctx.memory};
|
||||
mgp_func_context functx{ctx.db_accessor, ctx.view};
|
||||
auto graph = mgp_graph::NonWritableGraph(*ctx.db_accessor, ctx.view);
|
||||
|
||||
std::vector<TypedValue> args_list;
|
||||
args_list.reserve(nargs);
|
||||
for (std::size_t i = 0; i < nargs; ++i) {
|
||||
args_list.emplace_back(args[i]);
|
||||
}
|
||||
|
||||
auto function_argument_list = mgp_list(ctx.memory);
|
||||
procedure::ConstructArguments(args_list, func, fully_qualified_name, function_argument_list, graph);
|
||||
|
||||
mgp_func_result maybe_res;
|
||||
func_cb(&function_argument_list, &functx, &maybe_res, &memory);
|
||||
if (maybe_res.error_msg) {
|
||||
throw QueryRuntimeException(*maybe_res.error_msg);
|
||||
}
|
||||
|
||||
if (!maybe_res.value) {
|
||||
throw QueryRuntimeException(
|
||||
"Function '{}' didn't set the result nor the error message. Please either set the result by using "
|
||||
"mgp_func_result_set_value or the error by using mgp_func_result_set_error_msg.",
|
||||
fully_qualified_name);
|
||||
}
|
||||
|
||||
return {*(maybe_res.value), ctx.memory};
|
||||
};
|
||||
}
|
||||
// std::function<TypedValue(const TypedValue *, const int64_t, const FunctionContext &)> UserFunction(
|
||||
// const mgp_func &func, const std::string &fully_qualified_name) {
|
||||
// return [func, fully_qualified_name](const TypedValue *args, int64_t nargs, const FunctionContext &ctx) ->
|
||||
// TypedValue {
|
||||
// /// Find function is called to aquire the lock on Module pointer while user-defined function is executed
|
||||
// const auto &maybe_found =
|
||||
// procedure::FindFunction(procedure::gModuleRegistry, fully_qualified_name, utils::NewDeleteResource());
|
||||
// if (!maybe_found) {
|
||||
// throw QueryRuntimeException(
|
||||
// "Function '{}' has been unloaded. Please check query modules to confirm that function is loaded in
|
||||
// Memgraph.", fully_qualified_name);
|
||||
// }
|
||||
//
|
||||
// const auto &func_cb = func.cb;
|
||||
// mgp_memory memory{ctx.memory};
|
||||
// mgp_func_context functx{ctx.db_accessor, ctx.view};
|
||||
// auto graph = mgp_graph::NonWritableGraph(*ctx.db_accessor, ctx.view);
|
||||
//
|
||||
// std::vector<TypedValue> args_list;
|
||||
// args_list.reserve(nargs);
|
||||
// for (std::size_t i = 0; i < nargs; ++i) {
|
||||
// args_list.emplace_back(args[i]);
|
||||
// }
|
||||
//
|
||||
// auto function_argument_list = mgp_list(ctx.memory);
|
||||
// procedure::ConstructArguments(args_list, func, fully_qualified_name, function_argument_list, graph);
|
||||
//
|
||||
// mgp_func_result maybe_res;
|
||||
// func_cb(&function_argument_list, &functx, &maybe_res, &memory);
|
||||
// if (maybe_res.error_msg) {
|
||||
// throw QueryRuntimeException(*maybe_res.error_msg);
|
||||
// }
|
||||
//
|
||||
// if (!maybe_res.value) {
|
||||
// throw QueryRuntimeException(
|
||||
// "Function '{}' didn't set the result nor the error message. Please either set the result by using "
|
||||
// "mgp_func_result_set_value or the error by using mgp_func_result_set_error_msg.",
|
||||
// fully_qualified_name);
|
||||
// }
|
||||
//
|
||||
// return {*(maybe_res.value), ctx.memory};
|
||||
// };
|
||||
// }
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -1309,14 +1315,14 @@ std::function<TypedValue(const TypedValue *, int64_t, const FunctionContext &ctx
|
||||
if (function_name == "LOCALDATETIME") return LocalDateTime;
|
||||
if (function_name == "DURATION") return Duration;
|
||||
|
||||
const auto &maybe_found =
|
||||
procedure::FindFunction(procedure::gModuleRegistry, function_name, utils::NewDeleteResource());
|
||||
|
||||
if (maybe_found) {
|
||||
const auto *func = (*maybe_found).second;
|
||||
return UserFunction(*func, function_name);
|
||||
}
|
||||
|
||||
// const auto &maybe_found =
|
||||
// procedure::FindFunction(procedure::gModuleRegistry, function_name, utils::NewDeleteResource());
|
||||
//
|
||||
// if (maybe_found) {
|
||||
// const auto *func = (*maybe_found).second;
|
||||
// return UserFunction(*func, function_name);
|
||||
// }
|
||||
//
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -27,8 +27,8 @@
|
||||
#include "query/v2/plan/operator.hpp"
|
||||
#include "query/v2/plan/read_write_type_checker.hpp"
|
||||
#include "query/v2/stream.hpp"
|
||||
#include "query/v2/stream/streams.hpp"
|
||||
#include "query/v2/trigger.hpp"
|
||||
//#include "query/v2/stream/streams.hpp"
|
||||
//#include "query/v2/trigger.hpp"
|
||||
#include "storage/v3/isolation_level.hpp"
|
||||
#include "utils/event_counter.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
@ -179,12 +179,12 @@ struct InterpreterContext {
|
||||
utils::SkipList<QueryCacheEntry> ast_cache;
|
||||
utils::SkipList<PlanCacheEntry> plan_cache;
|
||||
|
||||
TriggerStore trigger_store;
|
||||
utils::ThreadPool after_commit_trigger_pool{1};
|
||||
// TriggerStore trigger_store;
|
||||
// utils::ThreadPool after_commit_trigger_pool{1};
|
||||
|
||||
const InterpreterConfig config;
|
||||
|
||||
query::v2::stream::Streams streams;
|
||||
// query::v2::stream::Streams streams;
|
||||
};
|
||||
|
||||
/// Function that is used to tell all active interpreters that they should stop
|
||||
@ -317,7 +317,7 @@ class Interpreter final {
|
||||
// move this unique_ptr into a shrared_ptr.
|
||||
std::unique_ptr<storage::v3::Storage::Accessor> db_accessor_;
|
||||
std::optional<DbAccessor> execution_db_accessor_;
|
||||
std::optional<TriggerContextCollector> trigger_context_collector_;
|
||||
// std::optional<TriggerContextCollector> trigger_context_collector_;
|
||||
bool in_explicit_transaction_{false};
|
||||
bool expect_rollback_{false};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,15 +25,20 @@
|
||||
#include "query/v2/common.hpp"
|
||||
#include "query/v2/frontend/ast/ast.hpp"
|
||||
#include "expr/semantic/symbol.hpp"
|
||||
#include "query/v2//bindings/typed_value.hpp"
|
||||
#include "query/v2//bindings/frame.hpp"
|
||||
#include "query/v2//bindings/symbol_table.hpp"
|
||||
#include "query/v2/bindings/typed_value.hpp"
|
||||
#include "query/v2/bindings/frame.hpp"
|
||||
#include "query/v2/bindings/symbol_table.hpp"
|
||||
#include "storage/v3/id_types.hpp"
|
||||
#include "utils/bound.hpp"
|
||||
#include "utils/fnv.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
#include "utils/visitor.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
#include "query/v2/accessors.hpp"
|
||||
|
||||
using VertexAccessor = memgraph::query::v2::accessors::VertexAccessor;
|
||||
using EdgeAccessor = memgraph::query::v2::accessors::EdgeAccessor;
|
||||
using Path = memgraph::query::v2::accessors::Path;
|
||||
cpp<#
|
||||
|
||||
(lcp:namespace memgraph)
|
||||
|
@ -216,13 +216,15 @@ namespace detail {
|
||||
bool SetVertexLabel::IsValid() const { return object.IsVisible(storage::v3::View::OLD); }
|
||||
|
||||
std::map<std::string, TypedValue> SetVertexLabel::ToMap(DbAccessor *dba) const {
|
||||
return {{"vertex", TypedValue{object}}, {"label", TypedValue{dba->LabelToName(label_id)}}};
|
||||
// return {{"vertex", TypedValue{object}}, {"label", TypedValue{dba->LabelToName(label_id)}}};
|
||||
return {};
|
||||
}
|
||||
|
||||
bool RemovedVertexLabel::IsValid() const { return object.IsVisible(storage::v3::View::OLD); }
|
||||
|
||||
std::map<std::string, TypedValue> RemovedVertexLabel::ToMap(DbAccessor *dba) const {
|
||||
return {{"vertex", TypedValue{object}}, {"label", TypedValue{dba->LabelToName(label_id)}}};
|
||||
// return {{"vertex", TypedValue{object}}, {"label", TypedValue{dba->LabelToName(label_id)}}};
|
||||
return {};
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
|
@ -47,7 +47,8 @@ struct CreatedObject {
|
||||
|
||||
bool IsValid() const { return object.IsVisible(storage::v3::View::OLD); }
|
||||
std::map<std::string, TypedValue> ToMap([[maybe_unused]] DbAccessor *dba) const {
|
||||
return {{ObjectString<TAccessor>(), TypedValue{object}}};
|
||||
// return {{ObjectString<TAccessor>(), TypedValue{object}}};
|
||||
return {};
|
||||
}
|
||||
|
||||
TAccessor object;
|
||||
@ -59,7 +60,8 @@ struct DeletedObject {
|
||||
|
||||
bool IsValid() const { return object.IsVisible(storage::v3::View::OLD); }
|
||||
std::map<std::string, TypedValue> ToMap([[maybe_unused]] DbAccessor *dba) const {
|
||||
return {{ObjectString<TAccessor>(), TypedValue{object}}};
|
||||
// return {{ObjectString<TAccessor>(), TypedValue{object}}};
|
||||
return {};
|
||||
}
|
||||
|
||||
TAccessor object;
|
||||
@ -72,10 +74,11 @@ struct SetObjectProperty {
|
||||
: object{object}, key{key}, old_value{std::move(old_value)}, new_value{std::move(new_value)} {}
|
||||
|
||||
std::map<std::string, TypedValue> ToMap(DbAccessor *dba) const {
|
||||
return {{ObjectString<TAccessor>(), TypedValue{object}},
|
||||
{"key", TypedValue{dba->PropertyToName(key)}},
|
||||
{"old", old_value},
|
||||
{"new", new_value}};
|
||||
return {};
|
||||
// return {{ObjectString<TAccessor>(), TypedValue{object}},
|
||||
// {"key", TypedValue{dba->PropertyToName(key)}},
|
||||
// {"old", old_value},
|
||||
// {"new", new_value}};
|
||||
}
|
||||
|
||||
bool IsValid() const { return object.IsVisible(storage::v3::View::OLD); }
|
||||
@ -92,9 +95,10 @@ struct RemovedObjectProperty {
|
||||
: object{object}, key{key}, old_value{std::move(old_value)} {}
|
||||
|
||||
std::map<std::string, TypedValue> ToMap(DbAccessor *dba) const {
|
||||
return {{ObjectString<TAccessor>(), TypedValue{object}},
|
||||
{"key", TypedValue{dba->PropertyToName(key)}},
|
||||
{"old", old_value}};
|
||||
return {};
|
||||
// return {{ObjectString<TAccessor>(), TypedValue{object}},
|
||||
// {"key", TypedValue{dba->PropertyToName(key)}},
|
||||
// {"old", old_value}};
|
||||
}
|
||||
|
||||
bool IsValid() const { return object.IsVisible(storage::v3::View::OLD); }
|
||||
|
Loading…
Reference in New Issue
Block a user