mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
AST.cpp
Go to the documentation of this file.
2
3#include "parse/ASTDot.hpp"
4#include "parse/ASTDumper.hpp"
6#include <bit>
8
9
10using namespace m;
11using namespace m::ast;
12
13
15 static uint64_t id(0);
16 std::ostringstream oss;
17 oss << "$q_" << id++;
18 Catalog &C = Catalog::Get();
19 return C.pool(oss.str().c_str());
20}
21
22
23/*======================================================================================================================
24 * Destructors
25 *====================================================================================================================*/
26
28{
29 for (auto &f : from) {
30 if (Stmt **stmt = std::get_if<Stmt*>(&f.source))
31 delete (*stmt);
32 }
33}
34
35
36/*======================================================================================================================
37 * hash()
38 *====================================================================================================================*/
39
40uint64_t Designator::hash() const
41{
42 using std::hash;
43 auto h = hash<ThreadSafePooledOptionalString>{}(attr_name.text);
44 if (has_table_name())
45 return std::rotl(hash<ThreadSafePooledString>{}(get_table_name()), 17) xor h;
46 else
47 return h;
48}
49
50uint64_t Constant::hash() const
51{
52 using std::hash;
53 return hash<ThreadSafePooledOptionalString>{}(tok.text);
54}
55
57{
58 uint64_t hash = fn->hash();
59 for (auto &arg : args)
60 hash ^= std::rotl(hash, 31) xor arg->hash();
61 return hash;
62}
63
64uint64_t UnaryExpr::hash() const
65{
66 return std::rotl(expr->hash(), 13) xor uint64_t(op().type);
67}
68
69uint64_t BinaryExpr::hash() const
70{
71 const auto hl = lhs->hash();
72 const auto hr = rhs->hash();
73 return std::rotl(hl, 41) xor std::rotl(hr, 17) xor uint64_t(op().type);
74}
75
76uint64_t QueryExpr::hash() const
77{
78 std::hash<void*> h;
79 return h(query.get());
80}
81
82
83/*======================================================================================================================
84 * operator==()
85 *====================================================================================================================*/
86
87bool ErrorExpr::operator==(const Expr &o) const { return cast<const ErrorExpr>(&o) != nullptr; }
88
89bool Designator::operator==(const Expr &o) const
90{
91 if (auto other = cast<const Designator>(&o)) {
92 if (this->has_table_name() != other->has_table_name()) return false;
93 return this->table_name.text == other->table_name.text and this->attr_name.text == other->attr_name.text;
94 }
95 return false;
96}
97
98bool Constant::operator==(const Expr &o) const
99{
100 if (auto other = cast<const Constant>(&o))
101 return this->tok.text == other->tok.text;
102 return false;
103}
104
106{
107 if (auto other = cast<const FnApplicationExpr>(&o)) {
108 if (*this->fn != *other->fn) return false;
109 if (this->args.size() != other->args.size()) return false;
110 for (std::size_t i = 0, end = this->args.size(); i != end; ++i) {
111 if (*this->args[i] != *other->args[i])
112 return false;
113 }
114 return true;
115 }
116 return false;
117}
118
119bool UnaryExpr::operator==(const Expr &o) const
120{
121 if (auto other = cast<const UnaryExpr>(&o))
122 return this->op().text == other->op().text and *this->expr == *other->expr;
123 return false;
124}
125
126bool BinaryExpr::operator==(const Expr &o) const
127{
128 if (auto other = cast<const BinaryExpr>(&o))
129 return this->op().text == other->op().text and *this->lhs == *other->lhs and *this->rhs == *other->rhs;
130 return false;
131}
132
133bool QueryExpr::operator==(const Expr &e) const
134{
135 if (auto other = cast<const QueryExpr>(&e))
136 return this->query.get() == other->query.get();
137 return false;
138}
139
140
141/*======================================================================================================================
142 * get_required()
143 *====================================================================================================================*/
144
146{
147 Schema schema;
148 auto visitor = overloaded {
149 [](auto&) { },
150 [&schema](const Designator &d) {
151 if (d.type()->is_primitive()) { // avoid non-primitive types, e.g. functions
152 Schema::Identifier id(d.table_name.text, d.attr_name.text.assert_not_none());
153 if (not schema.has(id)) // avoid duplicates
154 schema.add(std::move(id), d.type());
155 }
156 },
157 [&schema](const FnApplicationExpr &fn) {
158 if (fn.get_function().is_aggregate()) {
159 Catalog &C = Catalog::Get();
160 static std::ostringstream oss;
161 oss.str("");
162 oss << fn;
163 Schema::Identifier id(C.pool(oss.str()));
164 if (not schema.has(id)) // avoid duplicates
165 schema.add(std::move(id), fn.type());
166 throw visit_skip_subtree{};
167 }
168 }
169 };
170 visit(visitor, *this, m::tag<ConstPreOrderExprVisitor>());
171 return schema;
172}
173
174
175/*======================================================================================================================
176 * operator<<()
177 *====================================================================================================================*/
178
179std::ostream & m::ast::operator<<(std::ostream &out, const Expr &e) {
180 ASTPrinter p(out);
181 p.expand_nested_queries(false);
182 p(e);
183 return out;
184}
185
186std::ostream & m::ast::operator<<(std::ostream &out, const Clause &c) {
187 ASTPrinter p(out);
188 p.expand_nested_queries(false);
189 p(c);
190 return out;
191}
192
193std::ostream & m::ast::operator<<(std::ostream &out, const Command &cmd) {
194 ASTPrinter p(out);
195 p.expand_nested_queries(false);
196 p(cmd);
197 return out;
198}
199
200
201/*======================================================================================================================
202 * dot()
203 *====================================================================================================================*/
204
205void Expr::dot(std::ostream &out) const
206{
207 ASTDot dot(out);
208 dot(*this);
209}
210
211void Clause::dot(std::ostream &out) const
212{
213 ASTDot dot(out);
214 dot(*this);
215}
216
217void Stmt::dot(std::ostream &out) const
218{
219 ASTDot dot(out);
220 dot(*this);
221}
222
223
224/*======================================================================================================================
225 * dump()
226 *====================================================================================================================*/
227
229void Expr::dump(std::ostream &out) const
230{
231 ASTDumper dumper(out);
232 dumper(*this);
233 out << std::endl;
234}
235void Expr::dump() const { dump(std::cerr); }
236
237void Clause::dump(std::ostream &out) const
238{
239 ASTDumper dumper(out);
240 dumper(*this);
241 out << std::endl;
242}
243void Clause::dump() const { dump(std::cerr); }
244
245void Command::dump(std::ostream &out) const
246{
247 ASTDumper dumper(out);
248 dumper(*this);
249 out << std::endl;
250}
251void Command::dump() const { dump(std::cerr); }
253
254
255/*======================================================================================================================
256 * QueryExpr
257 *====================================================================================================================*/
258
260{
261 auto &stmt = as<const SelectStmt>(*query);
262 if (stmt.from) return false;
263 auto &select = as<const SelectClause>(*stmt.select);
264 M_insist(select.select.size() == 1);
265 if (not select.select[0].first->is_constant())
266 return false;
267 return true;
268}
269
271{
272 auto &stmt = as<const SelectStmt>(*query);
273 auto &select = as<const SelectClause>(*stmt.select);
274 M_insist(select.select.size() == 1);
275 if (select.select[0].first->can_be_null())
276 return true;
277 return false;
278}
279
280
281/*======================================================================================================================
282 * accept()
283 *====================================================================================================================*/
284
285/*===== Expressions ==================================================================================================*/
286
287#define ACCEPT(CLASS) \
288 void CLASS::accept(ASTExprVisitor &v) { v(*this); } \
289 void CLASS::accept(ConstASTExprVisitor &v) const { v(*this); }
291#undef ACCEPT
292
293
294/*----- Explicit instantiations -----*/
297
298namespace {
299
300template<bool C, bool PreOrder>
301struct recursive_expr_visitor : TheRecursiveExprVisitorBase<C>
302{
303 using super = TheRecursiveExprVisitorBase<C>;
304 template<typename T> using Const = typename super::template Const<T>;
305 using callback_t = std::conditional_t<C, ConstASTExprVisitor, ASTExprVisitor>;
306
307 private:
308 callback_t &callback_;
309
310 public:
311 recursive_expr_visitor(callback_t &callback) : callback_(callback) { }
312
313 using super::operator();
314 void operator()(Const<ErrorExpr> &e) override { callback_(e); }
315 void operator()(Const<Designator> &e) override { callback_(e); }
316 void operator()(Const<Constant> &e) override { callback_(e); }
317 void operator()(Const<QueryExpr> &e) override { callback_(e); }
318
319 void operator()(Const<FnApplicationExpr> &e) override {
320 if constexpr (PreOrder) try { callback_(e); } catch (visit_skip_subtree) { return; }
321 super::operator()(e);
322 if constexpr (not PreOrder) callback_(e);
323 }
324
325 void operator()(Const<UnaryExpr> &e) override {
326 if constexpr (PreOrder) try { callback_(e); } catch (visit_skip_subtree) { return; }
327 super::operator()(e);
328 if constexpr (not PreOrder) callback_(e);
329 }
330
331 void operator()(Const<BinaryExpr> &e) override {
332 if constexpr (PreOrder) try { callback_(e); } catch (visit_skip_subtree) { return; }
333 super::operator()(e);
334 if constexpr (not PreOrder) callback_(e);
335 }
336};
337
338}
339
340template<bool C>
342{
343 recursive_expr_visitor<C, /* PreOrder= */ true>{*this}(e);
344}
345
346template<bool C>
348{
349 recursive_expr_visitor<C, /* PreOrder= */ false>{*this}(e);
350}
351
352/*----- Explicit instantiations -----*/
357
358
359/*===== Clauses ======================================================================================================*/
360
361#define ACCEPT(CLASS) \
362 void CLASS::accept(ASTClauseVisitor &v) { v(*this); } \
363 void CLASS::accept(ConstASTClauseVisitor &v) const { v(*this); }
365#undef ACCEPT
366
367/*===== Constraints ==================================================================================================*/
368
369#define ACCEPT(CLASS) \
370 void CLASS::accept(ASTConstraintVisitor &v) { v(*this); } \
371 void CLASS::accept(ConstASTConstraintVisitor &v) const { v(*this); }
373#undef ACCEPT
374
375/*===== Commands =====================================================================================================*/
376
377#define ACCEPT(CLASS) \
378 void CLASS::accept(ASTCommandVisitor &v) { v(*this); } \
379 void CLASS::accept(ConstASTCommandVisitor &v) const { v(*this); }
381#undef ACCEPT
#define M_AST_EXPR_LIST(X)
Definition: AST.hpp:427
#define M_AST_CONSTRAINT_LIST(X)
Definition: AST.hpp:735
#define M_AST_COMMAND_LIST(X)
Definition: AST.hpp:1042
#define M_AST_CLAUSE_LIST(X)
Definition: AST.hpp:642
#define ACCEPT(CLASS)
#define id(X)
#define M_insist(...)
Definition: macro.hpp:129
‍mutable namespace
Definition: Backend.hpp:10
and
Definition: enum_ops.hpp:12
auto visit(Callable &&callable, Base &obj, m::tag< Callable > &&=m::tag< Callable >())
Generic implementation to visit a class hierarchy, with similar syntax as std::visit.
Definition: Visitor.hpp:138
The catalog contains all Databases and keeps track of all meta information of the database system.
Definition: Catalog.hpp:215
ThreadSafePooledString pool(const char *str) const
Creates an internalized copy of the string str by adding it to the internal StringPool.
Definition: Catalog.hpp:274
static Catalog & Get()
Return a reference to the single Catalog instance.
A data type representing a pooled (or internalized) object.
Definition: Pool.hpp:168
An Identifier is composed of a name and an optional prefix.
Definition: Schema.hpp:42
A Schema represents a sequence of identifiers, optionally with a prefix, and their associated types.
Definition: Schema.hpp:39
void add(entry_type e)
Adds the entry e to this Schema.
Definition: Schema.hpp:181
bool has(const Identifier &id) const
Returns true iff this Schema contains an entry with Identifier id.
Definition: Schema.hpp:140
Implements printing the AST in dot language.
Definition: ASTDot.hpp:13
Dumps a textual representation of the AST to an output stream.
Definition: ASTDumper.hpp:12
Pretty-prints the AST in SQL.
Definition: ASTPrinter.hpp:10
std::unique_ptr< Expr > lhs
Definition: AST.hpp:349
uint64_t hash() const override
Computes a hash of this, considering only syntactic properties.
Definition: AST.cpp:69
bool operator==(const Expr &other) const override
Returns true iff other is syntactically equal to this.
Definition: AST.cpp:126
std::unique_ptr< Expr > rhs
Definition: AST.hpp:350
Token op() const
Definition: AST.hpp:377
void dot(std::ostream &out) const
Definition: AST.cpp:211
void dump() const
Definition: AST.cpp:243
void dump() const
Definition: AST.cpp:251
bool operator==(const Expr &other) const override
Returns true iff other is syntactically equal to this.
Definition: AST.cpp:98
uint64_t hash() const override
Computes a hash of this, considering only syntactic properties.
Definition: AST.cpp:50
A designator.
Definition: AST.hpp:134
ThreadSafePooledString get_table_name() const
Definition: AST.hpp:197
uint64_t hash() const override
Computes a hash of this, considering only syntactic properties.
Definition: AST.cpp:40
Token table_name
Definition: AST.hpp:138
Token attr_name
Definition: AST.hpp:139
bool has_table_name() const
Definition: AST.hpp:196
bool operator==(const Expr &other) const override
Returns true iff other is syntactically equal to this.
Definition: AST.cpp:89
bool operator==(const Expr &other) const override
Returns true iff other is syntactically equal to this.
Definition: AST.cpp:87
An expression.
Definition: AST.hpp:39
void dot(std::ostream &out) const
Writes a Graphivz dot representation of this Expr to out.
Definition: AST.cpp:205
const Type * type() const
Returns the Type of this Expr.
Definition: AST.hpp:58
Schema get_required() const
Returns a Schema instance containing all required definitions.
Definition: AST.cpp:145
Token tok
the token of the expression; serves as an anchor to locate the expression in the source
Definition: AST.hpp:43
void dump() const
Definition: AST.cpp:235
A function application.
Definition: AST.hpp:246
uint64_t hash() const override
Computes a hash of this, considering only syntactic properties.
Definition: AST.cpp:56
std::vector< std::unique_ptr< Expr > > args
Definition: AST.hpp:250
bool operator==(const Expr &other) const override
Returns true iff other is syntactically equal to this.
Definition: AST.cpp:105
std::unique_ptr< Expr > fn
Definition: AST.hpp:249
std::vector< from_type > from
Definition: AST.hpp:563
bool operator==(const Expr &other) const override
Returns true iff other is syntactically equal to this.
Definition: AST.cpp:133
uint64_t hash() const override
Computes a hash of this, considering only syntactic properties.
Definition: AST.cpp:76
std::unique_ptr< Stmt > query
Definition: AST.hpp:390
bool can_be_null() const override
Returns true iff this Expr is nullable, i.e.
Definition: AST.cpp:270
static ThreadSafePooledString make_unique_alias()
Definition: AST.cpp:14
bool is_constant() const override
Returns true iff this Expr is constant, i.e.
Definition: AST.cpp:259
A SQL statement.
Definition: AST.hpp:794
void dot(std::ostream &out) const
Writes a Graphivz dot representation of this Stmt to out.
Definition: AST.cpp:217
void operator()(Const< Expr > &e)
Definition: AST.cpp:347
typename super::template Const< T > Const
Definition: AST.hpp:476
void operator()(Const< Expr > &e)
Definition: AST.cpp:341
typename super::template Const< T > Const
Definition: AST.hpp:465
A generic base class for implementing recursive ast::Expr visitors.
Definition: AST.hpp:442
ThreadSafePooledOptionalString text
declared as optional for dummy tokens
Definition: Token.hpp:16
Token op() const
Definition: AST.hpp:336
uint64_t hash() const override
Computes a hash of this, considering only syntactic properties.
Definition: AST.cpp:64
bool operator==(const Expr &other) const override
Returns true iff other is syntactically equal to this.
Definition: AST.cpp:119
std::unique_ptr< Expr > expr
Definition: AST.hpp:325
Definition: tag.hpp:8
Exception class which can be thrown to skip recursion of the subtree in pre-order visitors.
Definition: Visitor.hpp:18