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