diff --git a/src/glue/communication.cpp b/src/glue/communication.cpp index 90cf87c56..a91c4b16a 100644 --- a/src/glue/communication.cpp +++ b/src/glue/communication.cpp @@ -127,6 +127,8 @@ storage::Result ToBoltValue(const query::TypedValue &value, const storage return Value(value.ValueLocalDateTime()); case query::TypedValue::Type::Duration: return Value(value.ValueDuration()); + case query::TypedValue::Type::Graph: + throw communication::bolt::ValueException("Unsupported conversion from TypedValue to Value for Graph"); } } diff --git a/src/query/common.cpp b/src/query/common.cpp index 0bf56baa0..793ae8044 100644 --- a/src/query/common.cpp +++ b/src/query/common.cpp @@ -61,6 +61,7 @@ bool TypedValueCompare(const TypedValue &a, const TypedValue &b) { case TypedValue::Type::Vertex: case TypedValue::Type::Edge: case TypedValue::Type::Path: + case TypedValue::Type::Graph: throw QueryRuntimeException("Comparison is not defined for values of type {}.", a.type()); case TypedValue::Type::Null: LOG_FATAL("Invalid type"); diff --git a/src/query/graph.hpp b/src/query/graph.hpp new file mode 100644 index 000000000..8944f97d5 --- /dev/null +++ b/src/query/graph.hpp @@ -0,0 +1,63 @@ +// Copyright 2022 Memgraph Ltd. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source +// License, and you may not use this file except in compliance with the Business Source License. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +#pragma once + +#include +#include + +#include "query/db_accessor.hpp" +#include "utils/logging.hpp" +#include "utils/memory.hpp" +#include "utils/pmr/vector.hpp" + +namespace memgraph::query { + +/** + * A data structure that holds a graph. A graph consists of at least one + * vertex, and zero or more edges. + */ +class Graph { + public: + /** Allocator type so that STL containers are aware that we need one */ + using allocator_type = utils::Allocator; + + /** + * Create the graph with no elements + * Allocations are done using the given MemoryResource. + */ + explicit Graph(utils::MemoryResource *memory = utils::NewDeleteResource()) : vertices_(memory), edges_(memory) {} + + /** + * Create the graph starting with the given vertex. + * Allocations are done using the given MemoryResource. + */ + explicit Graph(const VertexAccessor &vertex, utils::MemoryResource *memory = utils::NewDeleteResource()) + : vertices_(memory), edges_(memory) {} + + /** Returns the number of expansions (edges) in this path. */ + auto size() const { return edges_.size(); } + + auto &vertices() { return vertices_; } + auto &edges() { return edges_; } + const auto &vertices() const { return vertices_; } + const auto &edges() const { return edges_; } + + utils::MemoryResource *GetMemoryResource() const { return vertices_.get_allocator().GetMemoryResource(); } + + private: + // Contains all the vertices in the Graph. + utils::pmr::vector vertices_; + // Contains all the edges in the Graph + utils::pmr::vector edges_; +}; + +} // namespace memgraph::query diff --git a/src/query/interpret/awesome_memgraph_functions.cpp b/src/query/interpret/awesome_memgraph_functions.cpp index 7fae2c190..41c46308c 100644 --- a/src/query/interpret/awesome_memgraph_functions.cpp +++ b/src/query/interpret/awesome_memgraph_functions.cpp @@ -587,6 +587,8 @@ TypedValue ValueType(const TypedValue *args, int64_t nargs, const FunctionContex return TypedValue("LOCAL_DATE_TIME", ctx.memory); case TypedValue::Type::Duration: return TypedValue("DURATION", ctx.memory); + case TypedValue::Type::Graph: + throw QueryRuntimeException("Trying to get graph"); } } diff --git a/src/query/interpret/eval.hpp b/src/query/interpret/eval.hpp index 398d25b5e..c397357ec 100644 --- a/src/query/interpret/eval.hpp +++ b/src/query/interpret/eval.hpp @@ -365,6 +365,9 @@ class ExpressionEvaluator : public ExpressionVisitor { } throw QueryRuntimeException("Invalid property name {} for LocalDateTime", prop_name); } + case TypedValue::Type::Graph: { + throw QueryRuntimeException("Invalid operation for Graph"); + } default: throw QueryRuntimeException("Only nodes, edges, maps and temporal types have properties to be looked-up."); } diff --git a/src/query/plan/operator.cpp b/src/query/plan/operator.cpp index 6e1296743..cd9de8318 100644 --- a/src/query/plan/operator.cpp +++ b/src/query/plan/operator.cpp @@ -31,6 +31,7 @@ #include "query/exceptions.hpp" #include "query/frontend/ast/ast.hpp" #include "query/frontend/semantic/symbol_table.hpp" +#include "query/graph.hpp" #include "query/interpret/eval.hpp" #include "query/path.hpp" #include "query/plan/scoped_profile.hpp" @@ -2612,7 +2613,7 @@ TypedValue DefaultAggregationOpValue(const Aggregate::Element &element, utils::M case Aggregation::Op::COLLECT_LIST: return TypedValue(TypedValue::TVector(memory)); case Aggregation::Op::PROJECT: // add here graph as aggregation value - return TypedValue(TypedValue::TMap(memory)); + return TypedValue(query::Graph(memory)); } } } // namespace @@ -2781,8 +2782,8 @@ class AggregateCursor : public Cursor { // we iterate over counts, values and aggregation info at the same time // todo fico remove: now when we have aggregation value, we can get how many values we aggregated till now - // which is stored in counts_ varaible. agg_value->values_.begin() always returns list pointer so we can emplace - // back new element + // which is stored in counts_ varaible. agg_value->values_.begin() always returns pointer to our aggregation method + // so we can emplace back new element auto count_it = agg_value->counts_.begin(); auto value_it = agg_value->values_.begin(); auto agg_elem_it = self_.aggregations_.begin(); @@ -2876,7 +2877,7 @@ class AggregateCursor : public Cursor { break; case Aggregation::Op::PROJECT: { EnsureOkForProject(input_value); - value_it->ValueMap().emplace("path", input_value); + value_it->ValueGraph().add("path", input_value); break; } case Aggregation::Op::COLLECT_MAP: diff --git a/src/query/procedure/mg_procedure_impl.cpp b/src/query/procedure/mg_procedure_impl.cpp index 0e707baf7..664d74c44 100644 --- a/src/query/procedure/mg_procedure_impl.cpp +++ b/src/query/procedure/mg_procedure_impl.cpp @@ -290,6 +290,8 @@ mgp_value_type FromTypedValueType(memgraph::query::TypedValue::Type type) { return MGP_VALUE_TYPE_LOCAL_DATE_TIME; case memgraph::query::TypedValue::Type::Duration: return MGP_VALUE_TYPE_DURATION; + case memgraph::query::TypedValue::Type::Graph: + throw std::logic_error{"No graph type"}; } } } // namespace @@ -2568,6 +2570,7 @@ std::ostream &PrintValue(const TypedValue &value, std::ostream *stream) { case TypedValue::Type::Vertex: case TypedValue::Type::Edge: case TypedValue::Type::Path: + case TypedValue::Type::Graph: LOG_FATAL("value must not be a graph element"); } } diff --git a/src/query/typed_value.cpp b/src/query/typed_value.cpp index 1b917d297..87695895f 100644 --- a/src/query/typed_value.cpp +++ b/src/query/typed_value.cpp @@ -214,6 +214,8 @@ TypedValue::TypedValue(const TypedValue &other, utils::MemoryResource *memory) : case Type::Duration: new (&duration_v) utils::Duration(other.duration_v); return; + case Type::Graph: + throw TypedValueException("Unsupported copy from TypedValue to TypedValue"); } LOG_FATAL("Unsupported TypedValue::Type"); } @@ -263,6 +265,8 @@ TypedValue::TypedValue(TypedValue &&other, utils::MemoryResource *memory) : memo case Type::Duration: new (&duration_v) utils::Duration(other.duration_v); break; + case Type::Graph: + throw TypedValueException("Unsupported copy from TypedValue to TypedValue"); } other.DestroyValue(); } @@ -297,6 +301,8 @@ TypedValue::operator storage::PropertyValue() const { storage::TemporalData{storage::TemporalType::LocalDateTime, local_date_time_v.MicrosecondsSinceEpoch()}); case Type::Duration: return storage::PropertyValue(storage::TemporalData{storage::TemporalType::Duration, duration_v.microseconds}); + case Type::Graph: + throw TypedValueException("Unsupported copy from TypedValue to TypedValue"); default: break; } @@ -331,6 +337,7 @@ DEFINE_VALUE_AND_TYPE_GETTERS(utils::Date, Date, date_v) DEFINE_VALUE_AND_TYPE_GETTERS(utils::LocalTime, LocalTime, local_time_v) DEFINE_VALUE_AND_TYPE_GETTERS(utils::LocalDateTime, LocalDateTime, local_date_time_v) DEFINE_VALUE_AND_TYPE_GETTERS(utils::Duration, Duration, duration_v) +DEFINE_VALUE_AND_TYPE_GETTERS(Graph, Graph, graph_v) #undef DEFINE_VALUE_AND_TYPE_GETTERS @@ -387,6 +394,8 @@ std::ostream &operator<<(std::ostream &os, const TypedValue::Type &type) { return os << "local_date_time"; case TypedValue::Type::Duration: return os << "duration"; + case TypedValue::Type::Graph: + return os << "graph"; } LOG_FATAL("Unsupported TypedValue::Type"); } @@ -522,6 +531,8 @@ TypedValue &TypedValue::operator=(const TypedValue &other) { case TypedValue::Type::Path: new (&path_v) Path(other.path_v, memory_); return *this; + case TypedValue::Type::Graph: + throw TypedValueException("Exception"); case Type::Date: new (&date_v) utils::Date(other.date_v); return *this; @@ -593,6 +604,8 @@ TypedValue &TypedValue::operator=(TypedValue &&other) noexcept(false) { case Type::Duration: new (&duration_v) utils::Duration(other.duration_v); break; + case TypedValue::Graph: + throw TypedValueException("A"); } other.DestroyValue(); } @@ -792,6 +805,8 @@ TypedValue operator==(const TypedValue &a, const TypedValue &b) { return TypedValue(a.ValueLocalDateTime() == b.ValueLocalDateTime(), a.GetMemoryResource()); case TypedValue::Type::Duration: return TypedValue(a.ValueDuration() == b.ValueDuration(), a.GetMemoryResource()); + case TypedValue::Type::Graph: + throw TypedValueException("Graph"); default: LOG_FATAL("Unhandled comparison for types"); } @@ -1100,6 +1115,8 @@ size_t TypedValue::Hash::operator()(const TypedValue &value) const { case TypedValue::Type::Duration: return utils::DurationHash{}(value.ValueDuration()); break; + case TypedValue::Type::Duration: + throw TypedValueException("a";) } LOG_FATAL("Unhandled TypedValue.type() in hash function"); } diff --git a/src/query/typed_value.hpp b/src/query/typed_value.hpp index e9d8a049e..472a8a1bd 100644 --- a/src/query/typed_value.hpp +++ b/src/query/typed_value.hpp @@ -21,6 +21,7 @@ #include #include "query/db_accessor.hpp" +#include "query/graph.hpp" #include "query/path.hpp" #include "utils/exceptions.hpp" #include "utils/memory.hpp" @@ -82,7 +83,8 @@ class TypedValue { Date, LocalTime, LocalDateTime, - Duration + Duration, + Graph }; // TypedValue at this exact moment of compilation is an incomplete type, and @@ -528,6 +530,7 @@ class TypedValue { utils::LocalTime local_time_v; utils::LocalDateTime local_date_time_v; utils::Duration duration_v; + Graph graph_v; }; /**