Remove UID tracking from AstStorage

Summary:
All AST nodes had a member `uid_` that was used as a key in
`SymbolTable`. It is renamed to `symbol_pos_` and it appears only in
`Identifier`, `NamedExpression` and `Aggregation`, since only those types were
used in `SymbolTable`. SymbolGenerator is now responsible for creating symbols
in `SymbolTable` and assigning positions to AST nodes.

Cloning and serialization code is now simpler since there is no need to track
UIDs.

Reviewers: teon.banek

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1836
This commit is contained in:
Marin Tomic 2019-02-05 13:16:07 +01:00
parent 145c81376f
commit c03ca5f8f0
23 changed files with 592 additions and 969 deletions

View File

@ -45,26 +45,14 @@ cpp<#
:capnp-load (lcp:capnp-load-vector "::storage::capnp::EdgeType"
"storage::EdgeType"))
(filter-lambda "query::plan::ExpansionLambda"
:slk-save (lambda (member)
#>cpp
std::vector<int32_t> saved_ast_uids;
slk::Save(self.${member}, builder, &saved_ast_uids);
cpp<#)
:slk-load (lambda (member)
#>cpp
std::vector<int32_t> loaded_ast_uids;
slk::Load(&self->${member}, reader, ast_storage, &loaded_ast_uids);
slk::Load(&self->${member}, reader, ast_storage);
cpp<#)
:capnp-type "DistOps.ExpansionLambda"
:capnp-save (lambda (builder member capnp-name)
#>cpp
std::vector<int> saved_ast_uids;
Save(${member}, &${builder}, &saved_ast_uids);
cpp<#)
:capnp-load (lambda (reader member capnp-name)
#>cpp
std::vector<int> loaded_ast_uids;
Load(&${member}, ${reader}, ast_storage, &loaded_ast_uids);
Load(&${member}, ${reader}, ast_storage);
cpp<#))
(symbol-table "query::SymbolTable" :capnp-type "Query.SymbolTable")
(timestamp :int64_t)

View File

@ -30,20 +30,20 @@ cpp<#
(defun slk-save-ast-pointer (member)
#>cpp
query::SaveAstPointer(self.${member}, builder, saved_uids);
query::SaveAstPointer(self.${member}, builder);
cpp<#)
(defun slk-load-ast-pointer (type)
(lambda (member)
#>cpp
self->${member} = query::LoadAstPointer<query::${type}>(storage, reader, loaded_uids);
self->${member} = query::LoadAstPointer<query::${type}>(storage, reader);
cpp<#))
(defun save-ast-pointer (builder member capnp-name)
#>cpp
if (${member}) {
auto ${capnp-name}_builder = ${builder}->init${capnp-name}();
Save(*${member}, &${capnp-name}_builder, saved_uids);
Save(*${member}, &${capnp-name}_builder);
}
cpp<#)
@ -52,7 +52,7 @@ cpp<#
#>cpp
if (${reader}.has${capnp-name}()) {
${member} = static_cast<${type}>(
Load(storage, ${reader}.get${capnp-name}(), loaded_uids));
Load(storage, ${reader}.get${capnp-name}()));
} else {
${member} = nullptr;
}
@ -63,7 +63,7 @@ cpp<#
size_t size = self.${member}.size();
slk::Save(size, builder);
for (const auto *val : self.${member}) {
query::SaveAstPointer(val, builder, saved_uids);
query::SaveAstPointer(val, builder);
}
cpp<#)
@ -76,22 +76,22 @@ cpp<#
for (size_t i = 0;
i < size;
++i) {
self->${member}[i] = query::LoadAstPointer<query::${type}>(storage, reader, loaded_uids);
self->${member}[i] = query::LoadAstPointer<query::${type}>(storage, reader);
}
cpp<#))
(defun save-ast-vector (type)
(lcp:capnp-save-vector "capnp::Tree" type
"[saved_uids](auto *builder, const auto &val) {
Save(*val, builder, saved_uids);
"[](auto *builder, const auto &val) {
Save(*val, builder);
}"))
(defun load-ast-vector (type)
(lcp:capnp-load-vector "capnp::Tree" type
(format
nil
"[storage, loaded_uids](const auto &reader) {
return static_cast<~A>(Load(storage, reader, loaded_uids));
"[storage](const auto &reader) {
return static_cast<~A>(Load(storage, reader));
}"
type)))
@ -101,7 +101,7 @@ cpp<#
slk::Save(size, builder);
for (const auto &entry : self.${member}) {
slk::Save(entry.first, builder);
query::SaveAstPointer(entry.second, builder, saved_uids);
query::SaveAstPointer(entry.second, builder);
}
cpp<#)
@ -114,7 +114,7 @@ cpp<#
++i) {
query::PropertyIx key;
slk::Load(&key, reader, storage);
auto *value = query::LoadAstPointer<query::Expression>(storage, reader, loaded_uids);
auto *value = query::LoadAstPointer<query::Expression>(storage, reader);
self->${member}.emplace(key, value);
}
cpp<#)
@ -127,7 +127,7 @@ cpp<#
auto key_builder = entries_builder[i].initKey();
Save(entry.first, &key_builder);
auto value_builder = entries_builder[i].initValue();
Save(*entry.second, &value_builder, saved_uids);
Save(*entry.second, &value_builder);
++i;
}
cpp<#)
@ -138,7 +138,7 @@ cpp<#
PropertyIx prop;
Load(&prop, entry.getKey(), storage);
${member}.emplace(prop, static_cast<Expression *>(
Load(storage, entry.getValue(), loaded_uids)));
Load(storage, entry.getValue())));
}
cpp<#)
@ -280,18 +280,9 @@ class AstStorage {
AstStorage(AstStorage &&) = default;
AstStorage &operator=(AstStorage &&) = default;
template <typename T>
T *Create() {
T *ptr = new T();
ptr->uid_ = ++max_existing_uid_;
std::unique_ptr<T> tmp(ptr);
storage_.emplace_back(std::move(tmp));
return ptr;
}
template <typename T, typename... Args>
T *Create(Args &&... args) {
T *ptr = new T(++max_existing_uid_, std::forward<Args>(args)...);
T *ptr = new T(std::forward<Args>(args)...);
std::unique_ptr<T> tmp(ptr);
storage_.emplace_back(std::move(tmp));
return ptr;
@ -315,7 +306,6 @@ class AstStorage {
// Public only for serialization access
std::vector<std::unique_ptr<Tree>> storage_;
int max_existing_uid_ = -1;
private:
int64_t FindOrAddName(const std::string &name,
@ -332,14 +322,7 @@ class AstStorage {
cpp<#
(lcp:define-class tree ()
((uid :int32_t :scope :public
:clone (lambda (source dest)
#>cpp
${dest} = ${source};
// TODO(mtomic): This is a hack. Adopting existing UIDs breaks everything
// because `AstStorage` keeps a counter for generating when `Create` is called.
storage->max_existing_uid_ = std::max(storage->max_existing_uid_, ${source});
cpp<#)))
()
(:abstractp t)
(:public
#>cpp
@ -350,28 +333,8 @@ cpp<#
#>cpp
friend class AstStorage;
cpp<#)
(:protected
#>cpp
explicit Tree(int uid) : uid_(uid) {}
cpp<#)
(:serialize (:slk :save-args '((saved-uids "std::vector<int32_t> *"))
:load-args '((storage "query::AstStorage *")
(loaded-uids "std::vector<int32_t> *")))
(:capnp
:save-args '((saved-uids "std::vector<int32_t> *"))
:load-args '((storage "AstStorage *")
(loaded-uids "std::vector<int32_t> *"))
:post-save (lambda (builder)
(declare (ignore builder))
;; This is a bit hacky because it relies on the fact that parent class
;; serialization is inlined so we can short-circuit and avoid serializing
;; the derived class.
#>cpp
if (utils::Contains(*saved_uids, self.uid_)) {
return;
}
saved_uids->push_back(self.uid_);
cpp<#)))
(:serialize (:slk :load-args '((storage "query::AstStorage *")))
(:capnp :load-args '((storage "AstStorage *"))))
(:clone :return-type (lambda (typename)
(format nil "~A*" typename))
:args '((storage "AstStorage *"))
@ -396,10 +359,6 @@ cpp<#
Expression() = default;
cpp<#)
(:protected
#>cpp
explicit Expression(int uid) : Tree(uid) {}
cpp<#)
(:private
#>cpp
friend class AstStorage;
@ -431,8 +390,7 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit Where(int uid) : Tree(uid) {}
Where(int uid, Expression *expression) : Tree(uid), expression_(expression) {}
explicit Where(Expression *expression) : expression_(expression) {}
cpp<#)
(:private
#>cpp
@ -463,9 +421,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit BinaryOperator(int uid) : Expression(uid) {}
BinaryOperator(int uid, Expression *expression1, Expression *expression2)
: Expression(uid), expression1_(expression1), expression2_(expression2) {}
BinaryOperator(Expression *expression1, Expression *expression2)
: expression1_(expression1), expression2_(expression2) {}
cpp<#)
(:private
#>cpp
@ -488,9 +445,7 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit UnaryOperator(int uid) : Expression(uid) {}
UnaryOperator(int uid, Expression *expression)
: Expression(uid), expression_(expression) {}
explicit UnaryOperator(Expression *expression) : expression_(expression) {}
cpp<#)
(:private
#>cpp
@ -567,7 +522,9 @@ cpp<#
(define-unary-operators))
(lcp:define-class aggregation (binary-operator)
((op "Op" :scope :public))
((op "Op" :scope :public)
(symbol-pos :int32_t :initval -1 :scope :public
:documentation "Symbol table position of the symbol this Aggregation is mapped to."))
(:public
(lcp:define-enum op
(count min max sum avg collect-list collect-map)
@ -597,17 +554,21 @@ cpp<#
}
return visitor.PostVisit(*this);
}
Aggregation *MapTo(const Symbol &symbol) {
symbol_pos_ = symbol.position();
return this;
}
cpp<#)
(:protected
#>cpp
// Use only for serialization.
Aggregation(int uid) : BinaryOperator(uid) {}
Aggregation(int uid, Op op) : BinaryOperator(uid), op_(op) {}
explicit Aggregation(Op op) : op_(op) {}
/// Aggregation's first expression is the value being aggregated. The second
/// expression is the key used only in COLLECT_MAP.
Aggregation(int uid, Expression *expression1, Expression *expression2, Op op)
: BinaryOperator(uid, expression1, expression2), op_(op) {
Aggregation(Expression *expression1, Expression *expression2, Op op)
: BinaryOperator(expression1, expression2), op_(op) {
// COUNT without expression denotes COUNT(*) in cypher.
DCHECK(expression1 || op == Aggregation::Op::COUNT)
<< "All aggregations, except COUNT require expression";
@ -663,14 +624,9 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit ListSlicingOperator(int uid) : Expression(uid) {}
ListSlicingOperator(int uid, Expression *list, Expression *lower_bound,
ListSlicingOperator(Expression *list, Expression *lower_bound,
Expression *upper_bound)
: Expression(uid),
list_(list),
lower_bound_(lower_bound),
upper_bound_(upper_bound) {}
: list_(list), lower_bound_(lower_bound), upper_bound_(upper_bound) {}
cpp<#)
(:private
#>cpp
@ -715,12 +671,9 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit IfOperator(int uid) : Expression(uid) {}
IfOperator(int uid, Expression *condition, Expression *then_expression,
IfOperator(Expression *condition, Expression *then_expression,
Expression *else_expression)
: Expression(uid),
condition_(condition),
: condition_(condition),
then_expression_(then_expression),
else_expression_(else_expression) {}
cpp<#)
@ -738,10 +691,6 @@ cpp<#
#>cpp
BaseLiteral() = default;
cpp<#)
(:protected
#>cpp
explicit BaseLiteral(int uid) : Expression(uid) {}
cpp<#)
(:private
#>cpp
friend class AstStorage;
@ -775,12 +724,11 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit PrimitiveLiteral(int uid) : BaseLiteral(uid) {}
template <typename T>
PrimitiveLiteral(int uid, T value) : BaseLiteral(uid), value_(value) {}
explicit PrimitiveLiteral(T value) : value_(value) {}
template <typename T>
PrimitiveLiteral(int uid, T value, int token_position)
: BaseLiteral(uid), value_(value), token_position_(token_position) {}
PrimitiveLiteral(T value, int token_position)
: value_(value), token_position_(token_position) {}
cpp<#)
(:serialize (:slk) (:capnp))
(:clone))
@ -809,9 +757,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit ListLiteral(int uid) : BaseLiteral(uid) {}
ListLiteral(int uid, const std::vector<Expression *> &elements)
: BaseLiteral(uid), elements_(elements) {}
explicit ListLiteral(const std::vector<Expression *> &elements)
: elements_(elements) {}
cpp<#)
(:private
#>cpp
@ -845,10 +792,9 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit MapLiteral(int uid) : BaseLiteral(uid) {}
MapLiteral(int uid,
const std::unordered_map<PropertyIx, Expression *> &elements)
: BaseLiteral(uid), elements_(elements) {}
explicit MapLiteral(
const std::unordered_map<PropertyIx, Expression *> &elements)
: elements_(elements) {}
cpp<#)
(:private
#>cpp
@ -859,7 +805,9 @@ cpp<#
(lcp:define-class identifier (expression)
((name "std::string" :scope :public)
(user-declared :bool :initval "true" :scope :public))
(user-declared :bool :initval "true" :scope :public)
(symbol-pos :int32_t :initval -1 :scope :public
:documentation "Symbol table position of the symbol this Identifier is mapped to."))
(:public
#>cpp
Identifier() = default;
@ -867,14 +815,17 @@ cpp<#
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<void>);
DEFVISITABLE(HierarchicalTreeVisitor);
Identifier *MapTo(const Symbol &symbol) {
symbol_pos_ = symbol.position();
return this;
}
cpp<#)
(:protected
#>cpp
Identifier(int uid) : Expression(uid) {}
Identifier(int uid, const std::string &name) : Expression(uid), name_(name) {}
Identifier(int uid, const std::string &name, bool user_declared)
: Expression(uid), name_(name), user_declared_(user_declared) {}
explicit Identifier(const std::string &name) : name_(name) {}
Identifier(const std::string &name, bool user_declared)
: name_(name), user_declared_(user_declared) {}
cpp<#)
(:private
#>cpp
@ -914,11 +865,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
PropertyLookup(int uid) : Expression(uid) {}
PropertyLookup(int uid, Expression *expression, PropertyIx property)
: Expression(uid),
expression_(expression),
property_(property) {}
PropertyLookup(Expression *expression, PropertyIx property)
: expression_(expression), property_(property) {}
cpp<#)
(:private
#>cpp
@ -967,11 +915,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
LabelsTest(int uid) : Expression(uid) {}
LabelsTest(int uid, Expression *expression,
const std::vector<LabelIx> &labels)
: Expression(uid), expression_(expression), labels_(labels) {}
LabelsTest(Expression *expression, const std::vector<LabelIx> &labels)
: expression_(expression), labels_(labels) {}
cpp<#)
(:private
#>cpp
@ -1019,12 +964,9 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit Function(int uid) : Expression(uid) {}
Function(int uid, const std::string &function_name,
Function(const std::string &function_name,
const std::vector<Expression *> &arguments)
: Expression(uid),
arguments_(arguments),
: arguments_(arguments),
function_name_(function_name),
function_(NameToFunction(function_name_)) {
DCHECK(function_) << "Unexpected missing function: " << function_name_;
@ -1090,10 +1032,9 @@ cpp<#
cpp<#)
(:protected
#>cpp
Reduce(int uid, Identifier *accumulator, Expression *initializer,
Identifier *identifier, Expression *list, Expression *expression)
: Expression(uid),
accumulator_(accumulator),
Reduce(Identifier *accumulator, Expression *initializer, Identifier *identifier,
Expression *list, Expression *expression)
: accumulator_(accumulator),
initializer_(initializer),
identifier_(identifier),
list_(list),
@ -1133,10 +1074,8 @@ cpp<#
)
(:private
#>cpp
Coalesce(int uid) : Expression(uid_) {}
Coalesce(int uid, const std::vector<Expression *> &expressions)
: Expression(uid), expressions_(expressions) {}
explicit Coalesce(const std::vector<Expression *> &expressions)
: expressions_(expressions) {}
friend class AstStorage;
cpp<#)
@ -1181,14 +1120,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
Extract(int uid) : Expression(uid) {}
Extract(int uid, Identifier *identifier, Expression *list,
Expression *expression)
: Expression(uid),
identifier_(identifier),
list_(list),
expression_(expression) {}
Extract(Identifier *identifier, Expression *list, Expression *expression)
: identifier_(identifier), list_(list), expression_(expression) {}
cpp<#)
(:private
#>cpp
@ -1232,12 +1165,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
All(int uid) : Expression(uid) {}
All(int uid, Identifier *identifier, Expression *list_expression,
Where *where)
: Expression(uid),
identifier_(identifier),
All(Identifier *identifier, Expression *list_expression, Where *where)
: identifier_(identifier),
list_expression_(list_expression),
where_(where) {}
cpp<#)
@ -1286,10 +1215,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
Single(int uid, Identifier *identifier, Expression *list_expression,
Where *where)
: Expression(uid),
identifier_(identifier),
Single(Identifier *identifier, Expression *list_expression, Where *where)
: identifier_(identifier),
list_expression_(list_expression),
where_(where) {}
cpp<#)
@ -1313,9 +1240,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit ParameterLookup(int uid) : Expression(uid) {}
ParameterLookup(int uid, int token_position)
: Expression(uid), token_position_(token_position) {}
explicit ParameterLookup(int token_position)
: token_position_(token_position) {}
cpp<#)
(:private
#>cpp
@ -1335,7 +1261,9 @@ cpp<#
:capnp-save #'save-ast-pointer
:capnp-load (load-ast-pointer "Expression *"))
(token-position :int32_t :initval -1 :scope :public
:documentation "This field contains token position of first token in named expression used to create name_. If NamedExpression object is not created from query or it is aliased leave this value at -1."))
:documentation "This field contains token position of first token in named expression used to create name_. If NamedExpression object is not created from query or it is aliased leave this value at -1.")
(symbol-pos :int32_t :initval -1 :scope :public
:documentation "Symbol table position of the symbol this NamedExpression is mapped to."))
(:public
#>cpp
using ::utils::Visitable<ExpressionVisitor<TypedValue>>::Accept;
@ -1352,19 +1280,20 @@ cpp<#
}
return visitor.PostVisit(*this);
}
NamedExpression *MapTo(const Symbol &symbol) {
symbol_pos_ = symbol.position();
return this;
}
cpp<#)
(:protected
#>cpp
explicit NamedExpression(int uid) : Tree(uid) {}
NamedExpression(int uid, const std::string &name) : Tree(uid), name_(name) {}
NamedExpression(int uid, const std::string &name, Expression *expression)
: Tree(uid), name_(name), expression_(expression) {}
NamedExpression(int uid, const std::string &name, Expression *expression,
explicit NamedExpression(const std::string &name) : name_(name) {}
NamedExpression(const std::string &name, Expression *expression)
: name_(name), expression_(expression) {}
NamedExpression(const std::string &name, Expression *expression,
int token_position)
: Tree(uid),
name_(name),
expression_(expression),
token_position_(token_position) {}
: name_(name), expression_(expression), token_position_(token_position) {}
cpp<#)
(:private
#>cpp
@ -1395,9 +1324,7 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit PatternAtom(int uid) : Tree(uid) {}
PatternAtom(int uid, Identifier *identifier)
: Tree(uid), identifier_(identifier) {}
explicit PatternAtom(Identifier *identifier) : identifier_(identifier) {}
cpp<#)
(:private
#>cpp
@ -1505,23 +1432,15 @@ cpp<#
:documentation "Evaluated to upper bound in variable length expands.")
(filter-lambda "Lambda" :scope :public
:documentation "Filter lambda for variable length expands. Can have an empty expression, but identifiers must be valid, because an optimization pass may inline other expressions into this lambda."
:slk-save (lambda (member)
#>cpp
slk::Save(self.${member}, builder, saved_uids);
cpp<#)
:slk-load (lambda (member)
#>cpp
slk::Load(&self->${member}, reader, storage, loaded_uids);
slk::Load(&self->${member}, reader, storage);
cpp<#))
(weight-lambda "Lambda" :scope :public
:documentation "Used in weighted shortest path. It must have valid expressions and identifiers. In all other expand types, it is empty."
:slk-save (lambda (member)
#>cpp
slk::Save(self.${member}, builder, saved_uids);
cpp<#)
:slk-load (lambda (member)
#>cpp
slk::Load(&self->${member}, reader, storage, loaded_uids);
slk::Load(&self->${member}, reader, storage);
cpp<#))
(total-weight "Identifier *" :initval "nullptr" :scope :public
:slk-save #'slk-save-ast-pointer
@ -1560,13 +1479,8 @@ cpp<#
:capnp-load (load-ast-pointer "Expression *")
:documentation "Evaluates the result of the lambda."))
(:documentation "Lambda for use in filtering or weight calculation during variable expand.")
(:serialize (:slk :save-args '((saved-uids "std::vector<int32_t> *"))
:load-args '((storage "query::AstStorage *")
(loaded-uids "std::vector<int32_t> *")))
(:capnp
:save-args '((saved-uids "std::vector<int32_t> *"))
:load-args '((storage "AstStorage *")
(loaded-uids "std::vector<int32_t> *"))))
(:serialize (:slk :load-args '((storage "query::AstStorage *")))
(:capnp :load-args '((storage "AstStorage *"))))
(:clone :args '((storage "AstStorage *"))))
#>cpp
bool Accept(HierarchicalTreeVisitor &visitor) override {
@ -1604,13 +1518,13 @@ cpp<#
(:protected
#>cpp
using PatternAtom::PatternAtom;
EdgeAtom(int uid, Identifier *identifier, Type type, Direction direction)
: PatternAtom(uid, identifier), type_(type), direction_(direction) {}
EdgeAtom(Identifier *identifier, Type type, Direction direction)
: PatternAtom(identifier), type_(type), direction_(direction) {}
// Creates an edge atom for a SINGLE expansion with the given .
EdgeAtom(int uid, Identifier *identifier, Type type, Direction direction,
EdgeAtom(Identifier *identifier, Type type, Direction direction,
const std::vector<EdgeTypeIx> &edge_types)
: PatternAtom(uid, identifier),
: PatternAtom(identifier),
type_(type),
direction_(direction),
edge_types_(edge_types) {}
@ -1654,10 +1568,6 @@ cpp<#
return visitor.PostVisit(*this);
}
cpp<#)
(:protected
#>cpp
explicit Pattern(int uid) : Tree(uid) {}
cpp<#)
(:private
#>cpp
friend class AstStorage;
@ -1676,10 +1586,6 @@ cpp<#
Clause() = default;
cpp<#)
(:protected
#>cpp
explicit Clause(int uid) : Tree(uid) {}
cpp<#)
(:private
#>cpp
friend class AstStorage;
@ -1712,10 +1618,6 @@ cpp<#
return visitor.PostVisit(*this);
}
cpp<#)
(:protected
#>cpp
explicit SingleQuery(int uid) : Tree(uid) {}
cpp<#)
(:private
#>cpp
friend class AstStorage;
@ -1750,12 +1652,10 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit CypherUnion(int uid) : Tree(uid) {}
CypherUnion(int uid, bool distinct) : Tree(uid), distinct_(distinct) {}
CypherUnion(int uid, bool distinct, SingleQuery *single_query,
explicit CypherUnion(bool distinct) : distinct_(distinct) {}
CypherUnion(bool distinct, SingleQuery *single_query,
std::vector<Symbol> union_symbols)
: Tree(uid),
single_query_(single_query),
: single_query_(single_query),
distinct_(distinct),
union_symbols_(union_symbols) {}
cpp<#)
@ -1777,10 +1677,6 @@ cpp<#
Query() = default;
cpp<#)
(:protected
#>cpp
explicit Query(int uid) : Tree(uid) {}
cpp<#)
(:private
#>cpp
friend class AstStorage;
@ -1812,10 +1708,6 @@ cpp<#
DEFVISITABLE(QueryVisitor<void>);
cpp<#)
(:protected
#>cpp
explicit CypherQuery(int uid) : Query(uid) {}
cpp<#)
(:private
#>cpp
friend class AstStorage;
@ -1837,10 +1729,6 @@ cpp<#
DEFVISITABLE(QueryVisitor<void>);
cpp<#)
(:protected
#>cpp
explicit ExplainQuery(int uid) : Query(uid) {}
cpp<#)
(:private
#>cpp
friend class AstStorage;
@ -1867,7 +1755,6 @@ cpp<#
cpp<#)
(:private
#>cpp
explicit ProfileQuery(int uid) : Query(uid) {}
friend class AstStorage;
cpp<#)
(:serialize (:slk) (:capnp))
@ -1914,10 +1801,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit IndexQuery(int uid) : Query(uid) {}
IndexQuery(int uid, Action action, LabelIx label,
std::vector<PropertyIx> properties)
: Query(uid), action_(action), label_(label), properties_(properties) {}
IndexQuery(Action action, LabelIx label, std::vector<PropertyIx> properties)
: action_(action), label_(label), properties_(properties) {}
cpp<#)
(:private
#>cpp
@ -1949,9 +1834,7 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit Create(int uid) : Clause(uid) {}
Create(int uid, std::vector<Pattern *> patterns)
: Clause(uid), patterns_(patterns) {}
explicit Create(std::vector<Pattern *> patterns) : patterns_(patterns) {}
cpp<#)
(:private
#>cpp
@ -1997,10 +1880,9 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit Match(int uid) : Clause(uid) {}
Match(int uid, bool optional) : Clause(uid), optional_(optional) {}
Match(int uid, bool optional, Where *where, std::vector<Pattern *> patterns)
: Clause(uid), patterns_(patterns), where_(where), optional_(optional) {}
explicit Match(bool optional) : optional_(optional) {}
Match(bool optional, Where *where, std::vector<Pattern *> patterns)
: patterns_(patterns), where_(where), optional_(optional) {}
cpp<#)
(:private
#>cpp
@ -2022,13 +1904,8 @@ cpp<#
:capnp-type "Tree" :capnp-init nil
:capnp-save #'save-ast-pointer
:capnp-load (load-ast-pointer "Expression *")))
(:serialize (:slk :save-args '((saved-uids "std::vector<int32_t> *"))
:load-args '((storage "query::AstStorage *")
(loaded-uids "std::vector<int32_t> *")))
(:capnp
:save-args '((saved-uids "std::vector<int32_t> *"))
:load-args '((storage "AstStorage *")
(loaded-uids "std::vector<int32_t> *"))))
(:serialize (:slk :load-args '((storage "query::AstStorage *")))
(:capnp :load-args '((storage "AstStorage *"))))
(:clone :args '((storage "AstStorage *"))))
(lcp:define-struct return-body ()
@ -2044,14 +1921,6 @@ cpp<#
:capnp-load (load-ast-vector "NamedExpression *")
:documentation "Expressions which are used to produce results.")
(order-by "std::vector<SortItem>"
:slk-save (lambda (member)
#>cpp
size_t size = self.${member}.size();
slk::Save(size, builder);
for (const auto &v : self.${member}) {
slk::Save(v, builder, saved_uids);
}
cpp<#)
:slk-load (lambda (member)
#>cpp
size_t size = 0;
@ -2060,21 +1929,15 @@ cpp<#
for (size_t i = 0;
i < size;
++i) {
slk::Load(&self->${member}[i], reader, storage, loaded_uids);
slk::Load(&self->${member}[i], reader, storage);
}
cpp<#)
:capnp-save (lcp:capnp-save-vector
"capnp::SortItem"
"SortItem"
"[saved_uids](auto *builder, const auto &val) {
Save(val, builder, saved_uids);
}")
:capnp-load (lcp:capnp-load-vector
"capnp::SortItem"
"SortItem"
"[storage, loaded_uids](const auto &reader) {
"[storage](const auto &reader) {
SortItem val;
Load(&val, reader, storage, loaded_uids);
Load(&val, reader, storage);
return val;
}")
:documentation "Expressions used for ordering the results.")
@ -2093,24 +1956,15 @@ cpp<#
:capnp-load (load-ast-pointer "Expression *")
:documentation "Optional expression on how many results to produce."))
(:documentation "Contents common to @c Return and @c With clauses.")
(:serialize (:slk :save-args '((saved-uids "std::vector<int32_t> *"))
:load-args '((storage "query::AstStorage *")
(loaded-uids "std::vector<int32_t> *")))
(:capnp
:save-args '((saved-uids "std::vector<int32_t> *"))
:load-args '((storage "AstStorage *")
(loaded-uids "std::vector<int32_t> *"))))
(:serialize (:slk :load-args '((storage "query::AstStorage *")))
(:capnp :load-args '((storage "AstStorage *"))))
(:clone :args '((storage "AstStorage *"))))
(lcp:define-class return (clause)
((body "ReturnBody" :scope :public
:slk-save (lambda (member)
#>cpp
slk::Save(self.${member}, builder, saved_uids);
cpp<#)
:slk-load (lambda (member)
#>cpp
slk::Load(&self->${member}, reader, storage, loaded_uids);
slk::Load(&self->${member}, reader, storage);
cpp<#)))
(:public
#>cpp
@ -2141,8 +1995,7 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit Return(int uid) : Clause(uid) {}
Return(int uid, ReturnBody &body) : Clause(uid), body_(body) {}
explicit Return(ReturnBody &body) : body_(body) {}
cpp<#)
(:private
#>cpp
@ -2153,13 +2006,9 @@ cpp<#
(lcp:define-class with (clause)
((body "ReturnBody" :scope :public
:slk-save (lambda (member)
#>cpp
slk::Save(self.${member}, builder, saved_uids);
cpp<#)
:slk-load (lambda (member)
#>cpp
slk::Load(&self->${member}, reader, storage, loaded_uids);
slk::Load(&self->${member}, reader, storage);
cpp<#))
(where "Where *" :initval "nullptr" :scope :public
:slk-save #'slk-save-ast-pointer
@ -2197,9 +2046,7 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit With(int uid) : Clause(uid) {}
With(int uid, ReturnBody &body, Where *where)
: Clause(uid), body_(body), where_(where) {}
With(ReturnBody &body, Where *where) : body_(body), where_(where) {}
cpp<#)
(:private
#>cpp
@ -2232,9 +2079,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit Delete(int uid) : Clause(uid) {}
Delete(int uid, bool detach, std::vector<Expression *> expressions)
: Clause(uid), expressions_(expressions), detach_(detach) {}
Delete(bool detach, std::vector<Expression *> expressions)
: expressions_(expressions), detach_(detach) {}
cpp<#)
(:private
#>cpp
@ -2269,11 +2115,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit SetProperty(int uid) : Clause(uid) {}
SetProperty(int uid, PropertyLookup *property_lookup, Expression *expression)
: Clause(uid),
property_lookup_(property_lookup),
expression_(expression) {}
SetProperty(PropertyLookup *property_lookup, Expression *expression)
: property_lookup_(property_lookup), expression_(expression) {}
cpp<#)
(:private
#>cpp
@ -2309,13 +2152,9 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit SetProperties(int uid) : Clause(uid) {}
SetProperties(int uid, Identifier *identifier, Expression *expression,
SetProperties(Identifier *identifier, Expression *expression,
bool update = false)
: Clause(uid),
identifier_(identifier),
expression_(expression),
update_(update) {}
: identifier_(identifier), expression_(expression), update_(update) {}
cpp<#)
(:private
#>cpp
@ -2362,10 +2201,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit SetLabels(int uid) : Clause(uid) {}
SetLabels(int uid, Identifier *identifier,
const std::vector<LabelIx> &labels)
: Clause(uid), identifier_(identifier), labels_(labels) {}
SetLabels(Identifier *identifier, const std::vector<LabelIx> &labels)
: identifier_(identifier), labels_(labels) {}
cpp<#)
(:private
#>cpp
@ -2394,9 +2231,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit RemoveProperty(int uid) : Clause(uid) {}
RemoveProperty(int uid, PropertyLookup *property_lookup)
: Clause(uid), property_lookup_(property_lookup) {}
explicit RemoveProperty(PropertyLookup *property_lookup)
: property_lookup_(property_lookup) {}
cpp<#)
(:private
#>cpp
@ -2443,10 +2279,8 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit RemoveLabels(int uid) : Clause(uid) {}
RemoveLabels(int uid, Identifier *identifier,
const std::vector<LabelIx> &labels)
: Clause(uid), identifier_(identifier), labels_(labels) {}
RemoveLabels(Identifier *identifier, const std::vector<LabelIx> &labels)
: identifier_(identifier), labels_(labels) {}
cpp<#)
(:private
#>cpp
@ -2505,13 +2339,9 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit Merge(int uid) : Clause(uid) {}
Merge(int uid, Pattern *pattern, std::vector<Clause *> on_match,
Merge(Pattern *pattern, std::vector<Clause *> on_match,
std::vector<Clause *> on_create)
: Clause(uid),
pattern_(pattern),
on_match_(on_match),
on_create_(on_create) {}
: pattern_(pattern), on_match_(on_match), on_create_(on_create) {}
cpp<#)
(:private
#>cpp
@ -2540,12 +2370,9 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit Unwind(int uid) : Clause(uid) {}
Unwind(int uid, NamedExpression *named_expression)
: Clause(uid), named_expression_(named_expression) {
DCHECK(named_expression)
<< "Unwind cannot take nullptr for named_expression";
explicit Unwind(NamedExpression *named_expression)
: named_expression_(named_expression) {
DCHECK(named_expression) << "Unwind cannot take nullptr for named_expression";
}
cpp<#)
(:private
@ -2584,13 +2411,10 @@ cpp<#
cpp<#)
(:protected
#>cpp
explicit AuthQuery(int uid) : Query(uid) {}
explicit AuthQuery(int uid, Action action, std::string user, std::string role,
std::string user_or_role, Expression *password,
std::vector<Privilege> privileges)
: Query(uid),
action_(action),
AuthQuery(Action action, std::string user, std::string role,
std::string user_or_role, Expression *password,
std::vector<Privilege> privileges)
: action_(action),
user_(user),
role_(role),
user_or_role_(user_or_role),
@ -2667,13 +2491,11 @@ cpp<#
cpp<#)
(:protected
#>cpp
StreamQuery(int uid) : Query(uid) {}
StreamQuery(int uid, Action action, std::string stream_name,
Expression *stream_uri, Expression *stream_topic,
Expression *transform_uri, Expression *batch_interval_in_ms,
Expression *batch_size, Expression *limit_batches)
: Query(uid),
action_(action),
StreamQuery(Action action, std::string stream_name, Expression *stream_uri,
Expression *stream_topic, Expression *transform_uri,
Expression *batch_interval_in_ms, Expression *batch_size,
Expression *limit_batches)
: action_(action),
stream_name_(std::move(stream_name)),
stream_uri_(stream_uri),
stream_topic_(stream_topic),

View File

@ -15,26 +15,22 @@ cpp<#
#>cpp
/// Primary function for saving Ast nodes via SLK.
void SaveAstPointer(const Tree *ast, slk::Builder *builder,
std::vector<int32_t> *saved_uids);
void SaveAstPointer(const Tree *ast, slk::Builder *builder);
Tree *Load(AstStorage *ast, const capnp::Tree::Reader &tree,
std::vector<int32_t> *loaded_uids);
Tree *Load(AstStorage *ast, const capnp::Tree::Reader &tree);
Tree *Load(AstStorage *ast, slk::Reader *reader,
std::vector<int32_t> *loaded_uids);
Tree *Load(AstStorage *ast, slk::Reader *reader);
/// Primary function for loading Ast nodes via SLK.
template <class TAst>
TAst *LoadAstPointer(AstStorage *ast, slk::Reader *reader,
std::vector<int32_t> *loaded_uids) {
TAst *LoadAstPointer(AstStorage *ast, slk::Reader *reader) {
static_assert(std::is_base_of<query::Tree, TAst>::value);
bool has_ptr = false;
slk::Load(&has_ptr, reader);
if (!has_ptr) {
return nullptr;
}
auto *ret = utils::Downcast<TAst>(Load(ast, reader, loaded_uids));
auto *ret = utils::Downcast<TAst>(Load(ast, reader));
if (!ret) {
throw slk::SlkDecodeException("Loading unknown Ast node type");
}
@ -44,58 +40,25 @@ cpp<#
(lcp:in-impl
#>cpp
void SaveAstPointer(const Tree *ast, slk::Builder *builder,
std::vector<int32_t> *saved_uids) {
void SaveAstPointer(const Tree *ast, slk::Builder *builder) {
slk::Save(static_cast<bool>(ast), builder);
if (!ast) {
return;
}
slk::Save(ast->uid_, builder);
if (utils::Contains(*saved_uids, ast->uid_)) {
return;
}
slk::Save(*ast, builder, saved_uids);
CHECK(!utils::Contains(*saved_uids, ast->uid_)) << "Serializing cyclic AST";
saved_uids->push_back(ast->uid_);
slk::Save(*ast, builder);
}
Tree *Load(AstStorage *ast, slk::Reader *reader,
std::vector<int32_t> *loaded_uids) {
// Check if element already deserialized and if yes, return existing
// element from storage.
int32_t uid;
slk::Load(&uid, reader);
if (utils::Contains(*loaded_uids, uid)) {
auto found = std::find_if(ast->storage_.begin(), ast->storage_.end(),
[&](const auto &n) { return n->uid_ == uid; });
CHECK(found != ast->storage_.end());
return found->get();
}
Tree *Load(AstStorage *ast, slk::Reader *reader) {
std::unique_ptr<Tree> root;
slk::ConstructAndLoad(&root, reader, ast, loaded_uids);
root->uid_ = uid;
slk::ConstructAndLoad(&root, reader, ast);
ast->storage_.emplace_back(std::move(root));
loaded_uids->push_back(uid);
ast->max_existing_uid_ = std::max(ast->max_existing_uid_, uid);
return ast->storage_.back().get();
}
Tree *Load(AstStorage *ast, const capnp::Tree::Reader &tree,
std::vector<int> *loaded_uids) {
// Check if element already deserialized and if yes, return existing
// element from storage.
auto uid = tree.getUid();
if (utils::Contains(*loaded_uids, uid)) {
auto found = std::find_if(ast->storage_.begin(), ast->storage_.end(),
[&](const auto &n) { return n->uid_ == uid; });
CHECK(found != ast->storage_.end());
return found->get();
}
Tree *Load(AstStorage *ast, const capnp::Tree::Reader &tree) {
std::unique_ptr<Tree> root;
::query::Load(&root, tree, ast, loaded_uids);
::query::Load(&root, tree, ast);
ast->storage_.emplace_back(std::move(root));
loaded_uids->emplace_back(uid);
ast->max_existing_uid_ = std::max(ast->max_existing_uid_, uid);
return ast->storage_.back().get();
}
cpp<#)

View File

@ -51,7 +51,8 @@ void SymbolGenerator::VisitReturnBody(ReturnBody &body, Where *where) {
user_symbols.emplace_back(sym_pair.second);
}
if (user_symbols.empty()) {
throw SemanticException("There are no variables in scope to use for '*'.");
throw SemanticException(
"There are no variables in scope to use for '*'.");
}
}
// WITH/RETURN clause removes declarations of all the previous variables and
@ -79,8 +80,8 @@ void SymbolGenerator::VisitReturnBody(ReturnBody &body, Where *where) {
}
// An improvement would be to infer the type of the expression, so that the
// new symbol would have a more specific type.
symbol_table_[*named_expr] = CreateSymbol(name, true, Symbol::Type::ANY,
named_expr->token_position_);
named_expr->MapTo(CreateSymbol(name, true, Symbol::Type::ANY,
named_expr->token_position_));
}
scope_.in_order_by = true;
for (const auto &order_pair : body.order_by) {
@ -198,7 +199,7 @@ bool SymbolGenerator::PostVisit(Unwind &unwind) {
if (HasSymbol(name)) {
throw RedeclareVariableError(name);
}
symbol_table_[*unwind.named_expression_] = CreateSymbol(name, true);
unwind.named_expression_->MapTo(CreateSymbol(name, true));
return true;
}
@ -212,7 +213,7 @@ bool SymbolGenerator::PostVisit(Match &) {
// reference symbols out of bind order.
for (auto &ident : scope_.identifiers_in_match) {
if (!HasSymbol(ident->name_)) throw UnboundVariableError(ident->name_);
symbol_table_[*ident] = scope_.symbols[ident->name_];
ident->MapTo(scope_.symbols[ident->name_]);
}
scope_.identifiers_in_match.clear();
return true;
@ -270,7 +271,7 @@ SymbolGenerator::ReturnType SymbolGenerator::Visit(Identifier &ident) {
if (!HasSymbol(ident.name_)) throw UnboundVariableError(ident.name_);
symbol = scope_.symbols[ident.name_];
}
symbol_table_[ident] = symbol;
ident.MapTo(symbol);
return true;
}
@ -302,9 +303,8 @@ bool SymbolGenerator::PreVisit(Aggregation &aggr) {
// Create a virtual symbol for aggregation result.
// Currently, we only have aggregation operators which return numbers.
auto aggr_name =
Aggregation::OpToString(aggr.op_) + std::to_string(aggr.uid_);
symbol_table_[aggr] =
symbol_table_.CreateSymbol(aggr_name, false, Symbol::Type::NUMBER);
Aggregation::OpToString(aggr.op_) + std::to_string(aggr.symbol_pos_);
aggr.MapTo(CreateSymbol(aggr_name, false, Symbol::Type::NUMBER));
scope_.in_aggregation = true;
scope_.has_aggregation = true;
return true;
@ -435,12 +435,12 @@ bool SymbolGenerator::PreVisit(EdgeAtom &edge_atom) {
} else {
// Create inner symbols, but don't bind them in scope, since they are to
// be used in the missing filter expression.
const auto *inner_edge = edge_atom.filter_lambda_.inner_edge;
symbol_table_[*inner_edge] = symbol_table_.CreateSymbol(
inner_edge->name_, inner_edge->user_declared_, Symbol::Type::EDGE);
const auto *inner_node = edge_atom.filter_lambda_.inner_node;
symbol_table_[*inner_node] = symbol_table_.CreateSymbol(
inner_node->name_, inner_node->user_declared_, Symbol::Type::VERTEX);
auto *inner_edge = edge_atom.filter_lambda_.inner_edge;
inner_edge->MapTo(symbol_table_.CreateSymbol(
inner_edge->name_, inner_edge->user_declared_, Symbol::Type::EDGE));
auto *inner_node = edge_atom.filter_lambda_.inner_node;
inner_node->MapTo(symbol_table_.CreateSymbol(
inner_node->name_, inner_node->user_declared_, Symbol::Type::VERTEX));
}
if (edge_atom.weight_lambda_.expression) {
VisitWithIdentifiers(edge_atom.weight_lambda_.expression,
@ -456,9 +456,9 @@ bool SymbolGenerator::PreVisit(EdgeAtom &edge_atom) {
if (HasSymbol(edge_atom.total_weight_->name_)) {
throw RedeclareVariableError(edge_atom.total_weight_->name_);
}
symbol_table_[*edge_atom.total_weight_] = GetOrCreateSymbol(
edge_atom.total_weight_->MapTo(GetOrCreateSymbol(
edge_atom.total_weight_->name_, edge_atom.total_weight_->user_declared_,
Symbol::Type::NUMBER);
Symbol::Type::NUMBER));
}
return false;
}
@ -480,8 +480,8 @@ void SymbolGenerator::VisitWithIdentifiers(
if (prev_symbol_it != scope_.symbols.end()) {
prev_symbol = prev_symbol_it->second;
}
symbol_table_[*identifier] =
CreateSymbol(identifier->name_, identifier->user_declared_);
identifier->MapTo(
CreateSymbol(identifier->name_, identifier->user_declared_));
prev_symbols.emplace_back(prev_symbol, identifier);
}
// Visit the expression with the new symbols bound.

View File

@ -11,25 +11,32 @@ namespace query {
class SymbolTable final {
public:
SymbolTable() {}
Symbol CreateSymbol(const std::string &name, bool user_declared,
Symbol::Type type = Symbol::Type::ANY,
int32_t token_position = -1) {
int32_t position = position_++;
return Symbol(name, position, user_declared, type, token_position);
const Symbol &CreateSymbol(const std::string &name, bool user_declared,
Symbol::Type type = Symbol::Type::ANY,
int32_t token_position = -1) {
CHECK(table_.size() <= std::numeric_limits<int32_t>::max())
<< "SymbolTable size doesn't fit into 32-bit integer!";
int32_t position = static_cast<int32_t>(table_.size());
table_.emplace_back(name, position, user_declared, type, token_position);
return table_.back();
}
auto &operator[](const Tree &tree) { return table_[tree.uid_]; }
Symbol &at(const Tree &tree) { return table_.at(tree.uid_); }
const Symbol &at(const Tree &tree) const { return table_.at(tree.uid_); }
const Symbol &at(const Identifier &ident) const {
return table_.at(ident.symbol_pos_);
}
const Symbol &at(const NamedExpression &nexpr) const {
return table_.at(nexpr.symbol_pos_);
}
const Symbol &at(const Aggregation &aggr) const {
return table_.at(aggr.symbol_pos_);
}
// TODO: Remove these since members are public
int32_t max_position() const { return position_; }
int32_t max_position() const { return static_cast<int32_t>(table_.size()); }
const auto &table() const { return table_; }
int32_t position_{0};
std::map<int32_t, Symbol> table_;
std::vector<Symbol> table_;
};
} // namespace query

View File

@ -127,9 +127,10 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
// a) Extract to ScanAllByLabel + Filter x2
auto make_prop_lookup = [&]() {
auto ident = storage_->Create<Identifier>(
scan.output_symbol_.name(), scan.output_symbol_.user_declared());
(*symbol_table_)[*ident] = scan.output_symbol_;
auto ident = storage_
->Create<Identifier>(scan.output_symbol_.name(),
scan.output_symbol_.user_declared())
->MapTo(scan.output_symbol_);
// TODO: When this extraction of a filter is removed, also remove
// property_name from ScanAll operators.
return storage_->Create<PropertyLookup>(
@ -224,9 +225,10 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
// Split to ScanAllByLabel + Filter on property
auto subtree = std::make_shared<ScanAllByLabel>(
scan.input(), scan.output_symbol_, scan.label_, scan.graph_view_);
auto ident = storage_->Create<Identifier>(
scan.output_symbol_.name(), scan.output_symbol_.user_declared());
(*symbol_table_)[*ident] = scan.output_symbol_;
auto ident = storage_
->Create<Identifier>(scan.output_symbol_.name(),
scan.output_symbol_.user_declared())
->MapTo(scan.output_symbol_);
auto prop_lookup = storage_->Create<PropertyLookup>(
ident, storage_->GetPropertyIx(scan.property_name_));
auto prop_equal =
@ -1259,20 +1261,21 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
}
auto make_ident = [this](const auto &symbol) {
auto *ident =
distributed_plan_.ast_storage.Create<Identifier>(symbol.name());
distributed_plan_.symbol_table[*ident] = symbol;
distributed_plan_.ast_storage.Create<Identifier>(symbol.name())
->MapTo(symbol);
return ident;
};
auto make_named_expr = [&](const auto &in_sym, const auto &out_sym) {
auto *nexpr = distributed_plan_.ast_storage.Create<NamedExpression>(
out_sym.name(), make_ident(in_sym));
distributed_plan_.symbol_table[*nexpr] = out_sym;
auto *nexpr =
distributed_plan_.ast_storage
.Create<NamedExpression>(out_sym.name(), make_ident(in_sym))
->MapTo(out_sym);
return nexpr;
};
auto make_merge_aggregation = [&](auto op, const auto &worker_sym) {
auto *worker_ident = make_ident(worker_sym);
auto merge_name = Aggregation::OpToString(op) +
std::to_string(worker_ident->uid_) + "<-" +
std::to_string(worker_ident->symbol_pos_) + "<-" +
worker_sym.name();
auto merge_sym = distributed_plan_.symbol_table.CreateSymbol(
merge_name, false, Symbol::Type::NUMBER);
@ -1338,9 +1341,10 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
auto *div_expr =
distributed_plan_.ast_storage.Create<DivisionOperator>(
master_sum_ident, to_float);
auto *as_avg = distributed_plan_.ast_storage.Create<NamedExpression>(
aggr.output_sym.name(), div_expr);
distributed_plan_.symbol_table[*as_avg] = aggr.output_sym;
auto *as_avg =
distributed_plan_.ast_storage
.Create<NamedExpression>(aggr.output_sym.name(), div_expr)
->MapTo(aggr.output_sym);
produce_exprs.emplace_back(as_avg);
break;
}

View File

@ -291,22 +291,14 @@ by having only one result from each worker.")
:capnp-load (load-ast-pointer "Expression *"))
(filter-lambda "ExpansionLambda" :scope :public
:documentation "Filter that must be satisfied for expansion to succeed."
:slk-save (lambda (member)
#>cpp
slk::Save(self.${member}, builder, &helper->saved_ast_uids);
cpp<#)
:slk-load (lambda (member)
#>cpp
slk::Load(&self->${member}, reader, &helper->ast_storage, &helper->loaded_ast_uids);
slk::Load(&self->${member}, reader, &helper->ast_storage);
cpp<#)
:capnp-type "ExpansionLambda"
:capnp-save (lambda (builder member capnp-name)
#>cpp
Save(${member}, &${builder}, &helper->saved_ast_uids);
cpp<#)
:capnp-load (lambda (reader member capnp-name)
#>cpp
Load(&${member}, ${reader}, &helper->ast_storage, &helper->loaded_ast_uids);
Load(&${member}, ${reader}, &helper->ast_storage);
cpp<#)))
(:documentation "BFS expansion operator suited for distributed execution.")
(:public

View File

@ -206,20 +206,17 @@ can serve as inputs to others and thus a sequence of operations is formed.")
virtual void set_input(std::shared_ptr<LogicalOperator>) = 0;
struct SaveHelper {
std::vector<int32_t> saved_ast_uids;
std::vector<LogicalOperator *> saved_ops;
};
struct LoadHelper {
AstStorage ast_storage;
std::vector<int32_t> loaded_ast_uids;
std::vector<std::pair<uint64_t, std::shared_ptr<LogicalOperator>>>
loaded_ops;
};
struct SlkLoadHelper {
AstStorage ast_storage;
std::vector<int32_t> loaded_ast_uids;
std::vector<std::shared_ptr<LogicalOperator>> loaded_ops;
};
cpp<#)
@ -236,21 +233,21 @@ can serve as inputs to others and thus a sequence of operations is formed.")
(defun slk-save-ast-pointer (member)
#>cpp
query::SaveAstPointer(self.${member}, builder, &helper->saved_ast_uids);
query::SaveAstPointer(self.${member}, builder);
cpp<#)
(defun slk-load-ast-pointer (type)
(lambda (member)
#>cpp
self->${member} = query::LoadAstPointer<query::${type}>(
&helper->ast_storage, reader, &helper->loaded_ast_uids);
&helper->ast_storage, reader);
cpp<#))
(defun save-ast-pointer (builder member capnp-name)
#>cpp
if (${member}) {
auto ${capnp-name}_builder = ${builder}->init${capnp-name}();
Save(*${member}, &${capnp-name}_builder, &helper->saved_ast_uids);
Save(*${member}, &${capnp-name}_builder);
}
cpp<#)
@ -259,8 +256,7 @@ can serve as inputs to others and thus a sequence of operations is formed.")
#>cpp
if (${reader}.has${capnp-name}()) {
${member} = static_cast<${ast-type}>(Load(&helper->ast_storage,
${reader}.get${capnp-name}(),
&helper->loaded_ast_uids));
${reader}.get${capnp-name}()));
} else {
${member} = nullptr;
}
@ -271,7 +267,7 @@ can serve as inputs to others and thus a sequence of operations is formed.")
size_t size = self.${member}.size();
slk::Save(size, builder);
for (const auto *val : self.${member}) {
query::SaveAstPointer(val, builder, &helper->saved_ast_uids);
query::SaveAstPointer(val, builder);
}
cpp<#)
@ -285,14 +281,14 @@ can serve as inputs to others and thus a sequence of operations is formed.")
i < size;
++i) {
self->${member}[i] = query::LoadAstPointer<query::${type}>(
&helper->ast_storage, reader, &helper->loaded_ast_uids);
&helper->ast_storage, reader);
}
cpp<#))
(defun save-ast-vector (ast-type)
(lcp:capnp-save-vector "::query::capnp::Tree" ast-type
"[helper](auto *builder, const auto &val) {
Save(*val, builder, &helper->saved_ast_uids);
Save(*val, builder);
}"))
(defun load-ast-vector (ast-type)
@ -300,8 +296,7 @@ can serve as inputs to others and thus a sequence of operations is formed.")
(format
nil
"[helper](const auto &reader) {
return static_cast<~A>(Load(&helper->ast_storage, reader,
&helper->loaded_ast_uids));
return static_cast<~A>(Load(&helper->ast_storage, reader));
}"
ast-type)))
@ -383,7 +378,7 @@ and false on every following Pull.")
slk::Save(size, builder);
for (const auto &kv : self.${member}) {
slk::Save(kv.first, builder);
query::SaveAstPointer(kv.second, builder, &helper->saved_ast_uids);
query::SaveAstPointer(kv.second, builder);
}
cpp<#)
@ -396,7 +391,7 @@ and false on every following Pull.")
storage::Property prop;
slk::Load(&prop, reader);
auto *expr = query::LoadAstPointer<query::Expression>(
&helper->ast_storage, reader, &helper->loaded_ast_uids);
&helper->ast_storage, reader);
self->${member}[i] = {prop, expr};
}
cpp<#)
@ -407,7 +402,7 @@ and false on every following Pull.")
auto prop_builder = ${builder}[i].initFirst();
storage::Save(${member}[i].first, &prop_builder);
auto expr_builder = ${builder}[i].initSecond();
Save(*${member}[i].second, &expr_builder, &helper->saved_ast_uids);
Save(*${member}[i].second, &expr_builder);
}
cpp<#)
@ -418,7 +413,7 @@ and false on every following Pull.")
storage::Property prop;
storage::Load(&prop, prop_reader);
auto *expr = static_cast<Expression *>(Load(
&helper->ast_storage, pair_reader.getSecond(), &helper->loaded_ast_uids));
&helper->ast_storage, pair_reader.getSecond()));
${member}.emplace_back(prop, expr);
}
cpp<#)
@ -725,7 +720,7 @@ given label.
break;
}
slk::Save(bound_type, builder);
query::SaveAstPointer(bound.value(), builder, &helper->saved_ast_uids);
query::SaveAstPointer(bound.value(), builder);
cpp<#)
(defun slk-load-optional-bound (member)
@ -750,7 +745,7 @@ given label.
throw slk::SlkDecodeException("Loading unknown BoundType");
}
auto *value = query::LoadAstPointer<query::Expression>(
&helper->ast_storage, reader, &helper->loaded_ast_uids);
&helper->ast_storage, reader);
self->${member}.emplace(utils::Bound<query::Expression *>(value, bound_type));
cpp<#)
@ -761,7 +756,7 @@ given label.
::utils::capnp::Bound<::query::capnp::Tree>::Type::INCLUSIVE :
::utils::capnp::Bound<::query::capnp::Tree>::Type::EXCLUSIVE);
auto value_builder = builder->initValue();
Save(*bound.value(), &value_builder, &helper->saved_ast_uids);
Save(*bound.value(), &value_builder);
}"))
(funcall (lcp:capnp-save-optional "::utils::capnp::Bound<::query::capnp::Tree>"
"utils::Bound<Expression *>"
@ -776,7 +771,7 @@ given label.
? utils::BoundType::INCLUSIVE
: utils::BoundType::EXCLUSIVE;
auto *value = static_cast<Expression *>(
Load(&helper->ast_storage, reader.getValue(), &helper->loaded_ast_uids));
Load(&helper->ast_storage, reader.getValue()));
return utils::Bound<Expression *>(value, type);
}"))
(funcall (lcp:capnp-load-optional "::utils::capnp::Bound<::query::capnp::Tree>"
@ -1023,40 +1018,25 @@ pulled.")
((inner-edge-symbol "Symbol" :documentation "Currently expanded edge symbol.")
(inner-node-symbol "Symbol" :documentation "Currently expanded node symbol.")
(expression "Expression *" :documentation "Expression used in lambda during expansion."
:slk-save (lambda (member)
#>cpp
query::SaveAstPointer(self.${member}, builder, saved_ast_uids);
cpp<#)
:slk-save #'slk-save-ast-pointer
:slk-load (lambda (member)
#>cpp
self->${member} = query::LoadAstPointer<query::Expression>(
ast_storage, reader, loaded_ast_uids);
ast_storage, reader);
cpp<#)
:capnp-type "Ast.Tree" :capnp-init nil
:capnp-save (lambda (builder member capnp-name)
#>cpp
if (${member}) {
auto ${capnp-name}_builder = ${builder}->init${capnp-name}();
Save(*${member}, &${capnp-name}_builder, saved_ast_uids);
}
cpp<#)
:capnp-save #'save-ast-pointer
:capnp-load (lambda (reader member capnp-name)
#>cpp
if (${reader}.has${capnp-name}()) {
${member} = static_cast<Expression *>(Load(ast_storage,
${reader}.get${capnp-name}(),
loaded_ast_uids));
${reader}.get${capnp-name}()));
} else {
${member} = nullptr;
}
cpp<#)))
(:serialize (:slk :save-args '((saved-ast-uids "std::vector<int32_t> *"))
:load-args '((ast-storage "query::AstStorage *")
(loaded-ast-uids "std::vector<int32_t> *")))
(:capnp
:save-args '((saved-ast-uids "std::vector<int32_t> *"))
:load-args '((ast-storage "AstStorage *")
(loaded-ast-uids "std::vector<int32_t> *"))))
(:serialize (:slk :load-args '((ast-storage "query::AstStorage *")))
(:capnp :load-args '((ast-storage "AstStorage *"))))
(:clone :args '((storage "AstStorage *"))))
(lcp:define-class expand-variable (logical-operator)
@ -1089,31 +1069,15 @@ pulled.")
:documentation "Optional upper bound of the variable length expansion, defaults are (1, inf)")
(filter-lambda "ExpansionLambda"
:scope :public
:slk-save (lambda (member)
#>cpp
slk::Save(self.${member}, builder, &helper->saved_ast_uids);
cpp<#)
:slk-load (lambda (member)
#>cpp
slk::Load(&self->${member}, reader, &helper->ast_storage, &helper->loaded_ast_uids);
slk::Load(&self->${member}, reader, &helper->ast_storage);
cpp<#)
:capnp-save (lambda (builder member capnp-name)
#>cpp
Save(${member}, &${builder}, &helper->saved_ast_uids);
cpp<#)
:capnp-load (lambda (reader member capnp-name)
#>cpp
Load(&${member}, ${reader}, &helper->ast_storage, &helper->loaded_ast_uids);
Load(&${member}, ${reader}, &helper->ast_storage);
cpp<#))
(weight-lambda "std::experimental::optional<ExpansionLambda>" :scope :public
:slk-save (lambda (member)
#>cpp
slk::Save(static_cast<bool>(self.${member}), builder);
if (!self.${member}) {
return;
}
slk::Save(*self.${member}, builder, &helper->saved_ast_uids);
cpp<#)
:slk-load (lambda (member)
#>cpp
bool has_value;
@ -1123,19 +1087,17 @@ pulled.")
return;
}
query::plan::ExpansionLambda lambda;
slk::Load(&lambda, reader, &helper->ast_storage, &helper->loaded_ast_uids);
slk::Load(&lambda, reader, &helper->ast_storage);
self->${member}.emplace(lambda);
cpp<#)
:capnp-save (lcp:capnp-save-optional
"capnp::ExpansionLambda" "ExpansionLambda"
"[helper](auto *builder, const auto &val) {
Save(val, builder, &helper->saved_ast_uids);
}")
"capnp::ExpansionLambda"
"ExpansionLambda")
:capnp-load (lcp:capnp-load-optional
"capnp::ExpansionLambda" "ExpansionLambda"
"[helper](const auto &reader) {
ExpansionLambda val;
Load(&val, reader, &helper->ast_storage, &helper->loaded_ast_uids);
Load(&val, reader, &helper->ast_storage);
return val;
}"))
(total-weight "std::experimental::optional<Symbol>" :scope :public

View File

@ -161,8 +161,7 @@ PropertyFilter::PropertyFilter(const SymbolTable &symbol_table,
}
PropertyFilter::PropertyFilter(
const SymbolTable &symbol_table, const Symbol &symbol,
PropertyIx property,
const SymbolTable &symbol_table, const Symbol &symbol, PropertyIx property,
const std::experimental::optional<PropertyFilter::Bound> &lower_bound,
const std::experimental::optional<PropertyFilter::Bound> &upper_bound)
: symbol_(symbol),
@ -251,10 +250,12 @@ void Filters::CollectPatternFilters(Pattern &pattern, SymbolTable &symbol_table,
collector.symbols_.insert(symbol); // PropertyLookup uses the symbol.
// Now handle the post-expansion filter.
// Create a new identifier and a symbol which will be filled in All.
auto *identifier = storage.Create<Identifier>(
atom->identifier_->name_, atom->identifier_->user_declared_);
symbol_table[*identifier] =
symbol_table.CreateSymbol(identifier->name_, false);
auto *identifier =
storage
.Create<Identifier>(atom->identifier_->name_,
atom->identifier_->user_declared_)
->MapTo(
symbol_table.CreateSymbol(atom->identifier_->name_, false));
// Create an equality expression and store it in all_filters_.
auto *property_lookup =
storage.Create<PropertyLookup>(identifier, prop_pair.first);
@ -282,8 +283,8 @@ void Filters::CollectPatternFilters(Pattern &pattern, SymbolTable &symbol_table,
FilterInfo filter_info{FilterInfo::Type::Property, prop_equal,
collector.symbols_};
// Store a PropertyFilter on the value of the property.
filter_info.property_filter.emplace(
symbol_table, symbol, prop_pair.first, prop_pair.second);
filter_info.property_filter.emplace(symbol_table, symbol, prop_pair.first,
prop_pair.second);
all_filters_.emplace_back(filter_info);
}
};

View File

@ -370,10 +370,9 @@ class ReturnBodyContext : public HierarchicalTreeVisitor {
if (!symbol.user_declared()) {
continue;
}
auto *ident = storage_.Create<Identifier>(symbol.name());
symbol_table_[*ident] = symbol;
auto *named_expr = storage_.Create<NamedExpression>(symbol.name(), ident);
symbol_table_[*named_expr] = symbol;
auto *ident = storage_.Create<Identifier>(symbol.name())->MapTo(symbol);
auto *named_expr =
storage_.Create<NamedExpression>(symbol.name(), ident)->MapTo(symbol);
// Fill output expressions and symbols with expanded identifiers.
named_expressions_.emplace_back(named_expr);
output_symbols_.emplace_back(symbol);

View File

@ -43,11 +43,5 @@ struct TypedValue {
}
struct SymbolTable {
position @0 :Int32;
table @1 :List(Entry);
struct Entry {
key @0 :Int32;
val @1 :Sem.Symbol;
}
table @0 :List(Sem.Symbol);
}

View File

@ -7,6 +7,7 @@
#include "query/serialization.capnp.h"
#include "query/typed_value.hpp"
#include "storage/distributed/rpc/serialization.hpp"
#include "utils/serialization.hpp"
namespace distributed {
class DataManager;
@ -31,27 +32,20 @@ void Load(TypedValueVectorCompare *comparator,
inline void Save(const SymbolTable &symbol_table,
capnp::SymbolTable::Builder *builder) {
builder->setPosition(symbol_table.max_position());
auto list_builder = builder->initTable(symbol_table.table().size());
size_t i = 0;
for (const auto &entry : symbol_table.table()) {
auto entry_builder = list_builder[i++];
entry_builder.setKey(entry.first);
auto sym_builder = entry_builder.initVal();
Save(entry.second, &sym_builder);
}
utils::SaveVector<capnp::Symbol, Symbol>(
symbol_table.table(), &list_builder,
[](auto *builder, const auto &symbol) { Save(symbol, builder); });
}
inline void Load(SymbolTable *symbol_table,
const capnp::SymbolTable::Reader &reader) {
symbol_table->position_ = reader.getPosition();
symbol_table->table_.clear();
for (const auto &entry_reader : reader.getTable()) {
int key = entry_reader.getKey();
Symbol val;
Load(&val, entry_reader.getVal());
symbol_table->table_[key] = val;
}
utils::LoadVector<capnp::Symbol, Symbol>(
&symbol_table->table_, reader.getTable(), [](const auto &reader) {
Symbol val;
Load(&val, reader);
return val;
});
}
void Save(const Parameters &parameters,
@ -69,12 +63,10 @@ namespace slk {
inline void Save(const query::SymbolTable &symbol_table,
slk::Builder *builder) {
slk::Save(symbol_table.position_, builder);
slk::Save(symbol_table.table_, builder);
}
inline void Load(query::SymbolTable *symbol_table, slk::Reader *reader) {
slk::Load(&symbol_table->position_, reader);
slk::Load(&symbol_table->table_, reader);
}

View File

@ -86,15 +86,13 @@ class CapnpAstGenerator : public Base {
{
query::capnp::Tree::Builder builder =
message.initRoot<query::capnp::Tree>();
std::vector<int> saved_uids;
Save(*visitor.query(), &builder, &saved_uids);
Save(*visitor.query(), &builder);
}
{
const query::capnp::Tree::Reader reader =
message.getRoot<query::capnp::Tree>();
std::vector<int> loaded_uids;
query_ = dynamic_cast<Query *>(Load(&storage_, reader, &loaded_uids));
query_ = dynamic_cast<Query *>(Load(&storage_, reader));
}
}
@ -124,14 +122,12 @@ class SlkAstGenerator : public Base {
slk::Builder builder;
{
std::vector<int32_t> saved_uids;
SaveAstPointer(visitor.query(), &builder, &saved_uids);
SaveAstPointer(visitor.query(), &builder);
}
{
slk::Reader reader(builder.data(), builder.size());
std::vector<int32_t> loaded_uids;
query_ = LoadAstPointer<Query>(&storage_, &reader, &loaded_uids);
query_ = LoadAstPointer<Query>(&storage_, &reader);
}
}

View File

@ -322,12 +322,9 @@ void BfsTest(Database *db, int lower_bound, int upper_bound,
context.symbol_table.CreateSymbol("inner_node", true);
query::Symbol inner_edge_sym =
context.symbol_table.CreateSymbol("inner_edge", true);
query::Identifier *blocked = IDENT("blocked");
query::Identifier *inner_node = IDENT("inner_node");
query::Identifier *inner_edge = IDENT("inner_edge");
context.symbol_table[*blocked] = blocked_sym;
context.symbol_table[*inner_node] = inner_node_sym;
context.symbol_table[*inner_edge] = inner_edge_sym;
query::Identifier *blocked = IDENT("blocked")->MapTo(blocked_sym);
query::Identifier *inner_node = IDENT("inner_node")->MapTo(inner_node_sym);
query::Identifier *inner_edge = IDENT("inner_edge")->MapTo(inner_edge_sym);
std::vector<VertexAddress> vertices;
std::vector<EdgeAddress> edges;

View File

@ -45,11 +45,11 @@ ExpandTuple MakeDistributedExpand(
GraphView graph_view) {
auto edge = EDGE(edge_identifier, direction);
auto edge_sym = symbol_table.CreateSymbol(edge_identifier, true);
symbol_table[*edge->identifier_] = edge_sym;
edge->identifier_->MapTo(edge_sym);
auto node = NODE(node_identifier);
auto node_sym = symbol_table.CreateSymbol(node_identifier, true);
symbol_table[*node->identifier_] = node_sym;
node->identifier_->MapTo(node_sym);
auto op = std::make_shared<DistributedExpand>(input, input_symbol, node_sym,
edge_sym, direction, edge_types,
@ -75,10 +75,9 @@ TEST_F(DistributedQueryPlan, PullProduceRpc) {
LIST(LITERAL(42), LITERAL(true), LITERAL("bla"), LITERAL(1), LITERAL(2));
auto x = symbol_table.CreateSymbol("x", true);
auto unwind = std::make_shared<plan::Unwind>(nullptr, list, x);
auto x_expr = IDENT("x");
symbol_table[*x_expr] = x;
auto x_ne = NEXPR("x", x_expr);
symbol_table[*x_ne] = symbol_table.CreateSymbol("x_ne", true);
auto x_expr = IDENT("x")->MapTo(x);
auto x_ne =
NEXPR("x", x_expr)->MapTo(symbol_table.CreateSymbol("x_ne", true));
auto produce = MakeProduce(unwind, x_ne);
// Test that the plan works locally.
@ -91,7 +90,7 @@ TEST_F(DistributedQueryPlan, PullProduceRpc) {
tx::CommandId command_id = dba->transaction().cid();
auto &evaluation_context = ctx.evaluation_context;
std::vector<query::Symbol> symbols{ctx.symbol_table[*x_ne]};
std::vector<query::Symbol> symbols{ctx.symbol_table.at(*x_ne)};
auto remote_pull = [this, &command_id, &evaluation_context, &symbols](
GraphDbAccessor &dba, int worker_id) {
return master().pull_clients().Pull(&dba, worker_id, plan_id, command_id,
@ -168,18 +167,14 @@ TEST_F(DistributedQueryPlan, PullProduceRpcWithGraphElements) {
auto p = std::make_shared<query::plan::ConstructNamedPath>(
r_m.op_, p_sym,
std::vector<Symbol>{n.sym_, r_m.edge_sym_, r_m.node_sym_});
auto return_n = IDENT("n");
symbol_table[*return_n] = n.sym_;
auto return_r = IDENT("r");
symbol_table[*return_r] = r_m.edge_sym_;
auto return_n_r = NEXPR("[n, r]", LIST(return_n, return_r));
symbol_table[*return_n_r] = symbol_table.CreateSymbol("", true);
auto return_m = NEXPR("m", IDENT("m"));
symbol_table[*return_m->expression_] = r_m.node_sym_;
symbol_table[*return_m] = symbol_table.CreateSymbol("", true);
auto return_p = NEXPR("p", IDENT("p"));
symbol_table[*return_p->expression_] = p_sym;
symbol_table[*return_p] = symbol_table.CreateSymbol("", true);
auto return_n = IDENT("n")->MapTo(n.sym_);
auto return_r = IDENT("r")->MapTo(r_m.edge_sym_);
auto return_n_r = NEXPR("[n, r]", LIST(return_n, return_r))
->MapTo(symbol_table.CreateSymbol("", true));
auto return_m = NEXPR("m", IDENT("m")->MapTo(r_m.node_sym_))
->MapTo(symbol_table.CreateSymbol("", true));
auto return_p = NEXPR("p", IDENT("p")->MapTo(p_sym))
->MapTo(symbol_table.CreateSymbol("", true));
auto produce = MakeProduce(p, return_n_r, return_m, return_p);
auto check_result = [prop](int worker_id,
@ -211,8 +206,8 @@ TEST_F(DistributedQueryPlan, PullProduceRpcWithGraphElements) {
tx::CommandId command_id = dba->transaction().cid();
auto &evaluation_context = ctx.evaluation_context;
std::vector<query::Symbol> symbols{ctx.symbol_table[*return_n_r],
ctx.symbol_table[*return_m], p_sym};
std::vector<query::Symbol> symbols{ctx.symbol_table.at(*return_n_r),
ctx.symbol_table.at(*return_m), p_sym};
auto remote_pull = [this, &command_id, &evaluation_context, &symbols](
GraphDbAccessor &dba, int worker_id) {
return master().pull_clients().Pull(&dba, worker_id, plan_id, command_id,
@ -246,8 +241,7 @@ TEST_F(DistributedQueryPlan, Synchronize) {
// SET
auto literal = LITERAL(42);
auto prop = PROPERTY_PAIR("prop");
auto m_p = PROPERTY_LOOKUP("m", prop);
symbol_table[*m_p->expression_] = r_m.node_sym_;
auto m_p = PROPERTY_LOOKUP(IDENT("m")->MapTo(r_m.node_sym_), prop);
auto set_m_p =
std::make_shared<plan::SetProperty>(r_m.op_, prop.second, m_p, literal);
@ -261,11 +255,9 @@ TEST_F(DistributedQueryPlan, Synchronize) {
std::make_shared<query::plan::Synchronize>(set_m_p, pull_remote, true);
// RETURN
auto n_p = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_p->expression_] = n.sym_;
auto return_n_p = NEXPR("n.prop", n_p);
auto return_n_p_sym = symbol_table.CreateSymbol("n.p", true);
symbol_table[*return_n_p] = return_n_p_sym;
auto n_p = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop);
auto return_n_p =
NEXPR("n.prop", n_p)->MapTo(symbol_table.CreateSymbol("n.p", true));
auto produce = MakeProduce(synchronize, return_n_p);
auto ctx = MakeContext(storage, symbol_table, &dba);
auto results = CollectProduce(*produce, &ctx);
@ -331,8 +323,7 @@ TEST_F(DistributedQueryPlan, PullRemoteOrderBy) {
// Query plan for: MATCH (n) RETURN n.prop ORDER BY n.prop;
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_p = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_p->expression_] = n.sym_;
auto n_p = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop);
auto order_by = std::make_shared<plan::OrderBy>(
n.op_, std::vector<SortItem>{{Ordering::ASC, n_p}},
std::vector<Symbol>{n.sym_});
@ -344,8 +335,8 @@ TEST_F(DistributedQueryPlan, PullRemoteOrderBy) {
order_by, plan_id, std::vector<SortItem>{{Ordering::ASC, n_p}},
std::vector<Symbol>{n.sym_});
auto n_p_ne = NEXPR("n.prop", n_p);
symbol_table[*n_p_ne] = symbol_table.CreateSymbol("n.prop", true);
auto n_p_ne =
NEXPR("n.prop", n_p)->MapTo(symbol_table.CreateSymbol("n.prop", true));
auto produce = MakeProduce(pull_remote_order_by, n_p_ne);
auto ctx = MakeContext(storage, symbol_table, &dba);
auto results = CollectProduce(*produce, &ctx);
@ -374,10 +365,10 @@ TEST_F(DistributedTransactionTimeout, Timeout) {
// Make distributed plan for MATCH (n) RETURN n
auto scan_all = MakeScanAll(storage, symbol_table, "n");
auto output = NEXPR("n", IDENT("n"));
auto output =
NEXPR("n", IDENT("n")->MapTo(scan_all.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(scan_all.op_, output);
symbol_table[*output->expression_] = scan_all.sym_;
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
const int plan_id = 42;
master().plan_dispatcher().DispatchPlan(plan_id, produce, symbol_table);
@ -387,7 +378,7 @@ TEST_F(DistributedTransactionTimeout, Timeout) {
evaluation_context.properties =
NamesToProperties(storage.properties_, dba.get());
evaluation_context.labels = NamesToLabels(storage.labels_, dba.get());
std::vector<query::Symbol> symbols{symbol_table[*output]};
std::vector<query::Symbol> symbols{symbol_table.at(*output)};
auto remote_pull = [this, &command_id, &evaluation_context, &symbols,
&dba]() {
return master()
@ -1205,7 +1196,8 @@ TYPED_TEST(TestPlanner, MatchReturnSum) {
auto merge_sum = SUM(IDENT("worker_sum"));
auto master_aggr = ExpectMasterAggregate({merge_sum}, {n_prop2});
ExpectPullRemote pull(
{symbol_table.at(*sum), symbol_table.at(*n_prop2->expression_)});
{symbol_table.at(*sum),
symbol_table.at(*dynamic_cast<Identifier *>(n_prop2->expression_))});
auto expected =
ExpectDistributed(MakeCheckers(ExpectScanAll(), aggr, pull, master_aggr,
ExpectProduce(), ExpectProduce()),
@ -1314,9 +1306,11 @@ TYPED_TEST(TestPlanner, CreateWithOrderByWhere) {
auto r_type = "r";
AstStorage storage;
auto ident_n = IDENT("n");
auto ident_r = IDENT("r");
auto ident_m = IDENT("m");
auto new_prop = PROPERTY_LOOKUP("new", prop);
auto r_prop = PROPERTY_LOOKUP("r", prop);
auto m_prop = PROPERTY_LOOKUP("m", prop);
auto r_prop = PROPERTY_LOOKUP(ident_r, prop);
auto m_prop = PROPERTY_LOOKUP(ident_m, prop);
auto query = QUERY(SINGLE_QUERY(
CREATE(
PATTERN(NODE("n"), EDGE("r", Direction::OUT, {r_type}), NODE("m"))),
@ -1325,9 +1319,9 @@ TYPED_TEST(TestPlanner, CreateWithOrderByWhere) {
auto symbol_table = query::MakeSymbolTable(query);
// Since this is a write query, we expect to accumulate to old used symbols.
auto acc = ExpectAccumulate({
symbol_table.at(*ident_n), // `n` in WITH
symbol_table.at(*r_prop->expression_), // `r` in ORDER BY
symbol_table.at(*m_prop->expression_), // `m` in WHERE
symbol_table.at(*ident_n), // `n` in WITH
symbol_table.at(*ident_r), // `r` in ORDER BY
symbol_table.at(*ident_m), // `m` in WHERE
});
auto planner = MakePlanner<TypeParam>(&dba, storage, symbol_table, query);
auto expected = ExpectDistributed(
@ -1480,8 +1474,8 @@ TYPED_TEST(TestPlanner, DistributedAvg) {
auto worker_aggr_op = std::dynamic_pointer_cast<Aggregate>(worker_plan);
ASSERT_TRUE(worker_aggr_op);
ASSERT_EQ(worker_aggr_op->aggregations_.size(), 2U);
symbol_table[*worker_sum] = worker_aggr_op->aggregations_[0].output_sym;
symbol_table[*worker_count] = worker_aggr_op->aggregations_[1].output_sym;
worker_sum->MapTo(worker_aggr_op->aggregations_[0].output_sym);
worker_count->MapTo(worker_aggr_op->aggregations_[1].output_sym);
}
auto worker_aggr = ExpectAggregate({worker_sum, worker_count}, {});
auto merge_sum = SUM(IDENT("worker_sum"));
@ -1817,16 +1811,13 @@ TEST(TestPlanner, DistributedCartesianIndexedScanByBothBounds) {
auto sym_a = symbol_table.CreateSymbol("a", true);
auto scan_a = std::make_shared<ScanAll>(nullptr, sym_a);
auto sym_b = symbol_table.CreateSymbol("b", true);
query::Expression *lower_expr = IDENT("a");
symbol_table[*lower_expr] = sym_a;
query::Expression *lower_expr = IDENT("a")->MapTo(sym_a);
auto lower_bound = utils::MakeBoundExclusive(lower_expr);
query::Expression *upper_expr = IDENT("a");
symbol_table[*upper_expr] = sym_a;
query::Expression *upper_expr = IDENT("a")->MapTo(sym_a);
auto upper_bound = utils::MakeBoundExclusive(upper_expr);
auto scan_b = std::make_shared<ScanAllByLabelPropertyRange>(
scan_a, sym_b, label, prop, "prop", lower_bound, upper_bound);
auto ident_b = IDENT("b");
symbol_table[*ident_b] = sym_b;
auto ident_b = IDENT("b")->MapTo(sym_b);
auto as_b = NEXPR("b", ident_b);
auto produce = std::make_shared<Produce>(
scan_b, std::vector<query::NamedExpression *>{as_b});
@ -1863,13 +1854,11 @@ TEST(TestPlanner, DistributedCartesianIndexedScanByLowerWithBothBounds) {
auto sym_b = symbol_table.CreateSymbol("b", true);
query::Expression *lower_expr = LITERAL(42);
auto lower_bound = utils::MakeBoundExclusive(lower_expr);
query::Expression *upper_expr = IDENT("a");
symbol_table[*upper_expr] = sym_a;
query::Expression *upper_expr = IDENT("a")->MapTo(sym_a);
auto upper_bound = utils::MakeBoundExclusive(upper_expr);
auto scan_b = std::make_shared<ScanAllByLabelPropertyRange>(
scan_a, sym_b, label, prop, "prop", lower_bound, upper_bound);
auto ident_b = IDENT("b");
symbol_table[*ident_b] = sym_b;
auto ident_b = IDENT("b")->MapTo(sym_b);
auto as_b = NEXPR("b", ident_b);
auto produce = std::make_shared<Produce>(
scan_b, std::vector<query::NamedExpression *>{as_b});
@ -1908,15 +1897,13 @@ TEST(TestPlanner, DistributedCartesianIndexedScanByUpperWithBothBounds) {
auto sym_a = symbol_table.CreateSymbol("a", true);
auto scan_a = std::make_shared<ScanAll>(nullptr, sym_a);
auto sym_b = symbol_table.CreateSymbol("b", true);
query::Expression *lower_expr = IDENT("a");
symbol_table[*lower_expr] = sym_a;
query::Expression *lower_expr = IDENT("a")->MapTo(sym_a);
auto lower_bound = utils::MakeBoundExclusive(lower_expr);
query::Expression *upper_expr = LITERAL(42);
auto upper_bound = utils::MakeBoundExclusive(upper_expr);
auto scan_b = std::make_shared<ScanAllByLabelPropertyRange>(
scan_a, sym_b, label, prop, "prop", lower_bound, upper_bound);
auto ident_b = IDENT("b");
symbol_table[*ident_b] = sym_b;
auto ident_b = IDENT("b")->MapTo(sym_b);
auto as_b = NEXPR("b", ident_b);
auto produce = std::make_shared<Produce>(
scan_b, std::vector<query::NamedExpression *>{as_b});

View File

@ -44,7 +44,7 @@ class ExpressionEvaluatorTest : public ::testing::Test {
const TypedValue &value) {
auto id = storage.Create<Identifier>(name, true);
auto symbol = symbol_table.CreateSymbol(name, true);
symbol_table[*id] = symbol;
id->MapTo(symbol);
frame[symbol] = value;
return id;
}
@ -630,7 +630,7 @@ TEST_F(ExpressionEvaluatorTest, LabelsTest) {
v1.add_label(dba->Label("NICE_DOG"));
auto *identifier = storage.Create<Identifier>("n");
auto node_symbol = symbol_table.CreateSymbol("n", true);
symbol_table[*identifier] = node_symbol;
identifier->MapTo(node_symbol);
frame[node_symbol] = v1;
{
auto *op = storage.Create<LabelsTest>(
@ -662,7 +662,7 @@ TEST_F(ExpressionEvaluatorTest, Aggregation) {
auto aggr = storage.Create<Aggregation>(storage.Create<PrimitiveLiteral>(42),
nullptr, Aggregation::Op::COUNT);
auto aggr_sym = symbol_table.CreateSymbol("aggr", true);
symbol_table[*aggr] = aggr_sym;
aggr->MapTo(aggr_sym);
frame[aggr_sym] = TypedValue(1);
auto value = Eval(aggr);
EXPECT_EQ(value.ValueInt(), 1);
@ -699,8 +699,8 @@ TEST_F(ExpressionEvaluatorTest, All) {
auto *all =
ALL("x", LIST(LITERAL(1), LITERAL(2)), WHERE(EQ(ident_x, LITERAL(1))));
const auto x_sym = symbol_table.CreateSymbol("x", true);
symbol_table[*all->identifier_] = x_sym;
symbol_table[*ident_x] = x_sym;
all->identifier_->MapTo(x_sym);
ident_x->MapTo(x_sym);
auto value = Eval(all);
ASSERT_TRUE(value.IsBool());
EXPECT_FALSE(value.ValueBool());
@ -710,7 +710,7 @@ TEST_F(ExpressionEvaluatorTest, FunctionAllNullList) {
AstStorage storage;
auto *all = ALL("x", LITERAL(PropertyValue::Null), WHERE(LITERAL(true)));
const auto x_sym = symbol_table.CreateSymbol("x", true);
symbol_table[*all->identifier_] = x_sym;
all->identifier_->MapTo(x_sym);
auto value = Eval(all);
EXPECT_TRUE(value.IsNull());
}
@ -719,7 +719,7 @@ TEST_F(ExpressionEvaluatorTest, FunctionAllWhereWrongType) {
AstStorage storage;
auto *all = ALL("x", LIST(LITERAL(1)), WHERE(LITERAL(2)));
const auto x_sym = symbol_table.CreateSymbol("x", true);
symbol_table[*all->identifier_] = x_sym;
all->identifier_->MapTo(x_sym);
EXPECT_THROW(Eval(all), QueryRuntimeException);
}
@ -729,8 +729,8 @@ TEST_F(ExpressionEvaluatorTest, FunctionSingle) {
auto *single =
SINGLE("x", LIST(LITERAL(1), LITERAL(2)), WHERE(EQ(ident_x, LITERAL(1))));
const auto x_sym = symbol_table.CreateSymbol("x", true);
symbol_table[*single->identifier_] = x_sym;
symbol_table[*ident_x] = x_sym;
single->identifier_->MapTo(x_sym);
ident_x->MapTo(x_sym);
auto value = Eval(single);
ASSERT_TRUE(value.IsBool());
EXPECT_TRUE(value.ValueBool());
@ -742,8 +742,8 @@ TEST_F(ExpressionEvaluatorTest, FunctionSingle2) {
auto *single = SINGLE("x", LIST(LITERAL(1), LITERAL(2)),
WHERE(GREATER(ident_x, LITERAL(0))));
const auto x_sym = symbol_table.CreateSymbol("x", true);
symbol_table[*single->identifier_] = x_sym;
symbol_table[*ident_x] = x_sym;
single->identifier_->MapTo(x_sym);
ident_x->MapTo(x_sym);
auto value = Eval(single);
ASSERT_TRUE(value.IsBool());
EXPECT_FALSE(value.ValueBool());
@ -754,7 +754,7 @@ TEST_F(ExpressionEvaluatorTest, FunctionSingleNullList) {
auto *single =
SINGLE("x", LITERAL(PropertyValue::Null), WHERE(LITERAL(true)));
const auto x_sym = symbol_table.CreateSymbol("x", true);
symbol_table[*single->identifier_] = x_sym;
single->identifier_->MapTo(x_sym);
auto value = Eval(single);
EXPECT_TRUE(value.IsNull());
}
@ -766,11 +766,11 @@ TEST_F(ExpressionEvaluatorTest, FunctionReduce) {
auto *reduce = REDUCE("sum", LITERAL(0), "x", LIST(LITERAL(1), LITERAL(2)),
ADD(ident_sum, ident_x));
const auto sum_sym = symbol_table.CreateSymbol("sum", true);
symbol_table[*reduce->accumulator_] = sum_sym;
symbol_table[*ident_sum] = sum_sym;
reduce->accumulator_->MapTo(sum_sym);
ident_sum->MapTo(sum_sym);
const auto x_sym = symbol_table.CreateSymbol("x", true);
symbol_table[*reduce->identifier_] = x_sym;
symbol_table[*ident_x] = x_sym;
reduce->identifier_->MapTo(x_sym);
ident_x->MapTo(x_sym);
auto value = Eval(reduce);
ASSERT_TRUE(value.IsInt());
EXPECT_EQ(value.ValueInt(), 3);
@ -783,8 +783,8 @@ TEST_F(ExpressionEvaluatorTest, FunctionExtract) {
EXTRACT("x", LIST(LITERAL(1), LITERAL(2), LITERAL(PropertyValue::Null)),
ADD(ident_x, LITERAL(1)));
const auto x_sym = symbol_table.CreateSymbol("x", true);
symbol_table[*extract->identifier_] = x_sym;
symbol_table[*ident_x] = x_sym;
extract->identifier_->MapTo(x_sym);
ident_x->MapTo(x_sym);
auto value = Eval(extract);
EXPECT_TRUE(value.IsList());
;
@ -800,8 +800,8 @@ TEST_F(ExpressionEvaluatorTest, FunctionExtractNull) {
auto *extract =
EXTRACT("x", LITERAL(PropertyValue::Null), ADD(ident_x, LITERAL(1)));
const auto x_sym = symbol_table.CreateSymbol("x", true);
symbol_table[*extract->identifier_] = x_sym;
symbol_table[*ident_x] = x_sym;
extract->identifier_->MapTo(x_sym);
ident_x->MapTo(x_sym);
auto value = Eval(extract);
EXPECT_TRUE(value.IsNull());
}
@ -811,8 +811,8 @@ TEST_F(ExpressionEvaluatorTest, FunctionExtractExceptions) {
auto *ident_x = IDENT("x");
auto *extract = EXTRACT("x", LITERAL("bla"), ADD(ident_x, LITERAL(1)));
const auto x_sym = symbol_table.CreateSymbol("x", true);
symbol_table[*extract->identifier_] = x_sym;
symbol_table[*ident_x] = x_sym;
extract->identifier_->MapTo(x_sym);
ident_x->MapTo(x_sym);
EXPECT_THROW(Eval(extract), QueryRuntimeException);
}
@ -853,10 +853,10 @@ class ExpressionEvaluatorPropertyLookup : public ExpressionEvaluatorTest {
std::make_pair("age", dba->Property("age"));
std::pair<std::string, storage::Property> prop_height =
std::make_pair("height", dba->Property("height"));
Expression *identifier = storage.Create<Identifier>("element");
Identifier *identifier = storage.Create<Identifier>("element");
Symbol symbol = symbol_table.CreateSymbol("element", true);
void SetUp() { symbol_table[*identifier] = symbol; }
void SetUp() { identifier->MapTo(symbol); }
auto Value(std::pair<std::string, storage::Property> property) {
auto *op = storage.Create<PropertyLookup>(
@ -905,7 +905,7 @@ class FunctionTest : public ExpressionEvaluatorTest {
auto *ident =
storage.Create<Identifier>("arg_" + std::to_string(i), true);
auto sym = symbol_table.CreateSymbol("arg_" + std::to_string(i), true);
symbol_table[*ident] = sym;
ident->MapTo(sym);
frame[sym] = tvs[i];
expressions.push_back(ident);
}

View File

@ -330,9 +330,9 @@ TYPED_TEST(TestPlanner, MatchMultiPatternSameExpandStart) {
// We expect the second pattern to generate only an Expand. Another
// ScanAll would be redundant, as it would generate the nodes obtained from
// expansion. Additionally, a uniqueness filter is expected.
CheckPlan<TypeParam>(
query, storage, ExpectScanAll(), ExpectExpand(), ExpectExpand(),
ExpectEdgeUniquenessFilter(), ExpectProduce());
CheckPlan<TypeParam>(query, storage, ExpectScanAll(), ExpectExpand(),
ExpectExpand(), ExpectEdgeUniquenessFilter(),
ExpectProduce());
}
TYPED_TEST(TestPlanner, MultiMatch) {
@ -456,12 +456,13 @@ TYPED_TEST(TestPlanner, CreateWithSum) {
FakeDbAccessor dba;
auto prop = dba.Property("prop");
AstStorage storage;
auto n_prop = PROPERTY_LOOKUP("n", prop);
auto ident_n = IDENT("n");
auto n_prop = PROPERTY_LOOKUP(ident_n, prop);
auto sum = SUM(n_prop);
auto query =
QUERY(SINGLE_QUERY(CREATE(PATTERN(NODE("n"))), WITH(sum, AS("sum"))));
auto symbol_table = query::MakeSymbolTable(query);
auto acc = ExpectAccumulate({symbol_table.at(*n_prop->expression_)});
auto acc = ExpectAccumulate({symbol_table.at(*ident_n)});
auto aggr = ExpectAggregate({sum}, {});
auto planner = MakePlanner<TypeParam>(&dba, storage, symbol_table, query);
// We expect both the accumulation and aggregation because the part before
@ -522,13 +523,14 @@ TYPED_TEST(TestPlanner, CreateReturnSumSkipLimit) {
FakeDbAccessor dba;
auto prop = dba.Property("prop");
AstStorage storage;
auto n_prop = PROPERTY_LOOKUP("n", prop);
auto ident_n = IDENT("n");
auto n_prop = PROPERTY_LOOKUP(ident_n, prop);
auto sum = SUM(n_prop);
auto query = QUERY(
SINGLE_QUERY(CREATE(PATTERN(NODE("n"))),
RETURN(sum, AS("s"), SKIP(LITERAL(2)), LIMIT(LITERAL(1)))));
auto symbol_table = query::MakeSymbolTable(query);
auto acc = ExpectAccumulate({symbol_table.at(*n_prop->expression_)});
auto acc = ExpectAccumulate({symbol_table.at(*ident_n)});
auto aggr = ExpectAggregate({sum}, {});
auto planner = MakePlanner<TypeParam>(&dba, storage, symbol_table, query);
CheckPlan(planner.plan(), symbol_table, ExpectCreateNode(), acc, aggr,
@ -558,9 +560,11 @@ TYPED_TEST(TestPlanner, CreateWithOrderByWhere) {
auto r_type = "r";
AstStorage storage;
auto ident_n = IDENT("n");
auto ident_r = IDENT("r");
auto ident_m = IDENT("m");
auto new_prop = PROPERTY_LOOKUP("new", prop);
auto r_prop = PROPERTY_LOOKUP("r", prop);
auto m_prop = PROPERTY_LOOKUP("m", prop);
auto r_prop = PROPERTY_LOOKUP(ident_r, prop);
auto m_prop = PROPERTY_LOOKUP(ident_m, prop);
auto query = QUERY(SINGLE_QUERY(
CREATE(
PATTERN(NODE("n"), EDGE("r", Direction::OUT, {r_type}), NODE("m"))),
@ -569,9 +573,9 @@ TYPED_TEST(TestPlanner, CreateWithOrderByWhere) {
auto symbol_table = query::MakeSymbolTable(query);
// Since this is a write query, we expect to accumulate to old used symbols.
auto acc = ExpectAccumulate({
symbol_table.at(*ident_n), // `n` in WITH
symbol_table.at(*r_prop->expression_), // `r` in ORDER BY
symbol_table.at(*m_prop->expression_), // `m` in WHERE
symbol_table.at(*ident_n), // `n` in WITH
symbol_table.at(*ident_r), // `r` in ORDER BY
symbol_table.at(*ident_m), // `m` in WHERE
});
auto planner = MakePlanner<TypeParam>(&dba, storage, symbol_table, query);
CheckPlan(planner.plan(), symbol_table, ExpectCreateNode(),

View File

@ -48,12 +48,10 @@ TEST(QueryPlan, Accumulate) {
EdgeAtom::Direction::BOTH, {}, "m", false, GraphView::OLD);
auto one = LITERAL(1);
auto n_p = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_p->expression_] = n.sym_;
auto n_p = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop);
auto set_n_p =
std::make_shared<plan::SetProperty>(r_m.op_, prop, n_p, ADD(n_p, one));
auto m_p = PROPERTY_LOOKUP("m", prop);
symbol_table[*m_p->expression_] = r_m.node_sym_;
auto m_p = PROPERTY_LOOKUP(IDENT("m")->MapTo(r_m.node_sym_), prop);
auto set_m_p =
std::make_shared<plan::SetProperty>(set_n_p, prop, m_p, ADD(m_p, one));
@ -63,10 +61,10 @@ TEST(QueryPlan, Accumulate) {
last_op, std::vector<Symbol>{n.sym_, r_m.node_sym_});
}
auto n_p_ne = NEXPR("n.p", n_p);
symbol_table[*n_p_ne] = symbol_table.CreateSymbol("n_p_ne", true);
auto m_p_ne = NEXPR("m.p", m_p);
symbol_table[*m_p_ne] = symbol_table.CreateSymbol("m_p_ne", true);
auto n_p_ne =
NEXPR("n.p", n_p)->MapTo(symbol_table.CreateSymbol("n_p_ne", true));
auto m_p_ne =
NEXPR("m.p", m_p)->MapTo(symbol_table.CreateSymbol("m_p_ne", true));
auto produce = MakeProduce(last_op, n_p_ne, m_p_ne);
auto context = MakeContext(storage, symbol_table, &dba);
auto results = CollectProduce(*produce, &context);
@ -119,27 +117,25 @@ std::shared_ptr<Produce> MakeAggregationProduce(
for (auto aggr_op : aggr_ops) {
// TODO change this from using IDENT to using AGGREGATION
// once AGGREGATION is handled properly in ExpressionEvaluation
auto named_expr = NEXPR("", IDENT("aggregation"));
auto aggr_sym = symbol_table.CreateSymbol("aggregation", true);
auto named_expr =
NEXPR("", IDENT("aggregation")->MapTo(aggr_sym))
->MapTo(symbol_table.CreateSymbol("named_expression", true));
named_expressions.push_back(named_expr);
symbol_table[*named_expr->expression_] =
symbol_table.CreateSymbol("aggregation", true);
symbol_table[*named_expr] =
symbol_table.CreateSymbol("named_expression", true);
// the key expression is only used in COLLECT_MAP
Expression *key_expr_ptr =
aggr_op == Aggregation::Op::COLLECT_MAP ? LITERAL("key") : nullptr;
aggregates.emplace_back(
Aggregate::Element{*aggr_inputs_it++, key_expr_ptr, aggr_op,
symbol_table[*named_expr->expression_]});
Aggregate::Element{*aggr_inputs_it++, key_expr_ptr, aggr_op, aggr_sym});
}
// Produce will also evaluate group_by expressions and return them after the
// aggregations.
for (auto group_by_expr : group_by_exprs) {
auto named_expr = NEXPR("", group_by_expr);
auto named_expr =
NEXPR("", group_by_expr)
->MapTo(symbol_table.CreateSymbol("named_expression", true));
named_expressions.push_back(named_expr);
symbol_table[*named_expr] =
symbol_table.CreateSymbol("named_expression", true);
}
auto aggregation =
std::make_shared<Aggregate>(input, aggregates, group_by_exprs, remember);
@ -179,8 +175,7 @@ class QueryPlanAggregateOps : public ::testing::Test {
Aggregation::Op::COLLECT_MAP}) {
// match all nodes and perform aggregations
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_p = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_p->expression_] = n.sym_;
auto n_p = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop);
std::vector<Expression *> aggregation_expressions(ops.size(), n_p);
std::vector<Expression *> group_bys;
@ -326,8 +321,7 @@ TEST(QueryPlan, AggregateGroupByValues) {
// match all nodes and perform aggregations
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_p = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_p->expression_] = n.sym_;
auto n_p = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop);
auto produce =
MakeAggregationProduce(n.op_, symbol_table, storage, {n_p},
@ -371,12 +365,9 @@ TEST(QueryPlan, AggregateMultipleGroupBy) {
// match all nodes and perform aggregations
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_p1 = PROPERTY_LOOKUP("n", prop1);
auto n_p2 = PROPERTY_LOOKUP("n", prop2);
auto n_p3 = PROPERTY_LOOKUP("n", prop3);
symbol_table[*n_p1->expression_] = n.sym_;
symbol_table[*n_p2->expression_] = n.sym_;
symbol_table[*n_p3->expression_] = n.sym_;
auto n_p1 = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop1);
auto n_p2 = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop2);
auto n_p3 = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop3);
auto produce = MakeAggregationProduce(n.op_, symbol_table, storage, {n_p1},
{Aggregation::Op::COUNT},
@ -394,9 +385,6 @@ TEST(QueryPlan, AggregateNoInput) {
SymbolTable symbol_table;
auto two = LITERAL(2);
auto output = NEXPR("two", IDENT("two"));
symbol_table[*output->expression_] = symbol_table.CreateSymbol("two", true);
auto produce = MakeAggregationProduce(nullptr, symbol_table, storage, {two},
{Aggregation::Op::COUNT}, {}, {});
auto context = MakeContext(storage, symbol_table, dba.get());
@ -425,8 +413,7 @@ TEST(QueryPlan, AggregateCountEdgeCases) {
SymbolTable symbol_table;
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_p = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_p->expression_] = n.sym_;
auto n_p = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop);
// returns -1 when there are no results
// otherwise returns MATCH (n) RETURN count(n.prop)
@ -485,10 +472,8 @@ TEST(QueryPlan, AggregateFirstValueTypes) {
SymbolTable symbol_table;
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_prop_string = PROPERTY_LOOKUP("n", prop_string);
symbol_table[*n_prop_string->expression_] = n.sym_;
auto n_prop_int = PROPERTY_LOOKUP("n", prop_int);
symbol_table[*n_prop_int->expression_] = n.sym_;
auto n_prop_string = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop_string);
auto n_prop_int = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop_int);
auto n_id = n_prop_string->expression_;
auto aggregate = [&](Expression *expression, Aggregation::Op aggr_op) {
@ -545,10 +530,8 @@ TEST(QueryPlan, AggregateTypes) {
SymbolTable symbol_table;
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_p1 = PROPERTY_LOOKUP("n", p1);
symbol_table[*n_p1->expression_] = n.sym_;
auto n_p2 = PROPERTY_LOOKUP("n", p2);
symbol_table[*n_p2->expression_] = n.sym_;
auto n_p1 = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), p1);
auto n_p2 = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), p2);
auto aggregate = [&](Expression *expression, Aggregation::Op aggr_op) {
auto produce = MakeAggregationProduce(n.op_, symbol_table, storage,
@ -599,16 +582,14 @@ TEST(QueryPlan, Unwind) {
auto x = symbol_table.CreateSymbol("x", true);
auto unwind_0 = std::make_shared<plan::Unwind>(nullptr, input_expr, x);
auto x_expr = IDENT("x");
symbol_table[*x_expr] = x;
auto x_expr = IDENT("x")->MapTo(x);
auto y = symbol_table.CreateSymbol("y", true);
auto unwind_1 = std::make_shared<plan::Unwind>(unwind_0, x_expr, y);
auto x_ne = NEXPR("x", x_expr);
symbol_table[*x_ne] = symbol_table.CreateSymbol("x_ne", true);
auto y_ne = NEXPR("y", IDENT("y"));
symbol_table[*y_ne->expression_] = y;
symbol_table[*y_ne] = symbol_table.CreateSymbol("y_ne", true);
auto x_ne =
NEXPR("x", x_expr)->MapTo(symbol_table.CreateSymbol("x_ne", true));
auto y_ne = NEXPR("y", IDENT("y")->MapTo(y))
->MapTo(symbol_table.CreateSymbol("y_ne", true));
auto produce = MakeProduce(unwind_1, x_ne, y_ne);
auto context = MakeContext(storage, symbol_table, dba.get());

View File

@ -151,13 +151,12 @@ TEST(QueryPlan, OrderBy) {
// order by and collect results
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_p = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_p->expression_] = n.sym_;
auto n_p = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop);
auto order_by = std::make_shared<plan::OrderBy>(
n.op_, std::vector<SortItem>{{order_value_pair.first, n_p}},
std::vector<Symbol>{n.sym_});
auto n_p_ne = NEXPR("n.p", n_p);
symbol_table[*n_p_ne] = symbol_table.CreateSymbol("n.p", true);
auto n_p_ne =
NEXPR("n.p", n_p)->MapTo(symbol_table.CreateSymbol("n.p", true));
auto produce = MakeProduce(order_by, n_p_ne);
auto context = MakeContext(storage, symbol_table, &dba);
auto results = CollectProduce(*produce, &context);
@ -194,10 +193,8 @@ TEST(QueryPlan, OrderByMultiple) {
// order by and collect results
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_p1 = PROPERTY_LOOKUP("n", p1);
symbol_table[*n_p1->expression_] = n.sym_;
auto n_p2 = PROPERTY_LOOKUP("n", p2);
symbol_table[*n_p2->expression_] = n.sym_;
auto n_p1 = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), p1);
auto n_p2 = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), p2);
// order the results so we get
// (p1: 0, p2: N-1)
// (p1: 0, p2: N-2)
@ -209,10 +206,10 @@ TEST(QueryPlan, OrderByMultiple) {
{Ordering::DESC, n_p2},
},
std::vector<Symbol>{n.sym_});
auto n_p1_ne = NEXPR("n.p1", n_p1);
symbol_table[*n_p1_ne] = symbol_table.CreateSymbol("n.p1", true);
auto n_p2_ne = NEXPR("n.p2", n_p2);
symbol_table[*n_p2_ne] = symbol_table.CreateSymbol("n.p2", true);
auto n_p1_ne =
NEXPR("n.p1", n_p1)->MapTo(symbol_table.CreateSymbol("n.p1", true));
auto n_p2_ne =
NEXPR("n.p2", n_p2)->MapTo(symbol_table.CreateSymbol("n.p2", true));
auto produce = MakeProduce(order_by, n_p1_ne, n_p2_ne);
auto context = MakeContext(storage, symbol_table, &dba);
auto results = CollectProduce(*produce, &context);
@ -261,8 +258,7 @@ TEST(QueryPlan, OrderByExceptions) {
// order by and expect an exception
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_p = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_p->expression_] = n.sym_;
auto n_p = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop);
auto order_by = std::make_shared<plan::OrderBy>(
n.op_, std::vector<SortItem>{{Ordering::ASC, n_p}},
std::vector<Symbol>{});

View File

@ -39,7 +39,7 @@ std::vector<std::vector<TypedValue>> CollectProduce(const Produce &produce,
// collect the symbols from the return clause
std::vector<Symbol> symbols;
for (auto named_expression : produce.named_expressions_)
symbols.emplace_back(context->symbol_table[*named_expression]);
symbols.emplace_back(context->symbol_table.at(*named_expression));
// stream out results
auto cursor = produce.MakeCursor(*context->db_accessor);
@ -86,7 +86,7 @@ ScanAllTuple MakeScanAll(AstStorage &storage, SymbolTable &symbol_table,
GraphView graph_view = GraphView::OLD) {
auto node = NODE(identifier);
auto symbol = symbol_table.CreateSymbol(identifier, true);
symbol_table[*node->identifier_] = symbol;
node->identifier_->MapTo(symbol);
auto logical_op = std::make_shared<ScanAll>(input, symbol, graph_view);
return ScanAllTuple{node, logical_op, symbol};
}
@ -104,7 +104,7 @@ ScanAllTuple MakeScanAllByLabel(
GraphView graph_view = GraphView::OLD) {
auto node = NODE(identifier);
auto symbol = symbol_table.CreateSymbol(identifier, true);
symbol_table[*node->identifier_] = symbol;
node->identifier_->MapTo(symbol);
auto logical_op =
std::make_shared<ScanAllByLabel>(input, symbol, label, graph_view);
return ScanAllTuple{node, logical_op, symbol};
@ -126,7 +126,7 @@ ScanAllTuple MakeScanAllByLabelPropertyRange(
GraphView graph_view = GraphView::OLD) {
auto node = NODE(identifier);
auto symbol = symbol_table.CreateSymbol(identifier, true);
symbol_table[*node->identifier_] = symbol;
node->identifier_->MapTo(symbol);
auto logical_op = std::make_shared<ScanAllByLabelPropertyRange>(
input, symbol, label, property, property_name, lower_bound, upper_bound,
graph_view);
@ -147,7 +147,7 @@ ScanAllTuple MakeScanAllByLabelPropertyValue(
GraphView graph_view = GraphView::OLD) {
auto node = NODE(identifier);
auto symbol = symbol_table.CreateSymbol(identifier, true);
symbol_table[*node->identifier_] = symbol;
node->identifier_->MapTo(symbol);
auto logical_op = std::make_shared<ScanAllByLabelPropertyValue>(
input, symbol, label, property, property_name, value, graph_view);
return ScanAllTuple{node, logical_op, symbol};
@ -170,11 +170,11 @@ ExpandTuple MakeExpand(AstStorage &storage, SymbolTable &symbol_table,
GraphView graph_view) {
auto edge = EDGE(edge_identifier, direction);
auto edge_sym = symbol_table.CreateSymbol(edge_identifier, true);
symbol_table[*edge->identifier_] = edge_sym;
edge->identifier_->MapTo(edge_sym);
auto node = NODE(node_identifier);
auto node_sym = symbol_table.CreateSymbol(node_identifier, true);
symbol_table[*node->identifier_] = node_sym;
node->identifier_->MapTo(node_sym);
auto op = std::make_shared<Expand>(input, input_symbol, node_sym, edge_sym,
direction, edge_types, existing_node,

View File

@ -69,15 +69,13 @@ TEST(QueryPlan, CreateReturn) {
node.properties.emplace_back(property.second, LITERAL(42));
auto create = std::make_shared<CreateNode>(nullptr, node);
auto named_expr_n = NEXPR("n", IDENT("n"));
symbol_table[*named_expr_n] = symbol_table.CreateSymbol("named_expr_n", true);
symbol_table[*named_expr_n->expression_] = node.symbol;
auto prop_lookup = PROPERTY_LOOKUP("n", property);
symbol_table[*prop_lookup->expression_] = node.symbol;
auto named_expr_n_p = NEXPR("n", prop_lookup);
symbol_table[*named_expr_n_p] =
symbol_table.CreateSymbol("named_expr_n_p", true);
symbol_table[*named_expr_n->expression_] = node.symbol;
auto named_expr_n =
NEXPR("n", IDENT("n")->MapTo(node.symbol))
->MapTo(symbol_table.CreateSymbol("named_expr_n", true));
auto prop_lookup = PROPERTY_LOOKUP(IDENT("n")->MapTo(node.symbol), property);
auto named_expr_n_p =
NEXPR("n", prop_lookup)
->MapTo(symbol_table.CreateSymbol("named_expr_n_p", true));
auto produce = MakeProduce(create, named_expr_n, named_expr_n_p);
auto context = MakeContext(storage, symbol_table, &dba);
@ -267,8 +265,7 @@ TEST(QueryPlan, Delete) {
// attempt to delete a vertex, and fail
{
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_get = storage.Create<Identifier>("n");
symbol_table[*n_get] = n.sym_;
auto n_get = storage.Create<Identifier>("n")->MapTo(n.sym_);
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, false);
auto context = MakeContext(storage, symbol_table, dba.get());
@ -281,8 +278,7 @@ TEST(QueryPlan, Delete) {
// detach delete a single vertex
{
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_get = storage.Create<Identifier>("n");
symbol_table[*n_get] = n.sym_;
auto n_get = storage.Create<Identifier>("n")->MapTo(n.sym_);
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, true);
Frame frame(symbol_table.max_position());
@ -299,8 +295,7 @@ TEST(QueryPlan, Delete) {
auto r_m =
MakeExpand(storage, symbol_table, n.op_, n.sym_, "r",
EdgeAtom::Direction::OUT, {}, "m", false, GraphView::NEW);
auto r_get = storage.Create<Identifier>("r");
symbol_table[*r_get] = r_m.edge_sym_;
auto r_get = storage.Create<Identifier>("r")->MapTo(r_m.edge_sym_);
auto delete_op = std::make_shared<plan::Delete>(
r_m.op_, std::vector<Expression *>{r_get}, false);
auto context = MakeContext(storage, symbol_table, dba.get());
@ -313,8 +308,7 @@ TEST(QueryPlan, Delete) {
// delete all remaining vertices
{
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_get = storage.Create<Identifier>("n");
symbol_table[*n_get] = n.sym_;
auto n_get = storage.Create<Identifier>("n")->MapTo(n.sym_);
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, false);
auto context = MakeContext(storage, symbol_table, dba.get());
@ -357,12 +351,9 @@ TEST(QueryPlan, DeleteTwiceDeleteBlockingEdge) {
EdgeAtom::Direction::BOTH, {}, "m", false, GraphView::OLD);
// getter expressions for deletion
auto n_get = storage.Create<Identifier>("n");
symbol_table[*n_get] = n.sym_;
auto r_get = storage.Create<Identifier>("r");
symbol_table[*r_get] = r_m.edge_sym_;
auto m_get = storage.Create<Identifier>("m");
symbol_table[*m_get] = r_m.node_sym_;
auto n_get = storage.Create<Identifier>("n")->MapTo(n.sym_);
auto r_get = storage.Create<Identifier>("r")->MapTo(r_m.edge_sym_);
auto m_get = storage.Create<Identifier>("m")->MapTo(r_m.node_sym_);
auto delete_op = std::make_shared<plan::Delete>(
r_m.op_, std::vector<Expression *>{n_get, r_get, m_get}, detach);
@ -398,15 +389,13 @@ TEST(QueryPlan, DeleteReturn) {
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_get = storage.Create<Identifier>("n");
symbol_table[*n_get] = n.sym_;
auto n_get = storage.Create<Identifier>("n")->MapTo(n.sym_);
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, true);
auto prop_lookup = PROPERTY_LOOKUP("n", prop);
symbol_table[*prop_lookup->expression_] = n.sym_;
auto n_p = storage.Create<NamedExpression>("n", prop_lookup);
symbol_table[*n_p] = symbol_table.CreateSymbol("bla", true);
auto prop_lookup = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop);
auto n_p = storage.Create<NamedExpression>("n", prop_lookup)
->MapTo(symbol_table.CreateSymbol("bla", true));
auto produce = MakeProduce(delete_op, n_p);
auto context = MakeContext(storage, symbol_table, &dba);
@ -449,8 +438,7 @@ TEST(QueryPlan, DeleteAdvance) {
SymbolTable symbol_table;
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_get = storage.Create<Identifier>("n");
symbol_table[*n_get] = n.sym_;
auto n_get = storage.Create<Identifier>("n")->MapTo(n.sym_);
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, false);
auto advance = std::make_shared<Accumulate>(
@ -489,13 +477,11 @@ TEST(QueryPlan, SetProperty) {
auto prop1 = dba.Property("prop1");
auto literal = LITERAL(42);
auto n_p = PROPERTY_LOOKUP("n", prop1);
symbol_table[*n_p->expression_] = n.sym_;
auto n_p = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop1);
auto set_n_p =
std::make_shared<plan::SetProperty>(r_m.op_, prop1, n_p, literal);
auto r_p = PROPERTY_LOOKUP("r", prop1);
symbol_table[*r_p->expression_] = r_m.edge_sym_;
auto r_p = PROPERTY_LOOKUP(IDENT("r")->MapTo(r_m.edge_sym_), prop1);
auto set_r_p =
std::make_shared<plan::SetProperty>(set_n_p, prop1, r_p, literal);
auto context = MakeContext(storage, symbol_table, &dba);
@ -544,10 +530,8 @@ TEST(QueryPlan, SetProperties) {
: plan::SetProperties::Op::REPLACE;
// set properties on r to n, and on r to m
auto r_ident = IDENT("r");
symbol_table[*r_ident] = r_m.edge_sym_;
auto m_ident = IDENT("m");
symbol_table[*m_ident] = r_m.node_sym_;
auto r_ident = IDENT("r")->MapTo(r_m.edge_sym_);
auto m_ident = IDENT("m")->MapTo(r_m.node_sym_);
auto set_r_to_n =
std::make_shared<plan::SetProperties>(r_m.op_, n.sym_, r_ident, op);
auto set_m_to_r = std::make_shared<plan::SetProperties>(
@ -647,12 +631,10 @@ TEST(QueryPlan, RemoveProperty) {
MakeExpand(storage, symbol_table, n.op_, n.sym_, "r",
EdgeAtom::Direction::OUT, {}, "m", false, GraphView::OLD);
auto n_p = PROPERTY_LOOKUP("n", prop1);
symbol_table[*n_p->expression_] = n.sym_;
auto n_p = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop1);
auto set_n_p = std::make_shared<plan::RemoveProperty>(r_m.op_, prop1, n_p);
auto r_p = PROPERTY_LOOKUP("r", prop1);
symbol_table[*r_p->expression_] = r_m.edge_sym_;
auto r_p = PROPERTY_LOOKUP(IDENT("r")->MapTo(r_m.edge_sym_), prop1);
auto set_r_p = std::make_shared<plan::RemoveProperty>(set_n_p, prop1, r_p);
auto context = MakeContext(storage, symbol_table, &dba);
EXPECT_EQ(2, PullAll(*set_r_p, &context));
@ -733,8 +715,7 @@ TEST(QueryPlan, NodeFilterSet) {
LITERAL(42));
auto node_filter = std::make_shared<Filter>(expand.op_, filter_expr);
// SET n.prop = n.prop + 1
auto set_prop = PROPERTY_LOOKUP("n", prop);
symbol_table[*set_prop->expression_] = scan_all.sym_;
auto set_prop = PROPERTY_LOOKUP(IDENT("n")->MapTo(scan_all.sym_), prop);
auto add = ADD(set_prop, LITERAL(1));
auto set = std::make_shared<plan::SetProperty>(node_filter, prop.second,
set_prop, add);
@ -771,13 +752,11 @@ TEST(QueryPlan, FilterRemove) {
auto expand =
MakeExpand(storage, symbol_table, scan_all.op_, scan_all.sym_, "r",
EdgeAtom::Direction::BOTH, {}, "m", false, GraphView::OLD);
auto filter_prop = PROPERTY_LOOKUP("n", prop);
symbol_table[*filter_prop->expression_] = scan_all.sym_;
auto filter_prop = PROPERTY_LOOKUP(IDENT("n")->MapTo(scan_all.sym_), prop);
auto filter =
std::make_shared<Filter>(expand.op_, LESS(filter_prop, LITERAL(43)));
// REMOVE n.prop
auto rem_prop = PROPERTY_LOOKUP("n", prop);
symbol_table[*rem_prop->expression_] = scan_all.sym_;
auto rem_prop = PROPERTY_LOOKUP(IDENT("n")->MapTo(scan_all.sym_), prop);
auto rem =
std::make_shared<plan::RemoveProperty>(filter, prop.second, rem_prop);
auto context = MakeContext(storage, symbol_table, &dba);
@ -838,14 +817,12 @@ TEST(QueryPlan, Merge) {
auto r_m =
MakeExpand(storage, symbol_table, std::make_shared<Once>(), n.sym_, "r",
EdgeAtom::Direction::BOTH, {}, "m", false, GraphView::OLD);
auto m_p = PROPERTY_LOOKUP("m", prop);
symbol_table[*m_p->expression_] = r_m.node_sym_;
auto m_p = PROPERTY_LOOKUP(IDENT("m")->MapTo(r_m.node_sym_), prop);
auto m_set = std::make_shared<plan::SetProperty>(r_m.op_, prop.second, m_p,
LITERAL(1));
// merge_create branch
auto n_p = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_p->expression_] = n.sym_;
auto n_p = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop);
auto n_set = std::make_shared<plan::SetProperty>(
std::make_shared<Once>(), prop.second, n_p, LITERAL(2));
@ -910,8 +887,7 @@ TEST(QueryPlan, SetPropertiesOnNull) {
AstStorage storage;
SymbolTable symbol_table;
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_ident = IDENT("n");
symbol_table[*n_ident] = n.sym_;
auto n_ident = IDENT("n")->MapTo(n.sym_);
auto optional = std::make_shared<plan::Optional>(nullptr, n.op_,
std::vector<Symbol>{n.sym_});
auto set_op = std::make_shared<plan::SetProperties>(
@ -929,8 +905,6 @@ TEST(QueryPlan, SetLabelsOnNull) {
AstStorage storage;
SymbolTable symbol_table;
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_ident = IDENT("n");
symbol_table[*n_ident] = n.sym_;
auto optional = std::make_shared<plan::Optional>(nullptr, n.op_,
std::vector<Symbol>{n.sym_});
auto set_op = std::make_shared<plan::SetLabels>(
@ -965,8 +939,6 @@ TEST(QueryPlan, RemoveLabelsOnNull) {
AstStorage storage;
SymbolTable symbol_table;
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_ident = IDENT("n");
symbol_table[*n_ident] = n.sym_;
auto optional = std::make_shared<plan::Optional>(nullptr, n.op_,
std::vector<Symbol>{n.sym_});
auto remove_op = std::make_shared<plan::RemoveLabels>(
@ -988,13 +960,11 @@ TEST(QueryPlan, DeleteSetProperty) {
SymbolTable symbol_table;
// MATCH (n) DELETE n SET n.property = 42
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_get = storage.Create<Identifier>("n");
symbol_table[*n_get] = n.sym_;
auto n_get = storage.Create<Identifier>("n")->MapTo(n.sym_);
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, false);
auto prop = PROPERTY_PAIR("property");
auto n_prop = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_prop->expression_] = n.sym_;
auto n_prop = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop);
auto set_op = std::make_shared<plan::SetProperty>(delete_op, prop.second,
n_prop, LITERAL(42));
auto context = MakeContext(storage, symbol_table, &dba);
@ -1013,17 +983,13 @@ TEST(QueryPlan, DeleteSetPropertiesFromMap) {
SymbolTable symbol_table;
// MATCH (n) DELETE n SET n = {property: 42}
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_get = storage.Create<Identifier>("n");
symbol_table[*n_get] = n.sym_;
auto n_get = storage.Create<Identifier>("n")->MapTo(n.sym_);
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, false);
auto prop = PROPERTY_PAIR("property");
auto n_prop = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_prop->expression_] = n.sym_;
std::unordered_map<PropertyIx, Expression *> prop_map;
prop_map.emplace(storage.GetPropertyIx(prop.first), LITERAL(42));
auto *rhs = storage.Create<MapLiteral>(prop_map);
symbol_table[*rhs] = n.sym_;
for (auto op_type :
{plan::SetProperties::Op::REPLACE, plan::SetProperties::Op::UPDATE}) {
auto set_op =
@ -1048,15 +1014,10 @@ TEST(QueryPlan, DeleteSetPropertiesFromVertex) {
SymbolTable symbol_table;
// MATCH (n) DELETE n SET n = n
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_get = storage.Create<Identifier>("n");
symbol_table[*n_get] = n.sym_;
auto n_get = storage.Create<Identifier>("n")->MapTo(n.sym_);
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, false);
auto prop = PROPERTY_PAIR("property");
auto n_prop = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_prop->expression_] = n.sym_;
auto *rhs = IDENT("n");
symbol_table[*rhs] = n.sym_;
auto *rhs = IDENT("n")->MapTo(n.sym_);
for (auto op_type :
{plan::SetProperties::Op::REPLACE, plan::SetProperties::Op::UPDATE}) {
auto set_op =
@ -1077,8 +1038,7 @@ TEST(QueryPlan, DeleteRemoveLabels) {
SymbolTable symbol_table;
// MATCH (n) DELETE n REMOVE n :label
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_get = storage.Create<Identifier>("n");
symbol_table[*n_get] = n.sym_;
auto n_get = storage.Create<Identifier>("n")->MapTo(n.sym_);
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, false);
std::vector<storage::Label> labels{dba->Label("label")};
@ -1099,13 +1059,11 @@ TEST(QueryPlan, DeleteRemoveProperty) {
SymbolTable symbol_table;
// MATCH (n) DELETE n REMOVE n.property
auto n = MakeScanAll(storage, symbol_table, "n");
auto n_get = storage.Create<Identifier>("n");
symbol_table[*n_get] = n.sym_;
auto n_get = storage.Create<Identifier>("n")->MapTo(n.sym_);
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, false);
auto prop = PROPERTY_PAIR("property");
auto n_prop = PROPERTY_LOOKUP("n", prop);
symbol_table[*n_prop->expression_] = n.sym_;
auto n_prop = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), prop);
auto rem_op =
std::make_shared<plan::RemoveProperty>(delete_op, prop.second, n_prop);
auto context = MakeContext(storage, symbol_table, &dba);

View File

@ -52,11 +52,10 @@ TEST_F(MatchReturnFixture, MatchReturn) {
auto test_pull_count = [&](GraphView graph_view) {
auto scan_all =
MakeScanAll(storage, symbol_table, "n", nullptr, graph_view);
auto output = NEXPR("n", IDENT("n"));
auto output =
NEXPR("n", IDENT("n")->MapTo(scan_all.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(scan_all.op_, output);
symbol_table[*output->expression_] = scan_all.sym_;
symbol_table[*output] =
symbol_table.CreateSymbol("named_expression_1", true);
auto context = MakeContext(storage, symbol_table, dba_.get());
return PullAll(*produce, &context);
};
@ -78,9 +77,9 @@ TEST_F(MatchReturnFixture, MatchReturnPath) {
Symbol path_sym = symbol_table.CreateSymbol("path", true);
auto make_path = std::make_shared<ConstructNamedPath>(
scan_all.op_, path_sym, std::vector<Symbol>{scan_all.sym_});
auto output = NEXPR("path", IDENT("path"));
symbol_table[*output->expression_] = path_sym;
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
auto output =
NEXPR("path", IDENT("path")->MapTo(path_sym))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(make_path, output);
auto results = Results<query::Path>(produce);
ASSERT_EQ(results.size(), 2);
@ -104,14 +103,12 @@ TEST(QueryPlan, MatchReturnCartesian) {
auto n = MakeScanAll(storage, symbol_table, "n");
auto m = MakeScanAll(storage, symbol_table, "m", n.op_);
auto return_n = NEXPR("n", IDENT("n"));
symbol_table[*return_n->expression_] = n.sym_;
symbol_table[*return_n] =
symbol_table.CreateSymbol("named_expression_1", true);
auto return_m = NEXPR("m", IDENT("m"));
symbol_table[*return_m->expression_] = m.sym_;
symbol_table[*return_m] =
symbol_table.CreateSymbol("named_expression_2", true);
auto return_n =
NEXPR("n", IDENT("n")->MapTo(n.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto return_m =
NEXPR("m", IDENT("m")->MapTo(m.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_2", true));
auto produce = MakeProduce(m.op_, return_n, return_m);
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
@ -138,7 +135,7 @@ TEST(QueryPlan, StandaloneReturn) {
auto output = NEXPR("n", LITERAL(42));
auto produce = MakeProduce(std::shared_ptr<LogicalOperator>(nullptr), output);
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
output->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
@ -189,9 +186,9 @@ TEST(QueryPlan, NodeFilterLabelsAndProperties) {
auto node_filter = std::make_shared<Filter>(n.op_, filter_expr);
// make a named expression and a produce
auto output = NEXPR("x", IDENT("n"));
symbol_table[*output->expression_] = n.sym_;
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
auto output =
NEXPR("x", IDENT("n")->MapTo(n.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(node_filter, output);
auto context = MakeContext(storage, symbol_table, &dba);
@ -244,13 +241,11 @@ TEST(QueryPlan, NodeFilterMultipleLabels) {
auto node_filter = std::make_shared<Filter>(n.op_, filter_expr);
// make a named expression and a produce
auto output = NEXPR("n", IDENT("n"));
auto output =
NEXPR("n", IDENT("n")->MapTo(n.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(node_filter, output);
// fill up the symbol table
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
symbol_table[*output->expression_] = n.sym_;
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
EXPECT_EQ(results.size(), 2);
@ -275,14 +270,12 @@ TEST(QueryPlan, Cartesian) {
auto n = MakeScanAll(storage, symbol_table, "n");
auto m = MakeScanAll(storage, symbol_table, "m");
auto return_n = NEXPR("n", IDENT("n"));
symbol_table[*return_n->expression_] = n.sym_;
symbol_table[*return_n] =
symbol_table.CreateSymbol("named_expression_1", true);
auto return_m = NEXPR("m", IDENT("m"));
symbol_table[*return_m->expression_] = m.sym_;
symbol_table[*return_m] =
symbol_table.CreateSymbol("named_expression_2", true);
auto return_n =
NEXPR("n", IDENT("n")->MapTo(n.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto return_m =
NEXPR("m", IDENT("m")->MapTo(m.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_2", true));
std::vector<Symbol> left_symbols{n.sym_};
std::vector<Symbol> right_symbols{m.sym_};
@ -311,14 +304,12 @@ TEST(QueryPlan, CartesianEmptySet) {
auto n = MakeScanAll(storage, symbol_table, "n");
auto m = MakeScanAll(storage, symbol_table, "m");
auto return_n = NEXPR("n", IDENT("n"));
symbol_table[*return_n->expression_] = n.sym_;
symbol_table[*return_n] =
symbol_table.CreateSymbol("named_expression_1", true);
auto return_m = NEXPR("m", IDENT("m"));
symbol_table[*return_m->expression_] = m.sym_;
symbol_table[*return_m] =
symbol_table.CreateSymbol("named_expression_2", true);
auto return_n =
NEXPR("n", IDENT("n")->MapTo(n.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto return_m =
NEXPR("m", IDENT("m")->MapTo(m.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_2", true));
std::vector<Symbol> left_symbols{n.sym_};
std::vector<Symbol> right_symbols{m.sym_};
@ -350,18 +341,15 @@ TEST(QueryPlan, CartesianThreeWay) {
auto n = MakeScanAll(storage, symbol_table, "n");
auto m = MakeScanAll(storage, symbol_table, "m");
auto l = MakeScanAll(storage, symbol_table, "l");
auto return_n = NEXPR("n", IDENT("n"));
symbol_table[*return_n->expression_] = n.sym_;
symbol_table[*return_n] =
symbol_table.CreateSymbol("named_expression_1", true);
auto return_m = NEXPR("m", IDENT("m"));
symbol_table[*return_m->expression_] = m.sym_;
symbol_table[*return_m] =
symbol_table.CreateSymbol("named_expression_2", true);
auto return_l = NEXPR("l", IDENT("l"));
symbol_table[*return_l->expression_] = l.sym_;
symbol_table[*return_l] =
symbol_table.CreateSymbol("named_expression_3", true);
auto return_n =
NEXPR("n", IDENT("n")->MapTo(n.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto return_m =
NEXPR("m", IDENT("m")->MapTo(m.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_2", true));
auto return_l =
NEXPR("l", IDENT("l")->MapTo(l.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_3", true));
std::vector<Symbol> n_symbols{n.sym_};
std::vector<Symbol> m_symbols{m.sym_};
@ -420,10 +408,9 @@ TEST_F(ExpandFixture, Expand) {
{}, "m", false, graph_view);
// make a named expression and a produce
auto output = NEXPR("m", IDENT("m"));
symbol_table[*output->expression_] = r_m.node_sym_;
symbol_table[*output] =
symbol_table.CreateSymbol("named_expression_1", true);
auto output =
NEXPR("m", IDENT("m")->MapTo(r_m.node_sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(r_m.op_, output);
auto context = MakeContext(storage, symbol_table, dba_.get());
return PullAll(*produce, &context);
@ -456,9 +443,9 @@ TEST_F(ExpandFixture, ExpandPath) {
auto path = std::make_shared<ConstructNamedPath>(
r_m.op_, path_sym,
std::vector<Symbol>{n.sym_, r_m.edge_sym_, r_m.node_sym_});
auto output = NEXPR("m", IDENT("m"));
symbol_table[*output->expression_] = path_sym;
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
auto output =
NEXPR("path", IDENT("path")->MapTo(path_sym))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(path, output);
std::vector<query::Path> expected_paths{{v1, r2, v3}, {v1, r1, v2}};
@ -560,7 +547,7 @@ class QueryPlanExpandVariable : public testing::Test {
auto n_to = NODE(node_to);
auto n_to_sym = symbol_table.CreateSymbol(node_to, true);
symbol_table[*n_to->identifier_] = n_to_sym;
n_to->identifier_->MapTo(n_to_sym);
if (std::is_same<TExpansionOperator, ExpandVariable>::value) {
// convert optional ints to optional expressions
@ -588,7 +575,7 @@ class QueryPlanExpandVariable : public testing::Test {
auto Edge(const std::string &identifier, EdgeAtom::Direction direction) {
auto edge = EDGE(identifier, direction);
auto edge_sym = symbol_table.CreateSymbol(identifier, true);
symbol_table[*edge->identifier_] = edge_sym;
edge->identifier_->MapTo(edge_sym);
return edge_sym;
}
@ -769,8 +756,8 @@ TEST_F(QueryPlanExpandVariable, NamedPath) {
AddMatch<ExpandVariable>(nullptr, "n", 0, EdgeAtom::Direction::OUT, {}, 2,
2, e, "m", GraphView::OLD);
auto find_symbol = [this](const std::string &name) {
for (const auto &pos_sym : symbol_table.table())
if (pos_sym.second.name() == name) return pos_sym.second;
for (const auto &sym : symbol_table.table())
if (sym.name() == name) return sym;
throw std::runtime_error("Symbol not found");
};
@ -884,7 +871,7 @@ class QueryPlanExpandWeightedShortestPath : public testing::Test {
}
auto ident_e = IDENT("e");
symbol_table[*ident_e] = weight_edge;
ident_e->MapTo(weight_edge);
// expand wshortest
auto node_sym = existing_node_input
@ -929,7 +916,7 @@ class QueryPlanExpandWeightedShortestPath : public testing::Test {
Expression *PropNe(Symbol symbol, int value) {
auto ident = IDENT("inner_element");
symbol_table[*ident] = symbol;
ident->MapTo(symbol);
return NEQ(PROPERTY_LOOKUP(ident, prop), LITERAL(value));
}
};
@ -1173,15 +1160,12 @@ TEST(QueryPlan, ExpandOptional) {
n.op_, r_m.op_, std::vector<Symbol>{r_m.edge_sym_, r_m.node_sym_});
// RETURN n, r, m
auto n_ne = NEXPR("n", IDENT("n"));
symbol_table[*n_ne->expression_] = n.sym_;
symbol_table[*n_ne] = symbol_table.CreateSymbol("n", true);
auto r_ne = NEXPR("r", IDENT("r"));
symbol_table[*r_ne->expression_] = r_m.edge_sym_;
symbol_table[*r_ne] = symbol_table.CreateSymbol("r", true);
auto m_ne = NEXPR("m", IDENT("m"));
symbol_table[*m_ne->expression_] = r_m.node_sym_;
symbol_table[*m_ne] = symbol_table.CreateSymbol("m", true);
auto n_ne = NEXPR("n", IDENT("n")->MapTo(n.sym_))
->MapTo(symbol_table.CreateSymbol("n", true));
auto r_ne = NEXPR("r", IDENT("r")->MapTo(r_m.edge_sym_))
->MapTo(symbol_table.CreateSymbol("r", true));
auto m_ne = NEXPR("m", IDENT("m")->MapTo(r_m.node_sym_))
->MapTo(symbol_table.CreateSymbol("m", true));
auto produce = MakeProduce(optional, n_ne, r_ne, m_ne);
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
@ -1214,9 +1198,8 @@ TEST(QueryPlan, OptionalMatchEmptyDB) {
// OPTIONAL MATCH (n)
auto n = MakeScanAll(storage, symbol_table, "n");
// RETURN n
auto n_ne = NEXPR("n", IDENT("n"));
symbol_table[*n_ne->expression_] = n.sym_;
symbol_table[*n_ne] = symbol_table.CreateSymbol("n", true);
auto n_ne = NEXPR("n", IDENT("n")->MapTo(n.sym_))
->MapTo(symbol_table.CreateSymbol("n", true));
auto optional = std::make_shared<plan::Optional>(nullptr, n.op_,
std::vector<Symbol>{n.sym_});
auto produce = MakeProduce(optional, n_ne);
@ -1236,19 +1219,17 @@ TEST(QueryPlan, OptionalMatchEmptyDBExpandFromNode) {
auto optional = std::make_shared<plan::Optional>(nullptr, n.op_,
std::vector<Symbol>{n.sym_});
// WITH n
auto n_ne = NEXPR("n", IDENT("n"));
symbol_table[*n_ne->expression_] = n.sym_;
auto n_ne = NEXPR("n", IDENT("n")->MapTo(n.sym_));
auto with_n_sym = symbol_table.CreateSymbol("n", true);
symbol_table[*n_ne] = with_n_sym;
n_ne->MapTo(with_n_sym);
auto with = MakeProduce(optional, n_ne);
// MATCH (n) -[r]-> (m)
auto r_m =
MakeExpand(storage, symbol_table, with, with_n_sym, "r",
EdgeAtom::Direction::OUT, {}, "m", false, GraphView::OLD);
// RETURN m
auto m_ne = NEXPR("m", IDENT("m"));
symbol_table[*m_ne->expression_] = r_m.node_sym_;
symbol_table[*m_ne] = symbol_table.CreateSymbol("m", true);
auto m_ne = NEXPR("m", IDENT("m")->MapTo(r_m.node_sym_))
->MapTo(symbol_table.CreateSymbol("m", true));
auto produce = MakeProduce(r_m.op_, m_ne);
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
@ -1279,26 +1260,24 @@ TEST(QueryPlan, OptionalMatchThenExpandToMissingNode) {
auto optional = std::make_shared<plan::Optional>(nullptr, node_filter,
std::vector<Symbol>{n.sym_});
// WITH n
auto n_ne = NEXPR("n", IDENT("n"));
symbol_table[*n_ne->expression_] = n.sym_;
auto n_ne = NEXPR("n", IDENT("n")->MapTo(n.sym_));
auto with_n_sym = symbol_table.CreateSymbol("n", true);
symbol_table[*n_ne] = with_n_sym;
n_ne->MapTo(with_n_sym);
auto with = MakeProduce(optional, n_ne);
// MATCH (m) -[r]-> (n)
auto m = MakeScanAll(storage, symbol_table, "m", with);
auto edge_direction = EdgeAtom::Direction::OUT;
auto edge = EDGE("r", edge_direction);
auto edge_sym = symbol_table.CreateSymbol("r", true);
symbol_table[*edge->identifier_] = edge_sym;
edge->identifier_->MapTo(edge_sym);
auto node = NODE("n");
symbol_table[*node->identifier_] = with_n_sym;
node->identifier_->MapTo(with_n_sym);
auto expand = std::make_shared<plan::Expand>(
m.op_, m.sym_, with_n_sym, edge_sym, edge_direction,
std::vector<storage::EdgeType>{}, true, GraphView::OLD);
// RETURN m
auto m_ne = NEXPR("m", IDENT("m"));
symbol_table[*m_ne->expression_] = m.sym_;
symbol_table[*m_ne] = symbol_table.CreateSymbol("m", true);
auto m_ne = NEXPR("m", IDENT("m")->MapTo(m.sym_))
->MapTo(symbol_table.CreateSymbol("m", true));
auto produce = MakeProduce(expand, m_ne);
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
@ -1332,10 +1311,9 @@ TEST(QueryPlan, ExpandExistingNode) {
std::vector<storage::EdgeType>{}, with_existing, GraphView::OLD);
// make a named expression and a produce
auto output = NEXPR("n", IDENT("n"));
symbol_table[*output->expression_] = n.sym_;
symbol_table[*output] =
symbol_table.CreateSymbol("named_expression_1", true);
auto output =
NEXPR("n", IDENT("n")->MapTo(n.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(r_n.op_, output);
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
@ -1421,10 +1399,9 @@ TEST(QueryPlan, EdgeFilter) {
auto edge_filter = std::make_shared<Filter>(r_m.op_, filter_expr);
// make a named expression and a produce
auto output = NEXPR("m", IDENT("m"));
symbol_table[*output->expression_] = r_m.node_sym_;
symbol_table[*output] =
symbol_table.CreateSymbol("named_expression_1", true);
auto output =
NEXPR("m", IDENT("m")->MapTo(r_m.node_sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(edge_filter, output);
auto context = MakeContext(storage, symbol_table, &dba);
return PullAll(*produce, &context);
@ -1462,12 +1439,10 @@ TEST(QueryPlan, EdgeFilterMultipleTypes) {
GraphView::OLD);
// make a named expression and a produce
auto output = NEXPR("m", IDENT("m"));
auto output =
NEXPR("m", IDENT("m")->MapTo(r_m.node_sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(r_m.op_, output);
// fill up the symbol table
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
symbol_table[*output->expression_] = r_m.node_sym_;
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
EXPECT_EQ(results.size(), 2);
@ -1489,14 +1464,12 @@ TEST(QueryPlan, Filter) {
SymbolTable symbol_table;
auto n = MakeScanAll(storage, symbol_table, "n");
auto e = PROPERTY_LOOKUP("n", property);
symbol_table[*e->expression_] = n.sym_;
auto e = PROPERTY_LOOKUP(IDENT("n")->MapTo(n.sym_), property);
auto f = std::make_shared<Filter>(n.op_, e);
auto output =
storage.Create<NamedExpression>("x", storage.Create<Identifier>("n"));
symbol_table[*output->expression_] = n.sym_;
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
NEXPR("x", IDENT("n")->MapTo(n.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(f, output);
auto context = MakeContext(storage, symbol_table, &dba);
EXPECT_EQ(CollectProduce(*produce, &context).size(), 2);
@ -1555,13 +1528,13 @@ TEST(QueryPlan, Distinct) {
auto x = symbol_table.CreateSymbol("x", true);
auto unwind = std::make_shared<plan::Unwind>(nullptr, input_expr, x);
auto x_expr = IDENT("x");
symbol_table[*x_expr] = x;
x_expr->MapTo(x);
auto distinct =
std::make_shared<plan::Distinct>(unwind, std::vector<Symbol>{x});
auto x_ne = NEXPR("x", x_expr);
symbol_table[*x_ne] = symbol_table.CreateSymbol("x_ne", true);
x_ne->MapTo(symbol_table.CreateSymbol("x_ne", true));
auto produce = MakeProduce(distinct, x_ne);
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
@ -1599,10 +1572,9 @@ TEST(QueryPlan, ScanAllByLabel) {
auto scan_all_by_label =
MakeScanAllByLabel(storage, symbol_table, "n", label);
// RETURN n
auto output = NEXPR("n", IDENT("n"));
auto output = NEXPR("n", IDENT("n")->MapTo(scan_all_by_label.sym_))
->MapTo(symbol_table.CreateSymbol("n", true));
auto produce = MakeProduce(scan_all_by_label.op_, output);
symbol_table[*output->expression_] = scan_all_by_label.sym_;
symbol_table[*output] = symbol_table.CreateSymbol("n", true);
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
ASSERT_EQ(results.size(), 1);
@ -1645,10 +1617,9 @@ TEST(QueryPlan, ScanAllByLabelProperty) {
storage, symbol_table, "n", label, prop, "prop",
Bound{LITERAL(lower), lower_type}, Bound{LITERAL(upper), upper_type});
// RETURN n
auto output = NEXPR("n", IDENT("n"));
auto output = NEXPR("n", IDENT("n")->MapTo(scan_all.sym_))
->MapTo(symbol_table.CreateSymbol("n", true));
auto produce = MakeProduce(scan_all.op_, output);
symbol_table[*output->expression_] = scan_all.sym_;
symbol_table[*output] = symbol_table.CreateSymbol("n", true);
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
ASSERT_EQ(results.size(), expected.size());
@ -1707,10 +1678,9 @@ TEST(QueryPlan, ScanAllByLabelPropertyEqualityNoError) {
auto scan_all = MakeScanAllByLabelPropertyValue(
storage, symbol_table, "n", label, prop, "prop", LITERAL(42));
// RETURN n
auto output = NEXPR("n", IDENT("n"));
auto output = NEXPR("n", IDENT("n")->MapTo(scan_all.sym_))
->MapTo(symbol_table.CreateSymbol("n", true));
auto produce = MakeProduce(scan_all.op_, output);
symbol_table[*output->expression_] = scan_all.sym_;
symbol_table[*output] = symbol_table.CreateSymbol("n", true);
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
ASSERT_EQ(results.size(), 1);
@ -1743,7 +1713,7 @@ TEST(QueryPlan, ScanAllByLabelPropertyValueError) {
SymbolTable symbol_table;
auto scan_all = MakeScanAll(storage, symbol_table, "m");
auto *ident_m = IDENT("m");
symbol_table[*ident_m] = scan_all.sym_;
ident_m->MapTo(scan_all.sym_);
auto scan_index = MakeScanAllByLabelPropertyValue(
storage, symbol_table, "n", label, prop, "prop", ident_m, scan_all.op_);
auto context = MakeContext(storage, symbol_table, dba.get());
@ -1771,7 +1741,7 @@ TEST(QueryPlan, ScanAllByLabelPropertyRangeError) {
SymbolTable symbol_table;
auto scan_all = MakeScanAll(storage, symbol_table, "m");
auto *ident_m = IDENT("m");
symbol_table[*ident_m] = scan_all.sym_;
ident_m->MapTo(scan_all.sym_);
{
// Lower bound isn't property value
auto scan_index = MakeScanAllByLabelPropertyRange(
@ -1827,10 +1797,9 @@ TEST(QueryPlan, ScanAllByLabelPropertyEqualNull) {
MakeScanAllByLabelPropertyValue(storage, symbol_table, "n", label, prop,
"prop", LITERAL(TypedValue::Null));
// RETURN n
auto output = NEXPR("n", IDENT("n"));
auto output = NEXPR("n", IDENT("n")->MapTo(scan_all.sym_))
->MapTo(symbol_table.CreateSymbol("n", true));
auto produce = MakeProduce(scan_all.op_, output);
symbol_table[*output->expression_] = scan_all.sym_;
symbol_table[*output] = symbol_table.CreateSymbol("n", true);
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
EXPECT_EQ(results.size(), 0);
@ -1863,10 +1832,9 @@ TEST(QueryPlan, ScanAllByLabelPropertyRangeNull) {
Bound{LITERAL(TypedValue::Null), Bound::Type::INCLUSIVE},
Bound{LITERAL(TypedValue::Null), Bound::Type::EXCLUSIVE});
// RETURN n
auto output = NEXPR("n", IDENT("n"));
auto output = NEXPR("n", IDENT("n")->MapTo(scan_all.sym_))
->MapTo(symbol_table.CreateSymbol("n", true));
auto produce = MakeProduce(scan_all.op_, output);
symbol_table[*output->expression_] = scan_all.sym_;
symbol_table[*output] = symbol_table.CreateSymbol("n", true);
auto context = MakeContext(storage, symbol_table, dba.get());
auto results = CollectProduce(*produce, &context);
EXPECT_EQ(results.size(), 0);
@ -1895,7 +1863,7 @@ TEST(QueryPlan, ScanAllByLabelPropertyNoValueInIndexContinuation) {
auto x = symbol_table.CreateSymbol("x", true);
auto unwind = std::make_shared<plan::Unwind>(nullptr, input_expr, x);
auto x_expr = IDENT("x");
symbol_table[*x_expr] = x;
x_expr->MapTo(x);
// MATCH (n :label {prop: x})
auto scan_all = MakeScanAllByLabelPropertyValue(
@ -1937,11 +1905,10 @@ TEST(QueryPlan, ScanAllEqualsScanAllByLabelProperty) {
auto dba = db.Access();
auto scan_all_by_label_property_value = MakeScanAllByLabelPropertyValue(
storage, symbol_table, "n", label, prop, "prop", LITERAL(prop_value));
auto output = NEXPR("n", IDENT("n"));
auto output =
NEXPR("n", IDENT("n")->MapTo(scan_all_by_label_property_value.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(scan_all_by_label_property_value.op_, output);
symbol_table[*output->expression_] = scan_all_by_label_property_value.sym_;
symbol_table[*output] =
symbol_table.CreateSymbol("named_expression_1", true);
auto context = MakeContext(storage, symbol_table, dba.get());
EXPECT_EQ(PullAll(*produce, &context), prop_count);
};
@ -1953,15 +1920,14 @@ TEST(QueryPlan, ScanAllEqualsScanAllByLabelProperty) {
auto dba_ptr = db.Access();
auto &dba = *dba_ptr;
auto scan_all = MakeScanAll(storage, symbol_table, "n");
auto e = PROPERTY_LOOKUP("n", std::make_pair("prop", prop));
symbol_table[*e->expression_] = scan_all.sym_;
auto e = PROPERTY_LOOKUP(IDENT("n")->MapTo(scan_all.sym_),
std::make_pair("prop", prop));
auto filter =
std::make_shared<Filter>(scan_all.op_, EQ(e, LITERAL(prop_value)));
auto output = NEXPR("n", IDENT("n"));
auto output =
NEXPR("n", IDENT("n")->MapTo(scan_all.sym_))
->MapTo(symbol_table.CreateSymbol("named_expression_1", true));
auto produce = MakeProduce(filter, output);
symbol_table[*output->expression_] = scan_all.sym_;
symbol_table[*output] =
symbol_table.CreateSymbol("named_expression_1", true);
auto context = MakeContext(storage, symbol_table, &dba);
EXPECT_EQ(PullAll(*produce, &context), prop_count);
};

View File

@ -30,19 +30,20 @@ TEST_F(TestSymbolGenerator, MatchNodeReturn) {
EXPECT_EQ(symbol_table.max_position(), 3);
auto match = dynamic_cast<Match *>(query_ast->single_query_->clauses_[0]);
auto pattern = match->patterns_[0];
auto pattern_sym = symbol_table[*pattern->identifier_];
auto pattern_sym = symbol_table.at(*pattern->identifier_);
EXPECT_EQ(pattern_sym.type(), Symbol::Type::PATH);
EXPECT_FALSE(pattern_sym.user_declared());
auto node_atom = dynamic_cast<NodeAtom *>(pattern->atoms_[0]);
auto node_sym = symbol_table[*node_atom->identifier_];
auto node_sym = symbol_table.at(*node_atom->identifier_);
EXPECT_EQ(node_sym.name(), "node_atom_1");
EXPECT_EQ(node_sym.type(), Symbol::Type::VERTEX);
auto ret = dynamic_cast<Return *>(query_ast->single_query_->clauses_[1]);
auto named_expr = ret->body_.named_expressions[0];
auto column_sym = symbol_table[*named_expr];
auto column_sym = symbol_table.at(*named_expr);
EXPECT_EQ(node_sym.name(), column_sym.name());
EXPECT_NE(node_sym, column_sym);
auto ret_sym = symbol_table[*named_expr->expression_];
auto ret_sym =
symbol_table.at(*dynamic_cast<Identifier *>(named_expr->expression_));
EXPECT_EQ(node_sym, ret_sym);
}
@ -55,7 +56,7 @@ TEST_F(TestSymbolGenerator, MatchNamedPattern) {
EXPECT_EQ(symbol_table.max_position(), 3);
auto match = dynamic_cast<Match *>(query_ast->single_query_->clauses_[0]);
auto pattern = match->patterns_[0];
auto pattern_sym = symbol_table[*pattern->identifier_];
auto pattern_sym = symbol_table.at(*pattern->identifier_);
EXPECT_EQ(pattern_sym.type(), Symbol::Type::PATH);
EXPECT_EQ(pattern_sym.name(), "p");
EXPECT_TRUE(pattern_sym.user_declared());
@ -93,15 +94,16 @@ TEST_F(TestSymbolGenerator, CreateNodeReturn) {
auto create = dynamic_cast<Create *>(query_ast->single_query_->clauses_[0]);
auto pattern = create->patterns_[0];
auto node_atom = dynamic_cast<NodeAtom *>(pattern->atoms_[0]);
auto node_sym = symbol_table[*node_atom->identifier_];
auto node_sym = symbol_table.at(*node_atom->identifier_);
EXPECT_EQ(node_sym.name(), "n");
EXPECT_EQ(node_sym.type(), Symbol::Type::VERTEX);
auto ret = dynamic_cast<Return *>(query_ast->single_query_->clauses_[1]);
auto named_expr = ret->body_.named_expressions[0];
auto column_sym = symbol_table[*named_expr];
auto column_sym = symbol_table.at(*named_expr);
EXPECT_EQ(node_sym.name(), column_sym.name());
EXPECT_NE(node_sym, column_sym);
auto ret_sym = symbol_table[*named_expr->expression_];
auto ret_sym =
symbol_table.at(*dynamic_cast<Identifier *>(named_expr->expression_));
EXPECT_EQ(node_sym, ret_sym);
}
@ -255,7 +257,7 @@ TEST_F(TestSymbolGenerator, MatchWithWhere) {
EXPECT_EQ(node_symbol, old);
auto with_n = symbol_table.at(*with_as_n);
EXPECT_NE(old, with_n);
auto n = symbol_table.at(*n_prop->expression_);
auto n = symbol_table.at(*dynamic_cast<Identifier *>(n_prop->expression_));
EXPECT_EQ(n, with_n);
}
@ -372,7 +374,8 @@ TEST_F(TestSymbolGenerator, MatchPropCreateNodeProp) {
// symbols: pattern * 2, `node_n`, `node_m`
EXPECT_EQ(symbol_table.max_position(), 4);
auto n = symbol_table.at(*node_n->identifier_);
EXPECT_EQ(n, symbol_table.at(*n_prop->expression_));
EXPECT_EQ(n,
symbol_table.at(*dynamic_cast<Identifier *>(n_prop->expression_)));
auto m = symbol_table.at(*node_m->identifier_);
EXPECT_NE(n, m);
}
@ -551,7 +554,8 @@ TEST_F(TestSymbolGenerator, MergeOnMatchOnCreate) {
EXPECT_EQ(symbol_table.max_position(), 6);
auto n = symbol_table.at(*match_n->identifier_);
EXPECT_EQ(n, symbol_table.at(*merge_n->identifier_));
EXPECT_EQ(n, symbol_table.at(*n_prop->expression_));
EXPECT_EQ(n,
symbol_table.at(*dynamic_cast<Identifier *>(n_prop->expression_)));
auto r = symbol_table.at(*edge_r->identifier_);
EXPECT_NE(r, n);
EXPECT_EQ(r, symbol_table.at(*ident_r));
@ -560,7 +564,8 @@ TEST_F(TestSymbolGenerator, MergeOnMatchOnCreate) {
EXPECT_NE(m, n);
EXPECT_NE(m, r);
EXPECT_NE(m, symbol_table.at(*as_r));
EXPECT_EQ(m, symbol_table.at(*m_prop->expression_));
EXPECT_EQ(m,
symbol_table.at(*dynamic_cast<Identifier *>(m_prop->expression_)));
}
TEST_F(TestSymbolGenerator, WithUnwindRedeclareReturn) {
@ -586,7 +591,8 @@ TEST_F(TestSymbolGenerator, WithUnwindReturn) {
// Symbols for: `list`, `elem`, `AS list`, `AS elem`
EXPECT_EQ(symbol_table.max_position(), 4);
const auto &list = symbol_table.at(*with_as_list);
EXPECT_EQ(list, symbol_table.at(*unwind->named_expression_->expression_));
EXPECT_EQ(list, symbol_table.at(*dynamic_cast<Identifier *>(
unwind->named_expression_->expression_)));
const auto &elem = symbol_table.at(*unwind->named_expression_);
EXPECT_NE(list, elem);
EXPECT_EQ(list, symbol_table.at(*ret_list));
@ -612,11 +618,13 @@ TEST_F(TestSymbolGenerator, MatchCrossReferenceVariable) {
// Symbols for pattern * 2, `n`, `m` and `AS n`
EXPECT_EQ(symbol_table.max_position(), 5);
auto n = symbol_table.at(*node_n->identifier_);
EXPECT_EQ(n, symbol_table.at(*n_prop->expression_));
EXPECT_EQ(n,
symbol_table.at(*dynamic_cast<Identifier *>(n_prop->expression_)));
EXPECT_EQ(n, symbol_table.at(*ident_n));
EXPECT_NE(n, symbol_table.at(*as_n));
auto m = symbol_table.at(*node_m->identifier_);
EXPECT_EQ(m, symbol_table.at(*m_prop->expression_));
EXPECT_EQ(m,
symbol_table.at(*dynamic_cast<Identifier *>(m_prop->expression_)));
EXPECT_NE(n, m);
EXPECT_NE(m, symbol_table.at(*as_n));
}
@ -638,7 +646,8 @@ TEST_F(TestSymbolGenerator, MatchWithAsteriskReturnAsterisk) {
// Symbols for pattern, `n`, `e`, `m`, `AS n.prop`.
EXPECT_EQ(symbol_table.max_position(), 5);
auto n = symbol_table.at(*node_n->identifier_);
EXPECT_EQ(n, symbol_table.at(*n_prop->expression_));
EXPECT_EQ(n,
symbol_table.at(*dynamic_cast<Identifier *>(n_prop->expression_)));
}
TEST_F(TestSymbolGenerator, MatchReturnAsteriskSameResult) {
@ -683,7 +692,8 @@ TEST_F(TestSymbolGenerator, MatchEdgeWithIdentifierInProperty) {
// Symbols for pattern, `n`, `r`, `m` and implicit in RETURN `r AS r`
EXPECT_EQ(symbol_table.max_position(), 5);
auto n = symbol_table.at(*node_n->identifier_);
EXPECT_EQ(n, symbol_table.at(*n_prop->expression_));
EXPECT_EQ(n,
symbol_table.at(*dynamic_cast<Identifier *>(n_prop->expression_)));
}
TEST_F(TestSymbolGenerator, MatchVariablePathUsingIdentifier) {
@ -701,7 +711,8 @@ TEST_F(TestSymbolGenerator, MatchVariablePathUsingIdentifier) {
// implicit in RETURN `r AS r`
EXPECT_EQ(symbol_table.max_position(), 9);
auto l = symbol_table.at(*node_l->identifier_);
EXPECT_EQ(l, symbol_table.at(*l_prop->expression_));
EXPECT_EQ(l,
symbol_table.at(*dynamic_cast<Identifier *>(l_prop->expression_)));
auto r = symbol_table.at(*edge->identifier_);
EXPECT_EQ(r.type(), Symbol::Type::EDGE_LIST);
}
@ -772,7 +783,8 @@ TEST_F(TestSymbolGenerator, MatchPropertySameIdentifier) {
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node_n)), RETURN("n")));
auto symbol_table = query::MakeSymbolTable(query);
auto n = symbol_table.at(*node_n->identifier_);
EXPECT_EQ(n, symbol_table.at(*n_prop->expression_));
EXPECT_EQ(n,
symbol_table.at(*dynamic_cast<Identifier *>(n_prop->expression_)));
}
TEST_F(TestSymbolGenerator, WithReturnAll) {
@ -901,12 +913,12 @@ TEST_F(TestSymbolGenerator, MatchBfsReturn) {
symbol_table.at(*bfs->filter_lambda_.inner_edge));
EXPECT_TRUE(symbol_table.at(*bfs->filter_lambda_.inner_edge).user_declared());
EXPECT_EQ(symbol_table.at(*bfs->filter_lambda_.inner_edge),
symbol_table.at(*r_prop->expression_));
symbol_table.at(*dynamic_cast<Identifier *>(r_prop->expression_)));
EXPECT_NE(symbol_table.at(*node_n->identifier_),
symbol_table.at(*bfs->filter_lambda_.inner_node));
EXPECT_TRUE(symbol_table.at(*bfs->filter_lambda_.inner_node).user_declared());
EXPECT_EQ(symbol_table.at(*node_n->identifier_),
symbol_table.at(*n_prop->expression_));
symbol_table.at(*dynamic_cast<Identifier *>(n_prop->expression_)));
}
TEST_F(TestSymbolGenerator, MatchBfsUsesEdgeSymbolError) {
@ -935,7 +947,8 @@ TEST_F(TestSymbolGenerator, MatchBfsUsesPreviousOuterSymbol) {
QUERY(SINGLE_QUERY(MATCH(PATTERN(node_a, bfs, NODE("m"))), RETURN("r")));
auto symbol_table = query::MakeSymbolTable(query);
EXPECT_EQ(symbol_table.at(*node_a->identifier_),
symbol_table.at(*bfs->filter_lambda_.expression));
symbol_table.at(
*dynamic_cast<Identifier *>(bfs->filter_lambda_.expression)));
}
TEST_F(TestSymbolGenerator, MatchBfsUsesLaterSymbolError) {
@ -971,12 +984,11 @@ TEST_F(TestSymbolGenerator, MatchVariableLambdaSymbols) {
// `AS res` and the auto-generated path name symbol.
EXPECT_EQ(symbol_table.max_position(), 7);
// All symbols except `AS res` are anonymously generated.
for (const auto &id_and_symbol : symbol_table.table()) {
const auto &symbol = id_and_symbol.second;
for (const auto &symbol : symbol_table.table()) {
if (symbol.name() == "res") {
EXPECT_TRUE(symbol.user_declared());
} else {
EXPECT_FALSE(id_and_symbol.second.user_declared());
EXPECT_FALSE(symbol.user_declared());
}
}
}
@ -1017,14 +1029,16 @@ TEST_F(TestSymbolGenerator, MatchWShortestReturn) {
symbol_table.at(*shortest->filter_lambda_.inner_edge));
EXPECT_TRUE(
symbol_table.at(*shortest->filter_lambda_.inner_edge).user_declared());
EXPECT_EQ(symbol_table.at(*shortest->weight_lambda_.inner_edge),
symbol_table.at(*r_weight->expression_));
EXPECT_EQ(
symbol_table.at(*shortest->weight_lambda_.inner_edge),
symbol_table.at(*dynamic_cast<Identifier *>(r_weight->expression_)));
EXPECT_NE(symbol_table.at(*shortest->weight_lambda_.inner_edge),
symbol_table.at(*shortest->filter_lambda_.inner_edge));
EXPECT_NE(symbol_table.at(*shortest->weight_lambda_.inner_node),
symbol_table.at(*shortest->filter_lambda_.inner_node));
EXPECT_EQ(symbol_table.at(*shortest->filter_lambda_.inner_edge),
symbol_table.at(*r_filter->expression_));
EXPECT_EQ(
symbol_table.at(*shortest->filter_lambda_.inner_edge),
symbol_table.at(*dynamic_cast<Identifier *>(r_filter->expression_)));
EXPECT_TRUE(
symbol_table.at(*shortest->filter_lambda_.inner_node).user_declared());
}