Branch data Line data Source code
1 : : #include <mutable/parse/AST.hpp> 2 : : 3 : : #include "parse/ASTDot.hpp" 4 : : #include "parse/ASTDumper.hpp" 5 : : #include "parse/ASTPrinter.hpp" 6 : : #include <bit> 7 : : #include <mutable/catalog/Catalog.hpp> 8 : : 9 : : 10 : : using namespace m; 11 : : using namespace m::ast; 12 : : 13 : : 14 : 47 : ThreadSafePooledString QueryExpr::make_unique_alias() { 15 : : static uint64_t id(0); 16 : 47 : std::ostringstream oss; 17 [ + - + - ]: 47 : oss << "$q_" << id++; 18 [ + - ]: 47 : Catalog &C = Catalog::Get(); 19 [ + - - + ]: 47 : return C.pool(oss.str().c_str()); 20 : 47 : } 21 : : 22 : : 23 : : /*====================================================================================================================== 24 : : * Destructors 25 : : *====================================================================================================================*/ 26 : : 27 : 1154 : FromClause::~FromClause() 28 : 1154 : { 29 [ + + ]: 1416 : for (auto &f : from) { 30 [ + + ]: 839 : if (Stmt **stmt = std::get_if<Stmt*>(&f.source)) 31 [ - + ]: 29 : delete (*stmt); 32 : : } 33 : 1154 : } 34 : : 35 : : 36 : : /*====================================================================================================================== 37 : : * hash() 38 : : *====================================================================================================================*/ 39 : : 40 : 526 : uint64_t Designator::hash() const 41 : : { 42 : : using std::hash; 43 : 526 : auto h = hash<ThreadSafePooledOptionalString>{}(attr_name.text); 44 [ - + ]: 526 : if (has_table_name()) 45 [ - + ]: 526 : return std::rotl(hash<ThreadSafePooledString>{}(get_table_name()), 17) xor h; 46 : : else 47 : 0 : return h; 48 : 526 : } 49 : : 50 : 6 : uint64_t Constant::hash() const 51 : : { 52 : : using std::hash; 53 : 6 : return hash<ThreadSafePooledOptionalString>{}(tok.text); 54 : : } 55 : : 56 : 0 : uint64_t FnApplicationExpr::hash() const 57 : : { 58 : 0 : uint64_t hash = fn->hash(); 59 [ # # ]: 0 : for (auto &arg : args) 60 : 0 : hash ^= std::rotl(hash, 31) xor arg->hash(); 61 : 0 : return hash; 62 : : } 63 : : 64 : 0 : uint64_t UnaryExpr::hash() const 65 : : { 66 : 0 : return std::rotl(expr->hash(), 13) xor uint64_t(op().type); 67 : 0 : } 68 : : 69 : 265 : uint64_t BinaryExpr::hash() const 70 : : { 71 : 265 : const auto hl = lhs->hash(); 72 : 265 : const auto hr = rhs->hash(); 73 : 265 : return std::rotl(hl, 41) xor std::rotl(hr, 17) xor uint64_t(op().type); 74 : 1 : } 75 : : 76 : 0 : uint64_t QueryExpr::hash() const 77 : : { 78 : : std::hash<void*> h; 79 : 0 : return h(query.get()); 80 : : } 81 : : 82 : : 83 : : /*====================================================================================================================== 84 : : * operator==() 85 : : *====================================================================================================================*/ 86 : : 87 : 0 : bool ErrorExpr::operator==(const Expr &o) const { return cast<const ErrorExpr>(&o) != nullptr; } 88 : : 89 : 418 : bool Designator::operator==(const Expr &o) const 90 : : { 91 [ + - ]: 418 : if (auto other = cast<const Designator>(&o)) { 92 [ - + ]: 418 : if (this->has_table_name() != other->has_table_name()) return false; 93 [ + - + - : 836 : return this->table_name.text == other->table_name.text and this->attr_name.text == other->attr_name.text; + - + - - + # # ] 94 : : } 95 : 0 : return false; 96 : 418 : } 97 : : 98 : 33 : bool Constant::operator==(const Expr &o) const 99 : : { 100 [ + - ]: 33 : if (auto other = cast<const Constant>(&o)) 101 [ + - ]: 33 : return this->tok.text == other->tok.text; 102 : 0 : return false; 103 : 33 : } 104 : : 105 : 20 : bool FnApplicationExpr::operator==(const Expr &o) const 106 : : { 107 [ + - ]: 20 : if (auto other = cast<const FnApplicationExpr>(&o)) { 108 [ + + ]: 20 : if (*this->fn != *other->fn) return false; 109 [ - + ]: 17 : if (this->args.size() != other->args.size()) return false; 110 [ + + ]: 34 : for (std::size_t i = 0, end = this->args.size(); i != end; ++i) { 111 [ - + ]: 17 : if (*this->args[i] != *other->args[i]) 112 : 0 : return false; 113 : 17 : } 114 : 17 : return true; 115 : : } 116 : 0 : return false; 117 : 20 : } 118 : : 119 : 0 : bool UnaryExpr::operator==(const Expr &o) const 120 : : { 121 [ # # ]: 0 : if (auto other = cast<const UnaryExpr>(&o)) 122 [ # # # # : 0 : return this->op().text == other->op().text and *this->expr == *other->expr; # # # # # # ] 123 : 0 : return false; 124 : 0 : } 125 : : 126 : 40 : bool BinaryExpr::operator==(const Expr &o) const 127 : : { 128 [ + - ]: 40 : if (auto other = cast<const BinaryExpr>(&o)) 129 [ + - - + : 80 : return this->op().text == other->op().text and *this->lhs == *other->lhs and *this->rhs == *other->rhs; + - + - + - + - + - ] 130 : 0 : return false; 131 : 40 : } 132 : : 133 : 0 : bool QueryExpr::operator==(const Expr &e) const 134 : : { 135 [ # # ]: 0 : if (auto other = cast<const QueryExpr>(&e)) 136 : 0 : return this->query.get() == other->query.get(); 137 : 0 : return false; 138 : 0 : } 139 : : 140 : : 141 : : /*====================================================================================================================== 142 : : * get_required() 143 : : *====================================================================================================================*/ 144 : : 145 : 0 : Schema Expr::get_required() const 146 : : { 147 : 0 : Schema schema; 148 : 0 : auto visitor = overloaded { 149 : 0 : [](auto&) { }, 150 : 0 : [&schema](const Designator &d) { 151 [ # # ]: 0 : if (d.type()->is_primitive()) { // avoid non-primitive types, e.g. functions 152 [ # # # # ]: 0 : Schema::Identifier id(d.table_name.text, d.attr_name.text.assert_not_none()); 153 [ # # # # ]: 0 : if (not schema.has(id)) // avoid duplicates 154 [ # # # # : 0 : schema.add(std::move(id), d.type()); # # ] 155 : 0 : } 156 : 0 : }, 157 : 0 : [&schema](const FnApplicationExpr &fn) { 158 [ # # ]: 0 : if (fn.get_function().is_aggregate()) { 159 : 0 : Catalog &C = Catalog::Get(); 160 [ # # # # : 0 : static std::ostringstream oss; # # ] 161 [ # # # # ]: 0 : oss.str(""); 162 : 0 : oss << fn; 163 [ # # # # ]: 0 : Schema::Identifier id(C.pool(oss.str())); 164 [ # # # # ]: 0 : if (not schema.has(id)) // avoid duplicates 165 [ # # # # : 0 : schema.add(std::move(id), fn.type()); # # ] 166 [ # # ]: 0 : throw visit_skip_subtree{}; 167 : 0 : } 168 : 0 : } 169 : : }; 170 [ # # ]: 0 : visit(visitor, *this, m::tag<ConstPreOrderExprVisitor>()); 171 : 0 : return schema; 172 [ # # ]: 0 : } 173 : : 174 : : 175 : : /*====================================================================================================================== 176 : : * operator<<() 177 : : *====================================================================================================================*/ 178 : : 179 : 6082 : std::ostream & m::ast::operator<<(std::ostream &out, const Expr &e) { 180 : 6082 : ASTPrinter p(out); 181 [ + - ]: 6082 : p.expand_nested_queries(false); 182 [ + - ]: 6082 : p(e); 183 : 6082 : return out; 184 : 6082 : } 185 : : 186 : 2 : std::ostream & m::ast::operator<<(std::ostream &out, const Clause &c) { 187 : 2 : ASTPrinter p(out); 188 [ + - ]: 2 : p.expand_nested_queries(false); 189 [ + - ]: 2 : p(c); 190 : 2 : return out; 191 : 2 : } 192 : : 193 : 0 : std::ostream & m::ast::operator<<(std::ostream &out, const Command &cmd) { 194 : 0 : ASTPrinter p(out); 195 [ # # ]: 0 : p.expand_nested_queries(false); 196 [ # # ]: 0 : p(cmd); 197 : 0 : return out; 198 : 0 : } 199 : : 200 : : 201 : : /*====================================================================================================================== 202 : : * dot() 203 : : *====================================================================================================================*/ 204 : : 205 : 0 : void Expr::dot(std::ostream &out) const 206 : : { 207 : 0 : ASTDot dot(out); 208 [ # # ]: 0 : dot(*this); 209 : 0 : } 210 : : 211 : 0 : void Clause::dot(std::ostream &out) const 212 : : { 213 : 0 : ASTDot dot(out); 214 [ # # ]: 0 : dot(*this); 215 : 0 : } 216 : : 217 : 0 : void Stmt::dot(std::ostream &out) const 218 : : { 219 : 0 : ASTDot dot(out); 220 [ # # ]: 0 : dot(*this); 221 : 0 : } 222 : : 223 : : 224 : : /*====================================================================================================================== 225 : : * dump() 226 : : *====================================================================================================================*/ 227 : : 228 : : M_LCOV_EXCL_START 229 : : void Expr::dump(std::ostream &out) const 230 : : { 231 : : ASTDumper dumper(out); 232 : : dumper(*this); 233 : : out << std::endl; 234 : : } 235 : : void Expr::dump() const { dump(std::cerr); } 236 : : 237 : : void Clause::dump(std::ostream &out) const 238 : : { 239 : : ASTDumper dumper(out); 240 : : dumper(*this); 241 : : out << std::endl; 242 : : } 243 : : void Clause::dump() const { dump(std::cerr); } 244 : : 245 : : void Command::dump(std::ostream &out) const 246 : : { 247 : : ASTDumper dumper(out); 248 : : dumper(*this); 249 : : out << std::endl; 250 : : } 251 : : void Command::dump() const { dump(std::cerr); } 252 : : M_LCOV_EXCL_STOP 253 : : 254 : : 255 : : /*====================================================================================================================== 256 : : * QueryExpr 257 : : *====================================================================================================================*/ 258 : : 259 : 18 : bool QueryExpr::is_constant() const 260 : : { 261 : 18 : auto &stmt = as<const SelectStmt>(*query); 262 [ + + ]: 18 : if (stmt.from) return false; 263 : 2 : auto &select = as<const SelectClause>(*stmt.select); 264 : 2 : M_insist(select.select.size() == 1); 265 [ + - ]: 2 : if (not select.select[0].first->is_constant()) 266 : 0 : return false; 267 : 2 : return true; 268 : 18 : } 269 : : 270 : 0 : bool QueryExpr::can_be_null() const 271 : : { 272 : 0 : auto &stmt = as<const SelectStmt>(*query); 273 : 0 : auto &select = as<const SelectClause>(*stmt.select); 274 : 0 : M_insist(select.select.size() == 1); 275 [ # # ]: 0 : if (select.select[0].first->can_be_null()) 276 : 0 : return true; 277 : 0 : return false; 278 : 0 : } 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); } 290 : 19349 : M_AST_EXPR_LIST(ACCEPT) 291 : : #undef ACCEPT 292 : : 293 : : 294 : : /*----- Explicit instantiations -----*/ 295 : : template struct m::ast::TheRecursiveExprVisitorBase<false>; 296 : : template struct m::ast::TheRecursiveExprVisitorBase<true>; 297 : : 298 : : namespace { 299 : : 300 : : template<bool C, bool PreOrder> 301 : : struct 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 : 319 : recursive_expr_visitor(callback_t &callback) : callback_(callback) { } 312 : : 313 : : using super::operator(); 314 : 0 : void operator()(Const<ErrorExpr> &e) override { callback_(e); } 315 : 565 : void operator()(Const<Designator> &e) override { callback_(e); } 316 : 21 : void operator()(Const<Constant> &e) override { callback_(e); } 317 : 0 : void operator()(Const<QueryExpr> &e) override { callback_(e); } 318 : : 319 : 19 : void operator()(Const<FnApplicationExpr> &e) override { 320 [ # # # # : 33 : if constexpr (PreOrder) try { callback_(e); } catch (visit_skip_subtree) { return; } + + + - ] 321 : 5 : super::operator()(e); 322 : 0 : if constexpr (not PreOrder) callback_(e); 323 : 33 : } 324 : : 325 : 3 : void operator()(Const<UnaryExpr> &e) override { 326 [ # # # # : 3 : if constexpr (PreOrder) try { callback_(e); } catch (visit_skip_subtree) { return; } + - # # ] 327 : 3 : super::operator()(e); 328 : 0 : if constexpr (not PreOrder) callback_(e); 329 : 3 : } 330 : : 331 : 276 : void operator()(Const<BinaryExpr> &e) override { 332 [ # # # # : 276 : if constexpr (PreOrder) try { callback_(e); } catch (visit_skip_subtree) { return; } + - # # ] 333 : 276 : super::operator()(e); 334 : 0 : if constexpr (not PreOrder) callback_(e); 335 : 276 : } 336 : : }; 337 : : 338 : : } 339 : : 340 : : template<bool C> 341 : 319 : void ThePreOrderExprVisitor<C>::operator()(Const<Expr> &e) 342 : : { 343 [ # # + - ]: 319 : recursive_expr_visitor<C, /* PreOrder= */ true>{*this}(e); 344 : 319 : } 345 : : 346 : : template<bool C> 347 : 0 : void ThePostOrderExprVisitor<C>::operator()(Const<Expr> &e) 348 : : { 349 [ # # # # ]: 0 : recursive_expr_visitor<C, /* PreOrder= */ false>{*this}(e); 350 : 0 : } 351 : : 352 : : /*----- Explicit instantiations -----*/ 353 : : template struct m::ast::ThePreOrderExprVisitor<false>; 354 : : template struct m::ast::ThePreOrderExprVisitor<true>; 355 : : template struct m::ast::ThePostOrderExprVisitor<false>; 356 : : template struct m::ast::ThePostOrderExprVisitor<true>; 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); } 364 : 1571 : M_AST_CLAUSE_LIST(ACCEPT) 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); } 372 : 22 : M_AST_CONSTRAINT_LIST(ACCEPT) 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); } 380 : 1479 : M_AST_COMMAND_LIST(ACCEPT) 381 : : #undef ACCEPT