mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
QueryGraph2SQL.cpp
Go to the documentation of this file.
2
5
6
7using namespace m;
8
10{
11 graph_ = &graph;
12 after_grouping_ = true;
13 out_ << "SELECT ";
14 if (graph_->projections().empty()) {
15 out_ << '*';
16 } else {
17 for (auto it = graph_->projections().begin(); it != graph_->projections().end(); ++it) {
18 if (it != graph_->projections().begin())
19 out_ << ", ";
21 }
22 }
23
24 after_grouping_ = false;
25 if (not graph_->sources().empty()) {
26 out_ << " FROM ";
27 for (auto it = graph_->sources().begin(); it != graph_->sources().end(); ++it) {
28 if (it != graph_->sources().begin())
29 out_ << ", ";
30 auto &ds = *it;
31 if (auto base = cast<BaseTable>(ds.get())) {
32 auto name = base->table().name();
33 out_ << name;
34 if (name != ds->alias()) {
35 M_insist(ds->alias().has_value());
36 out_ << " AS " << ds->alias();
37 }
38 } else if (auto query = cast<Query>(ds.get())) {
39 out_ << '(';
40 QueryGraph2SQL trans(out_);
41 trans.translate(query->query_graph());
42 out_ << ") AS ";
43 if (ds->alias().has_value())
44 out_ << ds->alias();
45 else
46 out_ << make_unique_alias(); // query is anonymous -> alias is never used but required by SQL syntax
47 } else {
48 M_unreachable("invalid variant");
49 }
50 }
51 }
52
53 cnf::CNF where;
54 for (auto &ds : graph_->sources())
55 where = where and ds->filter();
56 for (auto &j : graph_->joins())
57 where = where and j->condition();
58 if (not where.empty()) {
59 out_ << " WHERE ";
60 (*this)(where);
61 }
62
63 if (not graph_->group_by().empty()) {
64 out_ << " GROUP BY ";
65 for (auto it = graph_->group_by().begin(); it != graph_->group_by().end(); ++it) {
66 if (it != graph_->group_by().begin())
67 out_ << ", ";
68 (*this)(it->first);
69 if (it->second.has_value())
70 out_ << " AS " << it->second;
71 }
72 }
73
74 after_grouping_ = true;
75 if (not graph_->order_by().empty()) {
76 out_ << " ORDER BY ";
77 for (auto it = graph_->order_by().begin(); it != graph_->order_by().end(); ++it) {
78 if (it != graph_->order_by().begin())
79 out_ << ", ";
80 (*this)(it->first);
81 if (it->second)
82 out_ << " ASC";
83 else
84 out_ << " DESC";
85 }
86 }
87
88 if (auto limit = graph_->limit().limit, offset = graph_->limit().offset; limit != 0 or offset != 0 ) {
89 out_ << " LIMIT " << limit;
90 if (offset != 0)
91 out_ << " OFFSET " << offset;
92 }
93}
94
96{
97 /* Translate the given `Expr` recursively. Set `after_grouping` because we want to insert a projection for the
98 * output of the grouping operator. */
99 std::ostringstream expr;
100 QueryGraph2SQL expr_trans(expr, graph_, true);
101 expr_trans(*e);
102 /* Build an alias from the textual representation of the given `Expr` by replacing every occurrence of a special
103 * character with `_`. */
104 auto alias = to_string(*e);
105 alias = replace_all(alias, ".", "_");
106 alias = replace_all(alias, ",", "_");
107 alias = replace_all(alias, " ", "_");
108 alias = replace_all(alias, "(", "_");
109 alias = replace_all(alias, ")", "_");
110 /* Compare both translations and add an alias iff they differ. */
111 if (streq(expr.str().c_str(), alias.c_str()))
112 out_ << expr.str();
113 else
114 out_ << expr.str() << " AS " << alias;
115}
116
118 const std::pair<std::reference_wrapper<const ast::Expr>, ThreadSafePooledOptionalString> p)
119{
120 if (p.second.has_value()) {
121 /* With alias. Translate recursively and add the alias. */
122 (*this)(p.first.get());
123 out_ << " AS ";
124 std::string alias(*p.second);
125 alias = replace_all(alias, "$", "_"); // for `$res` in decorrelated queries
126 out_ << alias;
127 } else {
128 /* Without alias. Insert the given `Expr` and add an alias iff needed. */
129 insert_projection(&p.first.get());
130 }
131}
132
134{
135 static uint64_t id(0);
136 std::ostringstream oss;
137 oss << "alias_" << id++;
138 Catalog &C = Catalog::Get();
139 return C.pool(oss.str().c_str());
140}
141
142void QueryGraph2SQL::operator()(Const<ast::ErrorExpr>&)
143{
144 M_unreachable("graph must not contain errors");
145}
146
147void QueryGraph2SQL::operator()(Const<ast::Designator> &e)
148{
149 if (e.table_name)
150 out_ << e.table_name.text << '.';
151 out_ << e.attr_name.text;
152}
153
154void QueryGraph2SQL::operator()(Const<ast::Constant> &e)
155{
156 out_ << e.tok.text;
157}
158
159void QueryGraph2SQL::operator()(Const<ast::FnApplicationExpr> &e)
160{
161 if (after_grouping_) {
162 (*this)(*e.fn);
163 out_ << '(';
164 for (auto it = e.args.cbegin(), end = e.args.cend(); it != end; ++it) {
165 if (it != e.args.cbegin())
166 out_ << ", ";
167 (*this)(**it);
168 }
169 out_ << ')';
170 } else {
171 auto expr = to_string(e);
172 expr = replace_all(expr, ".", "_");
173 expr = replace_all(expr, ",", "_");
174 expr = replace_all(expr, " ", "_");
175 expr = replace_all(expr, "(", "_");
176 expr = replace_all(expr, ")", "_");
177 out_ << expr;
178 }
179}
180
181void QueryGraph2SQL::operator()(Const<ast::UnaryExpr> &e)
182{
183 out_ << '(' << e.op().text;
184 if (e.op() == TK_Not) out_ << ' ';
185 (*this)(*e.expr);
186 out_ << ')';
187}
188
189void QueryGraph2SQL::operator()(Const<ast::BinaryExpr> &e)
190{
191 out_ << '(';
192 (*this)(*e.lhs);
193 out_ << ' ' << e.op().text << ' ';
194 (*this)(*e.rhs);
195 out_ << ')';
196}
197
198void QueryGraph2SQL::operator()(Const<ast::QueryExpr> &e)
199{
200 out_ << e.alias() << "._res";
201}
202
204{
205 if (pred.negative())
206 out_ << "NOT ";
207 (*this)(*pred);
208}
209
211{
212 for (auto it = clause.begin(); it != clause.end(); ++it) {
213 if (it != clause.begin())
214 out_ << " OR ";
215 (*this)(*it);
216 }
217}
218
220{
221 if (cnf.empty())
222 out_ << "TRUE";
223 else if (cnf.size() == 1)
224 (*this)(cnf[0]);
225 else {
226 for (auto it = cnf.begin(); it != cnf.end(); ++it) {
227 if (it != cnf.begin())
228 out_ << " AND ";
229 out_ << '(';
230 (*this)(*it);
231 out_ << ')';
232 }
233 }
234}
#define id(X)
#define M_unreachable(MSG)
Definition: macro.hpp:146
#define M_insist(...)
Definition: macro.hpp:129
::wasm::Expression * expr()
Moves the underlying Binaryen ::wasm::Expression out of this.
Definition: WasmDSL.hpp:1558
‍mutable namespace
Definition: Backend.hpp:10
std::string replace_all(std::string str, const std::string &from, const std::string &to)
Definition: fn.hpp:35
bool streq(const char *first, const char *second)
Definition: fn.hpp:29
std::string to_string(const TokenType tt)
Definition: TokenType.hpp:58
and
Definition: enum_ops.hpp:12
ThreadSafeStringPool::proxy_optional_type ThreadSafePooledOptionalString
Definition: Pool.hpp:465
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
Translates a query graph in SQL.
void insert_projection(const ast::Expr *)
Inserts a projection for the given Expr which is computed by a grouping operator.
void translate_projection(std::pair< std::reference_wrapper< const ast::Expr >, ThreadSafePooledOptionalString >)
Translates a projection for the given pair of Expr and alias.
void translate(const QueryGraph &)
Translates the given QueryGraph into SQL.
void operator()(const QueryGraph &graph)
static ThreadSafePooledString make_unique_alias()
bool after_grouping_
the graph to translate
std::ostream & out_
the output stream to write to
const QueryGraph * graph_
The query graph represents all data sources and joins in a graph structure.
Definition: QueryGraph.hpp:172
const auto & group_by() const
Definition: QueryGraph.hpp:259
const std::vector< projection_type > & projections() const
Definition: QueryGraph.hpp:261
const auto & joins() const
Definition: QueryGraph.hpp:258
const auto & order_by() const
Definition: QueryGraph.hpp:262
const auto & sources() const
Definition: QueryGraph.hpp:257
uint64_t limit
Definition: QueryGraph.hpp:190
An expression.
Definition: AST.hpp:39
A CNF represents a conjunction of cnf::Clauses.
Definition: CNF.hpp:134
A cnf::Clause represents a disjunction of Predicates.
Definition: CNF.hpp:87
A Predicate contains a Expr of Boolean type in either positive or negative form.
Definition: CNF.hpp:16
bool negative() const
Returns true iff this Predicate is negative.
Definition: CNF.hpp:31