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