Branch data Line data Source code
1 : : #include <mutable/catalog/Schema.hpp>
2 : :
3 : : #include <algorithm>
4 : : #include <cmath>
5 : : #include <iostream>
6 : : #include <iterator>
7 : : #include <mutable/catalog/CardinalityEstimator.hpp>
8 : : #include <mutable/catalog/Catalog.hpp>
9 : : #include <mutable/catalog/CostFunction.hpp>
10 : : #include <mutable/catalog/CostFunctionCout.hpp>
11 : : #include <mutable/IR/Operator.hpp>
12 : : #include <mutable/IR/PlanTable.hpp>
13 : : #include <mutable/lex/Token.hpp>
14 : : #include <mutable/Options.hpp>
15 : : #include <mutable/parse/AST.hpp>
16 : : #include <mutable/util/enum_ops.hpp>
17 : : #include <mutable/util/fn.hpp>
18 : : #include <stdexcept>
19 : :
20 : :
21 : : using namespace m;
22 : :
23 : :
24 : : /*======================================================================================================================
25 : : * Schema
26 : : *====================================================================================================================*/
27 : :
28 : 120 : Schema::Identifier Schema::Identifier::GetConstant()
29 : : {
30 [ + - ]: 120 : return Identifier(Catalog::Get().pool("$const"));
31 : 0 : }
32 : :
33 : 3622 : Schema::Identifier::Identifier(const ast::Expr &expr)
34 [ + - + - ]: 3622 : : name(Catalog::Get().pool(""))
35 : : {
36 [ + - + + ]: 3622 : if (auto d = cast<const ast::Designator>(&expr)) {
37 [ + - + - ]: 292 : prefix = d->table_name.text;
38 [ + - + - ]: 292 : name = d->attr_name.text.assert_not_none();
39 : 292 : } else {
40 [ + - ]: 3330 : std::ostringstream oss;
41 [ + - ]: 3330 : oss << expr;
42 [ + - ]: 3330 : prefix = {};
43 [ + - + - : 3330 : name = Catalog::Get().pool(oss.str().c_str());
+ - - + ]
44 : 3330 : }
45 : 3622 : }
46 : :
47 [ # # ]: 0 : Schema::entry_type::entry_type() : id(Catalog::Get().pool("")) { }
48 : :
49 : : M_LCOV_EXCL_START
50 : : void Schema::dump(std::ostream &out) const { out << *this << std::endl; }
51 : : void Schema::dump() const { dump(std::cerr); }
52 : : M_LCOV_EXCL_STOP
53 : :
54 : :
55 : : /*======================================================================================================================
56 : : * Attribute
57 : : *====================================================================================================================*/
58 : :
59 : 4223 : bool Attribute::is_unique() const {
60 : 4223 : auto primary_key = table.primary_key();
61 : 7650 : auto pred = [this](const auto &ref){ return *this == ref.get(); };
62 [ - + + + ]: 7650 : return unique or (primary_key.size() == 1 and
63 [ + - ]: 3427 : std::find_if(primary_key.cbegin(), primary_key.cend(), pred) != primary_key.cend());
64 : 4223 : }
65 : :
66 : : M_LCOV_EXCL_START
67 : : void Attribute::dump(std::ostream &out) const
68 : : {
69 : : out << "Attribute `" << table.name() << "`.`" << name << "`, "
70 : : << "id " << id << ", "
71 : : << "type " << *type
72 : : << std::endl;
73 : : }
74 : :
75 : : void Attribute::dump() const { dump(std::cerr); }
76 : : M_LCOV_EXCL_STOP
77 : :
78 : :
79 : : /*======================================================================================================================
80 : : * ConcreteTable
81 : : *====================================================================================================================*/
82 : :
83 : 1027 : Schema ConcreteTable::schema(const ThreadSafePooledOptionalString &alias) const
84 : : {
85 : 1027 : Schema S;
86 [ + - + - : 5250 : for (auto attr = this->begin_all(); attr != this->end_all(); ++attr) {
+ - + + +
- ]
87 : 4223 : Schema::entry_type::constraints_t constraints{0};
88 [ + - - + ]: 4223 : if (attr->not_nullable)
89 [ # # ]: 0 : constraints |= Schema::entry_type::NOT_NULLABLE;
90 [ + - + - : 4223 : if (attr->is_unique())
+ + ]
91 [ + - ]: 866 : constraints |= Schema::entry_type::UNIQUE;
92 [ + - - + : 4223 : if (attr->reference and attr->reference->is_unique())
# # # # #
# ]
93 [ # # ]: 0 : constraints |= Schema::entry_type::REFERENCES_UNIQUE;
94 [ + - - + ]: 4223 : if (attr->is_hidden)
95 [ # # ]: 0 : constraints |= Schema::entry_type::IS_HIDDEN;
96 [ + - + + : 4223 : S.add({alias.has_value() ? alias : this->name(), attr->name}, attr->type, constraints);
+ - + - +
- + - + -
- + + - +
- + + + +
# # # # ]
97 : 4223 : }
98 : 1027 : return S;
99 [ + - ]: 1027 : }
100 : :
101 : 338 : void ConcreteTable::layout(const storage::DataLayoutFactory &factory) {
102 : 1244 : view v(cbegin_all(), cend_all(), [](auto it) -> auto & { return it->type; });
103 [ + - + - : 338 : layout_ = factory.make(v.begin(), v.end());
+ - ]
104 : 338 : }
105 : :
106 : : M_LCOV_EXCL_START
107 : : void ConcreteTable::dump(std::ostream &out) const
108 : : {
109 : : out << "Table `" << name_ << '`';
110 : : for (const auto &attr : attrs_)
111 : : out << "\n` " << attr.id << ": `" << attr.name << "` " << *attr.type;
112 : : out << std::endl;
113 : : }
114 : :
115 : : void ConcreteTable::dump() const { dump(std::cerr); }
116 : : M_LCOV_EXCL_STOP
117 : :
118 : :
119 : : /*======================================================================================================================
120 : : * MultiVersioningTable
121 : : *====================================================================================================================*/
122 : :
123 : 10 : MultiVersioningTable::MultiVersioningTable(std::unique_ptr<Table> table)
124 [ + - ]: 10 : : TableDecorator(std::move(table))
125 : 10 : {
126 [ + - ]: 10 : auto &C = Catalog::Get();
127 : :
128 : : /*----- Add hidden timestamp attributes. -----*/
129 [ + - ]: 10 : auto i8 = Type::Get_Integer(Type::TY_Vector, 8);
130 [ + - ]: 10 : auto ts_begin = C.pool("$ts_begin");
131 [ - + ]: 10 : auto ts_end = C.pool("$ts_end");
132 [ + - + - : 10 : table_->push_back(ts_begin, i8);
+ - ]
133 [ + - + - : 10 : table_->push_back(ts_end, i8);
+ - ]
134 [ + - ]: 10 : (*table_)[ts_begin].is_hidden = true;
135 [ + - ]: 10 : (*table_)[ts_begin].not_nullable = true;
136 [ + - ]: 10 : (*table_)[ts_end].is_hidden = true;
137 [ + - ]: 10 : (*table_)[ts_end].not_nullable = true;
138 : 10 : }
139 : :
140 : : M_LCOV_EXCL_START
141 : : void MultiVersioningTable::dump(std::ostream &out) const
142 : : {
143 : : out << "MultiVersioningTable Decorator" << std::endl;
144 : : table_->dump(out);
145 : : }
146 : :
147 : : void MultiVersioningTable::dump() const { dump(std::cerr); }
148 : : M_LCOV_EXCL_STOP
149 : :
150 : :
151 : : namespace {
152 : :
153 : :
154 : 0 : void apply_timestamp_filter(QueryGraph &G)
155 : : {
156 : 0 : Catalog &C = Catalog::Get();
157 : :
158 : 0 : auto pos = Position(nullptr);
159 [ # # ]: 0 : ast::Token ts_begin(pos, C.pool("$ts_begin"), TK_IDENTIFIER);
160 [ # # # # ]: 0 : ast::Token ts_end(pos, C.pool("$ts_end"), TK_IDENTIFIER);
161 : :
162 [ # # # # ]: 0 : for (auto &ds : G.sources()) {
163 [ # # # # ]: 0 : if (auto bt = cast<const BaseTable>(ds.get())) {
164 : : /* Set timestamp filter */
165 [ # # # # : 0 : auto it = std::find_if(bt->table().cbegin_hidden(),
# # ]
166 [ # # # # ]: 0 : bt->table().end_hidden(),
167 : 0 : [&](const Attribute & attr) {
168 : 0 : return attr.name == C.pool("$ts_begin");
169 : : });
170 : :
171 [ # # # # : 0 : if (it != bt->table().end_hidden()) {
# # # # ]
172 [ # # # # : 0 : ast::Token table_name(pos, bt->table().name(), TK_EOF);
# # # # ]
173 : : /*----- Build AST -----*/
174 : : // $ts_begin
175 [ # # ]: 0 : std::unique_ptr<ast::Expr> ts_begin_designator = std::make_unique<ast::Designator>(
176 : : ts_begin,
177 : : table_name,
178 : : ts_begin,
179 [ # # ]: 0 : Type::Get_Integer(Type::TY_Vector, 8),
180 [ # # ]: 0 : &*it
181 : : );
182 : :
183 : : // TST := transaction start time constant
184 [ # # # # ]: 0 : std::unique_ptr<ast::Expr> ts_begin_transaction_constant = std::make_unique<ast::Constant>(ast::Token(
185 : 0 : pos,
186 [ # # # # : 0 : C.pool(std::to_string(G.transaction()->start_time()).c_str()),
# # # # ]
187 : : m::TK_DEC_INT
188 : : ));
189 [ # # # # : 0 : ts_begin_transaction_constant->type(Type::Get_Integer(Type::TY_Vector, 8));
# # ]
190 : :
191 : : // $ts_begin <= TST
192 [ # # ]: 0 : std::unique_ptr<ast::Expr> ts_begin_filter_clause = std::make_unique<ast::BinaryExpr>(
193 [ # # # # ]: 0 : ast::Token(pos, C.pool("<="), TK_LESS_EQUAL),
194 : : std::move(ts_begin_designator),
195 : : std::move(ts_begin_transaction_constant)
196 : : );
197 [ # # # # : 0 : ts_begin_filter_clause->type(Type::Get_Boolean(Type::TY_Vector));
# # ]
198 : :
199 : : // $ts_end
200 [ # # ]: 0 : std::unique_ptr<ast::Expr> ts_end_designator = std::make_unique<ast::Designator>(
201 : : ts_end,
202 : : table_name,
203 : : ts_end,
204 [ # # ]: 0 : Type::Get_Integer(Type::TY_Vector, 8),
205 [ # # # # : 0 : &bt->table()[C.pool("$ts_end")]
# # ]
206 : : );
207 : :
208 : : // TST := transaction start time constant
209 [ # # # # ]: 0 : std::unique_ptr<ast::Expr> ts_end_transaction_constant = std::make_unique<ast::Constant>(ast::Token(
210 : 0 : pos,
211 [ # # # # : 0 : C.pool(std::to_string(G.transaction()->start_time()).c_str()),
# # # # ]
212 : : m::TK_DEC_INT
213 : : ));
214 [ # # # # : 0 : ts_end_transaction_constant->type(Type::Get_Integer(Type::TY_Vector, 8));
# # ]
215 : :
216 : : // $ts_end > TST
217 [ # # ]: 0 : std::unique_ptr<ast::Expr> ts_end_greater_transaction_expr = std::make_unique<ast::BinaryExpr>(
218 [ # # # # ]: 0 : ast::Token(pos, C.pool(">"), TK_GREATER),
219 : : std::move(ts_end_designator),
220 : : std::move(ts_end_transaction_constant)
221 : : );
222 [ # # # # : 0 : ts_end_greater_transaction_expr->type(Type::Get_Boolean(Type::TY_Vector));
# # ]
223 : :
224 : : // $ts_end
225 [ # # ]: 0 : std::unique_ptr<ast::Expr> ts_end_designator_2 = std::make_unique<ast::Designator>(
226 : : ts_end,
227 : : table_name,
228 : : ts_end,
229 [ # # ]: 0 : Type::Get_Integer(Type::TY_Vector, 8),
230 [ # # # # : 0 : &bt->table()[C.pool("$ts_end")]
# # ]
231 : : );
232 : :
233 : : // -1
234 [ # # # # ]: 0 : std::unique_ptr<ast::Expr> neg_one_constant = std::make_unique<ast::Constant>(ast::Token(
235 : 0 : pos,
236 [ # # ]: 0 : C.pool("-1"),
237 : : m::TK_DEC_INT
238 : : ));
239 [ # # # # : 0 : neg_one_constant->type(Type::Get_Integer(Type::TY_Vector, 8));
# # ]
240 : :
241 : : // $ts_end = -1
242 [ # # ]: 0 : std::unique_ptr<ast::Expr> ts_end_eq_zero = std::make_unique<ast::BinaryExpr>(
243 [ # # # # ]: 0 : ast::Token(pos, C.pool("="), TK_EQUAL),
244 : : std::move(ts_end_designator_2),
245 : : std::move(neg_one_constant)
246 : : );
247 [ # # # # : 0 : ts_end_eq_zero->type(Type::Get_Boolean(Type::TY_Vector));
# # ]
248 : :
249 : : // $ts_end > TST OR $ts_end = -1
250 [ # # ]: 0 : std::unique_ptr<ast::Expr> ts_end_filter_clause = std::make_unique<ast::BinaryExpr>(
251 [ # # # # ]: 0 : ast::Token(pos, C.pool("OR"), TK_Or),
252 : : std::move(ts_end_greater_transaction_expr),
253 : : std::move(ts_end_eq_zero)
254 : : );
255 [ # # # # : 0 : ts_end_filter_clause->type(Type::Get_Boolean(Type::TY_Vector));
# # ]
256 : :
257 : : // $ts_begin <= TST AND ($ts_end > TST OR $ts_end = 0)
258 [ # # ]: 0 : std::unique_ptr<ast::Expr> filter_expr = std::make_unique<ast::BinaryExpr>(
259 [ # # # # ]: 0 : ast::Token(pos, C.pool("AND"), TK_And),
260 : : std::move(ts_begin_filter_clause),
261 : : std::move(ts_end_filter_clause)
262 : : );
263 [ # # # # : 0 : filter_expr->type(Type::Get_Boolean(Type::TY_Vector));
# # ]
264 : :
265 [ # # ]: 0 : G.add_custom_filter(std::move(filter_expr), *ds);
266 : 0 : }
267 : 0 : }
268 : : }
269 : 0 : }
270 : :
271 : : __attribute__((constructor(202)))
272 : 1 : void register_pre_optimization()
273 : : {
274 : 1 : Catalog &C = Catalog::Get();
275 [ + - + - ]: 2 : C.register_pre_optimization(C.pool("multi-versioning"),
276 : 1 : apply_timestamp_filter,
277 : : "adds timestamp filters to the QueryGraph");
278 : 1 : }
279 : :
280 : :
281 : : }
282 : :
283 : :
284 : : /*======================================================================================================================
285 : : * Function
286 : : *====================================================================================================================*/
287 : :
288 : : constexpr const char * Function::FNID_TO_STR_[];
289 : : constexpr const char * Function::KIND_TO_STR_[];
290 : :
291 : : M_LCOV_EXCL_START
292 : : void Function::dump(std::ostream &out) const
293 : : {
294 : : out << "Function{ name = \"" << name << "\", fnid = " << FNID_TO_STR_[fnid] << ", kind = " << KIND_TO_STR_[kind]
295 : : << "}" << std::endl;
296 : : }
297 : : M_LCOV_EXCL_STOP
298 : :
299 : :
300 : : /*======================================================================================================================
301 : : * Database
302 : : *====================================================================================================================*/
303 : :
304 : 944 : Database::Database(ThreadSafePooledString name)
305 : 472 : : name(name)
306 : : {
307 [ + - + - : 472 : cardinality_estimator_ = Catalog::Get().create_cardinality_estimator(std::move(name));
- + ]
308 : 472 : }
309 : :
310 : 472 : Database::~Database()
311 : : {
312 [ - + ]: 472 : for (auto &f : functions_)
313 [ # # ]: 0 : delete f.second;
314 : 472 : }
315 : :
316 : 763 : Table & Database::add_table(ThreadSafePooledString name) {
317 : 763 : auto it = tables_.find(name);
318 [ + - # # ]: 763 : if (it != tables_.end()) throw std::invalid_argument("table with that name already exists");
319 [ + - + - ]: 763 : it = tables_.emplace_hint(it, std::move(name), Catalog::Get().table_factory().make(name));
320 : 763 : return *it->second;
321 : 0 : }
322 : :
323 : 78 : const Function * Database::get_function(const ThreadSafePooledString &name) const
324 : : {
325 : : try {
326 [ - + ]: 78 : return functions_.at(name);
327 [ - + ]: 79 : } catch (std::out_of_range) {
328 : : /* not defined within the database; search the global catalog */
329 [ + - + + ]: 78 : return Catalog::Get().get_function(name);
330 [ - + ]: 78 : }
331 : 156 : }
|