1 /* 2 Copyright (c) 2016, 2021, MariaDB 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; version 2 of the License. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with this program; if not, write to the Free Software 15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 16 17 #include "mariadb.h" 18 #include "sql_class.h" 19 #include "sql_lex.h" 20 #include "sql_cte.h" 21 #include "sql_view.h" // for make_valid_column_names 22 #include "sql_parse.h" 23 #include "sql_select.h" 24 25 26 /** 27 @brief 28 Add a new element to this with clause 29 30 @param elem The with element to add to this with clause 31 32 @details 33 The method adds the with element 'elem' to the elements 34 in this with clause. The method reports an error if 35 the number of the added element exceeds the value 36 of the constant max_number_of_elements_in_with_clause. 37 38 @retval 39 true if an error is reported 40 false otherwise 41 */ 42 43 bool With_clause::add_with_element(With_element *elem) 44 { 45 if (with_list.elements == max_number_of_elements_in_with_clause) 46 { 47 my_error(ER_TOO_MANY_DEFINITIONS_IN_WITH_CLAUSE, MYF(0)); 48 return true; 49 } 50 elem->owner= this; 51 elem->number= with_list.elements; 52 elem->spec->with_element= elem; 53 with_list.link_in_list(elem, &elem->next); 54 return false; 55 } 56 57 58 /** 59 @brief 60 Check dependencies between tables defined in a list of with clauses 61 62 @param 63 with_clauses_list Pointer to the first clause in the list 64 65 @details 66 For each with clause from the given list the procedure finds all 67 dependencies between tables defined in the clause by calling the 68 method With_clause::checked_dependencies. 69 Additionally, based on the info collected by this method the procedure 70 finds anchors for each recursive definition and moves them at the head 71 of the definition. 72 73 @retval 74 false on success 75 true on failure 76 */ 77 78 bool LEX::check_dependencies_in_with_clauses() 79 { 80 for (With_clause *with_clause= with_clauses_list; 81 with_clause; 82 with_clause= with_clause->next_with_clause) 83 { 84 if (with_clause->check_dependencies()) 85 return true; 86 if (with_clause->check_anchors()) 87 return true; 88 with_clause->move_anchors_ahead(); 89 } 90 return false; 91 } 92 93 94 /** 95 @brief 96 Resolve references to CTE in specification of hanging CTE 97 98 @details 99 A CTE to which there are no references in the query is called hanging CTE. 100 Although such CTE is not used for execution its specification must be 101 subject to context analysis. All errors concerning references to 102 non-existing tables or fields occurred in the specification must be 103 reported as well as all other errors caught at the prepare stage. 104 The specification of a hanging CTE might contain references to other 105 CTE outside of the specification and within it if the specification 106 contains a with clause. This function resolves all such references for 107 all hanging CTEs encountered in the processed query. 108 109 @retval 110 false on success 111 true on failure 112 */ 113 114 bool 115 LEX::resolve_references_to_cte_in_hanging_cte() 116 { 117 for (With_clause *with_clause= with_clauses_list; 118 with_clause; with_clause= with_clause->next_with_clause) 119 { 120 for (With_element *with_elem= with_clause->with_list.first; 121 with_elem; with_elem= with_elem->next) 122 { 123 if (!with_elem->is_referenced()) 124 { 125 TABLE_LIST *first_tbl= 126 with_elem->spec->first_select()->table_list.first; 127 TABLE_LIST **with_elem_end_pos= with_elem->head->tables_pos.end_pos; 128 if (first_tbl && resolve_references_to_cte(first_tbl, with_elem_end_pos)) 129 return true; 130 } 131 } 132 } 133 return false; 134 } 135 136 137 /** 138 @brief 139 Resolve table references to CTE from a sub-chain of table references 140 141 @param tables Points to the beginning of the sub-chain 142 @param tables_last Points to the address with the sub-chain barrier 143 144 @details 145 The method resolves tables references to CTE from the chain of 146 table references specified by the parameters 'tables' and 'tables_last'. 147 It resolves the references against the CTE definition occurred in a query 148 or the specification of a CTE whose parsing tree is represented by 149 this LEX structure. The method is always called right after the process 150 of parsing the query or of the specification of a CTE has been finished, 151 thus the chain of table references used in the parsed fragment has been 152 already built. It is assumed that parameters of the method specify a 153 a sub-chain of this chain. 154 If a table reference can be potentially a table reference to a CTE and it 155 has not been resolved yet then the method tries to find the definition 156 of the CTE against which the reference can be resolved. If it succeeds 157 it sets the field TABLE_LIST::with to point to the found definition. 158 It also sets the field TABLE_LIST::derived to point to the specification 159 of the found CTE and sets TABLE::db.str to empty_c_string. This will 160 allow to handle this table reference like a reference to a derived handle. 161 If another table reference has been already resolved against this CTE 162 and this CTE is not recursive then a clone of the CTE specification is 163 constructed using the function With_element::clone_parsed_spec() and 164 TABLE_LIST::derived is set to point to this clone rather than to the 165 original specification. 166 If the method does not find a matched CTE definition in the parsed fragment 167 then in the case when the flag this->only_cte_resolution is set to true 168 it just moves to the resolution of the next table reference from the 169 specified sub-chain while in the case when this->only_cte_resolution is set 170 to false the method additionally sets an mdl request for this table 171 reference. 172 173 @notes 174 The flag this->only_cte_resolution is set to true in the cases when 175 the failure to resolve a table reference as a CTE reference within 176 the fragment associated with this LEX structure does not imply that 177 this table reference cannot be resolved as such at all. 178 179 @retval false On success: no errors reported, no memory allocations failed 180 @retval true Otherwise 181 */ 182 183 bool LEX::resolve_references_to_cte(TABLE_LIST *tables, 184 TABLE_LIST **tables_last) 185 { 186 With_element *with_elem= 0; 187 188 for (TABLE_LIST *tbl= tables; tbl != *tables_last; tbl= tbl->next_global) 189 { 190 if (tbl->derived) 191 continue; 192 if (!tbl->db.length && !tbl->with) 193 tbl->with= tbl->select_lex->find_table_def_in_with_clauses(tbl); 194 if (!tbl->with) // no CTE matches table reference tbl 195 { 196 if (only_cte_resolution) 197 continue; 198 if (!tbl->db.length) // no database specified in table reference tbl 199 { 200 if (!thd->db.length) // no default database is set 201 { 202 my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); 203 return true; 204 } 205 if (copy_db_to(&tbl->db)) 206 return true; 207 if (!(tbl->table_options & TL_OPTION_ALIAS)) 208 tbl->mdl_request.init(MDL_key::TABLE, tbl->db.str, 209 tbl->table_name.str, 210 tbl->mdl_type, MDL_TRANSACTION); 211 tbl->mdl_request.set_type((tbl->lock_type >= TL_WRITE_ALLOW_WRITE) ? 212 MDL_SHARED_WRITE : MDL_SHARED_READ); 213 } 214 continue; 215 } 216 with_elem= tbl->with; 217 if (tbl->is_recursive_with_table() && 218 !tbl->is_with_table_recursive_reference()) 219 { 220 tbl->with->rec_outer_references++; 221 while ((with_elem= with_elem->get_next_mutually_recursive()) != 222 tbl->with) 223 with_elem->rec_outer_references++; 224 } 225 if (!with_elem->is_used_in_query || with_elem->is_recursive) 226 { 227 tbl->derived= with_elem->spec; 228 if (tbl->derived != tbl->select_lex->master_unit() && 229 !with_elem->is_recursive && 230 !tbl->is_with_table_recursive_reference()) 231 { 232 tbl->derived->move_as_slave(tbl->select_lex); 233 } 234 with_elem->is_used_in_query= true; 235 } 236 else 237 { 238 if (!(tbl->derived= tbl->with->clone_parsed_spec(thd->lex, tbl))) 239 return true; 240 } 241 tbl->db.str= empty_c_string; 242 tbl->db.length= 0; 243 tbl->schema_table= 0; 244 if (tbl->derived) 245 { 246 tbl->derived->first_select()->linkage= DERIVED_TABLE_TYPE; 247 } 248 if (tbl->with->is_recursive && tbl->is_with_table_recursive_reference()) 249 continue; 250 with_elem->inc_references(); 251 } 252 return false; 253 } 254 255 256 /** 257 @brief 258 Find out dependencies between CTEs, resolve references to them 259 260 @details 261 The function can be called in two modes. With this->with_cte_resolution 262 set to false the function only finds out all dependencies between CTEs 263 used in a query expression with a WITH clause whose parsing has been 264 just finished. Based on these dependencies recursive CTEs are detected. 265 If this->with_cte_resolution is set to true the function additionally 266 resolves all references to CTE occurred in this query expression. 267 268 @retval 269 true on failure 270 false on success 271 */ 272 273 bool 274 LEX::check_cte_dependencies_and_resolve_references() 275 { 276 if (check_dependencies_in_with_clauses()) 277 return true; 278 if (!with_cte_resolution) 279 return false; 280 if (resolve_references_to_cte(query_tables, query_tables_last)) 281 return true; 282 if (resolve_references_to_cte_in_hanging_cte()) 283 return true; 284 return false; 285 } 286 287 288 /** 289 @brief 290 Check dependencies between tables defined in this with clause 291 292 @details 293 The method performs the following for this with clause: 294 - checks that there are no definitions of the tables with the same name 295 - for each table T defined in this with clause looks for the tables 296 from the same with clause that are used in the query that specifies T 297 and set the dependencies of T on these tables in a bitmap. 298 - builds the transitive closure of the above direct dependencies 299 to find out all recursive definitions. 300 301 @retval 302 true if an error is reported 303 false otherwise 304 */ 305 306 bool With_clause::check_dependencies() 307 { 308 if (dependencies_are_checked) 309 return false; 310 /* 311 Look for for definitions with the same query name. 312 When found report an error and return true immediately. 313 For each table T defined in this with clause look for all other tables 314 from the same with clause that are used in the specification of T. 315 For each such table set the dependency bit in the dependency map of 316 the with element for T. 317 */ 318 for (With_element *with_elem= with_list.first; 319 with_elem; 320 with_elem= with_elem->next) 321 { 322 for (With_element *elem= with_list.first; 323 elem != with_elem; 324 elem= elem->next) 325 { 326 if (my_strcasecmp(system_charset_info, with_elem->get_name_str(), 327 elem->get_name_str()) == 0) 328 { 329 my_error(ER_DUP_QUERY_NAME, MYF(0), 330 with_elem->get_name_str()); 331 return true; 332 } 333 } 334 if (with_elem->check_dependencies_in_spec()) 335 return true; 336 } 337 /* Build the transitive closure of the direct dependencies found above */ 338 for (With_element *with_elem= with_list.first; 339 with_elem; 340 with_elem= with_elem->next) 341 with_elem->derived_dep_map= with_elem->base_dep_map; 342 for (With_element *with_elem= with_list.first; 343 with_elem; 344 with_elem= with_elem->next) 345 { 346 table_map with_elem_map= with_elem->get_elem_map(); 347 for (With_element *elem= with_list.first; elem; elem= elem->next) 348 { 349 if (elem->derived_dep_map & with_elem_map) 350 elem->derived_dep_map |= with_elem->derived_dep_map; 351 } 352 } 353 354 /* 355 Mark those elements where tables are defined with direct or indirect 356 recursion. 357 */ 358 for (With_element *with_elem= with_list.first; 359 with_elem; 360 with_elem= with_elem->next) 361 { 362 if (with_elem->derived_dep_map & with_elem->get_elem_map()) 363 with_elem->is_recursive= true; 364 } 365 366 dependencies_are_checked= true; 367 return false; 368 } 369 370 371 /* 372 This structure describes an element of the stack of embedded units. 373 The stack is used when looking for a definition of a table in 374 with clauses. The definition can be found only in the scopes 375 of the with clauses attached to the units from the stack. 376 The with clauses are looked through from starting from the top 377 element of the stack. 378 */ 379 380 struct st_unit_ctxt_elem 381 { 382 st_unit_ctxt_elem *prev; // the previous element of the stack 383 st_select_lex_unit *unit; 384 }; 385 386 387 /** 388 @brief 389 Find the dependencies of this element on its siblings in its specification 390 391 @details 392 For each table reference ref(T) from the FROM list of every select sl 393 immediately contained in the specification query of this element this 394 method searches for the definition of T in the the with clause which 395 this element belongs to. If such definition is found then the dependency 396 on it is set in sl->with_dep and in this->base_dep_map. 397 */ 398 399 bool With_element::check_dependencies_in_spec() 400 { 401 for (st_select_lex *sl= spec->first_select(); sl; sl= sl->next_select()) 402 { 403 st_unit_ctxt_elem ctxt0= {NULL, owner->owner}; 404 st_unit_ctxt_elem ctxt1= {&ctxt0, spec}; 405 check_dependencies_in_select(sl, &ctxt1, false, &sl->with_dep); 406 base_dep_map|= sl->with_dep; 407 } 408 return false; 409 } 410 411 412 /** 413 @brief 414 Search for the definition of a table among the elements of this with clause 415 416 @param table The reference to the table that is looked for 417 @param barrier The barrier with element for the search 418 419 @details 420 The function looks through the elements of this with clause trying to find 421 the definition of the given table. When it encounters the element with 422 the same query name as the table's name it returns this element. If no 423 such definitions are found the function returns NULL. 424 425 @retval 426 found with element if the search succeeded 427 NULL - otherwise 428 */ 429 430 With_element *With_clause::find_table_def(TABLE_LIST *table, 431 With_element *barrier) 432 { 433 for (With_element *with_elem= with_list.first; 434 with_elem != barrier; 435 with_elem= with_elem->next) 436 { 437 if (my_strcasecmp(system_charset_info, with_elem->get_name_str(), 438 table->table_name.str) == 0 && 439 !table->is_fqtn) 440 { 441 table->set_derived(); 442 with_elem->referenced= true; 443 return with_elem; 444 } 445 } 446 return NULL; 447 } 448 449 450 /** 451 @brief 452 Search for the definition of a table in with clauses 453 454 @param tbl The reference to the table that is looked for 455 @param ctxt The context describing in what with clauses of the upper 456 levels the table has to be searched for. 457 458 @details 459 The function looks for the definition of the table tbl in the definitions 460 of the with clauses from the upper levels specified by the parameter ctxt. 461 When it encounters the element with the same query name as the table's name 462 it returns this element. If no such definitions are found the function 463 returns NULL. 464 465 @retval 466 found with element if the search succeeded 467 NULL - otherwise 468 */ 469 470 With_element *find_table_def_in_with_clauses(TABLE_LIST *tbl, 471 st_unit_ctxt_elem *ctxt) 472 { 473 With_element *barrier= NULL; 474 for (st_unit_ctxt_elem *unit_ctxt_elem= ctxt; 475 unit_ctxt_elem; 476 unit_ctxt_elem= unit_ctxt_elem->prev) 477 { 478 st_select_lex_unit *unit= unit_ctxt_elem->unit; 479 With_clause *with_clause= unit->with_clause; 480 if (with_clause && 481 (tbl->with= with_clause->find_table_def(tbl, barrier))) 482 return tbl->with; 483 barrier= NULL; 484 if (unit->with_element && !unit->with_element->get_owner()->with_recursive) 485 { 486 /* 487 This unit is the specification if the with element unit->with_element. 488 The with element belongs to a with clause without the specifier RECURSIVE. 489 So when searching for the matching definition of tbl this with clause must 490 be looked up to this with element 491 */ 492 barrier= unit->with_element; 493 } 494 } 495 return NULL; 496 } 497 498 499 /** 500 @brief 501 Find the dependencies of this element on its siblings in a select 502 503 @param sl The select where to look for the dependencies 504 @param ctxt The structure specifying the scope of the definitions 505 of the with elements of the upper levels 506 @param in_sbq if true mark dependencies found in subqueries in 507 this->sq_dep_map 508 @param dep_map IN/OUT The bit where to mark the found dependencies 509 510 @details 511 For each table reference ref(T) from the FROM list of the select sl 512 the method searches in with clauses for the definition of the table T. 513 If the found definition belongs to the same with clause as this with 514 element then the method set dependency on T in the in/out parameter 515 dep_map, add if required - in this->sq_dep_map. 516 The parameter ctxt describes the proper context for the search 517 of the definition of T. 518 */ 519 520 void With_element::check_dependencies_in_select(st_select_lex *sl, 521 st_unit_ctxt_elem *ctxt, 522 bool in_subq, 523 table_map *dep_map) 524 { 525 With_clause *with_clause= sl->get_with_clause(); 526 for (TABLE_LIST *tbl= sl->table_list.first; tbl; tbl= tbl->next_local) 527 { 528 if (tbl->derived || tbl->nested_join) 529 continue; 530 tbl->with_internal_reference_map= 0; 531 /* 532 If there is a with clause attached to the unit containing sl 533 look first for the definition of tbl in this with clause. 534 If such definition is not found there look in the with 535 clauses of the upper levels. 536 If the definition of tbl is found somewhere in with clauses 537 then tbl->with is set to point to this definition 538 */ 539 if (with_clause && !tbl->with) 540 tbl->with= with_clause->find_table_def(tbl, NULL); 541 if (!tbl->with) 542 tbl->with= find_table_def_in_with_clauses(tbl, ctxt); 543 544 if (tbl->with && tbl->with->owner== this->owner) 545 { 546 /* 547 The found definition T of tbl belongs to the same 548 with clause as this with element. In this case: 549 - set the dependence on T in the bitmap dep_map 550 - set tbl->with_internal_reference_map with 551 the bitmap for this definition 552 - set the dependence on T in the bitmap this->sq_dep_map 553 if needed 554 */ 555 *dep_map|= tbl->with->get_elem_map(); 556 tbl->with_internal_reference_map= get_elem_map(); 557 if (in_subq) 558 sq_dep_map|= tbl->with->get_elem_map(); 559 else 560 top_level_dep_map|= tbl->with->get_elem_map(); 561 } 562 } 563 /* Now look for the dependencies in the subqueries of sl */ 564 st_select_lex_unit *inner_unit= sl->first_inner_unit(); 565 for (; inner_unit; inner_unit= inner_unit->next_unit()) 566 { 567 if (!inner_unit->with_element) 568 check_dependencies_in_unit(inner_unit, ctxt, in_subq, dep_map); 569 } 570 } 571 572 573 /** 574 @brief 575 Find a recursive reference to this with element in subqueries of a select 576 577 @param sel The select in whose subqueries the reference 578 to be looked for 579 580 @details 581 The function looks for a recursive reference to this with element in 582 subqueries of select sl. When the first such reference is found 583 it is returned as the result. 584 The function assumes that the identification of all CTE references 585 has been performed earlier. 586 587 @retval 588 Pointer to the found recursive reference if the search succeeded 589 NULL - otherwise 590 */ 591 592 TABLE_LIST *With_element::find_first_sq_rec_ref_in_select(st_select_lex *sel) 593 { 594 TABLE_LIST *rec_ref= NULL; 595 st_select_lex_unit *inner_unit= sel->first_inner_unit(); 596 for (; inner_unit; inner_unit= inner_unit->next_unit()) 597 { 598 st_select_lex *sl= inner_unit->first_select(); 599 for (; sl; sl= sl->next_select()) 600 { 601 for (TABLE_LIST *tbl= sl->table_list.first; tbl; tbl= tbl->next_local) 602 { 603 if (tbl->derived || tbl->nested_join) 604 continue; 605 if (tbl->with && tbl->with->owner== this->owner && 606 (tbl->with_internal_reference_map & mutually_recursive)) 607 { 608 rec_ref= tbl; 609 return rec_ref; 610 } 611 } 612 if ((rec_ref= find_first_sq_rec_ref_in_select(sl))) 613 return rec_ref; 614 } 615 } 616 return 0; 617 } 618 619 620 /** 621 @brief 622 Find the dependencies of this element on its siblings in a unit 623 624 @param unit The unit where to look for the dependencies 625 @param ctxt The structure specifying the scope of the definitions 626 of the with elements of the upper levels 627 @param in_sbq if true mark dependencies found in subqueries in 628 this->sq_dep_map 629 @param dep_map IN/OUT The bit where to mark the found dependencies 630 631 @details 632 This method searches in the unit 'unit' for the the references in FROM 633 lists of all selects contained in this unit and in the with clause 634 attached to this unit that refer to definitions of tables from the 635 same with clause as this element. 636 If such definitions are found then the dependencies on them are 637 set in the in/out parameter dep_map and optionally in this->sq_dep_map. 638 The parameter ctxt describes the proper context for the search. 639 */ 640 641 void With_element::check_dependencies_in_unit(st_select_lex_unit *unit, 642 st_unit_ctxt_elem *ctxt, 643 bool in_subq, 644 table_map *dep_map) 645 { 646 if (unit->with_clause) 647 check_dependencies_in_with_clause(unit->with_clause, ctxt, in_subq, dep_map); 648 in_subq |= unit->item != NULL; 649 st_unit_ctxt_elem unit_ctxt_elem= {ctxt, unit}; 650 st_select_lex *sl= unit->first_select(); 651 for (; sl; sl= sl->next_select()) 652 { 653 check_dependencies_in_select(sl, &unit_ctxt_elem, in_subq, dep_map); 654 } 655 } 656 657 658 /** 659 @brief 660 Find the dependencies of this element on its siblings in a with clause 661 662 @param witt_clause The with clause where to look for the dependencies 663 @param ctxt The structure specifying the scope of the definitions 664 of the with elements of the upper levels 665 @param in_sbq if true mark dependencies found in subqueries in 666 this->sq_dep_map 667 @param dep_map IN/OUT The bit where to mark the found dependencies 668 669 @details 670 This method searches in the with_clause for the the references in FROM 671 lists of all selects contained in the specifications of the with elements 672 from this with_clause that refer to definitions of tables from the 673 same with clause as this element. 674 If such definitions are found then the dependencies on them are 675 set in the in/out parameter dep_map and optionally in this->sq_dep_map. 676 The parameter ctxt describes the proper context for the search. 677 */ 678 679 void 680 With_element::check_dependencies_in_with_clause(With_clause *with_clause, 681 st_unit_ctxt_elem *ctxt, 682 bool in_subq, 683 table_map *dep_map) 684 { 685 for (With_element *with_elem= with_clause->with_list.first; 686 with_elem; 687 with_elem= with_elem->next) 688 { 689 check_dependencies_in_unit(with_elem->spec, ctxt, in_subq, dep_map); 690 } 691 } 692 693 694 /** 695 @brief 696 Find mutually recursive with elements and check that they have ancors 697 698 @details 699 This method performs the following: 700 - for each recursive with element finds all mutually recursive with it 701 - links each group of mutually recursive with elements into a ring chain 702 - checks that every group of mutually recursive with elements contains 703 at least one anchor 704 - checks that after removing any with element with anchor the remaining 705 with elements mutually recursive with the removed one are not recursive 706 anymore 707 708 @retval 709 true if an error is reported 710 false otherwise 711 */ 712 713 bool With_clause::check_anchors() 714 { 715 for (With_element *with_elem= with_list.first; 716 with_elem; 717 with_elem= with_elem->next) 718 { 719 if (!with_elem->is_recursive) 720 continue; 721 722 /* 723 It with_elem is recursive with element find all elements mutually recursive 724 with it (any recursive element is mutually recursive with itself). Mark all 725 these elements in the bitmap->mutually_recursive. Also link all these 726 elements into a ring chain. 727 */ 728 if (!with_elem->next_mutually_recursive) 729 { 730 With_element *last_mutually_recursive= with_elem; 731 table_map with_elem_dep= with_elem->derived_dep_map; 732 table_map with_elem_map= with_elem->get_elem_map(); 733 for (With_element *elem= with_elem; elem; elem= elem->next) 734 { 735 if (!elem->is_recursive) 736 continue; 737 738 if (elem == with_elem || 739 ((elem->derived_dep_map & with_elem_map) && 740 (with_elem_dep & elem->get_elem_map()))) 741 { 742 elem->next_mutually_recursive= with_elem; 743 last_mutually_recursive->next_mutually_recursive= elem; 744 last_mutually_recursive= elem; 745 with_elem->mutually_recursive|= elem->get_elem_map(); 746 } 747 } 748 for (With_element *elem= with_elem->next_mutually_recursive; 749 elem != with_elem; 750 elem= elem->next_mutually_recursive) 751 elem->mutually_recursive= with_elem->mutually_recursive; 752 } 753 754 /* 755 For each select from the specification of 'with_elem' check whether 756 it is an anchor i.e. does not depend on any with elements mutually 757 recursive with 'with_elem". 758 */ 759 for (st_select_lex *sl= with_elem->spec->first_select(); 760 sl; 761 sl= sl->next_select()) 762 { 763 if (with_elem->is_anchor(sl)) 764 { 765 with_elem->with_anchor= true; 766 break; 767 } 768 } 769 } 770 771 /* 772 Check that for any group of mutually recursive with elements 773 - there is at least one anchor 774 - after removing any with element with anchor the remaining with elements 775 mutually recursive with the removed one are not recursive anymore 776 */ 777 for (With_element *with_elem= with_list.first; 778 with_elem; 779 with_elem= with_elem->next) 780 { 781 if (!with_elem->is_recursive) 782 continue; 783 784 if (!with_elem->with_anchor) 785 { 786 /* 787 Check that the other with elements mutually recursive with 'with_elem' 788 contain at least one anchor. 789 */ 790 With_element *elem= with_elem; 791 while ((elem= elem->get_next_mutually_recursive()) != with_elem) 792 { 793 if (elem->with_anchor) 794 break; 795 } 796 if (elem == with_elem) 797 { 798 my_error(ER_RECURSIVE_WITHOUT_ANCHORS, MYF(0), 799 with_elem->get_name_str()); 800 return true; 801 } 802 } 803 else 804 { 805 /* 'with_elem' is a with element with an anchor */ 806 With_element *elem= with_elem; 807 /* 808 For the other with elements mutually recursive with 'with_elem' 809 set dependency bits between those elements in the field work_dep_map 810 and build transitive closure of these dependencies 811 */ 812 while ((elem= elem->get_next_mutually_recursive()) != with_elem) 813 elem->work_dep_map= elem->base_dep_map & elem->mutually_recursive; 814 elem= with_elem; 815 while ((elem= elem->get_next_mutually_recursive()) != with_elem) 816 { 817 table_map elem_map= elem->get_elem_map(); 818 With_element *el= with_elem; 819 while ((el= el->get_next_mutually_recursive()) != with_elem) 820 { 821 if (el->work_dep_map & elem_map) 822 el->work_dep_map|= elem->work_dep_map; 823 } 824 } 825 /* If the transitive closure displays any cycle report an arror */ 826 elem= with_elem; 827 while ((elem= elem->get_next_mutually_recursive()) != with_elem) 828 { 829 if (elem->work_dep_map & elem->get_elem_map()) 830 { 831 my_error(ER_UNACCEPTABLE_MUTUAL_RECURSION, MYF(0), 832 with_elem->get_name_str()); 833 return true; 834 } 835 } 836 } 837 } 838 839 return false; 840 } 841 842 843 /** 844 @brief 845 Move anchors at the beginning of the specifications for with elements 846 847 @details 848 This method moves anchors at the beginning of the specifications for 849 all recursive with elements. 850 */ 851 852 void With_clause::move_anchors_ahead() 853 { 854 for (With_element *with_elem= with_list.first; 855 with_elem; 856 with_elem= with_elem->next) 857 { 858 if (with_elem->is_recursive) 859 with_elem->move_anchors_ahead(); 860 } 861 } 862 863 864 /** 865 @brief 866 Move anchors at the beginning of the specification of this with element 867 868 @details 869 If the specification of this with element contains anchors the method 870 moves them at the very beginning of the specification. 871 Additionally for the other selects of the specification if none of them 872 contains a recursive reference to this with element or a mutually recursive 873 one the method looks for the first such reference in the first recursive 874 select and set a pointer to it in this->sq_rec_ref. 875 */ 876 877 void With_element::move_anchors_ahead() 878 { 879 st_select_lex *next_sl; 880 st_select_lex *new_pos= spec->first_select(); 881 new_pos->linkage= UNION_TYPE; 882 for (st_select_lex *sl= new_pos; sl; sl= next_sl) 883 { 884 next_sl= sl->next_select(); 885 if (is_anchor(sl)) 886 { 887 sl->move_node(new_pos); 888 if (new_pos == spec->first_select()) 889 { 890 enum sub_select_type type= new_pos->linkage; 891 new_pos->linkage= sl->linkage; 892 sl->linkage= type; 893 new_pos->with_all_modifier= sl->with_all_modifier; 894 sl->with_all_modifier= false; 895 } 896 new_pos= sl->next_select(); 897 } 898 else if (!sq_rec_ref && no_rec_ref_on_top_level()) 899 { 900 sq_rec_ref= find_first_sq_rec_ref_in_select(sl); 901 DBUG_ASSERT(sq_rec_ref != NULL); 902 } 903 } 904 first_recursive= new_pos; 905 spec->first_select()->linkage= DERIVED_TABLE_TYPE; 906 } 907 908 909 /** 910 @brief 911 Perform context analysis for all unreferenced tables defined in with clause 912 913 @param thd The context of the statement containing this with clause 914 915 @details 916 For each unreferenced table T defined in this with clause the method 917 calls the method With_element::prepare_unreferenced that performs 918 context analysis of the element with the definition of T. 919 920 @retval 921 false If context analysis does not report any error 922 true Otherwise 923 */ 924 925 bool With_clause::prepare_unreferenced_elements(THD *thd) 926 { 927 for (With_element *with_elem= with_list.first; 928 with_elem; 929 with_elem= with_elem->next) 930 { 931 if ((with_elem->is_hanging_recursive() || !with_elem->is_referenced()) && 932 with_elem->prepare_unreferenced(thd)) 933 return true; 934 } 935 936 return false; 937 } 938 939 940 /** 941 @brief 942 Save the specification of the given with table as a string 943 944 @param thd The context of the statement containing this with element 945 @param spec_start The beginning of the specification in the input string 946 @param spec_end The end of the specification in the input string 947 @param spec_offset The offset of the specification in the input string 948 949 @details 950 The method creates for a string copy of the specification used in this 951 element. The method is called when the element is parsed. The copy may be 952 used to create clones of the specification whenever they are needed. 953 954 @retval 955 false on success 956 true on failure 957 */ 958 959 bool With_element::set_unparsed_spec(THD *thd, char *spec_start, char *spec_end, 960 my_ptrdiff_t spec_offset) 961 { 962 stmt_prepare_mode= thd->m_parser_state->m_lip.stmt_prepare_mode; 963 unparsed_spec.length= spec_end - spec_start; 964 965 if (stmt_prepare_mode || !thd->lex->sphead) 966 unparsed_spec.str= spec_start; 967 else 968 unparsed_spec.str= thd->strmake(spec_start, unparsed_spec.length); 969 unparsed_spec_offset= spec_offset; 970 971 if (!unparsed_spec.str) 972 { 973 my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), 974 static_cast<int>(unparsed_spec.length)); 975 return true; 976 } 977 return false; 978 } 979 980 981 /** 982 @brief 983 Create a clone of the specification for the given with table 984 985 @param old_lex The LEX structure created for the query or CTE specification 986 where this With_element is defined 987 @param with_table The reference to the table defined in this element for which 988 the clone is created. 989 990 @details 991 The method creates a clone of the specification used in this element. 992 The clone is created for the given reference to the table defined by 993 this element. 994 The clone is created when the string with the specification saved in 995 unparsed_spec is fed into the parser as an input string. The parsing 996 this string a unit object representing the specification is built. 997 A chain of all table references occurred in the specification is also 998 formed. 999 The method includes the new unit and its sub-unit into hierarchy of 1000 the units of the main query. I also insert the constructed chain of the 1001 table references into the chain of all table references of the main query. 1002 The method resolves all references to CTE in the clone. 1003 1004 @note 1005 Clones is created only for not first references to tables defined in 1006 the with clause. They are necessary for merged specifications because 1007 the optimizer handles any such specification as independent on the others. 1008 When a table defined in the with clause is materialized in a temporary table 1009 one could do without specification clones. However in this case they 1010 are created as well, because currently different table references to a 1011 the same temporary table cannot share the same definition structure. 1012 1013 @retval 1014 pointer to the built clone if succeeds 1015 NULL - otherwise 1016 */ 1017 1018 st_select_lex_unit *With_element::clone_parsed_spec(LEX *old_lex, 1019 TABLE_LIST *with_table) 1020 { 1021 THD *thd= old_lex->thd; 1022 LEX *lex; 1023 st_select_lex_unit *res= NULL; 1024 1025 if (!(lex= (LEX*) new(thd->mem_root) st_lex_local)) 1026 return res; 1027 thd->lex= lex; 1028 1029 bool parse_status= false; 1030 st_select_lex *with_select; 1031 st_select_lex *last_clone_select; 1032 1033 char save_end= unparsed_spec.str[unparsed_spec.length]; 1034 const_cast<char*>(unparsed_spec.str)[unparsed_spec.length]= '\0'; 1035 1036 lex_start(thd); 1037 lex->clone_spec_offset= unparsed_spec_offset; 1038 lex->with_cte_resolution= true; 1039 /* 1040 There's no need to add SPs/SFs referenced in the clone to the global 1041 list of the SPs/SFs used in the query as they were added when the first 1042 reference to the cloned CTE was parsed. Yet the recursive call of the 1043 parser must to know that they were already included into the list. 1044 */ 1045 lex->sroutines= old_lex->sroutines; 1046 lex->sroutines_list_own_last= old_lex->sroutines_list_own_last; 1047 lex->sroutines_list_own_elements= old_lex->sroutines_list_own_elements; 1048 1049 /* 1050 The specification of a CTE is to be parsed as a regular query. 1051 At the very end of the parsing query the function 1052 check_cte_dependencies_and_resolve_references() will be called. 1053 It will check the dependencies between CTEs that are defined 1054 within the query and will resolve CTE references in this query. 1055 If a table reference is not resolved as a CTE reference within 1056 this query it still can be resolved as a reference to a CTE defined 1057 in the same clause as the CTE whose specification is to be parsed 1058 or defined in an embedding CTE definition. 1059 1060 Example: 1061 with 1062 cte1 as ( ... ), 1063 cte2 as ([WITH ...] select ... from cte1 ...) 1064 select ... from cte2 as r, ..., cte2 as s ... 1065 1066 Here the specification of cte2 has be cloned for table reference 1067 with alias s1. The specification contains a reference to cte1 1068 that is defined outside this specification. If the reference to 1069 cte1 cannot be resolved within the specification of cte2 it's 1070 not necessarily has to be a reference to a non-CTE table. That's 1071 why the flag lex->only_cte_resolution has to be set to true 1072 before parsing of the specification of cte2 invoked by this 1073 function starts. Otherwise an mdl_lock would be requested for s 1074 and this would not be correct. 1075 */ 1076 1077 lex->only_cte_resolution= true; 1078 1079 lex->stmt_lex= old_lex->stmt_lex ? old_lex->stmt_lex : old_lex; 1080 1081 parse_status= thd->sql_parser(old_lex, lex, 1082 (char*) unparsed_spec.str, 1083 (unsigned int)unparsed_spec.length, 1084 stmt_prepare_mode); 1085 1086 const_cast<char*>(unparsed_spec.str)[unparsed_spec.length]= save_end; 1087 with_select= lex->unit.first_select(); 1088 with_select->select_number= ++lex->stmt_lex->current_select_number; 1089 1090 if (parse_status) 1091 goto err; 1092 1093 /* 1094 The unit of the specification that just has been parsed is included 1095 as a slave of the select that contained in its from list the table 1096 reference for which the unit has been created. 1097 */ 1098 lex->unit.include_down(with_table->select_lex); 1099 lex->unit.set_slave(with_select); 1100 lex->unit.cloned_from= spec; 1101 1102 /* 1103 Now all references to the CTE defined outside of the cloned specification 1104 has to be resolved. Additionally if old_lex->only_cte_resolution == false 1105 for the table references that has not been resolved requests for mdl_locks 1106 has to be set. 1107 */ 1108 lex->only_cte_resolution= old_lex->only_cte_resolution; 1109 if (lex->resolve_references_to_cte(lex->query_tables, 1110 lex->query_tables_last)) 1111 { 1112 res= NULL; 1113 goto err; 1114 } 1115 1116 /* 1117 The global chain of TABLE_LIST objects created for the specification that 1118 just has been parsed is added to such chain that contains the reference 1119 to the CTE whose specification is parsed right after the TABLE_LIST object 1120 created for the reference. 1121 */ 1122 if (lex->query_tables) 1123 { 1124 head->tables_pos.set_start_pos(&with_table->next_global); 1125 head->tables_pos.set_end_pos(lex->query_tables_last); 1126 TABLE_LIST *next_tbl= with_table->next_global; 1127 if (next_tbl) 1128 { 1129 *(lex->query_tables->prev_global= next_tbl->prev_global)= 1130 lex->query_tables; 1131 *(next_tbl->prev_global= lex->query_tables_last)= next_tbl; 1132 } 1133 else 1134 { 1135 *(lex->query_tables->prev_global= old_lex->query_tables_last)= 1136 lex->query_tables; 1137 old_lex->query_tables_last= lex->query_tables_last; 1138 } 1139 } 1140 old_lex->sroutines_list_own_last= lex->sroutines_list_own_last; 1141 old_lex->sroutines_list_own_elements= lex->sroutines_list_own_elements; 1142 res= &lex->unit; 1143 res->with_element= this; 1144 1145 last_clone_select= lex->all_selects_list; 1146 while (last_clone_select->next_select_in_list()) 1147 last_clone_select= last_clone_select->next_select_in_list(); 1148 old_lex->all_selects_list= 1149 (st_select_lex*) (lex->all_selects_list-> 1150 insert_chain_before( 1151 (st_select_lex_node **) &(old_lex->all_selects_list), 1152 last_clone_select)); 1153 1154 lex->sphead= NULL; // in order not to delete lex->sphead 1155 lex_end(lex); 1156 err: 1157 thd->lex= old_lex; 1158 return res; 1159 } 1160 1161 1162 /** 1163 @brief 1164 Rename columns of the unit derived from the spec of this with element 1165 @param thd The context of the statement containing the with element 1166 @param unit The specification of the with element or its clone 1167 1168 @details 1169 The method assumes that the parameter unit is either specification itself 1170 of this with element or a clone of this specification. The looks through 1171 the column list in this with element. It reports an error if the cardinality 1172 of this list differs from the cardinality of select lists in 'unit'. 1173 Otherwise it renames the columns of the first select list and sets the flag 1174 unit->column_list_is_processed to true preventing renaming columns for the 1175 second time. 1176 1177 @retval 1178 true if an error was reported 1179 false otherwise 1180 */ 1181 1182 bool 1183 With_element::rename_columns_of_derived_unit(THD *thd, 1184 st_select_lex_unit *unit) 1185 { 1186 if (unit->columns_are_renamed) 1187 return false; 1188 1189 st_select_lex *select= unit->first_select(); 1190 1191 if (column_list.elements) // The column list is optional 1192 { 1193 List_iterator_fast<Item> it(select->item_list); 1194 List_iterator_fast<LEX_CSTRING> nm(column_list); 1195 Item *item; 1196 LEX_CSTRING *name; 1197 1198 if (column_list.elements != select->item_list.elements) 1199 { 1200 my_error(ER_WITH_COL_WRONG_LIST, MYF(0)); 1201 return true; 1202 } 1203 1204 Query_arena *arena, backup; 1205 arena= thd->activate_stmt_arena_if_needed(&backup); 1206 1207 /* Rename the columns of the first select in the unit */ 1208 while ((item= it++, name= nm++)) 1209 { 1210 item->set_name(thd, name->str, (uint) name->length, system_charset_info); 1211 item->is_autogenerated_name= false; 1212 } 1213 1214 if (arena) 1215 thd->restore_active_arena(arena, &backup); 1216 } 1217 else 1218 make_valid_column_names(thd, select->item_list); 1219 1220 unit->columns_are_renamed= true; 1221 1222 return false; 1223 } 1224 1225 1226 /** 1227 @brief 1228 Perform context analysis the definition of an unreferenced table 1229 1230 @param thd The context of the statement containing this with element 1231 1232 @details 1233 The method assumes that this with element contains the definition 1234 of a table that is not used anywhere. In this case one has to check 1235 that context conditions are met. 1236 1237 @retval 1238 true if an error was reported 1239 false otherwise 1240 */ 1241 1242 bool With_element::prepare_unreferenced(THD *thd) 1243 { 1244 bool rc= false; 1245 st_select_lex *first_sl= spec->first_select(); 1246 1247 /* Prevent name resolution for field references out of with elements */ 1248 for (st_select_lex *sl= first_sl; 1249 sl; 1250 sl= sl->next_select()) 1251 sl->context.outer_context= 0; 1252 1253 thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED; 1254 if (!spec->prepared && 1255 (spec->prepare(spec->derived, 0, 0) || 1256 rename_columns_of_derived_unit(thd, spec) || 1257 check_duplicate_names(thd, first_sl->item_list, 1))) 1258 rc= true; 1259 1260 thd->lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED; 1261 return rc; 1262 } 1263 1264 1265 bool With_element::is_anchor(st_select_lex *sel) 1266 { 1267 return !(mutually_recursive & sel->with_dep); 1268 } 1269 1270 1271 /** 1272 @brief 1273 Search for the definition of the given table referred in this select node 1274 1275 @param table reference to the table whose definition is searched for 1276 1277 @details 1278 The method looks for the definition of the table whose reference is occurred 1279 in the FROM list of this select node. First it searches for it in the 1280 with clause attached to the unit this select node belongs to. If such a 1281 definition is not found then the embedding units are looked through. 1282 1283 @retval 1284 pointer to the found definition if the search has been successful 1285 NULL - otherwise 1286 */ 1287 1288 With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) 1289 { 1290 With_element *found= NULL; 1291 With_clause *containing_with_clause= NULL; 1292 st_select_lex_unit *master_unit; 1293 st_select_lex *outer_sl; 1294 for (st_select_lex *sl= this; sl; sl= outer_sl) 1295 { 1296 /* 1297 If sl->master_unit() is the spec of a with element then the search for 1298 a definition was already done by With_element::check_dependencies_in_spec 1299 and it was unsuccesful. Yet for units cloned from the spec it has not 1300 been done yet. 1301 */ 1302 With_clause *attached_with_clause= sl->get_with_clause(); 1303 if (attached_with_clause && 1304 attached_with_clause != containing_with_clause && 1305 (found= attached_with_clause->find_table_def(table, NULL))) 1306 break; 1307 master_unit= sl->master_unit(); 1308 outer_sl= master_unit->outer_select(); 1309 With_element *with_elem= sl->get_with_element(); 1310 if (with_elem) 1311 { 1312 containing_with_clause= with_elem->get_owner(); 1313 With_element *barrier= containing_with_clause->with_recursive ? 1314 NULL : with_elem; 1315 if ((found= containing_with_clause->find_table_def(table, barrier))) 1316 break; 1317 if (outer_sl && !outer_sl->get_with_element()) 1318 break; 1319 } 1320 /* Do not look for the table's definition beyond the scope of the view */ 1321 if (master_unit->is_view) 1322 break; 1323 } 1324 return found; 1325 } 1326 1327 1328 bool TABLE_LIST::is_recursive_with_table() 1329 { 1330 return with && with->is_recursive; 1331 } 1332 1333 1334 /* 1335 A reference to a with table T is recursive if it occurs somewhere 1336 in the query specifying T or in the query specifying one of the tables 1337 mutually recursive with T. 1338 */ 1339 1340 bool TABLE_LIST::is_with_table_recursive_reference() 1341 { 1342 return (with_internal_reference_map && 1343 (with->get_mutually_recursive() & with_internal_reference_map)); 1344 } 1345 1346 1347 /* 1348 Specifications of with tables with recursive table references 1349 in non-mergeable derived tables are not allowed in this 1350 implementation. 1351 */ 1352 1353 1354 /* 1355 We say that the specification of a with table T is restricted 1356 if all below is true. 1357 1. Any immediate select of the specification contains at most one 1358 recursive table reference taking into account table references 1359 from mergeable derived tables. 1360 2. Any recursive table reference is not an inner operand of an 1361 outer join operation used in an immediate select of the 1362 specification. 1363 3. Any immediate select from the specification of T does not 1364 contain aggregate functions. 1365 4. The specification of T does not contain recursive table references. 1366 1367 If the specification of T is not restricted we call the corresponding 1368 with element unrestricted. 1369 1370 The SQL standards allows only with elements with restricted specification. 1371 By default we comply with the standards here. 1372 1373 Yet we allow unrestricted specification if the status variable 1374 'standards_compliant_cte' set to 'off'(0). 1375 */ 1376 1377 1378 /** 1379 @brief 1380 Check if this select makes the including specification unrestricted 1381 1382 @param 1383 only_standards_compliant true if the system variable 1384 'standards_compliant_cte' is set to 'on' 1385 @details 1386 This method checks whether the conditions 1-4 (see the comment above) 1387 are satisfied for this select. If not then mark this element as 1388 unrestricted and report an error if 'only_standards_compliant' is true. 1389 1390 @retval 1391 true if an error is reported 1392 false otherwise 1393 */ 1394 1395 bool st_select_lex::check_unrestricted_recursive(bool only_standard_compliant) 1396 { 1397 With_element *with_elem= get_with_element(); 1398 if (!with_elem ||!with_elem->is_recursive) 1399 { 1400 /* 1401 If this select is not from the specifiocation of a with elememt or 1402 if this not a recursive with element then there is nothing to check. 1403 */ 1404 return false; 1405 } 1406 1407 /* Check conditions 1-2 for restricted specification*/ 1408 table_map unrestricted= 0; 1409 table_map encountered= 0; 1410 if (with_elem->check_unrestricted_recursive(this, 1411 unrestricted, 1412 encountered)) 1413 return true; 1414 with_elem->get_owner()->add_unrestricted(unrestricted); 1415 1416 1417 /* Check conditions 3-4 for restricted specification*/ 1418 if ((with_sum_func && !with_elem->is_anchor(this)) || 1419 (with_elem->contains_sq_with_recursive_reference())) 1420 with_elem->get_owner()->add_unrestricted( 1421 with_elem->get_mutually_recursive()); 1422 1423 /* Report an error on unrestricted specification if this is required */ 1424 if (only_standard_compliant && with_elem->is_unrestricted()) 1425 { 1426 my_error(ER_NOT_STANDARD_COMPLIANT_RECURSIVE, 1427 MYF(0), with_elem->get_name_str()); 1428 return true; 1429 } 1430 1431 return false; 1432 } 1433 1434 1435 /** 1436 @brief 1437 Check if a select from the spec of this with element is partially restricted 1438 1439 @param 1440 sel select from the specification of this element where to check 1441 whether conditions 1-2 are satisfied 1442 unrestricted IN/OUT bitmap where to mark unrestricted specs 1443 encountered IN/OUT bitmap where to mark encountered recursive references 1444 @details 1445 This method checks whether the conditions 1-2 (see the comment above) 1446 are satisfied for the select sel. 1447 This method is called recursively for derived tables. 1448 1449 @retval 1450 true if an error is reported 1451 false otherwise 1452 */ 1453 1454 bool With_element::check_unrestricted_recursive(st_select_lex *sel, 1455 table_map &unrestricted, 1456 table_map &encountered) 1457 { 1458 /* Check conditions 1 for restricted specification*/ 1459 List_iterator<TABLE_LIST> ti(sel->leaf_tables); 1460 TABLE_LIST *tbl; 1461 while ((tbl= ti++)) 1462 { 1463 st_select_lex_unit *unit= tbl->get_unit(); 1464 if (unit) 1465 { 1466 if(!tbl->is_with_table()) 1467 { 1468 if (check_unrestricted_recursive(unit->first_select(), 1469 unrestricted, 1470 encountered)) 1471 return true; 1472 } 1473 if (!(tbl->is_recursive_with_table() && unit->with_element->owner == owner)) 1474 continue; 1475 With_element *with_elem= unit->with_element; 1476 if (encountered & with_elem->get_elem_map()) 1477 unrestricted|= with_elem->mutually_recursive; 1478 else if (with_elem ==this) 1479 encountered|= with_elem->get_elem_map(); 1480 } 1481 } 1482 for (With_element *with_elem= owner->with_list.first; 1483 with_elem; 1484 with_elem= with_elem->next) 1485 { 1486 if (!with_elem->is_recursive && (unrestricted & with_elem->get_elem_map())) 1487 continue; 1488 if (encountered & with_elem->get_elem_map()) 1489 { 1490 uint cnt= 0; 1491 table_map encountered_mr= encountered & with_elem->mutually_recursive; 1492 for (table_map map= encountered_mr >> with_elem->number; 1493 map != 0; 1494 map>>= 1) 1495 { 1496 if (map & 1) 1497 { 1498 if (cnt) 1499 { 1500 unrestricted|= with_elem->mutually_recursive; 1501 break; 1502 } 1503 else 1504 cnt++; 1505 } 1506 } 1507 } 1508 } 1509 1510 1511 /* Check conditions 2 for restricted specification*/ 1512 ti.rewind(); 1513 while ((tbl= ti++)) 1514 { 1515 if (!tbl->is_with_table_recursive_reference()) 1516 continue; 1517 for (TABLE_LIST *tab= tbl; tab; tab= tab->embedding) 1518 { 1519 if (tab->outer_join & (JOIN_TYPE_LEFT | JOIN_TYPE_RIGHT)) 1520 { 1521 unrestricted|= mutually_recursive; 1522 break; 1523 } 1524 } 1525 } 1526 return false; 1527 } 1528 1529 1530 /** 1531 @brief 1532 Check subqueries with recursive table references from FROM list of this select 1533 1534 @details 1535 For each recursive table reference from the FROM list of this select 1536 this method checks: 1537 - whether this reference is within a materialized derived table and 1538 if so it report an error 1539 - whether this reference is within a subquery and if so it set a flag 1540 in this subquery that disallows some optimization strategies for 1541 this subquery. 1542 1543 @retval 1544 true if an error is reported 1545 false otherwise 1546 */ 1547 1548 bool st_select_lex::check_subqueries_with_recursive_references() 1549 { 1550 List_iterator<TABLE_LIST> ti(leaf_tables); 1551 TABLE_LIST *tbl; 1552 while ((tbl= ti++)) 1553 { 1554 if (!(tbl->is_with_table_recursive_reference())) 1555 continue; 1556 With_element *rec_elem= tbl->with; 1557 st_select_lex_unit *sl_master; 1558 for (st_select_lex *sl= this; sl; sl= sl_master->outer_select()) 1559 { 1560 sl_master= sl->master_unit(); 1561 if (sl_master->with_element && 1562 sl_master->with_element->get_owner() == rec_elem->get_owner()) 1563 break; 1564 sl->uncacheable|= UNCACHEABLE_DEPENDENT; 1565 sl_master->uncacheable|= UNCACHEABLE_DEPENDENT; 1566 if (sl_master->derived) 1567 sl_master->derived->register_as_derived_with_rec_ref(rec_elem); 1568 if (sl_master->item) 1569 { 1570 Item_subselect *subq= (Item_subselect *) (sl_master->item); 1571 subq->register_as_with_rec_ref(rec_elem); 1572 } 1573 } 1574 } 1575 return false; 1576 } 1577 1578 1579 /** 1580 @brief 1581 Print this with clause 1582 1583 @param str Where to print to 1584 @param query_type The mode of printing 1585 1586 @details 1587 The method prints a string representation of this clause in the 1588 string str. The parameter query_type specifies the mode of printing. 1589 */ 1590 1591 void With_clause::print(String *str, enum_query_type query_type) 1592 { 1593 /* 1594 Any with clause contains just definitions of CTE tables. 1595 No data expansion is applied to these definitions. 1596 */ 1597 query_type= (enum_query_type) (query_type | QT_NO_DATA_EXPANSION); 1598 1599 str->append(STRING_WITH_LEN("with ")); 1600 if (with_recursive) 1601 str->append(STRING_WITH_LEN("recursive ")); 1602 for (With_element *with_elem= with_list.first; 1603 with_elem; 1604 with_elem= with_elem->next) 1605 { 1606 if (with_elem != with_list.first) 1607 str->append(", "); 1608 with_elem->print(str, query_type); 1609 } 1610 } 1611 1612 1613 /** 1614 @brief 1615 Print this with element 1616 1617 @param str Where to print to 1618 @param query_type The mode of printing 1619 1620 @details 1621 The method prints a string representation of this with element in the 1622 string str. The parameter query_type specifies the mode of printing. 1623 */ 1624 1625 void With_element::print(String *str, enum_query_type query_type) 1626 { 1627 str->append(get_name()); 1628 if (column_list.elements) 1629 { 1630 List_iterator_fast<LEX_CSTRING> li(column_list); 1631 str->append('('); 1632 for (LEX_CSTRING *col_name= li++; ; ) 1633 { 1634 str->append(col_name); 1635 col_name= li++; 1636 if (!col_name) 1637 { 1638 str->append(')'); 1639 break; 1640 } 1641 str->append(','); 1642 } 1643 } 1644 str->append(STRING_WITH_LEN(" as ")); 1645 str->append('('); 1646 spec->print(str, query_type); 1647 str->append(')'); 1648 } 1649 1650 1651 bool With_element::instantiate_tmp_tables() 1652 { 1653 List_iterator_fast<TABLE_LIST> li(rec_result->rec_table_refs); 1654 TABLE_LIST *rec_tbl; 1655 while ((rec_tbl= li++)) 1656 { 1657 TABLE *rec_table= rec_tbl->table; 1658 if (!rec_table->is_created() && 1659 instantiate_tmp_table(rec_table, 1660 rec_table->s->key_info, 1661 rec_result->tmp_table_param.start_recinfo, 1662 &rec_result->tmp_table_param.recinfo, 1663 0)) 1664 return true; 1665 1666 rec_table->file->extra(HA_EXTRA_WRITE_CACHE); 1667 rec_table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); 1668 } 1669 return false; 1670 } 1671 1672