memgraph/src/query/frontend/ast/ast.hpp
2024-03-01 14:38:18 +01:00

3729 lines
119 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2024 Memgraph Ltd.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
// License, and you may not use this file except in compliance with the Business Source License.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
#pragma once
#include <memory>
#include <unordered_map>
#include <variant>
#include <vector>
#include "query/frontend/ast/ast_visitor.hpp"
#include "query/frontend/semantic/symbol.hpp"
#include "query/interpret/awesome_memgraph_functions.hpp"
#include "query/typed_value.hpp"
#include "storage/v2/property_value.hpp"
#include "utils/typeinfo.hpp"
namespace memgraph::query {
struct LabelIx {
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const { return kType; }
std::string name;
int64_t ix;
};
struct PropertyIx {
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const { return kType; }
std::string name;
int64_t ix;
};
struct EdgeTypeIx {
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const { return kType; }
std::string name;
int64_t ix;
};
inline bool operator==(const LabelIx &a, const LabelIx &b) { return a.ix == b.ix && a.name == b.name; }
inline bool operator!=(const LabelIx &a, const LabelIx &b) { return !(a == b); }
inline bool operator==(const PropertyIx &a, const PropertyIx &b) { return a.ix == b.ix && a.name == b.name; }
inline bool operator!=(const PropertyIx &a, const PropertyIx &b) { return !(a == b); }
inline bool operator==(const EdgeTypeIx &a, const EdgeTypeIx &b) { return a.ix == b.ix && a.name == b.name; }
inline bool operator!=(const EdgeTypeIx &a, const EdgeTypeIx &b) { return !(a == b); }
} // namespace memgraph::query
namespace std {
template <>
struct hash<memgraph::query::LabelIx> {
size_t operator()(const memgraph::query::LabelIx &label) const { return label.ix; }
};
template <>
struct hash<memgraph::query::PropertyIx> {
size_t operator()(const memgraph::query::PropertyIx &prop) const { return prop.ix; }
};
template <>
struct hash<memgraph::query::EdgeTypeIx> {
size_t operator()(const memgraph::query::EdgeTypeIx &edge_type) const { return edge_type.ix; }
};
} // namespace std
namespace memgraph::query {
class Tree;
// It would be better to call this AstTree, but we already have a class Tree,
// which could be renamed to Node or AstTreeNode, but we also have a class
// called NodeAtom...
class AstStorage {
public:
AstStorage() = default;
AstStorage(const AstStorage &) = delete;
AstStorage &operator=(const AstStorage &) = delete;
AstStorage(AstStorage &&) = default;
AstStorage &operator=(AstStorage &&) = default;
template <typename T, typename... Args>
T *Create(Args &&...args) {
T *ptr = new T(std::forward<Args>(args)...);
std::unique_ptr<T> tmp(ptr);
storage_.emplace_back(std::move(tmp));
return ptr;
}
LabelIx GetLabelIx(const std::string &name) { return LabelIx{name, FindOrAddName(name, &labels_)}; }
PropertyIx GetPropertyIx(const std::string &name) { return PropertyIx{name, FindOrAddName(name, &properties_)}; }
EdgeTypeIx GetEdgeTypeIx(const std::string &name) { return EdgeTypeIx{name, FindOrAddName(name, &edge_types_)}; }
std::vector<std::string> labels_;
std::vector<std::string> edge_types_;
std::vector<std::string> properties_;
// Public only for serialization access
std::vector<std::unique_ptr<Tree>> storage_;
private:
int64_t FindOrAddName(const std::string &name, std::vector<std::string> *names) {
for (int64_t i = 0; i < names->size(); ++i) {
if ((*names)[i] == name) {
return i;
}
}
names->push_back(name);
return names->size() - 1;
}
};
class Tree {
public:
static const utils::TypeInfo kType;
virtual const utils::TypeInfo &GetTypeInfo() const { return kType; }
Tree() = default;
virtual ~Tree() {}
virtual Tree *Clone(AstStorage *storage) const = 0;
private:
friend class AstStorage;
};
class Expression : public memgraph::query::Tree,
public utils::Visitable<HierarchicalTreeVisitor>,
public utils::Visitable<ExpressionVisitor<TypedValue>>,
public utils::Visitable<ExpressionVisitor<TypedValue *>>,
public utils::Visitable<ExpressionVisitor<void>> {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
using utils::Visitable<HierarchicalTreeVisitor>::Accept;
using utils::Visitable<ExpressionVisitor<TypedValue>>::Accept;
using utils::Visitable<ExpressionVisitor<TypedValue *>>::Accept;
using utils::Visitable<ExpressionVisitor<void>>::Accept;
Expression() = default;
Expression *Clone(AstStorage *storage) const override = 0;
private:
friend class AstStorage;
};
class Where : public memgraph::query::Tree, public utils::Visitable<HierarchicalTreeVisitor> {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
using utils::Visitable<HierarchicalTreeVisitor>::Accept;
Where() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Expression *expression_{nullptr};
Where *Clone(AstStorage *storage) const override {
Where *object = storage->Create<Where>();
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
return object;
}
protected:
explicit Where(Expression *expression) : expression_(expression) {}
private:
friend class AstStorage;
};
class BinaryOperator : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
BinaryOperator() = default;
memgraph::query::Expression *expression1_{nullptr};
memgraph::query::Expression *expression2_{nullptr};
BinaryOperator *Clone(AstStorage *storage) const override = 0;
protected:
BinaryOperator(Expression *expression1, Expression *expression2)
: expression1_(expression1), expression2_(expression2) {}
private:
friend class AstStorage;
};
class UnaryOperator : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
UnaryOperator() = default;
memgraph::query::Expression *expression_{nullptr};
UnaryOperator *Clone(AstStorage *storage) const override = 0;
protected:
explicit UnaryOperator(Expression *expression) : expression_(expression) {}
private:
friend class AstStorage;
};
class OrOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
OrOperator *Clone(AstStorage *storage) const override {
OrOperator *object = storage->Create<OrOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class XorOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
XorOperator *Clone(AstStorage *storage) const override {
XorOperator *object = storage->Create<XorOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class AndOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
AndOperator *Clone(AstStorage *storage) const override {
AndOperator *object = storage->Create<AndOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class AdditionOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
AdditionOperator *Clone(AstStorage *storage) const override {
AdditionOperator *object = storage->Create<AdditionOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class SubtractionOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
SubtractionOperator *Clone(AstStorage *storage) const override {
SubtractionOperator *object = storage->Create<SubtractionOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class MultiplicationOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
MultiplicationOperator *Clone(AstStorage *storage) const override {
MultiplicationOperator *object = storage->Create<MultiplicationOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class DivisionOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
DivisionOperator *Clone(AstStorage *storage) const override {
DivisionOperator *object = storage->Create<DivisionOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class ModOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
ModOperator *Clone(AstStorage *storage) const override {
ModOperator *object = storage->Create<ModOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class NotEqualOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
NotEqualOperator *Clone(AstStorage *storage) const override {
NotEqualOperator *object = storage->Create<NotEqualOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class EqualOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
EqualOperator *Clone(AstStorage *storage) const override {
EqualOperator *object = storage->Create<EqualOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class LessOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
LessOperator *Clone(AstStorage *storage) const override {
LessOperator *object = storage->Create<LessOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class GreaterOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
GreaterOperator *Clone(AstStorage *storage) const override {
GreaterOperator *object = storage->Create<GreaterOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class LessEqualOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
LessEqualOperator *Clone(AstStorage *storage) const override {
LessEqualOperator *object = storage->Create<LessEqualOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class GreaterEqualOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
GreaterEqualOperator *Clone(AstStorage *storage) const override {
GreaterEqualOperator *object = storage->Create<GreaterEqualOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class InListOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
InListOperator *Clone(AstStorage *storage) const override {
InListOperator *object = storage->Create<InListOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class SubscriptOperator : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression1_->Accept(visitor) && expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
SubscriptOperator *Clone(AstStorage *storage) const override {
SubscriptOperator *object = storage->Create<SubscriptOperator>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
return object;
}
protected:
using BinaryOperator::BinaryOperator;
private:
friend class AstStorage;
};
class NotOperator : public memgraph::query::UnaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
NotOperator *Clone(AstStorage *storage) const override {
NotOperator *object = storage->Create<NotOperator>();
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
return object;
}
protected:
using UnaryOperator::UnaryOperator;
private:
friend class AstStorage;
};
class UnaryPlusOperator : public memgraph::query::UnaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
UnaryPlusOperator *Clone(AstStorage *storage) const override {
UnaryPlusOperator *object = storage->Create<UnaryPlusOperator>();
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
return object;
}
protected:
using UnaryOperator::UnaryOperator;
private:
friend class AstStorage;
};
class UnaryMinusOperator : public memgraph::query::UnaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
UnaryMinusOperator *Clone(AstStorage *storage) const override {
UnaryMinusOperator *object = storage->Create<UnaryMinusOperator>();
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
return object;
}
protected:
using UnaryOperator::UnaryOperator;
private:
friend class AstStorage;
};
class IsNullOperator : public memgraph::query::UnaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
IsNullOperator *Clone(AstStorage *storage) const override {
IsNullOperator *object = storage->Create<IsNullOperator>();
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
return object;
}
protected:
using UnaryOperator::UnaryOperator;
private:
friend class AstStorage;
};
class Aggregation : public memgraph::query::BinaryOperator {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class Op { COUNT, MIN, MAX, SUM, AVG, COLLECT_LIST, COLLECT_MAP, PROJECT };
Aggregation() = default;
static const constexpr char *const kCount = "COUNT";
static const constexpr char *const kMin = "MIN";
static const constexpr char *const kMax = "MAX";
static const constexpr char *const kSum = "SUM";
static const constexpr char *const kAvg = "AVG";
static const constexpr char *const kCollect = "COLLECT";
static const constexpr char *const kProject = "PROJECT";
static std::string OpToString(Op op) {
const char *op_strings[] = {kCount, kMin, kMax, kSum, kAvg, kCollect, kCollect, kProject};
return op_strings[static_cast<int>(op)];
}
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
if (expression1_) expression1_->Accept(visitor);
if (expression2_) expression2_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
Aggregation *MapTo(const Symbol &symbol) {
symbol_pos_ = symbol.position();
return this;
}
memgraph::query::Aggregation::Op op_;
/// Symbol table position of the symbol this Aggregation is mapped to.
int32_t symbol_pos_{-1};
bool distinct_{false};
Aggregation *Clone(AstStorage *storage) const override {
Aggregation *object = storage->Create<Aggregation>();
object->expression1_ = expression1_ ? expression1_->Clone(storage) : nullptr;
object->expression2_ = expression2_ ? expression2_->Clone(storage) : nullptr;
object->op_ = op_;
object->symbol_pos_ = symbol_pos_;
object->distinct_ = distinct_;
return object;
}
protected:
// Use only for serialization.
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(Expression *expression1, Expression *expression2, Op op, bool distinct)
: BinaryOperator(expression1, expression2), op_(op), distinct_(distinct) {
// COUNT without expression denotes COUNT(*) in cypher.
DMG_ASSERT(expression1 || op == Aggregation::Op::COUNT, "All aggregations, except COUNT require expression");
DMG_ASSERT((expression2 == nullptr) ^ (op == Aggregation::Op::COLLECT_MAP),
"The second expression is obligatory in COLLECT_MAP and "
"invalid otherwise");
}
private:
friend class AstStorage;
};
class ListSlicingOperator : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
ListSlicingOperator() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
bool cont = list_->Accept(visitor);
if (cont && lower_bound_) {
cont = lower_bound_->Accept(visitor);
}
if (cont && upper_bound_) {
upper_bound_->Accept(visitor);
}
}
return visitor.PostVisit(*this);
}
memgraph::query::Expression *list_{nullptr};
memgraph::query::Expression *lower_bound_{nullptr};
memgraph::query::Expression *upper_bound_{nullptr};
ListSlicingOperator *Clone(AstStorage *storage) const override {
ListSlicingOperator *object = storage->Create<ListSlicingOperator>();
object->list_ = list_ ? list_->Clone(storage) : nullptr;
object->lower_bound_ = lower_bound_ ? lower_bound_->Clone(storage) : nullptr;
object->upper_bound_ = upper_bound_ ? upper_bound_->Clone(storage) : nullptr;
return object;
}
protected:
ListSlicingOperator(Expression *list, Expression *lower_bound, Expression *upper_bound)
: list_(list), lower_bound_(lower_bound), upper_bound_(upper_bound) {}
private:
friend class AstStorage;
};
class IfOperator : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
IfOperator() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
condition_->Accept(visitor) && then_expression_->Accept(visitor) && else_expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
/// None of the expressions should be nullptr. If there is no else_expression, you should make it null
/// PrimitiveLiteral.
memgraph::query::Expression *condition_;
memgraph::query::Expression *then_expression_;
memgraph::query::Expression *else_expression_;
IfOperator *Clone(AstStorage *storage) const override {
IfOperator *object = storage->Create<IfOperator>();
object->condition_ = condition_ ? condition_->Clone(storage) : nullptr;
object->then_expression_ = then_expression_ ? then_expression_->Clone(storage) : nullptr;
object->else_expression_ = else_expression_ ? else_expression_->Clone(storage) : nullptr;
return object;
}
protected:
IfOperator(Expression *condition, Expression *then_expression, Expression *else_expression)
: condition_(condition), then_expression_(then_expression), else_expression_(else_expression) {}
private:
friend class AstStorage;
};
class BaseLiteral : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
BaseLiteral() = default;
BaseLiteral *Clone(AstStorage *storage) const override = 0;
private:
friend class AstStorage;
};
class PrimitiveLiteral : public memgraph::query::BaseLiteral {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
PrimitiveLiteral() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
DEFVISITABLE(HierarchicalTreeVisitor);
storage::PropertyValue value_;
/// This field contains token position of literal used to create PrimitiveLiteral object. If PrimitiveLiteral object
/// is not created from query, leave its value at -1.
int32_t token_position_{-1};
PrimitiveLiteral *Clone(AstStorage *storage) const override {
PrimitiveLiteral *object = storage->Create<PrimitiveLiteral>();
object->value_ = value_;
object->token_position_ = token_position_;
return object;
}
protected:
template <typename T>
explicit PrimitiveLiteral(T value) : value_(value) {}
template <typename T>
PrimitiveLiteral(T value, int token_position) : value_(value), token_position_(token_position) {}
private:
friend class AstStorage;
};
class ListLiteral : public memgraph::query::BaseLiteral {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
ListLiteral() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
for (auto expr_ptr : elements_)
if (!expr_ptr->Accept(visitor)) break;
}
return visitor.PostVisit(*this);
}
std::vector<memgraph::query::Expression *> elements_;
ListLiteral *Clone(AstStorage *storage) const override {
ListLiteral *object = storage->Create<ListLiteral>();
object->elements_.resize(elements_.size());
for (auto i0 = 0; i0 < elements_.size(); ++i0) {
object->elements_[i0] = elements_[i0] ? elements_[i0]->Clone(storage) : nullptr;
}
return object;
}
protected:
explicit ListLiteral(const std::vector<Expression *> &elements) : elements_(elements) {}
private:
friend class AstStorage;
};
class MapLiteral : public memgraph::query::BaseLiteral {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
MapLiteral() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
for (auto pair : elements_) {
if (!pair.second->Accept(visitor)) break;
}
}
return visitor.PostVisit(*this);
}
std::unordered_map<memgraph::query::PropertyIx, memgraph::query::Expression *> elements_;
MapLiteral *Clone(AstStorage *storage) const override {
MapLiteral *object = storage->Create<MapLiteral>();
for (const auto &entry : elements_) {
PropertyIx key = storage->GetPropertyIx(entry.first.name);
object->elements_[key] = entry.second->Clone(storage);
}
return object;
}
protected:
explicit MapLiteral(const std::unordered_map<PropertyIx, Expression *> &elements) : elements_(elements) {}
private:
friend class AstStorage;
};
struct MapProjectionData {
Expression *map_variable;
std::unordered_map<PropertyIx, Expression *> elements;
};
class MapProjectionLiteral : public memgraph::query::BaseLiteral {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
MapProjectionLiteral() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
map_variable_->Accept(visitor);
for (auto pair : elements_) {
if (!pair.second) continue;
if (!pair.second->Accept(visitor)) break;
}
}
return visitor.PostVisit(*this);
}
Expression *map_variable_;
std::unordered_map<PropertyIx, Expression *> elements_;
MapProjectionLiteral *Clone(AstStorage *storage) const override {
MapProjectionLiteral *object = storage->Create<MapProjectionLiteral>();
object->map_variable_ = map_variable_;
for (const auto &entry : elements_) {
auto key = storage->GetPropertyIx(entry.first.name);
if (!entry.second) {
object->elements_[key] = nullptr;
continue;
}
object->elements_[key] = entry.second->Clone(storage);
}
return object;
}
protected:
explicit MapProjectionLiteral(Expression *map_variable, std::unordered_map<PropertyIx, Expression *> &&elements)
: map_variable_(map_variable), elements_(std::move(elements)) {}
private:
friend class AstStorage;
};
class Identifier : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Identifier() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
DEFVISITABLE(HierarchicalTreeVisitor);
Identifier *MapTo(const Symbol &symbol) {
symbol_pos_ = symbol.position();
return this;
}
explicit Identifier(const std::string &name) : name_(name) {}
Identifier(const std::string &name, bool user_declared) : name_(name), user_declared_(user_declared) {}
std::string name_;
bool user_declared_{true};
/// Symbol table position of the symbol this Identifier is mapped to.
int32_t symbol_pos_{-1};
Identifier *Clone(AstStorage *storage) const override {
Identifier *object = storage->Create<Identifier>();
object->name_ = name_;
object->user_declared_ = user_declared_;
object->symbol_pos_ = symbol_pos_;
return object;
}
private:
friend class AstStorage;
};
class PropertyLookup : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class EvaluationMode { GET_OWN_PROPERTY, GET_ALL_PROPERTIES };
PropertyLookup() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Expression *expression_{nullptr};
memgraph::query::PropertyIx property_;
memgraph::query::PropertyLookup::EvaluationMode evaluation_mode_{EvaluationMode::GET_OWN_PROPERTY};
PropertyLookup *Clone(AstStorage *storage) const override {
PropertyLookup *object = storage->Create<PropertyLookup>();
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
object->property_ = storage->GetPropertyIx(property_.name);
object->evaluation_mode_ = evaluation_mode_;
return object;
}
protected:
PropertyLookup(Expression *expression, PropertyIx property)
: expression_(expression), property_(std::move(property)) {}
private:
friend class AstStorage;
};
class AllPropertiesLookup : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
AllPropertiesLookup() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Expression *expression_{nullptr};
AllPropertiesLookup *Clone(AstStorage *storage) const override {
AllPropertiesLookup *object = storage->Create<AllPropertiesLookup>();
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
return object;
}
protected:
explicit AllPropertiesLookup(Expression *expression) : expression_(expression) {}
private:
friend class AstStorage;
};
class LabelsTest : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
LabelsTest() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Expression *expression_{nullptr};
std::vector<memgraph::query::LabelIx> labels_;
LabelsTest *Clone(AstStorage *storage) const override {
LabelsTest *object = storage->Create<LabelsTest>();
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
object->labels_.resize(labels_.size());
for (auto i = 0; i < object->labels_.size(); ++i) {
object->labels_[i] = storage->GetLabelIx(labels_[i].name);
}
return object;
}
protected:
LabelsTest(Expression *expression, const std::vector<LabelIx> &labels) : expression_(expression), labels_(labels) {}
LabelsTest(Expression *expression, const std::vector<std::variant<LabelIx, Expression *>> &labels)
: expression_(expression) {
labels_.reserve(labels.size());
for (auto &label : labels) {
if (std::holds_alternative<LabelIx>(label)) {
labels_.push_back(std::get<LabelIx>(label));
} else {
throw SemanticException("You can't use expressions in labels test.");
}
}
}
private:
friend class AstStorage;
};
class Function : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Function() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
for (auto *argument : arguments_) {
if (!argument->Accept(visitor)) break;
}
}
return visitor.PostVisit(*this);
}
std::vector<memgraph::query::Expression *> arguments_;
std::string function_name_;
std::function<TypedValue(const TypedValue *, int64_t, const FunctionContext &)> function_;
Function *Clone(AstStorage *storage) const override {
Function *object = storage->Create<Function>();
object->arguments_.resize(arguments_.size());
for (auto i1 = 0; i1 < arguments_.size(); ++i1) {
object->arguments_[i1] = arguments_[i1] ? arguments_[i1]->Clone(storage) : nullptr;
}
object->function_name_ = function_name_;
object->function_ = function_;
return object;
}
protected:
Function(const std::string &function_name, const std::vector<Expression *> &arguments)
: arguments_(arguments), function_name_(function_name), function_(NameToFunction(function_name_)) {
if (!function_) {
throw SemanticException("Function '{}' doesn't exist.", function_name);
}
}
private:
friend class AstStorage;
};
class Reduce : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Reduce() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
accumulator_->Accept(visitor) && initializer_->Accept(visitor) && identifier_->Accept(visitor) &&
list_->Accept(visitor) && expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
/// Identifier for the accumulating variable
memgraph::query::Identifier *accumulator_{nullptr};
/// Expression which produces the initial accumulator value.
memgraph::query::Expression *initializer_{nullptr};
/// Identifier for the list element.
memgraph::query::Identifier *identifier_{nullptr};
/// Expression which produces a list to be reduced.
memgraph::query::Expression *list_{nullptr};
/// Expression which does the reduction, i.e. produces the new accumulator value.
memgraph::query::Expression *expression_{nullptr};
Reduce *Clone(AstStorage *storage) const override {
Reduce *object = storage->Create<Reduce>();
object->accumulator_ = accumulator_ ? accumulator_->Clone(storage) : nullptr;
object->initializer_ = initializer_ ? initializer_->Clone(storage) : nullptr;
object->identifier_ = identifier_ ? identifier_->Clone(storage) : nullptr;
object->list_ = list_ ? list_->Clone(storage) : nullptr;
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
return object;
}
protected:
Reduce(Identifier *accumulator, Expression *initializer, Identifier *identifier, Expression *list,
Expression *expression)
: accumulator_(accumulator),
initializer_(initializer),
identifier_(identifier),
list_(list),
expression_(expression) {}
private:
friend class AstStorage;
};
class Coalesce : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Coalesce() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
for (auto *expr : expressions_) {
if (!expr->Accept(visitor)) break;
}
}
return visitor.PostVisit(*this);
}
/// A list of expressions to evaluate. None of the expressions should be nullptr.
std::vector<memgraph::query::Expression *> expressions_;
Coalesce *Clone(AstStorage *storage) const override {
Coalesce *object = storage->Create<Coalesce>();
object->expressions_.resize(expressions_.size());
for (auto i2 = 0; i2 < expressions_.size(); ++i2) {
object->expressions_[i2] = expressions_[i2] ? expressions_[i2]->Clone(storage) : nullptr;
}
return object;
}
private:
explicit Coalesce(const std::vector<Expression *> &expressions) : expressions_(expressions) {}
friend class AstStorage;
};
class Extract : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Extract() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
identifier_->Accept(visitor) && list_->Accept(visitor) && expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
/// Identifier for the list element.
memgraph::query::Identifier *identifier_{nullptr};
/// Expression which produces a list which will be extracted.
memgraph::query::Expression *list_{nullptr};
/// Expression which produces the new value for list element.
memgraph::query::Expression *expression_{nullptr};
Extract *Clone(AstStorage *storage) const override {
Extract *object = storage->Create<Extract>();
object->identifier_ = identifier_ ? identifier_->Clone(storage) : nullptr;
object->list_ = list_ ? list_->Clone(storage) : nullptr;
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
return object;
}
protected:
Extract(Identifier *identifier, Expression *list, Expression *expression)
: identifier_(identifier), list_(list), expression_(expression) {}
private:
friend class AstStorage;
};
class All : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
All() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
identifier_->Accept(visitor) && list_expression_->Accept(visitor) && where_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Identifier *identifier_{nullptr};
memgraph::query::Expression *list_expression_{nullptr};
memgraph::query::Where *where_{nullptr};
All *Clone(AstStorage *storage) const override {
All *object = storage->Create<All>();
object->identifier_ = identifier_ ? identifier_->Clone(storage) : nullptr;
object->list_expression_ = list_expression_ ? list_expression_->Clone(storage) : nullptr;
object->where_ = where_ ? where_->Clone(storage) : nullptr;
return object;
}
protected:
All(Identifier *identifier, Expression *list_expression, Where *where)
: identifier_(identifier), list_expression_(list_expression), where_(where) {}
private:
friend class AstStorage;
};
class Single : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Single() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
identifier_->Accept(visitor) && list_expression_->Accept(visitor) && where_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Identifier *identifier_{nullptr};
memgraph::query::Expression *list_expression_{nullptr};
memgraph::query::Where *where_{nullptr};
Single *Clone(AstStorage *storage) const override {
Single *object = storage->Create<Single>();
object->identifier_ = identifier_ ? identifier_->Clone(storage) : nullptr;
object->list_expression_ = list_expression_ ? list_expression_->Clone(storage) : nullptr;
object->where_ = where_ ? where_->Clone(storage) : nullptr;
return object;
}
protected:
Single(Identifier *identifier, Expression *list_expression, Where *where)
: identifier_(identifier), list_expression_(list_expression), where_(where) {}
private:
friend class AstStorage;
};
class Any : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Any() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
identifier_->Accept(visitor) && list_expression_->Accept(visitor) && where_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Identifier *identifier_{nullptr};
memgraph::query::Expression *list_expression_{nullptr};
memgraph::query::Where *where_{nullptr};
Any *Clone(AstStorage *storage) const override {
Any *object = storage->Create<Any>();
object->identifier_ = identifier_ ? identifier_->Clone(storage) : nullptr;
object->list_expression_ = list_expression_ ? list_expression_->Clone(storage) : nullptr;
object->where_ = where_ ? where_->Clone(storage) : nullptr;
return object;
}
protected:
Any(Identifier *identifier, Expression *list_expression, Where *where)
: identifier_(identifier), list_expression_(list_expression), where_(where) {}
private:
friend class AstStorage;
};
class None : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
None() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
identifier_->Accept(visitor) && list_expression_->Accept(visitor) && where_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Identifier *identifier_{nullptr};
memgraph::query::Expression *list_expression_{nullptr};
memgraph::query::Where *where_{nullptr};
None *Clone(AstStorage *storage) const override {
None *object = storage->Create<None>();
object->identifier_ = identifier_ ? identifier_->Clone(storage) : nullptr;
object->list_expression_ = list_expression_ ? list_expression_->Clone(storage) : nullptr;
object->where_ = where_ ? where_->Clone(storage) : nullptr;
return object;
}
protected:
None(Identifier *identifier, Expression *list_expression, Where *where)
: identifier_(identifier), list_expression_(list_expression), where_(where) {}
private:
friend class AstStorage;
};
class ParameterLookup : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
ParameterLookup() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
DEFVISITABLE(HierarchicalTreeVisitor);
/// This field contains token position of *literal* used to create ParameterLookup object. If ParameterLookup object
/// is not created from a literal leave this value at -1.
int32_t token_position_{-1};
ParameterLookup *Clone(AstStorage *storage) const override {
ParameterLookup *object = storage->Create<ParameterLookup>();
object->token_position_ = token_position_;
return object;
}
protected:
explicit ParameterLookup(int token_position) : token_position_(token_position) {}
private:
friend class AstStorage;
};
class RegexMatch : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
RegexMatch() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
string_expr_->Accept(visitor) && regex_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Expression *string_expr_;
memgraph::query::Expression *regex_;
RegexMatch *Clone(AstStorage *storage) const override {
RegexMatch *object = storage->Create<RegexMatch>();
object->string_expr_ = string_expr_ ? string_expr_->Clone(storage) : nullptr;
object->regex_ = regex_ ? regex_->Clone(storage) : nullptr;
return object;
}
private:
friend class AstStorage;
RegexMatch(Expression *string_expr, Expression *regex) : string_expr_(string_expr), regex_(regex) {}
};
class NamedExpression : public memgraph::query::Tree,
public utils::Visitable<HierarchicalTreeVisitor>,
public utils::Visitable<ExpressionVisitor<TypedValue>>,
public utils::Visitable<ExpressionVisitor<TypedValue *>>,
public utils::Visitable<ExpressionVisitor<void>> {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
using utils::Visitable<ExpressionVisitor<TypedValue>>::Accept;
using utils::Visitable<ExpressionVisitor<void>>::Accept;
using utils::Visitable<HierarchicalTreeVisitor>::Accept;
NamedExpression() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
NamedExpression *MapTo(const Symbol &symbol) {
symbol_pos_ = symbol.position();
return this;
}
std::string name_;
memgraph::query::Expression *expression_{nullptr};
/// 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.
int32_t token_position_{-1};
/// Symbol table position of the symbol this NamedExpression is mapped to.
int32_t symbol_pos_{-1};
/// True if the variable is aliased
bool is_aliased_{false};
NamedExpression *Clone(AstStorage *storage) const override {
NamedExpression *object = storage->Create<NamedExpression>();
object->name_ = name_;
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
object->token_position_ = token_position_;
object->symbol_pos_ = symbol_pos_;
object->is_aliased_ = is_aliased_;
return object;
}
protected:
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)
: name_(name), expression_(expression), token_position_(token_position) {}
private:
friend class AstStorage;
};
class PatternAtom : public memgraph::query::Tree, public utils::Visitable<HierarchicalTreeVisitor> {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
using utils::Visitable<HierarchicalTreeVisitor>::Accept;
PatternAtom() = default;
memgraph::query::Identifier *identifier_{nullptr};
PatternAtom *Clone(AstStorage *storage) const override = 0;
protected:
explicit PatternAtom(Identifier *identifier) : identifier_(identifier) {}
private:
friend class AstStorage;
};
class NodeAtom : public memgraph::query::PatternAtom {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
if (auto *properties = std::get_if<std::unordered_map<PropertyIx, Expression *>>(&properties_)) {
bool cont = identifier_->Accept(visitor);
for (auto &property : *properties) {
if (cont) {
cont = property.second->Accept(visitor);
}
}
} else {
std::get<ParameterLookup *>(properties_)->Accept(visitor);
}
}
return visitor.PostVisit(*this);
}
std::vector<std::variant<memgraph::query::LabelIx, memgraph::query::Expression *>> labels_;
std::variant<std::unordered_map<memgraph::query::PropertyIx, memgraph::query::Expression *>,
memgraph::query::ParameterLookup *>
properties_;
NodeAtom *Clone(AstStorage *storage) const override {
NodeAtom *object = storage->Create<NodeAtom>();
object->identifier_ = identifier_ ? identifier_->Clone(storage) : nullptr;
object->labels_.resize(labels_.size());
for (auto i = 0; i < object->labels_.size(); ++i) {
if (const auto *label = std::get_if<LabelIx>(&labels_[i])) {
object->labels_[i] = storage->GetLabelIx(label->name);
} else {
object->labels_[i] = std::get<Expression *>(labels_[i])->Clone(storage);
}
}
if (const auto *properties = std::get_if<std::unordered_map<PropertyIx, Expression *>>(&properties_)) {
auto &new_obj_properties = std::get<std::unordered_map<PropertyIx, Expression *>>(object->properties_);
for (const auto &[property, value_expression] : *properties) {
PropertyIx key = storage->GetPropertyIx(property.name);
new_obj_properties[key] = value_expression->Clone(storage);
}
} else {
object->properties_ = std::get<ParameterLookup *>(properties_)->Clone(storage);
}
return object;
}
protected:
using PatternAtom::PatternAtom;
private:
friend class AstStorage;
};
class EdgeAtom : public memgraph::query::PatternAtom {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class Type : uint8_t { SINGLE, DEPTH_FIRST, BREADTH_FIRST, WEIGHTED_SHORTEST_PATH, ALL_SHORTEST_PATHS };
enum class Direction : uint8_t { IN, OUT, BOTH };
/// Lambda for use in filtering or weight calculation during variable expand.
struct Lambda {
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const { return kType; }
/// Argument identifier for the edge currently being traversed.
memgraph::query::Identifier *inner_edge{nullptr};
/// Argument identifier for the destination node of the edge.
memgraph::query::Identifier *inner_node{nullptr};
/// Argument identifier for the currently-accumulated path.
memgraph::query::Identifier *accumulated_path{nullptr};
/// Argument identifier for the weight of the currently-accumulated path.
memgraph::query::Identifier *accumulated_weight{nullptr};
/// Evaluates the result of the lambda.
memgraph::query::Expression *expression{nullptr};
Lambda Clone(AstStorage *storage) const {
Lambda object;
object.inner_edge = inner_edge ? inner_edge->Clone(storage) : nullptr;
object.inner_node = inner_node ? inner_node->Clone(storage) : nullptr;
object.accumulated_path = accumulated_path ? accumulated_path->Clone(storage) : nullptr;
object.accumulated_weight = accumulated_weight ? accumulated_weight->Clone(storage) : nullptr;
object.expression = expression ? expression->Clone(storage) : nullptr;
return object;
}
};
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
bool cont = identifier_->Accept(visitor);
if (auto *properties = std::get_if<std::unordered_map<query::PropertyIx, query::Expression *>>(&properties_)) {
for (auto &property : *properties) {
if (cont) {
cont = property.second->Accept(visitor);
}
}
} else {
std::get<ParameterLookup *>(properties_)->Accept(visitor);
}
if (cont && lower_bound_) {
cont = lower_bound_->Accept(visitor);
}
if (cont && upper_bound_) {
cont = upper_bound_->Accept(visitor);
}
if (cont && total_weight_) {
total_weight_->Accept(visitor);
}
}
return visitor.PostVisit(*this);
}
bool IsVariable() const {
switch (type_) {
case Type::DEPTH_FIRST:
case Type::BREADTH_FIRST:
case Type::WEIGHTED_SHORTEST_PATH:
case Type::ALL_SHORTEST_PATHS:
return true;
case Type::SINGLE:
return false;
}
}
memgraph::query::EdgeAtom::Type type_{Type::SINGLE};
memgraph::query::EdgeAtom::Direction direction_{Direction::BOTH};
std::vector<memgraph::query::EdgeTypeIx> edge_types_;
std::variant<std::unordered_map<memgraph::query::PropertyIx, memgraph::query::Expression *>,
memgraph::query::ParameterLookup *>
properties_;
/// Evaluates to lower bound in variable length expands.
memgraph::query::Expression *lower_bound_{nullptr};
/// Evaluated to upper bound in variable length expands.
memgraph::query::Expression *upper_bound_{nullptr};
/// 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.
memgraph::query::EdgeAtom::Lambda filter_lambda_;
/// Used in weighted shortest path. It must have valid expressions and identifiers. In all other expand types, it is
/// empty.
memgraph::query::EdgeAtom::Lambda weight_lambda_;
/// Variable where the total weight for weighted shortest path will be stored.
memgraph::query::Identifier *total_weight_{nullptr};
EdgeAtom *Clone(AstStorage *storage) const override {
EdgeAtom *object = storage->Create<EdgeAtom>();
object->identifier_ = identifier_ ? identifier_->Clone(storage) : nullptr;
object->type_ = type_;
object->direction_ = direction_;
object->edge_types_.resize(edge_types_.size());
for (auto i = 0; i < object->edge_types_.size(); ++i) {
object->edge_types_[i] = storage->GetEdgeTypeIx(edge_types_[i].name);
}
if (const auto *properties = std::get_if<std::unordered_map<PropertyIx, Expression *>>(&properties_)) {
auto &new_obj_properties = std::get<std::unordered_map<PropertyIx, Expression *>>(object->properties_);
for (const auto &[property, value_expression] : *properties) {
PropertyIx key = storage->GetPropertyIx(property.name);
new_obj_properties[key] = value_expression->Clone(storage);
}
} else {
object->properties_ = std::get<ParameterLookup *>(properties_)->Clone(storage);
}
object->lower_bound_ = lower_bound_ ? lower_bound_->Clone(storage) : nullptr;
object->upper_bound_ = upper_bound_ ? upper_bound_->Clone(storage) : nullptr;
object->filter_lambda_ = filter_lambda_.Clone(storage);
object->weight_lambda_ = weight_lambda_.Clone(storage);
object->total_weight_ = total_weight_ ? total_weight_->Clone(storage) : nullptr;
return object;
}
protected:
using PatternAtom::PatternAtom;
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(Identifier *identifier, Type type, Direction direction, const std::vector<EdgeTypeIx> &edge_types)
: PatternAtom(identifier), type_(type), direction_(direction), edge_types_(edge_types) {}
private:
friend class AstStorage;
};
class Pattern : public memgraph::query::Tree, public utils::Visitable<HierarchicalTreeVisitor> {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
using utils::Visitable<HierarchicalTreeVisitor>::Accept;
Pattern() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
bool cont = identifier_->Accept(visitor);
for (auto &part : atoms_) {
if (cont) {
cont = part->Accept(visitor);
}
}
}
return visitor.PostVisit(*this);
}
memgraph::query::Identifier *identifier_{nullptr};
std::vector<memgraph::query::PatternAtom *> atoms_;
Pattern *Clone(AstStorage *storage) const override {
Pattern *object = storage->Create<Pattern>();
object->identifier_ = identifier_ ? identifier_->Clone(storage) : nullptr;
object->atoms_.resize(atoms_.size());
for (auto i3 = 0; i3 < atoms_.size(); ++i3) {
object->atoms_[i3] = atoms_[i3] ? atoms_[i3]->Clone(storage) : nullptr;
}
return object;
}
private:
friend class AstStorage;
};
class Clause : public memgraph::query::Tree, public utils::Visitable<HierarchicalTreeVisitor> {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
using utils::Visitable<HierarchicalTreeVisitor>::Accept;
Clause() = default;
Clause *Clone(AstStorage *storage) const override = 0;
private:
friend class AstStorage;
};
class SingleQuery : public memgraph::query::Tree, public utils::Visitable<HierarchicalTreeVisitor> {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
using utils::Visitable<HierarchicalTreeVisitor>::Accept;
SingleQuery() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
for (auto &clause : clauses_) {
if (!clause->Accept(visitor)) break;
}
}
return visitor.PostVisit(*this);
}
std::vector<memgraph::query::Clause *> clauses_;
SingleQuery *Clone(AstStorage *storage) const override {
SingleQuery *object = storage->Create<SingleQuery>();
object->clauses_.resize(clauses_.size());
for (auto i4 = 0; i4 < clauses_.size(); ++i4) {
object->clauses_[i4] = clauses_[i4] ? clauses_[i4]->Clone(storage) : nullptr;
}
return object;
}
private:
friend class AstStorage;
};
class CypherUnion : public memgraph::query::Tree, public utils::Visitable<HierarchicalTreeVisitor> {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
using utils::Visitable<HierarchicalTreeVisitor>::Accept;
CypherUnion() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
single_query_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::SingleQuery *single_query_{nullptr};
bool distinct_{false};
/// Holds symbols that are created during symbol generation phase. These symbols are used when UNION/UNION ALL
/// combines single query results.
std::vector<Symbol> union_symbols_;
CypherUnion *Clone(AstStorage *storage) const override {
CypherUnion *object = storage->Create<CypherUnion>();
object->single_query_ = single_query_ ? single_query_->Clone(storage) : nullptr;
object->distinct_ = distinct_;
object->union_symbols_ = union_symbols_;
return object;
}
protected:
explicit CypherUnion(bool distinct) : distinct_(distinct) {}
CypherUnion(bool distinct, SingleQuery *single_query, std::vector<Symbol> union_symbols)
: single_query_(single_query), distinct_(distinct), union_symbols_(union_symbols) {}
private:
friend class AstStorage;
};
class Query : public memgraph::query::Tree, public utils::Visitable<QueryVisitor<void>> {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
using utils::Visitable<QueryVisitor<void>>::Accept;
Query() = default;
Query *Clone(AstStorage *storage) const override = 0;
private:
friend class AstStorage;
};
struct IndexHint {
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const { return kType; }
enum class IndexType { LABEL, LABEL_PROPERTY };
memgraph::query::IndexHint::IndexType index_type_;
memgraph::query::LabelIx label_;
std::optional<memgraph::query::PropertyIx> property_{std::nullopt};
IndexHint Clone(AstStorage *storage) const {
IndexHint object;
object.index_type_ = index_type_;
object.label_ = storage->GetLabelIx(label_.name);
if (property_) {
object.property_ = storage->GetPropertyIx(property_->name);
}
return object;
}
};
class CypherQuery : public memgraph::query::Query, public utils::Visitable<HierarchicalTreeVisitor> {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
CypherQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
single_query_->Accept(visitor);
for (auto *cypher_union : cypher_unions_) {
cypher_union->Accept(visitor);
}
}
return visitor.PostVisit(*this);
}
/// First and potentially only query.
memgraph::query::SingleQuery *single_query_{nullptr};
/// Contains remaining queries that should form and union with `single_query_`.
std::vector<memgraph::query::CypherUnion *> cypher_unions_;
/// Index hint
/// Suggestion: If were going to have multiple pre-query directives (not only index_hints_), they need to be
/// contained within a dedicated class/struct
std::vector<memgraph::query::IndexHint> index_hints_;
/// Memory limit
memgraph::query::Expression *memory_limit_{nullptr};
size_t memory_scale_{1024U};
CypherQuery *Clone(AstStorage *storage) const override {
CypherQuery *object = storage->Create<CypherQuery>();
object->single_query_ = single_query_ ? single_query_->Clone(storage) : nullptr;
object->cypher_unions_.resize(cypher_unions_.size());
for (auto i5 = 0; i5 < cypher_unions_.size(); ++i5) {
object->cypher_unions_[i5] = cypher_unions_[i5] ? cypher_unions_[i5]->Clone(storage) : nullptr;
}
object->index_hints_.resize(index_hints_.size());
for (auto i6 = 0; i6 < index_hints_.size(); ++i6) {
object->index_hints_[i6] = index_hints_[i6].Clone(storage);
}
object->memory_limit_ = memory_limit_ ? memory_limit_->Clone(storage) : nullptr;
object->memory_scale_ = memory_scale_;
return object;
}
private:
friend class AstStorage;
};
class ExplainQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
ExplainQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
/// The CypherQuery to explain.
memgraph::query::CypherQuery *cypher_query_{nullptr};
ExplainQuery *Clone(AstStorage *storage) const override {
ExplainQuery *object = storage->Create<ExplainQuery>();
object->cypher_query_ = cypher_query_ ? cypher_query_->Clone(storage) : nullptr;
return object;
}
private:
friend class AstStorage;
};
class ProfileQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
ProfileQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
/// The CypherQuery to profile.
memgraph::query::CypherQuery *cypher_query_{nullptr};
ProfileQuery *Clone(AstStorage *storage) const override {
ProfileQuery *object = storage->Create<ProfileQuery>();
object->cypher_query_ = cypher_query_ ? cypher_query_->Clone(storage) : nullptr;
return object;
}
private:
friend class AstStorage;
};
class IndexQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class Action { CREATE, DROP };
IndexQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::IndexQuery::Action action_;
memgraph::query::LabelIx label_;
std::vector<memgraph::query::PropertyIx> properties_;
IndexQuery *Clone(AstStorage *storage) const override {
IndexQuery *object = storage->Create<IndexQuery>();
object->action_ = action_;
object->label_ = storage->GetLabelIx(label_.name);
object->properties_.resize(properties_.size());
for (auto i = 0; i < object->properties_.size(); ++i) {
object->properties_[i] = storage->GetPropertyIx(properties_[i].name);
}
return object;
}
protected:
IndexQuery(Action action, LabelIx label, std::vector<PropertyIx> properties)
: action_(action), label_(std::move(label)), properties_(std::move(properties)) {}
private:
friend class AstStorage;
};
class Create : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Create() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
for (auto &pattern : patterns_) {
if (!pattern->Accept(visitor)) break;
}
}
return visitor.PostVisit(*this);
}
std::vector<memgraph::query::Pattern *> patterns_;
Create *Clone(AstStorage *storage) const override {
Create *object = storage->Create<Create>();
object->patterns_.resize(patterns_.size());
for (auto i6 = 0; i6 < patterns_.size(); ++i6) {
object->patterns_[i6] = patterns_[i6] ? patterns_[i6]->Clone(storage) : nullptr;
}
return object;
}
protected:
explicit Create(std::vector<Pattern *> patterns) : patterns_(patterns) {}
private:
friend class AstStorage;
};
class CallProcedure : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
CallProcedure() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
bool cont = true;
for (auto &arg : arguments_) {
if (!arg->Accept(visitor)) {
cont = false;
break;
}
}
if (cont) {
for (auto &ident : result_identifiers_) {
if (!ident->Accept(visitor)) {
cont = false;
break;
}
}
}
}
return visitor.PostVisit(*this);
}
std::string procedure_name_;
std::vector<memgraph::query::Expression *> arguments_;
std::vector<std::string> result_fields_;
std::vector<memgraph::query::Identifier *> result_identifiers_;
memgraph::query::Expression *memory_limit_{nullptr};
size_t memory_scale_{1024U};
bool is_write_;
bool void_procedure_{false};
CallProcedure *Clone(AstStorage *storage) const override {
CallProcedure *object = storage->Create<CallProcedure>();
object->procedure_name_ = procedure_name_;
object->arguments_.resize(arguments_.size());
for (auto i7 = 0; i7 < arguments_.size(); ++i7) {
object->arguments_[i7] = arguments_[i7] ? arguments_[i7]->Clone(storage) : nullptr;
}
object->result_fields_ = result_fields_;
object->result_identifiers_.resize(result_identifiers_.size());
for (auto i8 = 0; i8 < result_identifiers_.size(); ++i8) {
object->result_identifiers_[i8] = result_identifiers_[i8] ? result_identifiers_[i8]->Clone(storage) : nullptr;
}
object->memory_limit_ = memory_limit_ ? memory_limit_->Clone(storage) : nullptr;
object->memory_scale_ = memory_scale_;
object->is_write_ = is_write_;
object->void_procedure_ = void_procedure_;
return object;
}
private:
friend class AstStorage;
};
class Match : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Match() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
bool cont = true;
for (auto &pattern : patterns_) {
if (!pattern->Accept(visitor)) {
cont = false;
break;
}
}
if (cont && where_) {
where_->Accept(visitor);
}
}
return visitor.PostVisit(*this);
}
std::vector<memgraph::query::Pattern *> patterns_;
memgraph::query::Where *where_{nullptr};
bool optional_{false};
Match *Clone(AstStorage *storage) const override {
Match *object = storage->Create<Match>();
object->patterns_.resize(patterns_.size());
for (auto i9 = 0; i9 < patterns_.size(); ++i9) {
object->patterns_[i9] = patterns_[i9] ? patterns_[i9]->Clone(storage) : nullptr;
}
object->where_ = where_ ? where_->Clone(storage) : nullptr;
object->optional_ = optional_;
return object;
}
protected:
explicit Match(bool optional) : optional_(optional) {}
Match(bool optional, Where *where, std::vector<Pattern *> patterns)
: patterns_(patterns), where_(where), optional_(optional) {}
private:
friend class AstStorage;
};
/// Defines the order for sorting values (ascending or descending).
enum class Ordering { ASC, DESC };
struct SortItem {
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const { return kType; }
memgraph::query::Ordering ordering;
memgraph::query::Expression *expression;
SortItem Clone(AstStorage *storage) const {
SortItem object;
object.ordering = ordering;
object.expression = expression ? expression->Clone(storage) : nullptr;
return object;
}
};
/// Contents common to @c Return and @c With clauses.
struct ReturnBody {
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const { return kType; }
/// True if distinct results should be produced.
bool distinct{false};
/// True if asterisk was found in the return body.
bool all_identifiers{false};
/// Expressions which are used to produce results.
std::vector<memgraph::query::NamedExpression *> named_expressions;
/// Expressions used for ordering the results.
std::vector<memgraph::query::SortItem> order_by;
/// Optional expression on how many results to skip.
memgraph::query::Expression *skip{nullptr};
/// Optional expression on how many results to produce.
memgraph::query::Expression *limit{nullptr};
ReturnBody Clone(AstStorage *storage) const {
ReturnBody object;
object.distinct = distinct;
object.all_identifiers = all_identifiers;
object.named_expressions.resize(named_expressions.size());
for (auto i10 = 0; i10 < named_expressions.size(); ++i10) {
object.named_expressions[i10] = named_expressions[i10] ? named_expressions[i10]->Clone(storage) : nullptr;
}
object.order_by.resize(order_by.size());
for (auto i11 = 0; i11 < order_by.size(); ++i11) {
object.order_by[i11] = order_by[i11].Clone(storage);
}
object.skip = skip ? skip->Clone(storage) : nullptr;
object.limit = limit ? limit->Clone(storage) : nullptr;
return object;
}
};
class Return : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Return() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
bool cont = true;
for (auto &expr : body_.named_expressions) {
if (!expr->Accept(visitor)) {
cont = false;
break;
}
}
if (cont) {
for (auto &order_by : body_.order_by) {
if (!order_by.expression->Accept(visitor)) {
cont = false;
break;
}
}
}
if (cont && body_.skip) cont = body_.skip->Accept(visitor);
if (cont && body_.limit) cont = body_.limit->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::ReturnBody body_;
Return *Clone(AstStorage *storage) const override {
Return *object = storage->Create<Return>();
object->body_ = body_.Clone(storage);
return object;
}
protected:
explicit Return(ReturnBody &body) : body_(body) {}
private:
friend class AstStorage;
};
class With : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
With() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
bool cont = true;
for (auto &expr : body_.named_expressions) {
if (!expr->Accept(visitor)) {
cont = false;
break;
}
}
if (cont) {
for (auto &order_by : body_.order_by) {
if (!order_by.expression->Accept(visitor)) {
cont = false;
break;
}
}
}
if (cont && where_) cont = where_->Accept(visitor);
if (cont && body_.skip) cont = body_.skip->Accept(visitor);
if (cont && body_.limit) cont = body_.limit->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::ReturnBody body_;
memgraph::query::Where *where_{nullptr};
With *Clone(AstStorage *storage) const override {
With *object = storage->Create<With>();
object->body_ = body_.Clone(storage);
object->where_ = where_ ? where_->Clone(storage) : nullptr;
return object;
}
protected:
With(ReturnBody &body, Where *where) : body_(body), where_(where) {}
private:
friend class AstStorage;
};
class Delete : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Delete() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
for (auto &expr : expressions_) {
if (!expr->Accept(visitor)) break;
}
}
return visitor.PostVisit(*this);
}
std::vector<memgraph::query::Expression *> expressions_;
bool detach_{false};
Delete *Clone(AstStorage *storage) const override {
Delete *object = storage->Create<Delete>();
object->expressions_.resize(expressions_.size());
for (auto i12 = 0; i12 < expressions_.size(); ++i12) {
object->expressions_[i12] = expressions_[i12] ? expressions_[i12]->Clone(storage) : nullptr;
}
object->detach_ = detach_;
return object;
}
protected:
Delete(bool detach, std::vector<Expression *> expressions) : expressions_(expressions), detach_(detach) {}
private:
friend class AstStorage;
};
class SetProperty : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
SetProperty() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
property_lookup_->Accept(visitor) && expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::PropertyLookup *property_lookup_{nullptr};
memgraph::query::Expression *expression_{nullptr};
SetProperty *Clone(AstStorage *storage) const override {
SetProperty *object = storage->Create<SetProperty>();
object->property_lookup_ = property_lookup_ ? property_lookup_->Clone(storage) : nullptr;
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
return object;
}
protected:
SetProperty(PropertyLookup *property_lookup, Expression *expression)
: property_lookup_(property_lookup), expression_(expression) {}
private:
friend class AstStorage;
};
class SetProperties : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
SetProperties() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
identifier_->Accept(visitor) && expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Identifier *identifier_{nullptr};
memgraph::query::Expression *expression_{nullptr};
bool update_{false};
SetProperties *Clone(AstStorage *storage) const override {
SetProperties *object = storage->Create<SetProperties>();
object->identifier_ = identifier_ ? identifier_->Clone(storage) : nullptr;
object->expression_ = expression_ ? expression_->Clone(storage) : nullptr;
object->update_ = update_;
return object;
}
protected:
SetProperties(Identifier *identifier, Expression *expression, bool update = false)
: identifier_(identifier), expression_(expression), update_(update) {}
private:
friend class AstStorage;
};
class SetLabels : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
SetLabels() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
identifier_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Identifier *identifier_{nullptr};
std::vector<std::variant<memgraph::query::LabelIx, memgraph::query::Expression *>> labels_;
SetLabels *Clone(AstStorage *storage) const override {
SetLabels *object = storage->Create<SetLabels>();
object->identifier_ = identifier_ ? identifier_->Clone(storage) : nullptr;
object->labels_.resize(labels_.size());
for (auto i = 0; i < object->labels_.size(); ++i) {
if (const auto *label = std::get_if<LabelIx>(&labels_[i])) {
object->labels_[i] = storage->GetLabelIx(label->name);
} else {
object->labels_[i] = std::get<Expression *>(labels_[i])->Clone(storage);
}
}
return object;
}
protected:
SetLabels(Identifier *identifier, const std::vector<std::variant<LabelIx, Expression *>> &labels)
: identifier_(identifier), labels_(labels) {}
SetLabels(Identifier *identifier, const std::vector<LabelIx> &labels) : identifier_(identifier) {
for (const auto &label : labels) {
labels_.emplace_back(label);
}
}
private:
friend class AstStorage;
};
class RemoveProperty : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
RemoveProperty() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
property_lookup_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::PropertyLookup *property_lookup_{nullptr};
RemoveProperty *Clone(AstStorage *storage) const override {
RemoveProperty *object = storage->Create<RemoveProperty>();
object->property_lookup_ = property_lookup_ ? property_lookup_->Clone(storage) : nullptr;
return object;
}
protected:
explicit RemoveProperty(PropertyLookup *property_lookup) : property_lookup_(property_lookup) {}
private:
friend class AstStorage;
};
class RemoveLabels : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
RemoveLabels() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
identifier_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Identifier *identifier_{nullptr};
std::vector<std::variant<memgraph::query::LabelIx, memgraph::query::Expression *>> labels_;
RemoveLabels *Clone(AstStorage *storage) const override {
RemoveLabels *object = storage->Create<RemoveLabels>();
object->identifier_ = identifier_ ? identifier_->Clone(storage) : nullptr;
object->labels_.resize(labels_.size());
for (auto i = 0; i < object->labels_.size(); ++i) {
if (const auto *label = std::get_if<LabelIx>(&labels_[i])) {
object->labels_[i] = storage->GetLabelIx(label->name);
} else {
object->labels_[i] = std::get<Expression *>(labels_[i])->Clone(storage);
}
}
return object;
}
protected:
RemoveLabels(Identifier *identifier, const std::vector<std::variant<LabelIx, Expression *>> &labels)
: identifier_(identifier), labels_(labels) {}
RemoveLabels(Identifier *identifier, const std::vector<LabelIx> &labels) : identifier_(identifier) {
for (const auto &label : labels) {
labels_.emplace_back(label);
}
}
private:
friend class AstStorage;
};
class Merge : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Merge() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
bool cont = pattern_->Accept(visitor);
if (cont) {
for (auto &set : on_match_) {
if (!set->Accept(visitor)) {
cont = false;
break;
}
}
}
if (cont) {
for (auto &set : on_create_) {
if (!set->Accept(visitor)) {
cont = false;
break;
}
}
}
}
return visitor.PostVisit(*this);
}
memgraph::query::Pattern *pattern_{nullptr};
std::vector<memgraph::query::Clause *> on_match_;
std::vector<memgraph::query::Clause *> on_create_;
Merge *Clone(AstStorage *storage) const override {
Merge *object = storage->Create<Merge>();
object->pattern_ = pattern_ ? pattern_->Clone(storage) : nullptr;
object->on_match_.resize(on_match_.size());
for (auto i13 = 0; i13 < on_match_.size(); ++i13) {
object->on_match_[i13] = on_match_[i13] ? on_match_[i13]->Clone(storage) : nullptr;
}
object->on_create_.resize(on_create_.size());
for (auto i14 = 0; i14 < on_create_.size(); ++i14) {
object->on_create_[i14] = on_create_[i14] ? on_create_[i14]->Clone(storage) : nullptr;
}
return object;
}
protected:
Merge(Pattern *pattern, std::vector<Clause *> on_match, std::vector<Clause *> on_create)
: pattern_(pattern), on_match_(on_match), on_create_(on_create) {}
private:
friend class AstStorage;
};
class Unwind : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Unwind() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
named_expression_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::NamedExpression *named_expression_{nullptr};
Unwind *Clone(AstStorage *storage) const override {
Unwind *object = storage->Create<Unwind>();
object->named_expression_ = named_expression_ ? named_expression_->Clone(storage) : nullptr;
return object;
}
protected:
explicit Unwind(NamedExpression *named_expression) : named_expression_(named_expression) {
DMG_ASSERT(named_expression, "Unwind cannot take nullptr for named_expression");
}
private:
friend class AstStorage;
};
class AuthQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class Action {
CREATE_ROLE,
DROP_ROLE,
SHOW_ROLES,
CREATE_USER,
SET_PASSWORD,
DROP_USER,
SHOW_USERS,
SET_ROLE,
CLEAR_ROLE,
GRANT_PRIVILEGE,
DENY_PRIVILEGE,
REVOKE_PRIVILEGE,
SHOW_PRIVILEGES,
SHOW_ROLE_FOR_USER,
SHOW_USERS_FOR_ROLE,
GRANT_DATABASE_TO_USER,
DENY_DATABASE_FROM_USER,
REVOKE_DATABASE_FROM_USER,
SHOW_DATABASE_PRIVILEGES,
SET_MAIN_DATABASE,
};
enum class Privilege {
CREATE,
DELETE,
MATCH,
MERGE,
SET,
REMOVE,
INDEX,
STATS,
AUTH,
CONSTRAINT,
DUMP,
REPLICATION,
DURABILITY,
READ_FILE,
FREE_MEMORY,
TRIGGER,
CONFIG,
STREAM,
MODULE_READ,
MODULE_WRITE,
WEBSOCKET,
STORAGE_MODE,
TRANSACTION_MANAGEMENT,
MULTI_DATABASE_EDIT,
MULTI_DATABASE_USE,
COORDINATOR
};
enum class FineGrainedPrivilege { NOTHING, READ, UPDATE, CREATE_DELETE };
AuthQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::AuthQuery::Action action_;
std::string user_;
std::string role_;
std::string user_or_role_;
memgraph::query::Expression *password_{nullptr};
std::string database_;
std::vector<memgraph::query::AuthQuery::Privilege> privileges_;
std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
label_privileges_;
std::vector<std::unordered_map<memgraph::query::AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>
edge_type_privileges_;
AuthQuery *Clone(AstStorage *storage) const override {
AuthQuery *object = storage->Create<AuthQuery>();
object->action_ = action_;
object->user_ = user_;
object->role_ = role_;
object->user_or_role_ = user_or_role_;
object->password_ = password_ ? password_->Clone(storage) : nullptr;
object->database_ = database_;
object->privileges_ = privileges_;
object->label_privileges_ = label_privileges_;
object->edge_type_privileges_ = edge_type_privileges_;
return object;
}
protected:
AuthQuery(Action action, std::string user, std::string role, std::string user_or_role, Expression *password,
std::string database, std::vector<Privilege> privileges,
std::vector<std::unordered_map<FineGrainedPrivilege, std::vector<std::string>>> label_privileges,
std::vector<std::unordered_map<FineGrainedPrivilege, std::vector<std::string>>> edge_type_privileges)
: action_(action),
user_(user),
role_(role),
user_or_role_(user_or_role),
password_(password),
database_(database),
privileges_(privileges),
label_privileges_(label_privileges),
edge_type_privileges_(edge_type_privileges) {}
private:
friend class AstStorage;
};
/// Constant that holds all available privileges.
const std::vector<AuthQuery::Privilege> kPrivilegesAll = {AuthQuery::Privilege::CREATE,
AuthQuery::Privilege::DELETE,
AuthQuery::Privilege::MATCH,
AuthQuery::Privilege::MERGE,
AuthQuery::Privilege::SET,
AuthQuery::Privilege::REMOVE,
AuthQuery::Privilege::INDEX,
AuthQuery::Privilege::STATS,
AuthQuery::Privilege::AUTH,
AuthQuery::Privilege::CONSTRAINT,
AuthQuery::Privilege::DUMP,
AuthQuery::Privilege::REPLICATION,
AuthQuery::Privilege::READ_FILE,
AuthQuery::Privilege::DURABILITY,
AuthQuery::Privilege::FREE_MEMORY,
AuthQuery::Privilege::TRIGGER,
AuthQuery::Privilege::CONFIG,
AuthQuery::Privilege::STREAM,
AuthQuery::Privilege::MODULE_READ,
AuthQuery::Privilege::MODULE_WRITE,
AuthQuery::Privilege::WEBSOCKET,
AuthQuery::Privilege::TRANSACTION_MANAGEMENT,
AuthQuery::Privilege::STORAGE_MODE,
AuthQuery::Privilege::MULTI_DATABASE_EDIT,
AuthQuery::Privilege::MULTI_DATABASE_USE,
AuthQuery::Privilege::COORDINATOR};
class DatabaseInfoQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class InfoType { INDEX, CONSTRAINT, EDGE_TYPES, NODE_LABELS };
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::DatabaseInfoQuery::InfoType info_type_;
DatabaseInfoQuery *Clone(AstStorage *storage) const override {
DatabaseInfoQuery *object = storage->Create<DatabaseInfoQuery>();
object->info_type_ = info_type_;
return object;
}
};
class SystemInfoQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class InfoType { STORAGE, BUILD };
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::SystemInfoQuery::InfoType info_type_;
SystemInfoQuery *Clone(AstStorage *storage) const override {
SystemInfoQuery *object = storage->Create<SystemInfoQuery>();
object->info_type_ = info_type_;
return object;
}
};
struct Constraint {
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const { return kType; }
enum class Type { EXISTS, UNIQUE, NODE_KEY };
memgraph::query::Constraint::Type type;
memgraph::query::LabelIx label;
std::vector<memgraph::query::PropertyIx> properties;
Constraint Clone(AstStorage *storage) const {
Constraint object;
object.type = type;
object.label = storage->GetLabelIx(label.name);
object.properties.resize(properties.size());
for (auto i = 0; i < object.properties.size(); ++i) {
object.properties[i] = storage->GetPropertyIx(properties[i].name);
}
return object;
}
};
class ConstraintQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class ActionType { CREATE, DROP };
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::ConstraintQuery::ActionType action_type_;
memgraph::query::Constraint constraint_;
ConstraintQuery *Clone(AstStorage *storage) const override {
ConstraintQuery *object = storage->Create<ConstraintQuery>();
object->action_type_ = action_type_;
object->constraint_ = constraint_.Clone(storage);
return object;
}
};
class DumpQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(QueryVisitor<void>);
DumpQuery *Clone(AstStorage *storage) const override {
DumpQuery *object = storage->Create<DumpQuery>();
return object;
}
};
class ReplicationQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class Action { SET_REPLICATION_ROLE, SHOW_REPLICATION_ROLE, REGISTER_REPLICA, DROP_REPLICA, SHOW_REPLICAS };
enum class ReplicationRole { MAIN, REPLICA };
enum class SyncMode { SYNC, ASYNC };
ReplicationQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::ReplicationQuery::Action action_;
memgraph::query::ReplicationQuery::ReplicationRole role_;
std::string instance_name_;
memgraph::query::Expression *socket_address_{nullptr};
memgraph::query::Expression *coordinator_socket_address_{nullptr};
memgraph::query::Expression *port_{nullptr};
memgraph::query::ReplicationQuery::SyncMode sync_mode_;
ReplicationQuery *Clone(AstStorage *storage) const override {
ReplicationQuery *object = storage->Create<ReplicationQuery>();
object->action_ = action_;
object->role_ = role_;
object->instance_name_ = instance_name_;
object->socket_address_ = socket_address_ ? socket_address_->Clone(storage) : nullptr;
object->port_ = port_ ? port_->Clone(storage) : nullptr;
object->sync_mode_ = sync_mode_;
object->coordinator_socket_address_ =
coordinator_socket_address_ ? coordinator_socket_address_->Clone(storage) : nullptr;
return object;
}
private:
friend class AstStorage;
};
class CoordinatorQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class Action {
REGISTER_INSTANCE,
UNREGISTER_INSTANCE,
SET_INSTANCE_TO_MAIN,
SHOW_INSTANCES,
ADD_COORDINATOR_INSTANCE
};
enum class SyncMode { SYNC, ASYNC };
CoordinatorQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::CoordinatorQuery::Action action_;
std::string instance_name_;
memgraph::query::Expression *replication_socket_address_{nullptr};
memgraph::query::Expression *coordinator_socket_address_{nullptr};
memgraph::query::Expression *raft_socket_address_{nullptr};
memgraph::query::Expression *raft_server_id_{nullptr};
memgraph::query::CoordinatorQuery::SyncMode sync_mode_;
CoordinatorQuery *Clone(AstStorage *storage) const override {
auto *object = storage->Create<CoordinatorQuery>();
object->action_ = action_;
object->instance_name_ = instance_name_;
object->replication_socket_address_ =
replication_socket_address_ ? replication_socket_address_->Clone(storage) : nullptr;
object->sync_mode_ = sync_mode_;
object->coordinator_socket_address_ =
coordinator_socket_address_ ? coordinator_socket_address_->Clone(storage) : nullptr;
object->raft_socket_address_ = raft_socket_address_ ? raft_socket_address_->Clone(storage) : nullptr;
object->raft_server_id_ = raft_server_id_ ? raft_server_id_->Clone(storage) : nullptr;
return object;
}
private:
friend class AstStorage;
};
class EdgeImportModeQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class Status { ACTIVE, INACTIVE };
EdgeImportModeQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::EdgeImportModeQuery::Status status_;
EdgeImportModeQuery *Clone(AstStorage *storage) const override {
auto *object = storage->Create<EdgeImportModeQuery>();
object->status_ = status_;
return object;
}
private:
friend class AstStorage;
};
class LockPathQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class Action { LOCK_PATH, UNLOCK_PATH, STATUS };
LockPathQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::LockPathQuery::Action action_;
LockPathQuery *Clone(AstStorage *storage) const override {
LockPathQuery *object = storage->Create<LockPathQuery>();
object->action_ = action_;
return object;
}
private:
friend class AstStorage;
};
class LoadCsv : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
LoadCsv() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
row_var_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::Expression *file_;
bool with_header_;
bool ignore_bad_;
memgraph::query::Expression *delimiter_{nullptr};
memgraph::query::Expression *quote_{nullptr};
memgraph::query::Expression *nullif_{nullptr};
memgraph::query::Identifier *row_var_{nullptr};
LoadCsv *Clone(AstStorage *storage) const override {
LoadCsv *object = storage->Create<LoadCsv>();
object->file_ = file_ ? file_->Clone(storage) : nullptr;
object->with_header_ = with_header_;
object->ignore_bad_ = ignore_bad_;
object->delimiter_ = delimiter_ ? delimiter_->Clone(storage) : nullptr;
object->quote_ = quote_ ? quote_->Clone(storage) : nullptr;
object->nullif_ = nullif_;
object->row_var_ = row_var_ ? row_var_->Clone(storage) : nullptr;
return object;
}
protected:
explicit LoadCsv(Expression *file, bool with_header, bool ignore_bad, Expression *delimiter, Expression *quote,
Expression *nullif, Identifier *row_var)
: file_(file),
with_header_(with_header),
ignore_bad_(ignore_bad),
delimiter_(delimiter),
quote_(quote),
nullif_(nullif),
row_var_(row_var) {
DMG_ASSERT(row_var, "LoadCsv cannot take nullptr for identifier");
}
private:
friend class AstStorage;
};
class FreeMemoryQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(QueryVisitor<void>);
FreeMemoryQuery *Clone(AstStorage *storage) const override {
FreeMemoryQuery *object = storage->Create<FreeMemoryQuery>();
return object;
}
};
class TriggerQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class Action { CREATE_TRIGGER, DROP_TRIGGER, SHOW_TRIGGERS };
enum class EventType {
ANY,
VERTEX_CREATE,
EDGE_CREATE,
CREATE,
VERTEX_DELETE,
EDGE_DELETE,
DELETE,
VERTEX_UPDATE,
EDGE_UPDATE,
UPDATE
};
TriggerQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::TriggerQuery::Action action_;
memgraph::query::TriggerQuery::EventType event_type_;
std::string trigger_name_;
bool before_commit_;
std::string statement_;
TriggerQuery *Clone(AstStorage *storage) const override {
TriggerQuery *object = storage->Create<TriggerQuery>();
object->action_ = action_;
object->event_type_ = event_type_;
object->trigger_name_ = trigger_name_;
object->before_commit_ = before_commit_;
object->statement_ = statement_;
return object;
}
private:
friend class AstStorage;
};
class IsolationLevelQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class IsolationLevel { SNAPSHOT_ISOLATION, READ_COMMITTED, READ_UNCOMMITTED };
enum class IsolationLevelScope { NEXT, SESSION, GLOBAL };
IsolationLevelQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::IsolationLevelQuery::IsolationLevel isolation_level_;
memgraph::query::IsolationLevelQuery::IsolationLevelScope isolation_level_scope_;
IsolationLevelQuery *Clone(AstStorage *storage) const override {
IsolationLevelQuery *object = storage->Create<IsolationLevelQuery>();
object->isolation_level_ = isolation_level_;
object->isolation_level_scope_ = isolation_level_scope_;
return object;
}
private:
friend class AstStorage;
};
class StorageModeQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class StorageMode { IN_MEMORY_TRANSACTIONAL, IN_MEMORY_ANALYTICAL, ON_DISK_TRANSACTIONAL };
StorageModeQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::StorageModeQuery::StorageMode storage_mode_;
StorageModeQuery *Clone(AstStorage *storage) const override {
StorageModeQuery *object = storage->Create<StorageModeQuery>();
object->storage_mode_ = storage_mode_;
return object;
}
private:
friend class AstStorage;
};
class CreateSnapshotQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(QueryVisitor<void>);
CreateSnapshotQuery *Clone(AstStorage *storage) const override {
CreateSnapshotQuery *object = storage->Create<CreateSnapshotQuery>();
return object;
}
};
class StreamQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class Action {
CREATE_STREAM,
DROP_STREAM,
START_STREAM,
STOP_STREAM,
START_ALL_STREAMS,
STOP_ALL_STREAMS,
SHOW_STREAMS,
CHECK_STREAM
};
enum class Type { KAFKA, PULSAR };
StreamQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::StreamQuery::Action action_;
memgraph::query::StreamQuery::Type type_;
std::string stream_name_;
memgraph::query::Expression *batch_limit_{nullptr};
memgraph::query::Expression *timeout_{nullptr};
std::string transform_name_;
memgraph::query::Expression *batch_interval_{nullptr};
memgraph::query::Expression *batch_size_{nullptr};
std::variant<memgraph::query::Expression *, std::vector<std::string>> topic_names_{nullptr};
std::string consumer_group_;
memgraph::query::Expression *bootstrap_servers_{nullptr};
memgraph::query::Expression *service_url_{nullptr};
std::unordered_map<memgraph::query::Expression *, memgraph::query::Expression *> configs_;
std::unordered_map<memgraph::query::Expression *, memgraph::query::Expression *> credentials_;
StreamQuery *Clone(AstStorage *storage) const override {
StreamQuery *object = storage->Create<StreamQuery>();
object->action_ = action_;
object->type_ = type_;
object->stream_name_ = stream_name_;
object->batch_limit_ = batch_limit_ ? batch_limit_->Clone(storage) : nullptr;
object->timeout_ = timeout_ ? timeout_->Clone(storage) : nullptr;
object->transform_name_ = transform_name_;
object->batch_interval_ = batch_interval_ ? batch_interval_->Clone(storage) : nullptr;
object->batch_size_ = batch_size_ ? batch_size_->Clone(storage) : nullptr;
if (auto *topic_expression = std::get_if<Expression *>(&topic_names_)) {
if (*topic_expression == nullptr) {
object->topic_names_ = nullptr;
} else {
object->topic_names_ = (*topic_expression)->Clone(storage);
}
} else {
object->topic_names_ = std::get<std::vector<std::string>>(topic_names_);
}
object->consumer_group_ = consumer_group_;
object->bootstrap_servers_ = bootstrap_servers_ ? bootstrap_servers_->Clone(storage) : nullptr;
object->service_url_ = service_url_ ? service_url_->Clone(storage) : nullptr;
for (const auto &[key, value] : configs_) {
object->configs_[key->Clone(storage)] = value->Clone(storage);
}
for (const auto &[key, value] : credentials_) {
object->credentials_[key->Clone(storage)] = value->Clone(storage);
}
return object;
}
private:
friend class AstStorage;
};
class SettingQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class Action { SHOW_SETTING, SHOW_ALL_SETTINGS, SET_SETTING };
SettingQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::SettingQuery::Action action_;
memgraph::query::Expression *setting_name_{nullptr};
memgraph::query::Expression *setting_value_{nullptr};
SettingQuery *Clone(AstStorage *storage) const override {
SettingQuery *object = storage->Create<SettingQuery>();
object->action_ = action_;
object->setting_name_ = setting_name_ ? setting_name_->Clone(storage) : nullptr;
object->setting_value_ = setting_value_ ? setting_value_->Clone(storage) : nullptr;
return object;
}
private:
friend class AstStorage;
};
class VersionQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(QueryVisitor<void>);
VersionQuery *Clone(AstStorage *storage) const override {
VersionQuery *object = storage->Create<VersionQuery>();
return object;
}
};
class Foreach : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Foreach() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
named_expression_->Accept(visitor);
for (auto &clause : clauses_) {
clause->Accept(visitor);
}
}
return visitor.PostVisit(*this);
}
memgraph::query::NamedExpression *named_expression_{nullptr};
std::vector<memgraph::query::Clause *> clauses_;
Foreach *Clone(AstStorage *storage) const override {
Foreach *object = storage->Create<Foreach>();
object->named_expression_ = named_expression_ ? named_expression_->Clone(storage) : nullptr;
object->clauses_.resize(clauses_.size());
for (auto i15 = 0; i15 < clauses_.size(); ++i15) {
object->clauses_[i15] = clauses_[i15] ? clauses_[i15]->Clone(storage) : nullptr;
}
return object;
}
protected:
Foreach(NamedExpression *expression, std::vector<Clause *> clauses)
: named_expression_(expression), clauses_(clauses) {}
private:
friend class AstStorage;
};
class ShowConfigQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(QueryVisitor<void>);
ShowConfigQuery *Clone(AstStorage *storage) const override {
ShowConfigQuery *object = storage->Create<ShowConfigQuery>();
return object;
}
};
class TransactionQueueQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
enum class Action { SHOW_TRANSACTIONS, TERMINATE_TRANSACTIONS };
TransactionQueueQuery() = default;
DEFVISITABLE(QueryVisitor<void>);
memgraph::query::TransactionQueueQuery::Action action_;
std::vector<Expression *> transaction_id_list_;
TransactionQueueQuery *Clone(AstStorage *storage) const override {
auto *object = storage->Create<TransactionQueueQuery>();
object->action_ = action_;
object->transaction_id_list_ = transaction_id_list_;
return object;
}
};
class AnalyzeGraphQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(QueryVisitor<void>);
enum class Action { ANALYZE, DELETE };
memgraph::query::AnalyzeGraphQuery::Action action_;
std::vector<std::string> labels_;
AnalyzeGraphQuery *Clone(AstStorage *storage) const override {
auto *object = storage->Create<AnalyzeGraphQuery>();
object->action_ = action_;
object->labels_ = labels_;
return object;
}
};
class Exists : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
Exists() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
pattern_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
Exists *MapTo(const Symbol &symbol) {
symbol_pos_ = symbol.position();
return this;
}
memgraph::query::Pattern *pattern_{nullptr};
/// Symbol table position of the symbol this Aggregation is mapped to.
int32_t symbol_pos_{-1};
Exists *Clone(AstStorage *storage) const override {
Exists *object = storage->Create<Exists>();
object->pattern_ = pattern_ ? pattern_->Clone(storage) : nullptr;
object->symbol_pos_ = symbol_pos_;
return object;
}
protected:
Exists(Pattern *pattern) : pattern_(pattern) {}
private:
friend class AstStorage;
};
class PatternComprehension : public memgraph::query::Expression {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
PatternComprehension() = default;
DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<TypedValue *>);
DEFVISITABLE(ExpressionVisitor<void>);
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
if (variable_) {
variable_->Accept(visitor);
}
pattern_->Accept(visitor);
if (filter_) {
filter_->Accept(visitor);
}
resultExpr_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
PatternComprehension *MapTo(const Symbol &symbol) {
symbol_pos_ = symbol.position();
return this;
}
// The variable name.
Identifier *variable_{nullptr};
// The pattern to match.
Pattern *pattern_{nullptr};
// Optional WHERE clause for filtering.
Where *filter_{nullptr};
// The projection expression.
Expression *resultExpr_{nullptr};
/// Symbol table position of the symbol this Aggregation is mapped to.
int32_t symbol_pos_{-1};
PatternComprehension *Clone(AstStorage *storage) const override {
PatternComprehension *object = storage->Create<PatternComprehension>();
object->pattern_ = pattern_ ? pattern_->Clone(storage) : nullptr;
object->filter_ = filter_ ? filter_->Clone(storage) : nullptr;
object->resultExpr_ = resultExpr_ ? resultExpr_->Clone(storage) : nullptr;
object->symbol_pos_ = symbol_pos_;
return object;
}
protected:
PatternComprehension(Identifier *variable, Pattern *pattern) : variable_(variable), pattern_(pattern) {}
private:
friend class AstStorage;
};
class CallSubquery : public memgraph::query::Clause {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
CallSubquery() = default;
bool Accept(HierarchicalTreeVisitor &visitor) override {
if (visitor.PreVisit(*this)) {
cypher_query_->Accept(visitor);
}
return visitor.PostVisit(*this);
}
memgraph::query::CypherQuery *cypher_query_;
CallSubquery *Clone(AstStorage *storage) const override {
CallSubquery *object = storage->Create<CallSubquery>();
object->cypher_query_ = cypher_query_ ? cypher_query_->Clone(storage) : nullptr;
return object;
}
private:
friend class AstStorage;
};
class MultiDatabaseQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(QueryVisitor<void>);
enum class Action { CREATE, USE, DROP, SHOW };
memgraph::query::MultiDatabaseQuery::Action action_;
std::string db_name_;
MultiDatabaseQuery *Clone(AstStorage *storage) const override {
auto *object = storage->Create<MultiDatabaseQuery>();
object->action_ = action_;
object->db_name_ = db_name_;
return object;
}
};
class ShowDatabasesQuery : public memgraph::query::Query {
public:
static const utils::TypeInfo kType;
const utils::TypeInfo &GetTypeInfo() const override { return kType; }
DEFVISITABLE(QueryVisitor<void>);
ShowDatabasesQuery *Clone(AstStorage *storage) const override {
auto *object = storage->Create<ShowDatabasesQuery>();
return object;
}
};
} // namespace memgraph::query