Branch data Line data Source code
1 : : #include "parse/ASTDumper.hpp" 2 : : 3 : : #include <mutable/catalog/Schema.hpp> 4 : : 5 : : 6 : : using namespace m; 7 : : using namespace m::ast; 8 : : 9 : : 10 : 0 : void ASTDumper::print_type(const Expr &e) const 11 : : { 12 [ # # ]: 0 : if (e.has_type()) { 13 : 0 : out << " of type " << *e.type(); 14 [ # # ]: 0 : if (auto pt = cast<const PrimitiveType>(e.type())) 15 : 0 : out << (pt->is_scalar() ? " scalar" : " vectorial"); 16 : 0 : } 17 : 0 : } 18 : : 19 : : /*===== Expr =========================================================================================================*/ 20 : : 21 : 0 : void ASTDumper::operator()(Const<ErrorExpr> &e) 22 : : { 23 : 0 : indent() << "ErrorExpr '" << e.tok.text << "' (" << e.tok.pos << ')'; 24 : 0 : } 25 : : 26 : 0 : void ASTDumper::operator()(Const<Designator> &e) 27 : : { 28 [ # # ]: 0 : if (e.has_explicit_table_name()) { 29 : 0 : indent() << "Designator"; 30 : 0 : print_type(e); 31 : 0 : ++indent_; 32 : 0 : indent() << "table name '" << e.table_name.text << "' (" << e.table_name.pos << ')'; 33 : 0 : indent() << "attribute name '" << e.attr_name.text << "' (" << e.attr_name.pos << ')'; 34 : 0 : --indent_; 35 : 0 : } else { 36 : 0 : indent() << "Identifier '" << e.attr_name.text << '\''; 37 [ # # # # : 0 : if (e.has_table_name()) out << " deduced to table '" << e.get_table_name() << '\''; # # ] 38 : 0 : print_type(e); 39 : 0 : out << " (" << e.attr_name.pos << ')'; 40 : : } 41 : 0 : } 42 : : 43 : 0 : void ASTDumper::operator()(Const<Constant> &e) 44 : : { 45 : 0 : indent() << "Constant " << e.tok.text; 46 [ # # ]: 0 : if (e.has_type()) out << " of type " << *e.type(); 47 : 0 : out << " (" << e.tok.pos << ')'; 48 : 0 : } 49 : : 50 : 0 : void ASTDumper::operator()(Const<FnApplicationExpr> &e) 51 : : { 52 : 0 : indent() << "FnApplicationExpr"; 53 : 0 : print_type(e); 54 : 0 : ++indent_; 55 : 0 : (*this)(*e.fn); 56 [ # # ]: 0 : if (not e.args.empty()) { 57 : 0 : indent() << "args"; 58 : 0 : ++indent_; 59 [ # # ]: 0 : for (auto &expr : e.args) 60 : 0 : (*this)(*expr); 61 : 0 : --indent_; 62 : 0 : } 63 : 0 : --indent_; 64 : 0 : } 65 : : 66 : 0 : void ASTDumper::operator()(Const<UnaryExpr> &e) 67 : : { 68 [ # # # # ]: 0 : indent() << "UnaryExpr '" << e.op().text << "'"; 69 : 0 : print_type(e); 70 [ # # # # ]: 0 : out << " (" << e.op().pos << ')'; 71 : 0 : ++indent_; 72 : 0 : (*this)(*e.expr); 73 : 0 : --indent_; 74 : 1 : } 75 : : 76 : 0 : void ASTDumper::operator()(Const<BinaryExpr> &e) 77 : : { 78 [ # # # # ]: 0 : indent() << "BinaryExpr '" << e.op().text << "'"; 79 : 0 : print_type(e); 80 [ # # # # ]: 0 : out << " (" << e.op().pos << ')'; 81 : 0 : ++indent_; 82 : 0 : (*this)(*e.lhs); 83 : 0 : (*this)(*e.rhs); 84 : 0 : --indent_; 85 : 0 : } 86 : : 87 : 0 : void ASTDumper::operator()(Const<QueryExpr> &e) 88 : : { 89 : 0 : indent() << "QueryExpr"; 90 : 0 : print_type(e); 91 : 0 : ++indent_; 92 : 0 : (*this)(*e.query); 93 : 0 : --indent_; 94 : 0 : } 95 : : 96 : : 97 : : /*===== Clause =======================================================================================================*/ 98 : : 99 : 0 : void ASTDumper::operator()(Const<ErrorClause> &c) 100 : : { 101 : 0 : indent() << "ErrorClause '" << c.tok.text << "' (" << c.tok.pos << ')'; 102 : 0 : } 103 : : 104 : 0 : void ASTDumper::operator()(Const<SelectClause> &c) 105 : : { 106 : 0 : indent() << "SelectClause (" << c.tok.pos << ')'; 107 : 0 : ++indent_; 108 [ # # ]: 0 : if (c.select_all) 109 : 0 : indent() << "* (" << c.select_all.pos << ')'; 110 [ # # ]: 0 : for (auto &s : c.select) { 111 [ # # ]: 0 : if (s.second) { 112 : 0 : indent() << "AS '" << s.second.text << "' (" << s.second.pos << ')'; 113 : 0 : ++indent_; 114 : 0 : (*this)(*s.first); 115 : 0 : --indent_; 116 : 0 : } else { 117 : 0 : (*this)(*s.first); 118 : : } 119 : : } 120 : 0 : --indent_; 121 : 0 : } 122 : : 123 : 0 : void ASTDumper::operator()(Const<FromClause> &c) 124 : : { 125 : 0 : indent() << "FromClause (" << c.tok.pos << ')'; 126 : 0 : ++indent_; 127 [ # # ]: 0 : for (auto f : c.from) { 128 [ # # # # ]: 0 : if (f.alias) { 129 [ # # # # : 0 : indent() << "AS '" << f.alias.text << "' (" << f.alias.pos << ')'; # # # # # # # # ] 130 : 0 : ++indent_; 131 [ # # ]: 0 : if (auto tok = std::get_if<Token>(&f.source)) { 132 [ # # # # : 0 : indent() << tok->text << " (" << tok->pos << ')'; # # # # # # ] 133 [ # # ]: 0 : } else if (auto stmt = std::get_if<Stmt*>(&f.source)) { 134 [ # # ]: 0 : (*this)(**stmt); 135 : 0 : } else { 136 [ # # ]: 0 : M_unreachable("illegal variant"); 137 : : } 138 : 0 : --indent_; 139 : 0 : } else { 140 [ # # ]: 0 : M_insist(std::holds_alternative<Token>(f.source), "nested statements require an alias"); 141 [ # # ]: 0 : Token &tok = std::get<Token>(f.source); 142 [ # # # # : 0 : indent() << tok.text << " (" << tok.pos << ')'; # # # # # # ] 143 : : } 144 : 0 : } 145 : 0 : --indent_; 146 : 0 : } 147 : : 148 : 0 : void ASTDumper::operator()(Const<WhereClause> &c) 149 : : { 150 : 0 : indent() << "WhereClause (" << c.tok.pos << ')'; 151 : 0 : ++indent_; 152 : 0 : (*this)(*c.where); 153 : 0 : --indent_; 154 : 0 : } 155 : : 156 : : 157 : 0 : void ASTDumper::operator()(Const<GroupByClause> &c) 158 : : { 159 : 0 : indent() << "GroupByClause (" << c.tok.pos << ')'; 160 : 0 : ++indent_; 161 [ # # ]: 0 : for (auto &[expr, alias] : c.group_by) { 162 [ # # ]: 0 : if (alias) 163 : 0 : indent() << "AS '" << alias.text << "' (" << alias.pos << ')'; 164 : 0 : ++indent_; 165 : 0 : (*this)(*expr); 166 : 0 : --indent_; 167 : : } 168 : 0 : --indent_; 169 : 0 : } 170 : : 171 : 0 : void ASTDumper::operator()(Const<HavingClause> &c) 172 : : { 173 : 0 : indent() << "HavingClause (" << c.tok.pos << ')'; 174 : 0 : ++indent_; 175 : 0 : (*this)(*c.having); 176 : 0 : --indent_; 177 : 0 : } 178 : : 179 : 0 : void ASTDumper::operator()(Const<OrderByClause> &c) 180 : : { 181 : 0 : indent() << "OrderByClause (" << c.tok.pos << ')'; 182 : 0 : ++indent_; 183 [ # # ]: 0 : for (auto &o : c.order_by) { 184 : 0 : indent() << (o.second ? "ASC" : "DESC"); 185 : 0 : ++indent_; 186 : 0 : (*this)(*o.first); 187 : 0 : --indent_; 188 : : } 189 : 0 : --indent_; 190 : 0 : } 191 : : 192 : 0 : void ASTDumper::operator()(Const<LimitClause> &c) 193 : : { 194 : 0 : indent() << "LimitClause (" << c.tok.pos << ')'; 195 : 0 : ++indent_; 196 : : 197 : 0 : indent() << "LIMIT " << c.limit.text << " (" << c.limit.pos << ')'; 198 : : 199 [ # # ]: 0 : if (c.offset) 200 : 0 : indent() << "OFFSET " << c.offset.text << " (" << c.offset.pos << ')'; 201 : : 202 : 0 : --indent_; 203 : 0 : } 204 : : 205 : : 206 : : /*===== Constraint ===================================================================================================*/ 207 : : 208 : 0 : void ASTDumper::operator()(Const<PrimaryKeyConstraint> &c) 209 : : { 210 : 0 : indent() << "PrimaryKeyConstraint (" << c.tok.pos << ')'; 211 : 0 : } 212 : : 213 : 0 : void ASTDumper::operator()(Const<UniqueConstraint> &c) 214 : : { 215 : 0 : indent() << "UniqueConstraint (" << c.tok.pos << ')'; 216 : 0 : } 217 : : 218 : 0 : void ASTDumper::operator()(Const<NotNullConstraint> &c) 219 : : { 220 : 0 : indent() << "NotNullConstraint (" << c.tok.pos << ')'; 221 : 0 : } 222 : : 223 : 0 : void ASTDumper::operator()(Const<CheckConditionConstraint> &c) 224 : : { 225 : 0 : indent() << "CheckConditionConstraint (" << c.tok.pos << ')'; 226 : 0 : ++indent_; 227 : 0 : (*this)(*c.cond); 228 : 0 : --indent_; 229 : 0 : } 230 : : 231 : 0 : void ASTDumper::operator()(Const<ReferenceConstraint> &c) 232 : : { 233 : 0 : indent() << "ReferenceConstraint (" << c.tok.pos << ')'; 234 : 0 : ++indent_; 235 : 0 : indent() << c.table_name.text << '(' << c.attr_name.text << ')'; 236 : 0 : --indent_; 237 : 0 : } 238 : : 239 : : 240 : : /*===== Instruction ==================================================================================================*/ 241 : : 242 : 0 : void ASTDumper::operator()(Const<Instruction> &inst) 243 : : { 244 : 0 : out << "Instruction(" << inst.name; 245 [ # # ]: 0 : for (auto &arg : inst.args) 246 : 0 : out << ", " << arg; 247 : 0 : out << ')'; 248 : 0 : } 249 : : 250 : : 251 : : /*===== Stmt =========================================================================================================*/ 252 : : 253 : 0 : void ASTDumper::operator()(Const<ErrorStmt> &s) 254 : : { 255 : 0 : indent() << "ErrorStmt: '" << s.tok.text << "' (" << s.tok.pos << ')'; 256 : 0 : } 257 : : 258 : 0 : void ASTDumper::operator()(Const<EmptyStmt> &s) 259 : : { 260 : 0 : indent() << "EmptyStmt: '" << s.tok.text << "' (" << s.tok.pos << ')'; 261 : 0 : } 262 : : 263 : 0 : void ASTDumper::operator()(Const<CreateDatabaseStmt> &s) 264 : : { 265 : 0 : indent() << "CreateDatabaseStmt: '" << s.database_name.text << "' (" << s.database_name.pos << ')'; 266 : 0 : } 267 : : 268 : 0 : void ASTDumper::operator()(Const<DropDatabaseStmt> &s) 269 : : { 270 : 0 : indent() << "DropDatabaseStmt: '" << s.database_name.text << "' (" << s.database_name.pos << ')'; 271 : 0 : ++indent_; 272 [ # # ]: 0 : if (s.has_if_exists) 273 : 0 : indent() << "if exists: true"; 274 : 0 : --indent_; 275 : 0 : } 276 : : 277 : 0 : void ASTDumper::operator()(Const<UseDatabaseStmt> &s) 278 : : { 279 : 0 : indent() << "UseDatabaseStmt: '" << s.database_name.text << "' (" << s.database_name.pos << ')'; 280 : 0 : } 281 : : 282 : 0 : void ASTDumper::operator()(Const<CreateTableStmt> &s) 283 : : { 284 : 0 : indent() << "CreateTableStmt: table " << s.table_name.text << " (" << s.table_name.pos << ')'; 285 : 0 : ++indent_; 286 : 0 : indent() << "attributes"; 287 : 0 : ++indent_; 288 [ # # ]: 0 : for (auto &attr : s.attributes) { 289 : 0 : indent() << attr->name.text << " : " << *attr->type << " (" << attr->name.pos << ')'; 290 : 0 : ++indent_; 291 [ # # ]: 0 : for (auto &c : attr->constraints) { 292 [ # # ]: 0 : if (is<PrimaryKeyConstraint>(c)) { 293 : 0 : indent() << "PRIMARY KEY (" << c->tok.pos << ')'; 294 [ # # ]: 0 : } else if (is<UniqueConstraint>(c)) { 295 : 0 : indent() << "UNIQUE (" << c->tok.pos << ')'; 296 [ # # ]: 0 : } else if (is<NotNullConstraint>(c)) { 297 : 0 : indent() << "NOT NULL (" << c->tok.pos << ')'; 298 [ # # ]: 0 : } else if (auto check = cast<CheckConditionConstraint>(c.get())) { 299 : 0 : indent() << "CHECK (" << c->tok.pos << ')'; 300 : 0 : ++indent_; 301 : 0 : (*this)(*check->cond); 302 : 0 : --indent_; 303 [ # # ]: 0 : } else if (auto ref = cast<ReferenceConstraint>(c.get())) { 304 : 0 : indent() << "REFERENCES " << ref->table_name.text << '(' << ref->attr_name.text << ") (" << c->tok.pos 305 : 0 : << ')'; 306 : 0 : } else { 307 : 0 : M_unreachable("invalid constraint"); 308 : : } 309 : : } 310 : 0 : --indent_; 311 : : } 312 : 0 : --indent_; 313 : 0 : --indent_; 314 : 0 : } 315 : : 316 : 0 : void ASTDumper::operator()(Const<DropTableStmt> &s) 317 : : { 318 : 0 : indent() << "DropTableStmt:"; 319 : 0 : ++indent_; 320 : 0 : indent() << "tables"; 321 : 0 : ++indent_; 322 [ # # ]: 0 : for (auto &table_name : s.table_names) 323 : 0 : indent() << table_name->text << " (" << table_name->pos << ')'; 324 : 0 : --indent_; 325 [ # # ]: 0 : if (s.has_if_exists) 326 : 0 : indent() << "if exists: true"; 327 : 0 : --indent_; 328 : 0 : } 329 : : 330 : 0 : void ASTDumper::operator()(Const<CreateIndexStmt> &s) 331 : : { 332 : 0 : indent() << "CreateIndexStmt:"; 333 : 0 : ++indent_; 334 : : 335 [ # # ]: 0 : if (s.has_unique) 336 : 0 : indent() << "unique: true"; 337 [ # # ]: 0 : if (s.has_if_not_exists) 338 : 0 : indent() << "if not exists: true"; 339 [ # # ]: 0 : if (s.index_name) 340 : 0 : indent() << "index name: " << s.index_name.text; 341 [ # # ]: 0 : if (s.method) 342 : 0 : indent() << "method: " << s.method.text; 343 : : 344 : 0 : indent() << "table name: " << s.table_name.text; 345 : 0 : indent() << "fields"; 346 : 0 : ++indent_; 347 [ # # ]: 0 : for (auto &expr : s.key_fields) (*this)(*expr); 348 : 0 : --indent_; 349 : 0 : --indent_; 350 : 0 : } 351 : : 352 : 0 : void ASTDumper::operator()(Const<DropIndexStmt> &s) 353 : : { 354 : 0 : indent() << "DropIndexStmt:"; 355 : 0 : ++indent_; 356 : : 357 [ # # ]: 0 : if (s.has_if_exists) 358 : 0 : indent() << "if exists: true"; 359 : : 360 : 0 : indent() << "indexes"; 361 : 0 : ++indent_; 362 [ # # ]: 0 : for (auto &idx : s.index_names) indent() << (*idx).text; 363 : 0 : --indent_; 364 : 0 : --indent_; 365 : : 366 : 0 : } 367 : : 368 : 0 : void ASTDumper::operator()(Const<SelectStmt> &s) 369 : : { 370 : 0 : indent() << "SelectStmt"; 371 : 0 : ++indent_; 372 : : 373 : 0 : (*this)(*s.select); 374 : : 375 [ # # ]: 0 : if (s.from) (*this)(*s.from); 376 [ # # ]: 0 : if (s.where) (*this)(*s.where); 377 [ # # ]: 0 : if (s.group_by) (*this)(*s.group_by); 378 [ # # ]: 0 : if (s.having) (*this)(*s.having); 379 [ # # ]: 0 : if (s.order_by) (*this)(*s.order_by); 380 [ # # ]: 0 : if (s.limit) (*this)(*s.limit); 381 : : 382 : 0 : --indent_; 383 : 0 : } 384 : : 385 : 0 : void ASTDumper::operator()(Const<InsertStmt> &s) 386 : : { 387 : 0 : indent() << "InsertStmt: table " << s.table_name.text << " (" << s.table_name.pos << ')'; 388 : 0 : ++indent_; 389 : 0 : indent() << "values"; 390 : 0 : ++indent_; 391 [ # # ]: 0 : for (std::size_t idx = 0, end = s.tuples.size(); idx != end; ++idx) { 392 : 0 : indent() << '[' << idx << ']'; 393 : 0 : const InsertStmt::tuple_t &v = s.tuples[idx]; 394 : 0 : ++indent_; 395 [ # # ]: 0 : for (auto &e : v) { 396 [ # # # # ]: 0 : switch (e.first) { 397 : : case InsertStmt::I_Default: 398 : 0 : indent() << "DEFAULT"; 399 : 0 : break; 400 : : 401 : : case InsertStmt::I_Null: 402 : 0 : indent() << "NULL"; 403 : 0 : break; 404 : : 405 : : case InsertStmt::I_Expr: 406 : 0 : (*this)(*e.second); 407 : 0 : break; 408 : : } 409 : : } 410 : 0 : --indent_; 411 : 0 : } 412 : 0 : --indent_; 413 : 0 : --indent_; 414 : 0 : } 415 : : 416 : 0 : void ASTDumper::operator()(Const<UpdateStmt> &s) 417 : : { 418 : 0 : indent() << "UpdateStmt: table " << s.table_name.text << " (" << s.table_name.pos << ')'; 419 : 0 : ++indent_; 420 : 0 : indent() << "set"; 421 : 0 : ++indent_; 422 [ # # ]: 0 : for (auto &s : s.set) { 423 : 0 : indent() << s.first.text << " (" << s.first.pos << ')'; 424 : 0 : ++indent_; 425 : 0 : (*this)(*s.second); 426 : 0 : --indent_; 427 : : } 428 : 0 : --indent_; 429 : : 430 [ # # ]: 0 : if (s.where) (*this)(*s.where); 431 : : 432 : 0 : --indent_; 433 : 0 : } 434 : : 435 : 0 : void ASTDumper::operator()(Const<DeleteStmt> &s) 436 : : { 437 : 0 : indent() << "DeleteStmt: table " << s.table_name.text << " (" << s.table_name.pos << ')'; 438 : : 439 [ # # ]: 0 : if (s.where) { 440 : 0 : ++indent_; 441 : 0 : (*this)(*s.where); 442 : 0 : --indent_; 443 : 0 : } 444 : 0 : } 445 : : 446 : 0 : void ASTDumper::operator()(Const<DSVImportStmt> &s) 447 : : { 448 : 0 : indent() << "ImportStmt (DSV): table " << s.table_name.text << " (" << s.table_name.pos << ')'; 449 : : 450 : 0 : ++indent_; 451 : 0 : indent() << s.path.text << " (" << s.path.pos << ')'; 452 [ # # ]: 0 : if (s.rows) 453 : 0 : indent() << "rows " << s.rows.text << " (" << s.rows.pos << ')'; 454 [ # # ]: 0 : if (s.delimiter) 455 : 0 : indent() << "delimiter " << s.delimiter.text << " (" << s.delimiter.pos << ')'; 456 [ # # ]: 0 : if (s.has_header) 457 : 0 : indent() << "HAS HEADER"; 458 [ # # ]: 0 : if (s.skip_header) 459 : 0 : indent() << "SKIP HEADER"; 460 : 0 : --indent_; 461 : 0 : }