1 /* Copyright (c) 2017, MariaDB
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; version 2 of the License.
6 
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11 
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
15 
16 #include "mariadb.h"
17 #include "sql_list.h"
18 #include "sql_tvc.h"
19 #include "sql_class.h"
20 #include "opt_range.h"
21 #include "sql_select.h"
22 #include "sql_explain.h"
23 #include "sql_parse.h"
24 #include "sql_cte.h"
25 
26 /**
27   @brief
28     Fix fields for TVC values
29 
30   @param
31     @param thd	 The context of the statement
32     @param li	 The iterator on the list of lists
33 
34   @details
35     Call fix_fields procedure for TVC values.
36 
37   @retval
38     true     if an error was reported
39     false    otherwise
40 */
41 
fix_fields_for_tvc(THD * thd,List_iterator_fast<List_item> & li)42 bool fix_fields_for_tvc(THD *thd, List_iterator_fast<List_item> &li)
43 {
44   DBUG_ENTER("fix_fields_for_tvc");
45   List_item *lst;
46   li.rewind();
47 
48   while ((lst= li++))
49   {
50     List_iterator<Item> it(*lst);
51     Item *item;
52 
53     while ((item= it++))
54     {
55       /*
56         Some items have already been fixed.
57         For example Item_splocal items get fixed in
58         Item_splocal::append_for_log(), which is called from subst_spvars()
59         while replacing their values to NAME_CONST()s.
60         So fix only those that have not been.
61       */
62       if (item->fix_fields_if_needed_for_scalar(thd, it.ref()) ||
63           item->check_is_evaluable_expression_or_error())
64 	DBUG_RETURN(true);
65     }
66   }
67   DBUG_RETURN(false);
68 }
69 
70 
71 /**
72   @brief
73     Defines types of matrix columns elements where matrix rows are defined by
74     some lists of values.
75 
76   @param
77     @param thd   	 The context of the statement
78     @param li	     	 The iterator on the list of lists
79     @param holders   	 The structure where types of matrix columns are stored
80     @param first_list_el_count  Count of the list values. It should be the same
81                                 for each list of lists elements. It contains
82 			        number of elements of the first list from list of
83                                 lists.
84 
85   @details
86     For each list list_a from list of lists the procedure gets its elements
87     types and aggregates them with the previous ones stored in holders. If
88     list_a is the first one in the list of lists its elements types are put in
89     holders. The errors can be reported when count of list_a elements is
90     different from the first_list_el_count. Also error can be reported whe
91     n aggregation can't be made.
92 
93   @retval
94     true    if an error was reported
95     false   otherwise
96 */
97 
join_type_handlers_for_tvc(THD * thd,List_iterator_fast<List_item> & li,Type_holder * holders,uint first_list_el_count)98 bool join_type_handlers_for_tvc(THD *thd, List_iterator_fast<List_item> &li,
99 			        Type_holder *holders, uint first_list_el_count)
100 {
101   DBUG_ENTER("join_type_handlers_for_tvc");
102   List_item *lst;
103   li.rewind();
104   bool first= true;
105 
106   while ((lst= li++))
107   {
108     List_iterator_fast<Item> it(*lst);
109     Item *item;
110 
111     if (first_list_el_count != lst->elements)
112     {
113       my_message(ER_WRONG_NUMBER_OF_VALUES_IN_TVC,
114                  ER_THD(thd, ER_WRONG_NUMBER_OF_VALUES_IN_TVC),
115                  MYF(0));
116       DBUG_RETURN(true);
117     }
118     for (uint pos= 0; (item=it++); pos++)
119     {
120       const Type_handler *item_type_handler= item->real_type_handler();
121       if (first)
122         holders[pos].set_handler(item_type_handler);
123       else if (holders[pos].aggregate_for_result(item_type_handler))
124       {
125         my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
126                  holders[pos].type_handler()->name().ptr(),
127                  item_type_handler->name().ptr(),
128                  "TABLE VALUE CONSTRUCTOR");
129         DBUG_RETURN(true);
130       }
131     }
132     first= false;
133   }
134   DBUG_RETURN(false);
135 }
136 
137 
138 /**
139   @brief
140     Define attributes of matrix columns elements where matrix rows are defined
141     by some lists of values.
142 
143   @param
144     @param thd	  	  The context of the statement
145     @param li	     	  The iterator on the list of lists
146     @param holders   	  The structure where names of matrix columns are stored
147     @param count_of_lists Count of list of lists elements
148     @param first_list_el_count  Count of the list values. It should be the same
149                                 for each list of lists elements. It contains
150 				number of elements of the first list from list
151                                 of lists.
152 
153   @details
154     For each list list_a from list of lists the procedure gets its elements
155     attributes and aggregates them with the previous ones stored in holders.
156     The errors can be reported when aggregation can't be made.
157 
158   @retval
159     true     if an error was reported
160     false    otherwise
161 */
162 
get_type_attributes_for_tvc(THD * thd,List_iterator_fast<List_item> & li,Type_holder * holders,uint count_of_lists,uint first_list_el_count)163 bool get_type_attributes_for_tvc(THD *thd,
164 			         List_iterator_fast<List_item> &li,
165                                  Type_holder *holders, uint count_of_lists,
166 				 uint first_list_el_count)
167 {
168   DBUG_ENTER("get_type_attributes_for_tvc");
169   List_item *lst;
170   li.rewind();
171 
172   for (uint pos= 0; pos < first_list_el_count; pos++)
173   {
174     if (holders[pos].alloc_arguments(thd, count_of_lists))
175       DBUG_RETURN(true);
176   }
177 
178   while ((lst= li++))
179   {
180     List_iterator_fast<Item> it(*lst);
181     Item *item;
182     for (uint holder_pos= 0 ; (item= it++); holder_pos++)
183     {
184       DBUG_ASSERT(item->fixed);
185       holders[holder_pos].add_argument(item);
186     }
187   }
188 
189   for (uint pos= 0; pos < first_list_el_count; pos++)
190   {
191     if (holders[pos].aggregate_attributes(thd))
192       DBUG_RETURN(true);
193   }
194   DBUG_RETURN(false);
195 }
196 
197 
198 /**
199   @brief
200     Prepare of TVC
201 
202   @param
203     @param thd	        The context of the statement
204     @param sl	     	The select where this TVC is defined
205     @param tmp_result	Structure that contains the information
206 			about where to send the result of the query
207     @param unit_arg  	The union where sl is defined
208 
209   @details
210     Gets types and attributes of values of this TVC that will be used
211     for temporary table creation for this TVC. It creates Item_type_holders
212     for each element of the first list from list of lists (VALUES from tvc),
213     using its elements name, defined type and attribute.
214 
215   @retval
216     true     if an error was reported
217     false    otherwise
218 */
219 
prepare(THD * thd,SELECT_LEX * sl,select_result * tmp_result,st_select_lex_unit * unit_arg)220 bool table_value_constr::prepare(THD *thd, SELECT_LEX *sl,
221 				 select_result *tmp_result,
222 				 st_select_lex_unit *unit_arg)
223 {
224   DBUG_ENTER("table_value_constr::prepare");
225   select_lex->in_tvc= true;
226   List_iterator_fast<List_item> li(lists_of_values);
227 
228   List_item *first_elem= li++;
229   uint cnt= first_elem->elements;
230   Type_holder *holders;
231 
232   if (cnt == 0)
233   {
234     my_error(ER_EMPTY_ROW_IN_TVC, MYF(0));
235     DBUG_RETURN(true);
236   }
237 
238   if (fix_fields_for_tvc(thd, li))
239     DBUG_RETURN(true);
240 
241   if (!(holders= new (thd->stmt_arena->mem_root) Type_holder[cnt]) ||
242        join_type_handlers_for_tvc(thd, li, holders, cnt) ||
243        get_type_attributes_for_tvc(thd, li, holders,
244 				   lists_of_values.elements, cnt))
245     DBUG_RETURN(true);
246 
247   List_iterator_fast<Item> it(*first_elem);
248   Item *item;
249   Query_arena *arena, backup;
250   arena=thd->activate_stmt_arena_if_needed(&backup);
251 
252   sl->item_list.empty();
253   for (uint pos= 0; (item= it++); pos++)
254   {
255     /* Error's in 'new' will be detected after loop */
256     Item_type_holder *new_holder= new (thd->mem_root)
257                       Item_type_holder(thd, item, holders[pos].type_handler(),
258                                        &holders[pos]/*Type_all_attributes*/,
259                                        holders[pos].get_maybe_null());
260     new_holder->fix_fields(thd, 0);
261     sl->item_list.push_back(new_holder);
262   }
263   if (arena)
264     thd->restore_active_arena(arena, &backup);
265 
266   if (unlikely(thd->is_fatal_error))
267     DBUG_RETURN(true); // out of memory
268 
269   result= tmp_result;
270 
271   if (result && result->prepare(sl->item_list, unit_arg))
272     DBUG_RETURN(true);
273 
274   /*
275     setup_order() for a TVC is not called when the following is true
276     (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW)
277   */
278 
279   thd->where="order clause";
280   ORDER *order= sl->order_list.first;
281   for (; order; order=order->next)
282   {
283     Item *order_item= *order->item;
284     if (order_item->type() == Item::INT_ITEM && order_item->basic_const_item())
285     {
286       uint count= 0;
287       if (order->counter_used)
288         count= order->counter; // counter was once resolved
289       else
290         count= (uint) order_item->val_int();
291       if (!count || count > first_elem->elements)
292       {
293         my_error(ER_BAD_FIELD_ERROR, MYF(0),
294                  order_item->full_name(), thd->where);
295         DBUG_RETURN(true);
296       }
297       order->in_field_list= 1;
298       order->counter= count;
299       order->counter_used= 1;
300     }
301   }
302 
303   select_lex->in_tvc= false;
304   DBUG_RETURN(false);
305 }
306 
307 
308 /**
309     Save Query Plan Footprint
310 */
311 
save_explain_data_intern(THD * thd,Explain_query * output)312 int table_value_constr::save_explain_data_intern(THD *thd,
313 						 Explain_query *output)
314 {
315   const char *message= "No tables used";
316   DBUG_ENTER("table_value_constr::save_explain_data_intern");
317   DBUG_PRINT("info", ("Select %p, type %s, message %s",
318 		      select_lex, select_lex->type,
319 		      message));
320   DBUG_ASSERT(have_query_plan == QEP_AVAILABLE);
321 
322   /* There should be no attempts to save query plans for merged selects */
323   DBUG_ASSERT(!select_lex->master_unit()->derived ||
324                select_lex->master_unit()->derived->is_materialized_derived() ||
325                select_lex->master_unit()->derived->is_with_table());
326 
327   explain= new (output->mem_root) Explain_select(output->mem_root,
328                                                  thd->lex->analyze_stmt);
329   if (!explain)
330     DBUG_RETURN(1);
331 
332   select_lex->set_explain_type(true);
333 
334   explain->select_id= select_lex->select_number;
335   explain->select_type= select_lex->type;
336   explain->linkage= select_lex->linkage;
337   explain->using_temporary= false;
338   explain->using_filesort= false;
339   /* Setting explain->message means that all other members are invalid */
340   explain->message= message;
341 
342   if (select_lex->master_unit()->derived)
343     explain->connection_type= Explain_node::EXPLAIN_NODE_DERIVED;
344 
345   for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit();
346        unit;
347        unit= unit->next_unit())
348   {
349     explain->add_child(unit->first_select()->select_number);
350   }
351 
352   output->add_node(explain);
353 
354   if (select_lex->is_top_level_node())
355     output->query_plan_ready();
356 
357   DBUG_RETURN(0);
358 }
359 
360 
361 /**
362   Optimization of TVC
363 */
364 
optimize(THD * thd)365 bool table_value_constr::optimize(THD *thd)
366 {
367   create_explain_query_if_not_exists(thd->lex, thd->mem_root);
368   have_query_plan= QEP_AVAILABLE;
369 
370   if (select_lex->select_number != UINT_MAX &&
371       select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ &&
372       have_query_plan != QEP_NOT_PRESENT_YET &&
373       thd->lex->explain && // for "SET" command in SPs.
374       (!thd->lex->explain->get_select(select_lex->select_number)))
375   {
376     if (save_explain_data_intern(thd, thd->lex->explain))
377       return true;
378   }
379 
380   if (select_lex->optimize_unflattened_subqueries(true))
381     return true;
382 
383   return false;
384 }
385 
386 
387 /**
388   Execute of TVC
389 */
390 
exec(SELECT_LEX * sl)391 bool table_value_constr::exec(SELECT_LEX *sl)
392 {
393   DBUG_ENTER("table_value_constr::exec");
394   List_iterator_fast<List_item> li(lists_of_values);
395   List_item *elem;
396   ha_rows send_records= 0;
397 
398   if (select_options & SELECT_DESCRIBE)
399     DBUG_RETURN(false);
400 
401   if (result->send_result_set_metadata(sl->item_list,
402                                        Protocol::SEND_NUM_ROWS |
403                                        Protocol::SEND_EOF))
404   {
405     DBUG_RETURN(true);
406   }
407 
408   while ((elem= li++))
409   {
410     if (send_records >= sl->master_unit()->select_limit_cnt)
411       break;
412     int rc= result->send_data(*elem);
413     if (!rc)
414       send_records++;
415     else if (rc > 0)
416       DBUG_RETURN(true);
417   }
418 
419   if (result->send_eof())
420     DBUG_RETURN(true);
421 
422   DBUG_RETURN(false);
423 }
424 
425 
426 /**
427   @brief
428     Print list
429 
430   @param str         The reference on the string representation of the list
431   @param list	     The list that needed to be print
432   @param query_type  The mode of printing
433 
434   @details
435     The method saves a string representation of list in the
436     string str.
437 */
438 
print_list_item(String * str,List_item * list,enum_query_type query_type)439 void print_list_item(String *str, List_item *list,
440 		     enum_query_type query_type)
441 {
442   bool is_first_elem= true;
443   List_iterator_fast<Item> it(*list);
444   Item *item;
445 
446   str->append('(');
447 
448   while ((item= it++))
449   {
450     if (is_first_elem)
451       is_first_elem= false;
452     else
453       str->append(',');
454 
455     item->print(str, query_type);
456   }
457 
458   str->append(')');
459 }
460 
461 
462 /**
463   @brief
464     Print this TVC
465 
466   @param thd         The context of the statement
467   @param str         The reference on the string representation of this TVC
468   @param query_type  The mode of printing
469 
470   @details
471     The method saves a string representation of this TVC in the
472     string str.
473 */
474 
print(THD * thd,String * str,enum_query_type query_type)475 void table_value_constr::print(THD *thd, String *str,
476 			       enum_query_type query_type)
477 {
478   DBUG_ASSERT(thd);
479 
480   str->append(STRING_WITH_LEN("values "));
481 
482   bool is_first_elem= true;
483   List_iterator_fast<List_item> li(lists_of_values);
484   List_item *list;
485 
486   while ((list= li++))
487   {
488     if (is_first_elem)
489       is_first_elem= false;
490     else
491       str->append(',');
492 
493     print_list_item(str, list, query_type);
494   }
495   if (select_lex->order_list.elements)
496   {
497     str->append(STRING_WITH_LEN(" order by "));
498     select_lex->print_order(str, select_lex->order_list.first, query_type);
499   }
500   select_lex->print_limit(thd, str, query_type);
501 }
502 
503 
504 /**
505   @brief
506     Create list of lists for TVC from the list of this IN predicate
507 
508   @param thd         The context of the statement
509   @param values      TVC list of values
510 
511   @details
512     The method uses the list of values of this IN predicate to build
513     an equivalent list of values that can be used in TVC.
514 
515     E.g.:
516 
517     <value_list> = 5,2,7
518     <transformed_value_list> = (5),(2),(7)
519 
520     <value_list> = (5,2),(7,1)
521     <transformed_value_list> = (5,2),(7,1)
522 
523   @retval
524     false     if the method succeeds
525     true      otherwise
526 */
527 
create_value_list_for_tvc(THD * thd,List<List<Item>> * values)528 bool Item_func_in::create_value_list_for_tvc(THD *thd,
529 				             List< List<Item> > *values)
530 {
531   bool is_list_of_rows= args[1]->type() == Item::ROW_ITEM;
532 
533   for (uint i=1; i < arg_count; i++)
534   {
535     char col_name[8];
536     List<Item> *tvc_value;
537     if (!(tvc_value= new (thd->mem_root) List<Item>()))
538       return true;
539 
540     if (is_list_of_rows)
541     {
542       Item_row *row_list= (Item_row *)(args[i]->build_clone(thd));
543 
544       if (!row_list)
545         return true;
546 
547       for (uint j=0; j < row_list->cols(); j++)
548       {
549         if (i == 1)
550 	{
551           sprintf(col_name, "_col_%i", j+1);
552           row_list->element_index(j)->set_name(thd, col_name, strlen(col_name),
553                                                thd->charset());
554         }
555 	if (tvc_value->push_back(row_list->element_index(j),
556 				 thd->mem_root))
557 	  return true;
558       }
559     }
560     else
561     {
562       if (i == 1)
563       {
564         sprintf(col_name, "_col_%i", 1);
565         args[i]->set_name(thd, col_name, strlen(col_name), thd->charset());
566       }
567       Item *arg_clone= args[i]->build_clone(thd);
568       if (!arg_clone || tvc_value->push_back(arg_clone))
569         return true;
570     }
571 
572     if (values->push_back(tvc_value, thd->mem_root))
573       return true;
574   }
575   return false;
576 }
577 
578 
579 /**
580   @brief
581     Create name for the derived table defined by TVC
582 
583   @param thd               The context of the statement
584   @param parent_select     The SELECT where derived table is used
585   @param alias		   The returned created name
586 
587   @details
588     Create name for the derived table using current TVC number
589     for this parent_select stored in parent_select
590 
591   @retval
592     true     if creation fails
593     false    otherwise
594 */
595 
create_tvc_name(THD * thd,st_select_lex * parent_select,LEX_CSTRING * alias)596 static bool create_tvc_name(THD *thd, st_select_lex *parent_select,
597 			    LEX_CSTRING *alias)
598 {
599   char buff[6];
600 
601   alias->length= my_snprintf(buff, sizeof(buff),
602                             "tvc_%u",
603 			     parent_select ? parent_select->curr_tvc_name : 0);
604   alias->str= thd->strmake(buff, alias->length);
605   if (!alias->str)
606     return true;
607 
608   return false;
609 }
610 
611 
612 /**
613   @brief
614   Check whether TVC used in unit is to be wrapped into select
615 
616   @details
617     TVC used in unit that contains more than one members is to be wrapped
618     into select if it is tailed with ORDER BY ... LIMIT n [OFFSET m]
619 
620   @retval
621     true     if TVC is to be wrapped
622     false    otherwise
623 */
624 
to_be_wrapped_as_with_tail()625 bool table_value_constr::to_be_wrapped_as_with_tail()
626 {
627   return select_lex->master_unit()->first_select()->next_select() &&
628          select_lex->order_list.elements && select_lex->explicit_limit;
629 }
630 
631 
632 /**
633   @brief
634   Wrap table value constructor into a select
635 
636   @param thd               The context handler
637   @param tvc_sl            The TVC to wrap
638   @parent_select           The parent select if tvc_sl used in a subquery
639 
640   @details
641     The function wraps the TVC tvc_sl into a select:
642     the function transforms the TVC of the form VALUES (v1), ... (vn) into
643     the select of the form
644     SELECT * FROM (VALUES (v1), ... (vn)) tvc_x
645 
646   @retval pointer to the result of of the transformation if successful
647           NULL - otherwise
648 */
649 
650 static
wrap_tvc(THD * thd,st_select_lex * tvc_sl,st_select_lex * parent_select)651 st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl,
652                         st_select_lex *parent_select)
653 {
654   LEX *lex= thd->lex;
655   select_result *save_result= lex->result;
656   uint8 save_derived_tables= lex->derived_tables;
657   thd->lex->result= NULL;
658 
659   Query_arena backup;
660   Query_arena *arena= thd->activate_stmt_arena_if_needed(&backup);
661 
662   Item *item;
663   SELECT_LEX *wrapper_sl;
664   SELECT_LEX_UNIT *derived_unit;
665 
666   /*
667     Create SELECT_LEX wrapper_sl of the select used in the result
668     of the transformation
669   */
670   if (!(wrapper_sl= new (thd->mem_root) SELECT_LEX()))
671     goto err;
672   wrapper_sl->select_number= ++thd->lex->stmt_lex->current_select_number;
673   wrapper_sl->parent_lex= lex; /* Used in init_query. */
674   wrapper_sl->init_query();
675   wrapper_sl->init_select();
676 
677   wrapper_sl->nest_level= tvc_sl->nest_level;
678   wrapper_sl->parsing_place= tvc_sl->parsing_place;
679   wrapper_sl->linkage= tvc_sl->linkage;
680   wrapper_sl->exclude_from_table_unique_test=
681                                  tvc_sl->exclude_from_table_unique_test;
682 
683   lex->current_select= wrapper_sl;
684   item= new (thd->mem_root) Item_field(thd, &wrapper_sl->context,
685                                        NULL, NULL, &star_clex_str);
686   if (item == NULL || add_item_to_list(thd, item))
687     goto err;
688   (wrapper_sl->with_wild)++;
689 
690   /* Include the newly created select into the global list of selects */
691   wrapper_sl->include_global((st_select_lex_node**)&lex->all_selects_list);
692 
693   /* Substitute select node used of TVC for the newly created select */
694   tvc_sl->substitute_in_tree(wrapper_sl);
695 
696   /*
697     Create a unit for the substituted select used for TVC and attach it
698     to the the wrapper select wrapper_sl as the only unit. The created
699     unit is the unit for the derived table tvc_x of the transformation.
700   */
701   if (!(derived_unit= new (thd->mem_root) SELECT_LEX_UNIT()))
702     goto err;
703   derived_unit->init_query();
704   derived_unit->thd= thd;
705   derived_unit->include_down(wrapper_sl);
706 
707   /*
708     Attach the select used of TVC as the only slave to the unit for
709     the derived table tvc_x of the transformation
710   */
711   derived_unit->add_slave(tvc_sl);
712   tvc_sl->linkage= DERIVED_TABLE_TYPE;
713 
714   /*
715     Generate the name of the derived table created for TVC and
716     add it to the FROM list of the wrapping select
717   */
718   Table_ident *ti;
719   LEX_CSTRING alias;
720   TABLE_LIST *derived_tab;
721   if (!(ti= new (thd->mem_root) Table_ident(derived_unit)) ||
722       create_tvc_name(thd, parent_select, &alias))
723     goto err;
724   if (!(derived_tab=
725           wrapper_sl->add_table_to_list(thd,
726 				        ti, &alias, 0,
727                                         TL_READ, MDL_SHARED_READ)))
728     goto err;
729   wrapper_sl->add_joined_table(derived_tab);
730   wrapper_sl->add_where_field(derived_unit->first_select());
731   wrapper_sl->context.table_list= wrapper_sl->table_list.first;
732   wrapper_sl->context.first_name_resolution_table= wrapper_sl->table_list.first;
733   wrapper_sl->table_list.first->derived_type= DTYPE_TABLE | DTYPE_MATERIALIZE;
734   lex->derived_tables|= DERIVED_SUBQUERY;
735 
736   if (arena)
737     thd->restore_active_arena(arena, &backup);
738   lex->result= save_result;
739   return wrapper_sl;
740 
741 err:
742   if (arena)
743     thd->restore_active_arena(arena, &backup);
744   lex->result= save_result;
745   lex->derived_tables= save_derived_tables;
746   return 0;
747 }
748 
749 
750 /**
751   @brief
752   Wrap TVC with ORDER BY ... LIMIT tail into a select
753 
754   @param thd               The context handler
755   @param tvc_sl            The TVC to wrap
756 
757   @details
758     The function wraps the TVC tvc_sl into a select:
759     the function transforms the TVC with tail of the form
760     VALUES (v1), ... (vn) ORDER BY ... LIMIT n [OFFSET m]
761     into the select with the same tail of the form
762     SELECT * FROM (VALUES (v1), ... (vn)) tvc_x
763       ORDER BY ... LIMIT n [OFFSET m]
764 
765   @retval pointer to the result of of the transformation if successful
766           NULL - otherwise
767 */
768 
wrap_tvc_with_tail(THD * thd,st_select_lex * tvc_sl)769 st_select_lex *wrap_tvc_with_tail(THD *thd, st_select_lex *tvc_sl)
770 {
771   st_select_lex *wrapper_sl= wrap_tvc(thd, tvc_sl, NULL);
772   if (!wrapper_sl)
773     return NULL;
774 
775   wrapper_sl->order_list= tvc_sl->order_list;
776   wrapper_sl->select_limit= tvc_sl->select_limit;
777   wrapper_sl->offset_limit= tvc_sl->offset_limit;
778   wrapper_sl->braces= tvc_sl->braces;
779   wrapper_sl->explicit_limit= tvc_sl->explicit_limit;
780   tvc_sl->order_list.empty();
781   tvc_sl->select_limit= NULL;
782   tvc_sl->offset_limit= NULL;
783   tvc_sl->braces= 0;
784   tvc_sl->explicit_limit= false;
785   if (tvc_sl->select_number == 1)
786   {
787     tvc_sl->select_number= wrapper_sl->select_number;
788     wrapper_sl->select_number= 1;
789   }
790   if (tvc_sl->master_unit()->union_distinct == tvc_sl)
791   {
792     wrapper_sl->master_unit()->union_distinct= wrapper_sl;
793   }
794   thd->lex->current_select= wrapper_sl;
795   return wrapper_sl;
796 }
797 
798 
799 /**
800   @brief
801   Wrap TVC in a subselect into a select
802 
803   @param thd               The context handler
804   @param tvc_sl            The TVC to wrap
805 
806   @details
807     The function wraps the TVC tvc_sl used in a subselect into a select
808     the function transforms the TVC of the form VALUES (v1), ... (vn)
809     into the select the form
810     SELECT * FROM (VALUES (v1), ... (vn)) tvc_x
811     and replaces the subselect with the result of the transformation.
812 
813   @retval wrapping select if successful
814           0  otherwise
815 */
816 
817 st_select_lex *
wrap_tvc_into_select(THD * thd,st_select_lex * tvc_sl)818 Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl)
819 {
820   LEX *lex= thd->lex;
821   /* SELECT_LEX object where the transformation is performed */
822   SELECT_LEX *parent_select= lex->current_select;
823   SELECT_LEX *wrapper_sl= wrap_tvc(thd, tvc_sl, parent_select);
824   if (wrapper_sl)
825   {
826     if (engine->engine_type() == subselect_engine::SINGLE_SELECT_ENGINE)
827       ((subselect_single_select_engine *) engine)->change_select(wrapper_sl);
828   }
829   lex->current_select= parent_select;
830   return wrapper_sl;
831 }
832 
833 
834 /*
835   @brief
836    Check whether the items are of comparable type or not
837 
838   @details
839     This check are done because materialization is not performed
840     if the left expr and right expr are of the same types.
841     @see subquery_types_allow_materialization()
842 
843   @retval
844    0 comparable
845    1 not comparable
846 */
847 
cmp_row_types(Item * item1,Item * item2)848 static bool cmp_row_types(Item* item1, Item* item2)
849 {
850   uint n= item1->cols();
851   if (item2->check_cols(n))
852     return true;
853 
854   for (uint i=0; i < n; i++)
855   {
856     Item *inner= item1->element_index(i);
857     Item *outer= item2->element_index(i);
858     if (!inner->type_handler()->subquery_type_allows_materialization(inner,
859                                                                      outer,
860                                                                      true))
861       return true;
862   }
863   return false;
864 }
865 
866 
867 /**
868   @brief
869     Transform IN predicate into IN subquery
870 
871   @param thd     The context of the statement
872   @param arg     Not used
873 
874   @details
875     The method transforms this IN predicate into in equivalent IN subquery:
876 
877     <left_expr> IN (<value_list>)
878     =>
879     <left_expr> IN (SELECT * FROM (VALUES <transformed_value_list>) AS tvc_#)
880 
881     E.g.:
882 
883     <value_list> = 5,2,7
884     <transformed_value_list> = (5),(2),(7)
885 
886     <value_list> = (5,2),(7,1)
887     <transformed_value_list> = (5,2),(7,1)
888 
889     If the transformation succeeds the method returns the result IN subquery,
890     otherwise this IN predicate is returned.
891 
892   @retval
893     pointer to the result of transformation if succeeded
894     pointer to this IN predicate otherwise
895 */
896 
in_predicate_to_in_subs_transformer(THD * thd,uchar * arg)897 Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
898 							uchar *arg)
899 {
900   if (!transform_into_subq)
901     return this;
902 
903   transform_into_subq= false;
904 
905   List<List_item> values;
906 
907   LEX *lex= thd->lex;
908   /* SELECT_LEX object where the transformation is performed */
909   SELECT_LEX *parent_select= lex->current_select;
910   uint8 save_derived_tables= lex->derived_tables;
911 
912   /*
913     Make sure that create_tmp_table will not fail due to too long keys.
914     Here the strategy would mainly use materialization, so we need to make
915     sure that the materialized table can be created.
916 
917     The checks here are the same as in subquery_type_allows_materialization()
918   */
919   uint32 length= max_length_of_left_expr();
920   if (!length  || length > tmp_table_max_key_length() ||
921       args[0]->cols() > tmp_table_max_key_parts())
922     return this;
923 
924   for (uint i=1; i < arg_count; i++)
925   {
926     if (!args[i]->const_item() || cmp_row_types(args[i], args[0]))
927       return this;
928   }
929 
930   Query_arena backup;
931   Query_arena *arena= thd->activate_stmt_arena_if_needed(&backup);
932 
933   /*
934     Create SELECT_LEX of the subquery SQ used in the result of transformation
935   */
936   if (mysql_new_select(lex, 1, NULL))
937     goto err;
938   mysql_init_select(lex);
939   /* Create item list as '*' for the subquery SQ */
940   Item *item;
941   SELECT_LEX *sq_select; // select for IN subquery;
942   sq_select= lex->current_select;
943   sq_select->parsing_place= SELECT_LIST;
944   item= new (thd->mem_root) Item_field(thd, &sq_select->context,
945                                        NULL, NULL, &star_clex_str);
946   if (item == NULL || add_item_to_list(thd, item))
947     goto err;
948   (sq_select->with_wild)++;
949   /*
950     Create derived table DT that will wrap TVC in the result of transformation
951   */
952   SELECT_LEX *tvc_select; // select for tvc
953   SELECT_LEX_UNIT *derived_unit; // unit for tvc_select
954   if (mysql_new_select(lex, 1, NULL))
955     goto err;
956   mysql_init_select(lex);
957   tvc_select= lex->current_select;
958   derived_unit= tvc_select->master_unit();
959   tvc_select->linkage= DERIVED_TABLE_TYPE;
960 
961   /* Create TVC used in the transformation */
962   if (create_value_list_for_tvc(thd, &values))
963     goto err;
964   if (!(tvc_select->tvc=
965           new (thd->mem_root)
966 	    table_value_constr(values,
967                                tvc_select,
968                                tvc_select->options)))
969     goto err;
970 
971   lex->current_select= sq_select;
972 
973   /*
974     Create the name of the wrapping derived table and
975     add it to the FROM list of the subquery SQ
976    */
977   Table_ident *ti;
978   LEX_CSTRING alias;
979   TABLE_LIST *derived_tab;
980   if (!(ti= new (thd->mem_root) Table_ident(derived_unit)) ||
981       create_tvc_name(thd, parent_select, &alias))
982     goto err;
983   if (!(derived_tab=
984           sq_select->add_table_to_list(thd,
985 				       ti, &alias, 0,
986                                        TL_READ, MDL_SHARED_READ)))
987     goto err;
988   sq_select->add_joined_table(derived_tab);
989   sq_select->add_where_field(derived_unit->first_select());
990   sq_select->context.table_list= sq_select->table_list.first;
991   sq_select->context.first_name_resolution_table= sq_select->table_list.first;
992   sq_select->table_list.first->derived_type= DTYPE_TABLE | DTYPE_MATERIALIZE;
993   lex->derived_tables|= DERIVED_SUBQUERY;
994 
995   sq_select->where= 0;
996   sq_select->set_braces(false);
997   derived_unit->set_with_clause(0);
998 
999   /* Create IN subquery predicate */
1000   sq_select->parsing_place= parent_select->parsing_place;
1001   Item_in_subselect *in_subs;
1002   Item *sq;
1003   if (!(in_subs=
1004           new (thd->mem_root) Item_in_subselect(thd, args[0], sq_select)))
1005     goto err;
1006   in_subs->converted_from_in_predicate= TRUE;
1007   sq= in_subs;
1008   if (negated)
1009     sq= negate_expression(thd, in_subs);
1010   else
1011     in_subs->emb_on_expr_nest= emb_on_expr_nest;
1012 
1013   if (arena)
1014     thd->restore_active_arena(arena, &backup);
1015   thd->lex->current_select= parent_select;
1016 
1017   if (sq->fix_fields(thd, (Item **)&sq))
1018     goto err;
1019 
1020   parent_select->curr_tvc_name++;
1021   return sq;
1022 
1023 err:
1024   if (arena)
1025     thd->restore_active_arena(arena, &backup);
1026   lex->derived_tables= save_derived_tables;
1027   thd->lex->current_select= parent_select;
1028   return NULL;
1029 }
1030 
1031 
max_length_of_left_expr()1032 uint32 Item_func_in::max_length_of_left_expr()
1033 {
1034   uint n= args[0]->cols();
1035   uint32 length= 0;
1036   for (uint i=0; i < n; i++)
1037     length+= args[0]->element_index(i)->max_length;
1038   return length;
1039 }
1040 
1041 
1042 /**
1043   @brief
1044     Check if this IN-predicate can be transformed in IN-subquery
1045     with TVC
1046 
1047   @param thd     The context of the statement
1048 
1049   @details
1050     Compare the number of elements in the list of
1051     values in this IN-predicate with the
1052     in_subquery_conversion_threshold special variable
1053 
1054   @retval
1055     true     if transformation can be made
1056     false    otherwise
1057 */
1058 
to_be_transformed_into_in_subq(THD * thd)1059 bool Item_func_in::to_be_transformed_into_in_subq(THD *thd)
1060 {
1061   uint values_count= arg_count-1;
1062 
1063   if (args[1]->type() == Item::ROW_ITEM)
1064     values_count*= ((Item_row *)(args[1]))->cols();
1065 
1066   if (thd->variables.in_subquery_conversion_threshold == 0 ||
1067       thd->variables.in_subquery_conversion_threshold > values_count)
1068     return false;
1069 
1070   return true;
1071 }
1072 
1073 
1074 /**
1075   @brief
1076     Transform IN predicates into IN subqueries in WHERE and ON expressions
1077 
1078   @param thd     The context of the statement
1079 
1080   @details
1081     For each IN predicate from AND parts of the WHERE condition and/or
1082     ON expressions of the SELECT for this join the method performs
1083     the intransformation into an equivalent IN sunquery if it's needed.
1084 
1085   @retval
1086     false     always
1087 */
1088 
transform_in_predicates_into_in_subq(THD * thd)1089 bool JOIN::transform_in_predicates_into_in_subq(THD *thd)
1090 {
1091   DBUG_ENTER("JOIN::transform_in_predicates_into_in_subq");
1092   if (!select_lex->in_funcs.elements)
1093     DBUG_RETURN(false);
1094 
1095   SELECT_LEX *save_current_select= thd->lex->current_select;
1096   enum_parsing_place save_parsing_place= select_lex->parsing_place;
1097   thd->lex->current_select= select_lex;
1098   if (conds)
1099   {
1100     select_lex->parsing_place= IN_WHERE;
1101     conds=
1102       conds->transform(thd,
1103 		       &Item::in_predicate_to_in_subs_transformer,
1104                        (uchar*) 0);
1105     if (!conds)
1106       DBUG_RETURN(true);
1107     select_lex->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
1108     select_lex->where= conds;
1109   }
1110 
1111   if (join_list)
1112   {
1113     TABLE_LIST *table;
1114     List_iterator<TABLE_LIST> li(*join_list);
1115     select_lex->parsing_place= IN_ON;
1116 
1117     while ((table= li++))
1118     {
1119       if (table->on_expr)
1120       {
1121         table->on_expr=
1122           table->on_expr->transform(thd,
1123 		                    &Item::in_predicate_to_in_subs_transformer,
1124                                     (uchar*) 0);
1125 	if (!table->on_expr)
1126 	  DBUG_RETURN(true);
1127 	table->prep_on_expr= table->on_expr ?
1128                              table->on_expr->copy_andor_structure(thd) : 0;
1129       }
1130     }
1131   }
1132 
1133   select_lex->in_funcs.empty();
1134   select_lex->parsing_place= save_parsing_place;
1135   thd->lex->current_select= save_current_select;
1136   DBUG_RETURN(false);
1137 }
1138 
1139