3#include <mutable/mutable-config.hpp>
12#include <unordered_map>
21struct OperatorVisitor;
56 std::unique_ptr<OperatorInformation>
info_;
59 mutable std::size_t id_ = -1UL;
74 std::unique_ptr<OperatorInformation>
info(std::unique_ptr<OperatorInformation> new_info) {
76 swap(new_info, info_);
85 std::size_t
id()
const {
86 M_insist(id_ != -1UL,
"id must be first set by calling `assign_post_order_ids()`");
91 void id(std::size_t
id)
const { id_ =
id; }
100 virtual void accept(OperatorVisitor &v) = 0;
107 void minimize_schema();
110 void dot(std::ostream &out)
const;
112 void dump(std::ostream &out)
const;
141 for (
auto c : children_)
149 children_.push_back(child);
151 schema() += child->
schema();
157 if (i >= children_.size())
159 auto old = children_[i];
160 children_[i] = child;
166 for (
auto c : children_)
173 const std::vector<Producer*> &
children()
const {
return children_; }
177 if (i >= children_.size())
183 std::vector<Producer*> &
children() {
return children_; }
187 auto next_start_id = start_id;
188 for (
auto c : children_) {
189 c->assign_post_order_ids(next_start_id);
190 next_start_id = c->id() + 1;
196 for (
auto c : children_)
215 const auto &
callback()
const {
return callback_; }
217 void accept(OperatorVisitor &v)
override;
232 void accept(OperatorVisitor &v)
override;
247 void accept(OperatorVisitor &v)
override;
260 , alias_(
std::move(alias))
264 S.add({alias_, e.id.name}, e.type, e.constraints);
274 void accept(OperatorVisitor &v)
override;
292 auto old_filter = std::move(filter_);
293 filter_ = std::move(f);
297 void accept(OperatorVisitor &v)
override;
306 M_insist(this->filter().size() == 1,
"a disjunctive filter must have exactly one clause");
307 M_insist(this->filter()[0].size() >= 2,
"a disjunctive filter must have at least two predicates ");
314 void accept(OperatorVisitor &v)
override;
321 Schema::entry_type::UNIQUE | Schema::entry_type::REFERENCES_UNIQUE;
331 const auto old_num_entries = schema().num_entries();
332 Consumer::add_child(child);
335 for (
auto i = old_num_entries; i != schema().num_entries(); ++i)
336 schema()[i].constraints &= ~REMOVED_CONSTRAINTS;
339 auto old = Consumer::set_child(child, i);
342 for (
auto &e : schema())
343 e.constraints &= ~REMOVED_CONSTRAINTS;
354 void accept(OperatorVisitor &v)
override;
376 children().push_back(child);
381 for (std::size_t i = 0; i < projections_.size(); ++i) {
382 if (
auto D = cast<const ast::Designator>(projections_[i].first)) {
384 S[i].constraints |= child->
schema()[
id].second.constraints;
391 if (i >= children().size())
393 auto old = children()[i];
394 children()[i] = child;
399 for (std::size_t i = 0; i < projections_.size(); ++i) {
400 if (
auto D = cast<const ast::Designator>(projections_[i].first)) {
402 S[i].constraints |= child->
schema()[
id].second.constraints;
409 const std::vector<projection_type> &
projections()
const {
return projections_; }
410 std::vector<projection_type> &
projections() {
return projections_; }
412 void accept(OperatorVisitor &v)
override;
435 std::size_t
limit()
const {
return limit_; }
436 std::size_t
offset()
const {
return offset_; }
438 void accept(OperatorVisitor &v)
override;
448 std::vector<std::reference_wrapper<const ast::FnApplicationExpr>>
aggregates_;
452 std::vector<std::reference_wrapper<const ast::FnApplicationExpr>> aggregates);
462 children().push_back(child);
467 for (std::size_t i = 0; i < group_by_.size(); ++i) {
468 if (
auto D = cast<const ast::Designator>(group_by_[i].first)) {
470 S[i].constraints |= child->
schema()[
id].second.constraints;
477 if (i >= children().size())
479 auto old = children()[i];
480 children()[i] = child;
485 for (std::size_t i = 0; i < group_by_.size(); ++i) {
486 if (
auto D = cast<const ast::Designator>(group_by_[i].first)) {
488 S[i].constraints |= child->
schema()[
id].second.constraints;
495 const auto &
group_by()
const {
return group_by_; }
499 void accept(OperatorVisitor &v)
override;
506 std::vector<std::reference_wrapper<const ast::FnApplicationExpr>>
aggregates_;
509 AggregationOperator(std::vector<std::reference_wrapper<const ast::FnApplicationExpr>> aggregates);
519 children().push_back(child);
525 if (i >= children().size())
527 auto old = children()[i];
528 children()[i] = child;
536 void accept(OperatorVisitor &v)
override;
554 const auto &
order_by()
const {
return order_by_; }
556 void accept(OperatorVisitor &v)
override;
560#define M_OPERATOR_LIST(X) \
562 X(CallbackOperator) \
566 X(DisjunctiveFilterOperator) \
568 X(ProjectionOperator) \
570 X(GroupingOperator) \
571 X(AggregationOperator) \
582 using super = std::conditional_t<C, ConstOperatorVisitor, OperatorVisitor>;
587 for (
auto child : c->children())
596 using super = std::conditional_t<C, ConstOperatorVisitor, OperatorVisitor>;
600 for (
auto child : c->children())
#define M_OPERATOR_LIST(X)
#define M_DECLARE_VISITOR(VISITOR_NAME, BASE_CLASS, CLASS_LIST)
Defines a visitor VISITOR_NAME to visit the class hierarchy rooted in BASE_CLASS and with subclasses ...
#define M_MAKE_STL_VISITABLE(VISITOR, BASE_CLASS, CLASS_LIST)
Defines a function visit() to make the class hierarchy STL-style visitable with VISITOR.
ThePreOrderOperatorVisitor< true > ConstPreOrderOperatorVisitor
ThePreOrderOperatorVisitor< false > PreOrderOperatorVisitor
void swap(PlanTableBase< Actual > &first, PlanTableBase< Actual > &second)
ThreadSafeStringPool::proxy_type ThreadSafePooledString
ThePostOrderOperatorVisitor< false > PostOrderOperatorVisitor
void accept(OperatorVisitor &v) override
const auto & aggregates() const
virtual void add_child(Producer *child) override
Adds a child to this Consumer and updates this Consumers schema accordingly.
virtual Producer * set_child(Producer *child, std::size_t i) override
Sets the i-th child of this Consumer.
std::vector< std::reference_wrapper< const ast::FnApplicationExpr > > aggregates_
the aggregates to compute
void accept(ConstOperatorVisitor &v) const override
AggregationOperator clone_node() const
Creates and returns a copy of this single operator node, i.e.
CallbackOperator clone_node() const
Creates and returns a copy of this single operator node, i.e.
std::function< void(const Schema &, const Tuple &)> callback_type
void accept(OperatorVisitor &v) override
void accept(ConstOperatorVisitor &v) const override
CallbackOperator(callback_type callback)
const auto & callback() const
A Consumer is an Operator that can be evaluated on a sequence of tuples.
void reset_ids() const override
Resets the IDs of the operator tree rooted in this.
virtual Producer * set_child(Producer *child, std::size_t i)
Sets the i-th child of this Consumer.
Producer * child(std::size_t i) const
Returns the i-th child of this Consumer.
std::vector< Producer * > & children()
virtual void add_child(Producer *child)
Adds a child to this Consumer and updates this Consumers schema accordingly.
Consumer(Consumer &&)=default
const std::vector< Producer * > & children() const
Returns a reference to the children of this Consumer.
std::vector< Producer * > children_
the children of this Consumer
void assign_post_order_ids(std::size_t start_id=0UL) const override
Assigns IDs to the operator tree rooted in this in post-order starting with ID start_id.
DisjunctiveFilterOperator clone_node() const
Creates and returns a copy of this single operator node, i.e.
void accept(OperatorVisitor &v) override
void accept(ConstOperatorVisitor &v) const override
DisjunctiveFilterOperator(cnf::CNF filter)
const cnf::CNF & filter() const
const cnf::CNF filter(cnf::CNF f)
FilterOperator clone_node() const
Creates and returns a copy of this single operator node, i.e.
void accept(ConstOperatorVisitor &v) const override
void accept(OperatorVisitor &v) override
FilterOperator(cnf::CNF filter)
std::vector< group_type > group_by_
the compound grouping key
std::vector< std::reference_wrapper< const ast::FnApplicationExpr > > aggregates_
the aggregates to compute
virtual void add_child(Producer *child) override
Adds a child to this Consumer and updates this Consumers schema accordingly.
void accept(ConstOperatorVisitor &v) const override
QueryGraph::group_type group_type
GroupingOperator clone_node() const
Creates and returns a copy of this single operator node, i.e.
const auto & aggregates() const
const auto & group_by() const
virtual Producer * set_child(Producer *child, std::size_t i) override
Sets the i-th child of this Consumer.
void accept(OperatorVisitor &v) override
const cnf::CNF & predicate() const
JoinOperator clone_node() const
Creates and returns a copy of this single operator node, i.e.
virtual void add_child(Producer *child) override
Adds a child to this Consumer and updates this Consumers schema accordingly.
virtual Producer * set_child(Producer *child, std::size_t i) override
Sets the i-th child of this Consumer.
JoinOperator(cnf::CNF predicate)
void accept(OperatorVisitor &v) override
void accept(ConstOperatorVisitor &v) const override
LimitOperator clone_node() const
Creates and returns a copy of this single operator node, i.e.
LimitOperator(std::size_t limit, std::size_t offset)
void accept(OperatorVisitor &v) override
std::size_t limit() const
void accept(ConstOperatorVisitor &v) const override
std::size_t offset() const
std::conditional_t< C, ConstOperatorVisitor, OperatorVisitor > super
typename super::template Const< T > Const
void operator()(Const< Operator > &op) override
std::conditional_t< C, ConstOperatorVisitor, OperatorVisitor > super
void operator()(Const< Operator > &op) override
typename super::template Const< T > Const
Drops the produced results and outputs only the number of result tuples produced.
void accept(ConstOperatorVisitor &v) const override
NoOpOperator clone_node() const
Creates and returns a copy of this single operator node, i.e.
NoOpOperator(std::ostream &out)
void accept(OperatorVisitor &v) override
This interface allows for attaching arbitrary data to Operator instances.
An Operator represents an operation in a query plan.
virtual void reset_ids() const
Resets the IDs of the operator tree rooted in this.
OperatorData * data() const
Returns the OperatorData attached to this Operator.
Operator(Operator &&other)
const OperatorInformation & info() const
Schema & schema()
Returns the Schema of this Operator.
virtual void assign_post_order_ids(std::size_t start_id=0UL) const
Assigns IDs to the operator tree rooted in this in post-order starting with ID start_id.
const Schema & schema() const
Returns the Schema of this Operator.
OperatorData * data(OperatorData *data) const
Attached OperatorData data to this Operator.
virtual void accept(OperatorVisitor &v)=0
std::size_t id_
the ID of this Operator; used as index in the DP table of PhysicalOperator
OperatorInformation & info()
Schema schema_
the schema of this Operator
friend M_EXPORT std::ostream & operator<<(std::ostream &out, const Operator &op)
virtual void accept(ConstOperatorVisitor &v) const =0
void id(std::size_t id) const
Sets the ID of this.
friend void swap(Operator &first, Operator &second)
std::unique_ptr< OperatorInformation > info_
additional information about this Operator
std::size_t id() const
Returns the ID of this.
OperatorData * data_
the data object associated to this Operator; may be nullptr
std::unique_ptr< OperatorInformation > info(std::unique_ptr< OperatorInformation > new_info)
Prints the produced Tuples to a std::ostream instance.
void accept(OperatorVisitor &v) override
PrintOperator clone_node() const
Creates and returns a copy of this single operator node, i.e.
PrintOperator(std::ostream &out)
void accept(ConstOperatorVisitor &v) const override
A Producer is an Operator that can be evaluated to a sequence of tuples.
Consumer * parent() const
Returns the parent of this Producer.
Consumer * parent_
the parent of this Producer
Consumer * parent(Consumer *c)
Sets the parent of this Producer.
std::vector< projection_type > projections_
std::vector< projection_type > & projections()
QueryGraph::projection_type projection_type
virtual Producer * set_child(Producer *child, std::size_t i) override
Sets the i-th child of this Consumer.
ProjectionOperator clone_node() const
Creates and returns a copy of this single operator node, i.e.
virtual void add_child(Producer *child) override
Adds a child to this Consumer and updates this Consumers schema accordingly.
void accept(OperatorVisitor &v) override
void accept(ConstOperatorVisitor &v) const override
const std::vector< projection_type > & projections() const
std::pair< std::reference_wrapper< const ast::Expr >, ThreadSafePooledOptionalString > projection_type
std::pair< std::reference_wrapper< const ast::Expr >, bool > order_type
true means ascending, false means descending
std::pair< std::reference_wrapper< const ast::Expr >, ThreadSafePooledOptionalString > group_type
void accept(OperatorVisitor &v) override
ScanOperator clone_node() const
Creates and returns a copy of this single operator node, i.e.
const ThreadSafePooledString & alias() const
const Store & store() const
void accept(ConstOperatorVisitor &v) const override
ScanOperator(const Store &store, ThreadSafePooledString alias)
ThreadSafePooledString alias_
An Identifier is composed of a name and an optional prefix.
A Schema represents a sequence of identifiers, optionally with a prefix, and their associated types.
Implements a small and efficient set over integers in the range of 0 to 63 (including).
std::vector< order_type > order_by_
the order to sort by
const auto & order_by() const
QueryGraph::order_type order_type
SortingOperator clone_node() const
Creates and returns a copy of this single operator node, i.e.
void accept(ConstOperatorVisitor &v) const override
SortingOperator(std::vector< order_type > order_by)
void accept(OperatorVisitor &v) override
Defines a generic store interface.
const Table & table() const
virtual Schema schema(const ThreadSafePooledOptionalString &alias={}) const =0
Returns a Schema for this Table given the alias alias.
A CNF represents a conjunction of cnf::Clauses.
Signals that an argument to a function of method was invalid.
Signals that an index-based or key-based access was out of range.
Exception class which can be thrown to skip recursion of the subtree in pre-order visitors.