1 /* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
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, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #include "sql/dd/info_schema/show.h"
24 
25 #include <string.h>
26 
27 #include "lex_string.h"
28 #include "m_string.h"
29 #include "my_sqlcommand.h"
30 #include "sql/dd/info_schema/show_query_builder.h"  // Select_lex_builder
31 #include "sql/dd/info_schema/table_stats.h"
32 #include "sql/dd/string_type.h"
33 #include "sql/item_cmpfunc.h"  // Item_func_case
34 #include "sql/key.h"
35 #include "sql/parse_tree_node_base.h"
36 #include "sql/sql_class.h"
37 #include "sql/sql_lex.h"
38 #include "sql/table.h"
39 #include "sql_string.h"
40 
41 namespace dd {
42 namespace info_schema {
43 
44 //  Build a substitute query for SHOW CHARSETS.
45 
build_show_character_set_query(const POS & pos,THD * thd,const String * wild,Item * where_cond)46 SELECT_LEX *build_show_character_set_query(const POS &pos, THD *thd,
47                                            const String *wild,
48                                            Item *where_cond) {
49   static const LEX_CSTRING system_view_name = {
50       STRING_WITH_LEN("CHARACTER_SETS")};
51 
52   // Define field name literal used in query to be built.
53   static const LEX_CSTRING field_charset = {
54       STRING_WITH_LEN("CHARACTER_SET_NAME")};
55   static const LEX_CSTRING alias_charset = {STRING_WITH_LEN("Charset")};
56 
57   static const LEX_CSTRING field_desc = {STRING_WITH_LEN("DESCRIPTION")};
58   static const LEX_CSTRING alias_desc = {STRING_WITH_LEN("Description")};
59 
60   static const LEX_CSTRING field_collate = {
61       STRING_WITH_LEN("DEFAULT_COLLATE_NAME")};
62   static const LEX_CSTRING alias_collate = {
63       STRING_WITH_LEN("Default collation")};
64 
65   static const LEX_CSTRING field_maxlen = {STRING_WITH_LEN("MAXLEN")};
66   static const LEX_CSTRING alias_maxlen = {STRING_WITH_LEN("Maxlen")};
67 
68   /*
69      Build sub query.
70 
71      ...
72      SELECT
73        CHARACTER_SET_NAME as Charset,
74        DESCRIPTION as Description,
75        DEFAULT_COLLATE_NAME as `Default collation`,
76        MAXLEN as `Maxlen`
77      ...
78   */
79   Select_lex_builder sub_query(&pos, thd);
80   if (sub_query.add_select_item(field_charset, alias_charset) ||
81       sub_query.add_select_item(field_desc, alias_desc))
82     return nullptr;
83 
84   if (thd->variables.default_collation_for_utf8mb4 ==
85       &my_charset_utf8mb4_0900_ai_ci) {
86     if (sub_query.add_select_item(field_collate, alias_collate)) return nullptr;
87   } else {
88     MEM_ROOT *const mem_root = thd->mem_root;
89 
90     // ... CHARACTER_SETS ...
91     Item *charset_item =
92         new (mem_root) Item_field(pos, NullS, NullS, field_charset.str);
93     if (charset_item == nullptr) return nullptr;
94 
95     // ... 'utf8mb4' ...
96     Item *utf8mb4_item = new (mem_root)
97         Item_string(STRING_WITH_LEN("utf8mb4"), system_charset_info);
98     if (utf8mb4_item == nullptr) return nullptr;
99 
100     // ... = ...
101     Item *if_cond =
102         new (mem_root) Item_func_eq(pos, charset_item, utf8mb4_item);
103     if (if_cond == nullptr) return nullptr;
104 
105     // ... 'utf8mb4_general_ci' ...
106     Item *if_then = new (mem_root)
107         Item_string(STRING_WITH_LEN("utf8mb4_general_ci"), system_charset_info);
108     if (if_then == nullptr) return nullptr;
109 
110     // ... DEFAULT_COLLATE_NAME ...
111     Item *if_else =
112         new (mem_root) Item_field(pos, NullS, NullS, field_collate.str);
113     if (if_else == nullptr) return nullptr;
114 
115     /*
116       IF(CHARACTER_SETS = 'utf8mb4', 'utf8mb4_general_ci', DEFAULT_COLLATE_NAME)
117     */
118     Item *if_func = new (mem_root) Item_func_if(pos, if_cond, if_then, if_else);
119     if (if_func == nullptr || sub_query.add_select_expr(if_func, alias_collate))
120       return nullptr;
121   }
122 
123   if (sub_query.add_select_item(field_maxlen, alias_maxlen)) return nullptr;
124 
125   // ... FROM information_schema.<table_name> ...
126   if (sub_query.add_from_item(INFORMATION_SCHEMA_NAME, system_view_name))
127     return nullptr;
128 
129   /*
130     Build the top level query
131   */
132 
133   Select_lex_builder top_query(&pos, thd);
134 
135   // SELECT * FROM <sub_query> ...
136   if (top_query.add_star_select_item() ||
137       top_query.add_from_item(
138           sub_query.prepare_derived_table(system_view_name)))
139     return nullptr;
140 
141   // SELECT * FROM <sub_query> WHERE Charset LIKE <value> ...
142   if (wild) {
143     Item *like = top_query.prepare_like_item(alias_charset, wild);
144     if (!like || top_query.add_condition(like)) return nullptr;
145   } else if (where_cond && top_query.add_condition(where_cond))
146     return nullptr;
147 
148   // ... ORDER BY 'Charset' ...
149   if (top_query.add_order_by(alias_charset)) return nullptr;
150 
151   SELECT_LEX *sl = top_query.prepare_select_lex();
152 
153   // sql_command is set to SQL_QUERY after above call, so.
154   thd->lex->sql_command = SQLCOM_SHOW_CHARSETS;
155 
156   return sl;
157 }
158 
159 // Build a substitute query for SHOW COLLATION.
160 
build_show_collation_query(const POS & pos,THD * thd,const String * wild,Item * where_cond)161 SELECT_LEX *build_show_collation_query(const POS &pos, THD *thd,
162                                        const String *wild, Item *where_cond) {
163   static const LEX_CSTRING system_view_name = {STRING_WITH_LEN("COLLATIONS")};
164 
165   // Define field name literal used in query to be built.
166   static const LEX_CSTRING field_collation = {
167       STRING_WITH_LEN("COLLATION_NAME")};
168   static const LEX_CSTRING alias_collation = {STRING_WITH_LEN("Collation")};
169 
170   static const LEX_CSTRING field_charset = {
171       STRING_WITH_LEN("CHARACTER_SET_NAME")};
172   static const LEX_CSTRING alias_charset = {STRING_WITH_LEN("Charset")};
173 
174   static const LEX_CSTRING field_id = {STRING_WITH_LEN("ID")};
175   static const LEX_CSTRING alias_id = {STRING_WITH_LEN("Id")};
176 
177   static const LEX_CSTRING field_default = {STRING_WITH_LEN("IS_DEFAULT")};
178   static const LEX_CSTRING alias_default = {STRING_WITH_LEN("Default")};
179 
180   static const LEX_CSTRING field_compiled = {STRING_WITH_LEN("IS_COMPILED")};
181   static const LEX_CSTRING alias_compiled = {STRING_WITH_LEN("Compiled")};
182 
183   static const LEX_CSTRING field_sortlen = {STRING_WITH_LEN("SORTLEN")};
184   static const LEX_CSTRING alias_sortlen = {STRING_WITH_LEN("Sortlen")};
185 
186   static const LEX_CSTRING field_pad_attribute = {
187       STRING_WITH_LEN("PAD_ATTRIBUTE")};
188   static const LEX_CSTRING alias_pad_attribute = {
189       STRING_WITH_LEN("Pad_attribute")};
190 
191   /*
192      Build sub query.
193 
194      ...
195       SELECT COLLATION_NAME as `Collation`,
196              CHARACTER_SET_NAME as `Charset`,
197              ID as `Id`,
198              IS_DEFAULT as `Default`,
199              IS_COMPILED as `Compiled`,
200              SORTLEN as `Sortlen`,
201              PAD_ATTRIBUTE AS `Pad_attribute`
202      ...
203   */
204   Select_lex_builder sub_query(&pos, thd);
205   if (sub_query.add_select_item(field_collation, alias_collation) ||
206       sub_query.add_select_item(field_charset, alias_charset) ||
207       sub_query.add_select_item(field_id, alias_id))
208     return nullptr;
209 
210   if (thd->variables.default_collation_for_utf8mb4 ==
211       &my_charset_utf8mb4_0900_ai_ci) {
212     if (sub_query.add_select_item(field_default, alias_default)) return nullptr;
213   } else {
214     MEM_ROOT *const mem_root = thd->mem_root;
215 
216     // ... `ID` ...
217     Item *case_value_item =
218         new (mem_root) Item_field(pos, NullS, NullS, field_id.str);
219     if (case_value_item == nullptr) return nullptr;  // OOM
220 
221     List<Item> case_when_list;
222 
223     // ... WHEN <ID of utf8mb4_general_ci> ...
224     Item *old_default_collation =
225         new (mem_root) Item_uint(my_charset_utf8mb4_general_ci.number);
226     if (old_default_collation == nullptr ||
227         case_when_list.push_back(old_default_collation))
228       return nullptr;  // OOM
229 
230     // ... THEN 'Yes' ...
231     Item *force_old_default_collation =
232         new (mem_root) Item_string(STRING_WITH_LEN("Yes"), system_charset_info);
233     if (force_old_default_collation == nullptr ||
234         case_when_list.push_back(force_old_default_collation))
235       return nullptr;  // OOM
236 
237     // ... WHEN <ID of utf8mb4_0900_ai_ci> ...
238     Item *new_default_collation =
239         new (mem_root) Item_uint(my_charset_utf8mb4_0900_ai_ci.number);
240     if (new_default_collation == nullptr ||
241         case_when_list.push_back(new_default_collation))
242       return nullptr;  // OOM
243 
244     // ... THEN '' ...
245     Item *suppress_new_default_collation =
246         new (mem_root) Item_string(STRING_WITH_LEN(""), system_charset_info);
247     if (suppress_new_default_collation == nullptr ||
248         case_when_list.push_back(suppress_new_default_collation))
249       return nullptr;  // OOM
250 
251     // ... ELSE IS_DEFAULT ...
252     Item *case_else_item =
253         new (mem_root) Item_field(pos, NullS, NullS, field_default.str);
254     if (case_else_item == nullptr) return nullptr;
255 
256     // CASE `ID`
257     //   WHEN <ID of utf8mb4_general_ci> THEN TRUE
258     //   WHEN <ID of utf8mb4_0900_ai_ci> THEN FALSE
259     //   ELSE `IS_DEFAULT`
260     Item *case_func = new (mem_root)
261         Item_func_case(pos, case_when_list, case_value_item, case_else_item);
262     if (case_func == nullptr ||
263         sub_query.add_select_expr(case_func, alias_default))
264       return nullptr;
265   }
266 
267   if (sub_query.add_select_item(field_compiled, alias_compiled) ||
268       sub_query.add_select_item(field_sortlen, alias_sortlen) ||
269       sub_query.add_select_item(field_pad_attribute, alias_pad_attribute))
270     return nullptr;
271 
272   // ... FROM information_schema.<table_name> ...
273   if (sub_query.add_from_item(INFORMATION_SCHEMA_NAME, system_view_name))
274     return nullptr;
275 
276   /*
277     Build the top level query
278   */
279 
280   Select_lex_builder top_query(&pos, thd);
281 
282   // SELECT * FROM <sub_query> ...
283   if (top_query.add_star_select_item() ||
284       top_query.add_from_item(
285           sub_query.prepare_derived_table(system_view_name)))
286     return nullptr;
287 
288   // SELECT * FROM <sub_query> WHERE Collation LIKE <value> ...
289   if (wild) {
290     Item *like = top_query.prepare_like_item(alias_collation, wild);
291     if (!like || top_query.add_condition(like)) return nullptr;
292   } else if (where_cond && top_query.add_condition(where_cond))
293     return nullptr;
294 
295   // ... ORDER BY 'Collation' ...
296   if (top_query.add_order_by(alias_collation)) return nullptr;
297 
298   SELECT_LEX *sl = top_query.prepare_select_lex();
299 
300   // sql_command is set to SQL_QUERY after above call, so.
301   thd->lex->sql_command = SQLCOM_SHOW_COLLATIONS;
302 
303   return sl;
304 }
305 
306 // Build a substitute query for SHOW DATABASES.
307 
build_show_databases_query(const POS & pos,THD * thd,String * wild,Item * where_cond)308 SELECT_LEX *build_show_databases_query(const POS &pos, THD *thd, String *wild,
309                                        Item *where_cond) {
310   static const LEX_CSTRING system_view_name = {STRING_WITH_LEN("SCHEMATA")};
311 
312   // Define field name literal used in query to be built.
313   static const LEX_CSTRING field_schema_name = {STRING_WITH_LEN("SCHEMA_NAME")};
314   static const LEX_CSTRING alias_database = {STRING_WITH_LEN("Database")};
315 
316   // Build the alias 'Database (<dbname>%)'
317   String_type alias;
318   alias.append(alias_database.str);
319   if (wild) {
320     alias.append(" (");
321     alias.append(wild->ptr(), wild->length());
322     alias.append(")");
323   }
324   char *tmp = static_cast<char *>(thd->alloc(alias.length() + 1));
325   memcpy(tmp, alias.c_str(), alias.length());
326   *(tmp + alias.length()) = '\0';
327   LEX_CSTRING alias_lex_string = {tmp, alias.length()};
328 
329   /*
330      Build sub query.
331 
332      ...
333        SELECT SCHEMA_NAME as `Database`,
334           FROM information_schema.schemata;
335      ...
336   */
337   Select_lex_builder sub_query(&pos, thd);
338   if (sub_query.add_select_item(field_schema_name, alias_database) ||
339       sub_query.add_from_item(INFORMATION_SCHEMA_NAME, system_view_name))
340     return nullptr;
341 
342   /*
343     Build the top level query
344   */
345 
346   Select_lex_builder top_query(&pos, thd);
347 
348   // SELECT * FROM <sub_query> ...
349   if (top_query.add_select_item(alias_database, alias_lex_string) ||
350       top_query.add_from_item(
351           sub_query.prepare_derived_table(system_view_name)))
352     return nullptr;
353 
354   // SELECT * FROM <sub_query> WHERE Database LIKE <value> ...
355   if (wild) {
356     // Convert IS db and table name to desired form.
357     dd::info_schema::convert_table_name_case(wild->ptr(), nullptr);
358 
359     Item *like = top_query.prepare_like_item(alias_database, wild);
360     if (!like || top_query.add_condition(like)) return nullptr;
361   } else if (where_cond && top_query.add_condition(where_cond))
362     return nullptr;
363 
364   // ... ORDER BY 'Database' ...
365   if (top_query.add_order_by(alias_database)) return nullptr;
366 
367   SELECT_LEX *sl = top_query.prepare_select_lex();
368 
369   // sql_command is set to SQL_QUERY after above call, so.
370   thd->lex->sql_command = SQLCOM_SHOW_DATABASES;
371 
372   return sl;
373 }
374 
375 /**
376   Add fields required by SHOW TABLE STATUS.
377 
378   @param query - Select_lex_builder to which we add fields.
379   @param alias_as_alias - Add select items of the form,
380                           'alias AS alias'. This is required
381                           for top level query, as the real field
382                           names would be valied only the sub
383                           query that we are building for SHOW
384                           TABLE STATUS. Check comments in
385                           sql/dd/show.h for more details.
386 
387   @returns false on success.
388            true on failure.
389 */
390 
add_table_status_fields(Select_lex_builder * query,bool alias_as_alias)391 static bool add_table_status_fields(Select_lex_builder *query,
392                                     bool alias_as_alias) {
393   // Field for SHOW TABLE STATUS
394   static const LEX_CSTRING field_engine = {STRING_WITH_LEN("ENGINE")};
395   static const LEX_CSTRING alias_engine = {STRING_WITH_LEN("Engine")};
396 
397   static const LEX_CSTRING field_version = {STRING_WITH_LEN("VERSION")};
398   static const LEX_CSTRING alias_version = {STRING_WITH_LEN("Version")};
399 
400   static const LEX_CSTRING field_row_format = {STRING_WITH_LEN("ROW_FORMAT")};
401   static const LEX_CSTRING alias_row_format = {STRING_WITH_LEN("Row_format")};
402 
403   static const LEX_CSTRING field_rows = {STRING_WITH_LEN("TABLE_ROWS")};
404   static const LEX_CSTRING alias_rows = {STRING_WITH_LEN("Rows")};
405 
406   static const LEX_CSTRING field_avg_row_length = {
407       STRING_WITH_LEN("AVG_ROW_LENGTH")};
408   static const LEX_CSTRING alias_avg_row_length = {
409       STRING_WITH_LEN("Avg_row_length")};
410 
411   static const LEX_CSTRING field_data_length = {STRING_WITH_LEN("DATA_LENGTH")};
412   static const LEX_CSTRING alias_data_length = {STRING_WITH_LEN("Data_length")};
413 
414   static const LEX_CSTRING field_max_data_length = {
415       STRING_WITH_LEN("MAX_DATA_LENGTH")};
416   static const LEX_CSTRING alias_max_data_length = {
417       STRING_WITH_LEN("Max_data_length")};
418 
419   static const LEX_CSTRING field_index_length = {
420       STRING_WITH_LEN("INDEX_LENGTH")};
421   static const LEX_CSTRING alias_index_length = {
422       STRING_WITH_LEN("Index_length")};
423 
424   static const LEX_CSTRING field_data_free = {STRING_WITH_LEN("DATA_FREE")};
425   static const LEX_CSTRING alias_data_free = {STRING_WITH_LEN("Data_free")};
426 
427   static const LEX_CSTRING field_auto_increment = {
428       STRING_WITH_LEN("AUTO_INCREMENT")};
429   static const LEX_CSTRING alias_auto_increment = {
430       STRING_WITH_LEN("Auto_increment")};
431 
432   static const LEX_CSTRING field_create_time = {STRING_WITH_LEN("CREATE_TIME")};
433   static const LEX_CSTRING alias_create_time = {STRING_WITH_LEN("Create_time")};
434 
435   static const LEX_CSTRING field_update_time = {STRING_WITH_LEN("UPDATE_TIME")};
436   static const LEX_CSTRING alias_update_time = {STRING_WITH_LEN("Update_time")};
437 
438   static const LEX_CSTRING field_check_time = {STRING_WITH_LEN("CHECK_TIME")};
439   static const LEX_CSTRING alias_check_time = {STRING_WITH_LEN("Check_time")};
440 
441   static const LEX_CSTRING field_collation = {
442       STRING_WITH_LEN("TABLE_COLLATION")};
443   static const LEX_CSTRING alias_collation = {STRING_WITH_LEN("Collation")};
444 
445   static const LEX_CSTRING field_checksum = {STRING_WITH_LEN("CHECKSUM")};
446   static const LEX_CSTRING alias_checksum = {STRING_WITH_LEN("Checksum")};
447 
448   static const LEX_CSTRING field_create_options = {
449       STRING_WITH_LEN("CREATE_OPTIONS")};
450   static const LEX_CSTRING alias_create_options = {
451       STRING_WITH_LEN("Create_options")};
452 
453   static const LEX_CSTRING field_comment = {STRING_WITH_LEN("TABLE_COMMENT")};
454   static const LEX_CSTRING alias_comment = {STRING_WITH_LEN("Comment")};
455 
456   if (alias_as_alias == false) {
457     if (query->add_select_item(field_engine, alias_engine) ||
458         query->add_select_item(field_version, alias_version) ||
459         query->add_select_item(field_row_format, alias_row_format) ||
460         query->add_select_item(field_rows, alias_rows) ||
461         query->add_select_item(field_avg_row_length, alias_avg_row_length) ||
462         query->add_select_item(field_data_length, alias_data_length) ||
463         query->add_select_item(field_max_data_length, alias_max_data_length) ||
464         query->add_select_item(field_index_length, alias_index_length) ||
465         query->add_select_item(field_data_free, alias_data_free) ||
466         query->add_select_item(field_auto_increment, alias_auto_increment) ||
467         query->add_select_item(field_create_time, alias_create_time) ||
468         query->add_select_item(field_update_time, alias_update_time) ||
469         query->add_select_item(field_check_time, alias_check_time) ||
470         query->add_select_item(field_collation, alias_collation) ||
471         query->add_select_item(field_checksum, alias_checksum) ||
472         query->add_select_item(field_create_options, alias_create_options) ||
473         query->add_select_item(field_comment, alias_comment))
474       return true;
475   } else {
476     if (query->add_select_item(alias_engine, alias_engine) ||
477         query->add_select_item(alias_version, alias_version) ||
478         query->add_select_item(alias_row_format, alias_row_format) ||
479         query->add_select_item(alias_rows, alias_rows) ||
480         query->add_select_item(alias_avg_row_length, alias_avg_row_length) ||
481         query->add_select_item(alias_data_length, alias_data_length) ||
482         query->add_select_item(alias_max_data_length, alias_max_data_length) ||
483         query->add_select_item(alias_index_length, alias_index_length) ||
484         query->add_select_item(alias_data_free, alias_data_free) ||
485         query->add_select_item(alias_auto_increment, alias_auto_increment) ||
486         query->add_select_item(alias_create_time, alias_create_time) ||
487         query->add_select_item(alias_update_time, alias_update_time) ||
488         query->add_select_item(alias_check_time, alias_check_time) ||
489         query->add_select_item(alias_collation, alias_collation) ||
490         query->add_select_item(alias_checksum, alias_checksum) ||
491         query->add_select_item(alias_create_options, alias_create_options) ||
492         query->add_select_item(alias_comment, alias_comment))
493       return true;
494   }
495 
496   return false;
497 }
498 
499 // Build a substitute query for SHOW TABLES / TABLE STATUS.
500 
build_show_tables_query(const POS & pos,THD * thd,String * wild,Item * where_cond,bool include_status_fields)501 SELECT_LEX *build_show_tables_query(const POS &pos, THD *thd, String *wild,
502                                     Item *where_cond,
503                                     bool include_status_fields) {
504   static const LEX_CSTRING system_view_name = {STRING_WITH_LEN("TABLES")};
505 
506   // Define field name literal used in query to be built.
507   static const LEX_CSTRING field_table = {STRING_WITH_LEN("TABLE_NAME")};
508   static const LEX_CSTRING alias_table = {STRING_WITH_LEN("Name")};
509 
510   static const LEX_CSTRING field_database = {STRING_WITH_LEN("TABLE_SCHEMA")};
511   static const LEX_CSTRING alias_database = {STRING_WITH_LEN("Database")};
512 
513   static const LEX_CSTRING field_table_type = {STRING_WITH_LEN("TABLE_TYPE")};
514   static const LEX_CSTRING alias_table_type = {STRING_WITH_LEN("Table_type")};
515 
516   // Get the current logged in schema name
517   size_t dummy;
518   if (thd->lex->select_lex->db == nullptr &&
519       thd->lex->copy_db_to(&thd->lex->select_lex->db, &dummy))
520     return nullptr;
521 
522   // Convert IS db and table name to desired form.
523   dd::info_schema::convert_table_name_case(thd->lex->select_lex->db,
524                                            wild ? wild->ptr() : nullptr);
525 
526   LEX_STRING cur_db = {thd->lex->select_lex->db,
527                        strlen(thd->lex->select_lex->db)};
528 
529   if (check_and_convert_db_name(&cur_db, false) != Ident_name_check::OK)
530     return nullptr;
531 
532   /*
533     Build the alias 'Tables_in_<dbname> %' we are building
534     SHOW TABLES and not SHOW TABLE STATUS
535   */
536   String_type alias;
537 
538   if (include_status_fields) {
539     // Set the output alias for first column of SHOW TABLE STATUS as 'Name'
540     alias.append(alias_table.str);
541   } else {
542     // Build the output alias for SHOW TABLES
543     alias.append("Tables_in_");
544     alias.append(cur_db.str);
545     if (wild) {
546       alias.append(" (");
547       alias.append(wild->ptr());
548       alias.append(")");
549     }
550   }
551   char *tmp = static_cast<char *>(thd->alloc(alias.length() + 1));
552   memcpy(tmp, alias.c_str(), alias.length());
553   *(tmp + alias.length()) = '\0';
554   LEX_CSTRING alias_lex_string = {tmp, alias.length()};
555 
556   /*
557      Build sub query.
558      ...
559   */
560   Select_lex_builder sub_query(&pos, thd);
561   if (sub_query.add_select_item(field_database, alias_database) ||
562       sub_query.add_select_item(field_table, alias_lex_string) ||
563       (include_status_fields == true &&
564        add_table_status_fields(&sub_query, false)) ||
565       (include_status_fields == false && thd->lex->verbose &&
566        sub_query.add_select_item(field_table_type, alias_table_type)))
567     return nullptr;
568 
569   // ... FROM information_schema.tables ...
570   if (sub_query.add_from_item(INFORMATION_SCHEMA_NAME, system_view_name))
571     return nullptr;
572 
573   /*
574     Build the top level query
575   */
576 
577   Select_lex_builder top_query(&pos, thd);
578 
579   // SELECT * FROM <sub_query> ...
580   if (top_query.add_select_item(alias_lex_string, alias_lex_string) ||
581       (include_status_fields == true &&
582        add_table_status_fields(&top_query, true)) ||
583       (include_status_fields == false && thd->lex->verbose &&
584        top_query.add_select_item(alias_table_type, alias_table_type)) ||
585       top_query.add_from_item(
586           sub_query.prepare_derived_table(system_view_name)))
587     return nullptr;
588 
589   // ... WHERE 'Database' = <dbname> ...
590   Item *database_condition =
591       top_query.prepare_equal_item(alias_database, to_lex_cstring(cur_db));
592   if (top_query.add_condition(database_condition)) return nullptr;
593 
594   // ... [ AND ] Table LIKE <value> ...
595   if (wild) {
596     Item *like = top_query.prepare_like_item(alias_lex_string, wild);
597     if (!like || top_query.add_condition(like)) return nullptr;
598   }
599 
600   // ... [ AND ] <user provided condition> ...
601   if (where_cond && top_query.add_condition(where_cond)) return nullptr;
602 
603   // ... ORDER BY 'Table' ...
604   if (top_query.add_order_by(alias_lex_string)) return nullptr;
605 
606   SELECT_LEX *sl = top_query.prepare_select_lex();
607 
608   // sql_command is set to SQL_QUERY after above call, so.
609   if (include_status_fields)
610     thd->lex->sql_command = SQLCOM_SHOW_TABLE_STATUS;
611   else
612     thd->lex->sql_command = SQLCOM_SHOW_TABLES;
613 
614   return sl;
615 }
616 
617 // Build a substitute query for SHOW COLUMNS/FIELDS OR DESCRIBE.
618 
build_show_columns_query(const POS & pos,THD * thd,Table_ident * table_ident,const String * wild,Item * where_cond)619 SELECT_LEX *build_show_columns_query(const POS &pos, THD *thd,
620                                      Table_ident *table_ident,
621                                      const String *wild, Item *where_cond) {
622   static const LEX_CSTRING system_view_name = {STRING_WITH_LEN("COLUMNS")};
623 
624   // Define field name literal used in query to be built.
625   static const LEX_CSTRING field_database = {STRING_WITH_LEN("TABLE_SCHEMA")};
626   static const LEX_CSTRING alias_database = {STRING_WITH_LEN("Database")};
627 
628   static const LEX_CSTRING field_table = {STRING_WITH_LEN("TABLE_NAME")};
629   static const LEX_CSTRING alias_table = {STRING_WITH_LEN("Table")};
630 
631   static const LEX_CSTRING field_field = {STRING_WITH_LEN("COLUMN_NAME")};
632   static const LEX_CSTRING alias_field = {STRING_WITH_LEN("Field")};
633 
634   static const LEX_CSTRING field_column_type = {STRING_WITH_LEN("COLUMN_TYPE")};
635   static const LEX_CSTRING alias_column_type = {STRING_WITH_LEN("Type")};
636 
637   static const LEX_CSTRING field_collation = {
638       STRING_WITH_LEN("COLLATION_NAME")};
639   static const LEX_CSTRING alias_collation = {STRING_WITH_LEN("Collation")};
640 
641   static const LEX_CSTRING field_null = {STRING_WITH_LEN("IS_NULLABLE")};
642   static const LEX_CSTRING alias_null = {STRING_WITH_LEN("Null")};
643 
644   static const LEX_CSTRING field_key = {STRING_WITH_LEN("COLUMN_KEY")};
645   static const LEX_CSTRING alias_key = {STRING_WITH_LEN("Key")};
646 
647   static const LEX_CSTRING field_default = {STRING_WITH_LEN("COLUMN_DEFAULT")};
648   static const LEX_CSTRING alias_default = {STRING_WITH_LEN("Default")};
649 
650   static const LEX_CSTRING field_extra = {STRING_WITH_LEN("EXTRA")};
651   static const LEX_CSTRING alias_extra = {STRING_WITH_LEN("Extra")};
652 
653   static const LEX_CSTRING field_privileges = {STRING_WITH_LEN("PRIVILEGES")};
654   static const LEX_CSTRING alias_privileges = {STRING_WITH_LEN("Privileges")};
655 
656   static const LEX_CSTRING field_comment = {STRING_WITH_LEN("COLUMN_COMMENT")};
657   static const LEX_CSTRING alias_comment = {STRING_WITH_LEN("Comment")};
658 
659   static const LEX_CSTRING field_ordinal_position = {
660       STRING_WITH_LEN("ORDINAL_POSITION")};
661   static const LEX_CSTRING alias_ordinal_position = {
662       STRING_WITH_LEN("Ordinal_position")};
663 
664   // Get the current logged in schema name
665   LEX_CSTRING cur_db;
666   if (table_ident->db.str) {
667     cur_db.str = table_ident->db.str;
668     cur_db.length = table_ident->db.length;
669   } else if (thd->lex->copy_db_to(&cur_db.str, &cur_db.length))
670     return nullptr;
671 
672   // Convert IS db and table name to desired form.
673   dd::info_schema::convert_table_name_case(
674       const_cast<char *>(cur_db.str),
675       const_cast<char *>(table_ident->table.str));
676 
677   /*
678      Build sub query.
679      ...
680   */
681   Select_lex_builder sub_query(&pos, thd);
682   if (sub_query.add_select_item(field_database, alias_database) ||
683       sub_query.add_select_item(field_table, alias_table) ||
684       sub_query.add_select_item(field_field, alias_field) ||
685       sub_query.add_select_item(field_column_type, alias_column_type) ||
686       (thd->lex->verbose == true &&
687        sub_query.add_select_item(field_collation, alias_collation)) ||
688       sub_query.add_select_item(field_null, alias_null) ||
689       sub_query.add_select_item(field_key, alias_key) ||
690       sub_query.add_select_item(field_default, alias_default) ||
691       sub_query.add_select_item(field_extra, alias_extra) ||
692       (thd->lex->verbose == true &&
693        sub_query.add_select_item(field_privileges, alias_privileges)) ||
694       (thd->lex->verbose == true &&
695        sub_query.add_select_item(field_comment, alias_comment)) ||
696       sub_query.add_select_item(field_ordinal_position, alias_ordinal_position))
697     return nullptr;
698 
699   // ... FROM information_schema.columns ...
700   if (sub_query.add_from_item(INFORMATION_SCHEMA_NAME, system_view_name))
701     return nullptr;
702 
703   /*
704     Build the top level query
705   */
706 
707   Select_lex_builder top_query(&pos, thd);
708 
709   // SELECT * FROM <sub_query> ...
710   if (top_query.add_select_item(alias_field, alias_field) ||
711       top_query.add_select_item(alias_column_type, alias_column_type) ||
712       (thd->lex->verbose == true &&
713        top_query.add_select_item(alias_collation, alias_collation)) ||
714       top_query.add_select_item(alias_null, alias_null) ||
715       top_query.add_select_item(alias_key, alias_key) ||
716       top_query.add_select_item(alias_default, alias_default) ||
717       top_query.add_select_item(alias_extra, alias_extra) ||
718       (thd->lex->verbose == true &&
719        top_query.add_select_item(alias_privileges, alias_privileges)) ||
720       (thd->lex->verbose == true &&
721        top_query.add_select_item(alias_comment, alias_comment)) ||
722       top_query.add_from_item(
723           sub_query.prepare_derived_table(system_view_name)))
724     return nullptr;
725 
726   // ... WHERE 'Database' = <dbname> ...
727   Item *database_condition =
728       top_query.prepare_equal_item(alias_database, cur_db);
729   if (!database_condition || top_query.add_condition(database_condition))
730     return nullptr;
731 
732   // ... AND Table = table_ident->table->str ...
733   Item *table_condition =
734       top_query.prepare_equal_item(alias_table, table_ident->table);
735   if (!table_condition || top_query.add_condition(table_condition))
736     return nullptr;
737 
738   // ... [ AND ] Field LIKE <value> ...
739   if (wild) {
740     Item *like = top_query.prepare_like_item(alias_field, wild);
741     if (!like || top_query.add_condition(like)) return nullptr;
742   }
743 
744   // ... [ AND ] <user provided condition> ...
745   if (where_cond && top_query.add_condition(where_cond)) return nullptr;
746 
747   // ... ORDER BY 'Ordinal_position' ...
748   if (top_query.add_order_by(alias_ordinal_position)) return nullptr;
749 
750   // Prepare the SELECT_LEX
751   SELECT_LEX *sl = top_query.prepare_select_lex();
752   if (sl == nullptr) return nullptr;
753 
754   // sql_command is set to SQL_QUERY after above call, so.
755   thd->lex->sql_command = SQLCOM_SHOW_FIELDS;
756 
757   return sl;
758 }
759 
760 // Build a substitute query for SHOW INDEX|KEYS|INDEXES
761 
build_show_keys_query(const POS & pos,THD * thd,Table_ident * table_ident,Item * where_cond)762 SELECT_LEX *build_show_keys_query(const POS &pos, THD *thd,
763                                   Table_ident *table_ident, Item *where_cond) {
764   LEX_CSTRING system_view_name = {STRING_WITH_LEN("SHOW_STATISTICS")};
765 
766   // Define field name literal used in query to be built.
767 
768   static const LEX_CSTRING field_database = {STRING_WITH_LEN("TABLE_SCHEMA")};
769   static const LEX_CSTRING alias_database = {STRING_WITH_LEN("Database")};
770 
771   static const LEX_CSTRING field_table = {STRING_WITH_LEN("TABLE_NAME")};
772   static const LEX_CSTRING alias_table = {STRING_WITH_LEN("Table")};
773 
774   static const LEX_CSTRING field_non_unique = {STRING_WITH_LEN("NON_UNIQUE")};
775   static const LEX_CSTRING alias_non_unique = {STRING_WITH_LEN("Non_unique")};
776 
777   static const LEX_CSTRING field_key = {STRING_WITH_LEN("INDEX_NAME")};
778   static const LEX_CSTRING alias_key = {STRING_WITH_LEN("Key_name")};
779 
780   static const LEX_CSTRING field_seq_in_index = {
781       STRING_WITH_LEN("SEQ_IN_INDEX")};
782   static const LEX_CSTRING alias_seq_in_index = {
783       STRING_WITH_LEN("Seq_in_index")};
784 
785   static const LEX_CSTRING field_column_name = {STRING_WITH_LEN("COLUMN_NAME")};
786   static const LEX_CSTRING alias_column_name = {STRING_WITH_LEN("Column_name")};
787 
788   static const LEX_CSTRING field_collation = {STRING_WITH_LEN("COLLATION")};
789   static const LEX_CSTRING alias_collation = {STRING_WITH_LEN("Collation")};
790 
791   static const LEX_CSTRING field_cardinality = {STRING_WITH_LEN("CARDINALITY")};
792   static const LEX_CSTRING alias_cardinality = {STRING_WITH_LEN("Cardinality")};
793 
794   static const LEX_CSTRING field_sub_part = {STRING_WITH_LEN("SUB_PART")};
795   static const LEX_CSTRING alias_sub_part = {STRING_WITH_LEN("Sub_part")};
796 
797   static const LEX_CSTRING field_packed = {STRING_WITH_LEN("PACKED")};
798   static const LEX_CSTRING alias_packed = {STRING_WITH_LEN("Packed")};
799 
800   static const LEX_CSTRING field_null = {STRING_WITH_LEN("NULLABLE")};
801   static const LEX_CSTRING alias_null = {STRING_WITH_LEN("Null")};
802 
803   static const LEX_CSTRING field_type = {STRING_WITH_LEN("INDEX_TYPE")};
804   static const LEX_CSTRING alias_type = {STRING_WITH_LEN("Index_type")};
805 
806   static const LEX_CSTRING field_comment = {STRING_WITH_LEN("COMMENT")};
807   static const LEX_CSTRING alias_comment = {STRING_WITH_LEN("Comment")};
808 
809   static const LEX_CSTRING field_index_comment = {
810       STRING_WITH_LEN("INDEX_COMMENT")};
811   static const LEX_CSTRING alias_index_comment = {
812       STRING_WITH_LEN("Index_comment")};
813 
814   static const LEX_CSTRING field_is_visible = {STRING_WITH_LEN("IS_VISIBLE")};
815   static const LEX_CSTRING alias_visible = {STRING_WITH_LEN("Visible")};
816 
817   static const LEX_CSTRING alias_index_pos = {
818       STRING_WITH_LEN("INDEX_ORDINAL_POSITION")};
819 
820   static const LEX_CSTRING alias_column_pos = {
821       STRING_WITH_LEN("COLUMN_ORDINAL_POSITION")};
822 
823   static const LEX_CSTRING field_expression = {STRING_WITH_LEN("EXPRESSION")};
824   static const LEX_CSTRING alias_expression = {STRING_WITH_LEN("Expression")};
825 
826   // Get the current logged in schema name
827   LEX_CSTRING cur_db;
828   if (table_ident->db.str) {
829     cur_db.str = table_ident->db.str;
830     cur_db.length = table_ident->db.length;
831   } else if (thd->lex->copy_db_to(&cur_db.str, &cur_db.length))
832     return nullptr;
833 
834   // Convert IS db and table name to desired form.
835   dd::info_schema::convert_table_name_case(
836       const_cast<char *>(cur_db.str),
837       const_cast<char *>(table_ident->table.str));
838 
839   /*
840      Build sub query.
841      ...
842   */
843   Select_lex_builder sub_query(&pos, thd);
844   if (sub_query.add_select_item(field_database, alias_database) ||
845       sub_query.add_select_item(field_table, alias_table) ||
846       sub_query.add_select_item(field_non_unique, alias_non_unique) ||
847       sub_query.add_select_item(field_key, alias_key) ||
848       sub_query.add_select_item(field_seq_in_index, alias_seq_in_index) ||
849       sub_query.add_select_item(field_column_name, alias_column_name) ||
850       sub_query.add_select_item(field_collation, alias_collation) ||
851       sub_query.add_select_item(field_cardinality, alias_cardinality) ||
852       sub_query.add_select_item(field_sub_part, alias_sub_part) ||
853       sub_query.add_select_item(field_packed, alias_packed) ||
854       sub_query.add_select_item(field_null, alias_null) ||
855       sub_query.add_select_item(field_type, alias_type) ||
856       sub_query.add_select_item(field_comment, alias_comment) ||
857       sub_query.add_select_item(field_index_comment, alias_index_comment) ||
858       sub_query.add_select_item(field_is_visible, alias_visible) ||
859       sub_query.add_select_item(field_expression, alias_expression) ||
860       sub_query.add_select_item(alias_index_pos, alias_index_pos) ||
861       sub_query.add_select_item(alias_column_pos, alias_column_pos))
862     return nullptr;
863 
864   // ... FROM information_schema.columns ...
865   if (sub_query.add_from_item(INFORMATION_SCHEMA_NAME, system_view_name))
866     return nullptr;
867 
868   /*
869     Build the top level query
870   */
871 
872   Select_lex_builder top_query(&pos, thd);
873 
874   // SELECT * FROM <sub_query> ...
875   if (top_query.add_select_item(alias_table, alias_table) ||
876       top_query.add_select_item(alias_non_unique, alias_non_unique) ||
877       top_query.add_select_item(alias_key, alias_key) ||
878       top_query.add_select_item(alias_seq_in_index, alias_seq_in_index) ||
879       top_query.add_select_item(alias_column_name, alias_column_name) ||
880       top_query.add_select_item(alias_collation, alias_collation) ||
881       top_query.add_select_item(alias_cardinality, alias_cardinality) ||
882       top_query.add_select_item(alias_sub_part, alias_sub_part) ||
883       top_query.add_select_item(alias_packed, alias_packed) ||
884       top_query.add_select_item(alias_null, alias_null) ||
885       top_query.add_select_item(alias_type, alias_type) ||
886       top_query.add_select_item(alias_comment, alias_comment) ||
887       top_query.add_select_item(alias_index_comment, alias_index_comment) ||
888       top_query.add_select_item(alias_visible, alias_visible) ||
889       top_query.add_select_item(alias_expression, alias_expression) ||
890       top_query.add_from_item(
891           sub_query.prepare_derived_table(system_view_name)))
892     return nullptr;
893 
894   // ... WHERE 'Database' = <dbname> ...
895   Item *database_condition =
896       top_query.prepare_equal_item(alias_database, cur_db);
897   if (!database_condition || top_query.add_condition(database_condition))
898     return nullptr;
899 
900   // ... AND Table = table_ident->table->str ...
901   Item *table_condition =
902       top_query.prepare_equal_item(alias_table, table_ident->table);
903   if (!table_condition || top_query.add_condition(table_condition))
904     return nullptr;
905 
906   // ... [ AND ] <user provided condition> ...
907   if (where_cond && top_query.add_condition(where_cond)) return nullptr;
908 
909   // ... ORDER BY 'INDEX_ORDINAL_POSITION, COLUMN_ORDINAL_POSITION' ...
910   if (top_query.add_order_by(alias_index_pos) ||
911       top_query.add_order_by(alias_column_pos))
912     return nullptr;
913 
914   // Prepare the SELECT_LEX
915   SELECT_LEX *sl = top_query.prepare_select_lex();
916   if (sl == nullptr) return nullptr;
917 
918   // sql_command is set to SQL_QUERY after above call, so.
919   thd->lex->sql_command = SQLCOM_SHOW_KEYS;
920 
921   return sl;
922 }
923 
924 // Build a substitute query for SHOW TRIGGERS
925 
build_show_triggers_query(const POS & pos,THD * thd,String * wild,Item * where_cond)926 SELECT_LEX *build_show_triggers_query(const POS &pos, THD *thd, String *wild,
927                                       Item *where_cond) {
928   static const LEX_CSTRING system_view_name = {STRING_WITH_LEN("TRIGGERS")};
929 
930   // Define field name literal used in query to be built.
931   static const LEX_CSTRING field_database = {
932       STRING_WITH_LEN("EVENT_OBJECT_SCHEMA")};
933   static const LEX_CSTRING alias_database = {STRING_WITH_LEN("Database")};
934 
935   static const LEX_CSTRING field_trigger = {STRING_WITH_LEN("TRIGGER_NAME")};
936   static const LEX_CSTRING alias_trigger = {STRING_WITH_LEN("Trigger")};
937 
938   static const LEX_CSTRING field_manipulation = {
939       STRING_WITH_LEN("EVENT_MANIPULATION")};
940   static const LEX_CSTRING alias_manipulation = {STRING_WITH_LEN("Event")};
941 
942   static const LEX_CSTRING field_table = {
943       STRING_WITH_LEN("EVENT_OBJECT_TABLE")};
944   static const LEX_CSTRING alias_table = {STRING_WITH_LEN("Table")};
945 
946   static const LEX_CSTRING field_statement = {
947       STRING_WITH_LEN("ACTION_STATEMENT")};
948   static const LEX_CSTRING alias_statement = {STRING_WITH_LEN("Statement")};
949 
950   static const LEX_CSTRING field_timing = {STRING_WITH_LEN("ACTION_TIMING")};
951   static const LEX_CSTRING alias_timing = {STRING_WITH_LEN("Timing")};
952 
953   static const LEX_CSTRING field_created = {STRING_WITH_LEN("CREATED")};
954   static const LEX_CSTRING alias_created = {STRING_WITH_LEN("Created")};
955 
956   static const LEX_CSTRING field_sql_mode = {STRING_WITH_LEN("SQL_MODE")};
957   static const LEX_CSTRING alias_sql_mode = {STRING_WITH_LEN("sql_mode")};
958 
959   static const LEX_CSTRING field_definer = {STRING_WITH_LEN("DEFINER")};
960   static const LEX_CSTRING alias_definer = {STRING_WITH_LEN("Definer")};
961 
962   static const LEX_CSTRING field_client_cs = {
963       STRING_WITH_LEN("CHARACTER_SET_CLIENT")};
964   static const LEX_CSTRING alias_client_cs = {
965       STRING_WITH_LEN("character_set_client")};
966 
967   static const LEX_CSTRING field_conn_coll = {
968       STRING_WITH_LEN("COLLATION_CONNECTION")};
969   static const LEX_CSTRING alias_conn_coll = {
970       STRING_WITH_LEN("collation_connection")};
971 
972   static const LEX_CSTRING field_db_coll = {
973       STRING_WITH_LEN("DATABASE_COLLATION")};
974   static const LEX_CSTRING alias_db_coll = {
975       STRING_WITH_LEN("Database Collation")};
976 
977   static const LEX_CSTRING field_action_order = {
978       STRING_WITH_LEN("ACTION_ORDER")};
979   static const LEX_CSTRING alias_action_order = {
980       STRING_WITH_LEN("action_order")};
981 
982   // Get the current logged in schema name
983   size_t dummy;
984   if (thd->lex->select_lex->db == nullptr &&
985       thd->lex->copy_db_to(&thd->lex->select_lex->db, &dummy))
986     return nullptr;
987 
988   // Convert IS db and table name to desired form.
989   dd::info_schema::convert_table_name_case(thd->lex->select_lex->db,
990                                            wild ? wild->ptr() : nullptr);
991 
992   LEX_STRING cur_db = {thd->lex->select_lex->db,
993                        strlen(thd->lex->select_lex->db)};
994 
995   if (check_and_convert_db_name(&cur_db, false) != Ident_name_check::OK)
996     return nullptr;
997 
998   /*
999      Build sub query.
1000      ...
1001   */
1002   Select_lex_builder sub_query(&pos, thd);
1003   if (sub_query.add_select_item(field_database, alias_database) ||
1004       sub_query.add_select_item(field_trigger, alias_trigger) ||
1005       sub_query.add_select_item(field_manipulation, alias_manipulation) ||
1006       sub_query.add_select_item(field_table, alias_table) ||
1007       sub_query.add_select_item(field_statement, alias_statement) ||
1008       sub_query.add_select_item(field_timing, alias_timing) ||
1009       sub_query.add_select_item(field_created, alias_created) ||
1010       sub_query.add_select_item(field_sql_mode, alias_sql_mode) ||
1011       sub_query.add_select_item(field_definer, alias_definer) ||
1012       sub_query.add_select_item(field_client_cs, alias_client_cs) ||
1013       sub_query.add_select_item(field_conn_coll, alias_conn_coll) ||
1014       sub_query.add_select_item(field_db_coll, alias_db_coll) ||
1015       sub_query.add_select_item(field_action_order, alias_action_order))
1016     return nullptr;
1017 
1018   // ... FROM information_schema.tables ...
1019   if (sub_query.add_from_item(INFORMATION_SCHEMA_NAME, system_view_name))
1020     return nullptr;
1021 
1022   /*
1023     Build the top level query
1024   */
1025 
1026   Select_lex_builder top_query(&pos, thd);
1027 
1028   // SELECT * FROM <sub_query> ...
1029   if (top_query.add_select_item(alias_trigger, alias_trigger) ||
1030       top_query.add_select_item(alias_manipulation, alias_manipulation) ||
1031       top_query.add_select_item(alias_table, alias_table) ||
1032       top_query.add_select_item(alias_statement, alias_statement) ||
1033       top_query.add_select_item(alias_timing, alias_timing) ||
1034       top_query.add_select_item(alias_created, alias_created) ||
1035       top_query.add_select_item(alias_sql_mode, alias_sql_mode) ||
1036       top_query.add_select_item(alias_definer, alias_definer) ||
1037       top_query.add_select_item(alias_client_cs, alias_client_cs) ||
1038       top_query.add_select_item(alias_conn_coll, alias_conn_coll) ||
1039       top_query.add_select_item(alias_db_coll, alias_db_coll) ||
1040       top_query.add_from_item(
1041           sub_query.prepare_derived_table(system_view_name)))
1042     return nullptr;
1043 
1044   // ... WHERE 'Database' = <dbname> ...
1045   Item *database_condition =
1046       top_query.prepare_equal_item(alias_database, to_lex_cstring(cur_db));
1047   if (top_query.add_condition(database_condition)) return nullptr;
1048 
1049   // ... [ AND ] Table LIKE <value> ...
1050   if (wild) {
1051     Item *like = top_query.prepare_like_item(alias_table, wild);
1052     if (!like || top_query.add_condition(like)) return nullptr;
1053   }
1054 
1055   // ... [ AND ] <user provided condition> ...
1056   if (where_cond && top_query.add_condition(where_cond)) return nullptr;
1057 
1058   // ... ORDER BY 'Table, Event, Timing, Action order' ...
1059   if (top_query.add_order_by(alias_table) ||
1060       top_query.add_order_by(alias_manipulation) ||
1061       top_query.add_order_by(alias_timing) ||
1062       top_query.add_order_by(alias_action_order))
1063     return nullptr;
1064 
1065   SELECT_LEX *sl = top_query.prepare_select_lex();
1066 
1067   // sql_command is set to SQL_QUERY after above call, so.
1068   thd->lex->sql_command = SQLCOM_SHOW_TRIGGERS;
1069 
1070   return sl;
1071 }
1072 
1073 // Build a substitute query for SHOW PROCEDURES / FUNCTIONS
1074 
build_show_procedures_query(const POS & pos,THD * thd,String * wild,Item * where_cond)1075 SELECT_LEX *build_show_procedures_query(const POS &pos, THD *thd, String *wild,
1076                                         Item *where_cond) {
1077   enum_sql_command current_cmd = thd->lex->sql_command;
1078 
1079   static const LEX_CSTRING system_view_name = {STRING_WITH_LEN("ROUTINES")};
1080 
1081   // Define field name literal used in query to be built.
1082   static const LEX_CSTRING field_db = {STRING_WITH_LEN("ROUTINE_SCHEMA")};
1083   static const LEX_CSTRING alias_db = {STRING_WITH_LEN("Db")};
1084 
1085   static const LEX_CSTRING field_name = {STRING_WITH_LEN("ROUTINE_NAME")};
1086   static const LEX_CSTRING alias_name = {STRING_WITH_LEN("Name")};
1087 
1088   static const LEX_CSTRING field_type = {STRING_WITH_LEN("ROUTINE_TYPE")};
1089   static const LEX_CSTRING alias_type = {STRING_WITH_LEN("Type")};
1090 
1091   static const LEX_CSTRING field_definer = {STRING_WITH_LEN("DEFINER")};
1092   static const LEX_CSTRING alias_definer = {STRING_WITH_LEN("Definer")};
1093 
1094   static const LEX_CSTRING field_modified = {STRING_WITH_LEN("LAST_ALTERED")};
1095   static const LEX_CSTRING alias_modified = {STRING_WITH_LEN("Modified")};
1096 
1097   static const LEX_CSTRING field_created = {STRING_WITH_LEN("CREATED")};
1098   static const LEX_CSTRING alias_created = {STRING_WITH_LEN("Created")};
1099 
1100   static const LEX_CSTRING field_security_type = {
1101       STRING_WITH_LEN("SECURITY_TYPE")};
1102   static const LEX_CSTRING alias_security_type = {
1103       STRING_WITH_LEN("Security_type")};
1104 
1105   static const LEX_CSTRING field_comment = {STRING_WITH_LEN("ROUTINE_COMMENT")};
1106   static const LEX_CSTRING alias_comment = {STRING_WITH_LEN("Comment")};
1107 
1108   static const LEX_CSTRING field_client_cs = {
1109       STRING_WITH_LEN("CHARACTER_SET_CLIENT")};
1110   static const LEX_CSTRING alias_client_cs = {
1111       STRING_WITH_LEN("character_set_client")};
1112 
1113   static const LEX_CSTRING field_conn_coll = {
1114       STRING_WITH_LEN("COLLATION_CONNECTION")};
1115   static const LEX_CSTRING alias_conn_coll = {
1116       STRING_WITH_LEN("collation_connection")};
1117 
1118   static const LEX_CSTRING field_db_coll = {
1119       STRING_WITH_LEN("DATABASE_COLLATION")};
1120   static const LEX_CSTRING alias_db_coll = {
1121       STRING_WITH_LEN("Database Collation")};
1122 
1123   /*
1124      Build sub query.
1125      ...
1126   */
1127   Select_lex_builder sub_query(&pos, thd);
1128   if (sub_query.add_select_item(field_db, alias_db) ||
1129       sub_query.add_select_item(field_name, alias_name) ||
1130       sub_query.add_select_item(field_type, alias_type) ||
1131       sub_query.add_select_item(field_definer, alias_definer) ||
1132       sub_query.add_select_item(field_modified, alias_modified) ||
1133       sub_query.add_select_item(field_created, alias_created) ||
1134       sub_query.add_select_item(field_security_type, alias_security_type) ||
1135       sub_query.add_select_item(field_comment, alias_comment) ||
1136       sub_query.add_select_item(field_client_cs, alias_client_cs) ||
1137       sub_query.add_select_item(field_conn_coll, alias_conn_coll) ||
1138       sub_query.add_select_item(field_db_coll, alias_db_coll))
1139     return nullptr;
1140 
1141   // ... FROM information_schema.tables ...
1142   if (sub_query.add_from_item(INFORMATION_SCHEMA_NAME, system_view_name))
1143     return nullptr;
1144 
1145   /*
1146     Build the top level query
1147   */
1148 
1149   Select_lex_builder top_query(&pos, thd);
1150 
1151   // SELECT * FROM <sub_query> ...
1152   if (top_query.add_star_select_item() ||
1153       top_query.add_from_item(
1154           sub_query.prepare_derived_table(system_view_name)))
1155     return nullptr;
1156 
1157   // ... WHERE 'Type' = 'PROCEDURE | FUNCTION'
1158   const char *current_type = thd->lex->sql_command == SQLCOM_SHOW_STATUS_PROC
1159                                  ? "PROCEDURE"
1160                                  : "FUNCTION";
1161   LEX_CSTRING tmp_lex_string = {current_type, strlen(current_type)};
1162   Item *type_condition =
1163       top_query.prepare_equal_item(alias_type, tmp_lex_string);
1164   if (top_query.add_condition(type_condition)) return nullptr;
1165 
1166   // ... [ AND ] Name LIKE <value> ...
1167   if (wild) {
1168     Item *like = top_query.prepare_like_item(alias_name, wild);
1169     if (!like || top_query.add_condition(like)) return nullptr;
1170   }
1171 
1172   // ... [ AND ] <user provided condition> ...
1173   if (where_cond && top_query.add_condition(where_cond)) return nullptr;
1174 
1175   // ... ORDER BY 'Db, Name' ...
1176   if (top_query.add_order_by(alias_db) || top_query.add_order_by(alias_name))
1177     return nullptr;
1178 
1179   SELECT_LEX *sl = top_query.prepare_select_lex();
1180 
1181   // sql_command is set to SQL_QUERY after above call, so.
1182   thd->lex->sql_command = current_cmd;
1183 
1184   return sl;
1185 }
1186 
1187 // Build a substitute query for SHOW EVENTS
1188 
build_show_events_query(const POS & pos,THD * thd,String * wild,Item * where_cond)1189 SELECT_LEX *build_show_events_query(const POS &pos, THD *thd, String *wild,
1190                                     Item *where_cond) {
1191   static const LEX_CSTRING system_view_name = {STRING_WITH_LEN("EVENTS")};
1192 
1193   // Define field name literal used in query to be built.
1194   static const LEX_CSTRING field_db = {STRING_WITH_LEN("EVENT_SCHEMA")};
1195   static const LEX_CSTRING alias_db = {STRING_WITH_LEN("Db")};
1196 
1197   static const LEX_CSTRING field_name = {STRING_WITH_LEN("EVENT_NAME")};
1198   static const LEX_CSTRING alias_name = {STRING_WITH_LEN("Name")};
1199 
1200   static const LEX_CSTRING field_definer = {STRING_WITH_LEN("DEFINER")};
1201   static const LEX_CSTRING alias_definer = {STRING_WITH_LEN("Definer")};
1202 
1203   static const LEX_CSTRING field_zone = {STRING_WITH_LEN("TIME_ZONE")};
1204   static const LEX_CSTRING alias_zone = {STRING_WITH_LEN("Time zone")};
1205 
1206   static const LEX_CSTRING field_type = {STRING_WITH_LEN("EVENT_TYPE")};
1207   static const LEX_CSTRING alias_type = {STRING_WITH_LEN("Type")};
1208 
1209   static const LEX_CSTRING field_execute_at = {STRING_WITH_LEN("EXECUTE_AT")};
1210   static const LEX_CSTRING alias_execute_at = {STRING_WITH_LEN("Execute at")};
1211 
1212   static const LEX_CSTRING field_interval_value = {
1213       STRING_WITH_LEN("INTERVAL_VALUE")};
1214   static const LEX_CSTRING alias_interval_value = {
1215       STRING_WITH_LEN("Interval value")};
1216 
1217   static const LEX_CSTRING field_interval_field = {
1218       STRING_WITH_LEN("INTERVAL_FIELD")};
1219   static const LEX_CSTRING alias_interval_field = {
1220       STRING_WITH_LEN("Interval field")};
1221 
1222   static const LEX_CSTRING field_starts = {STRING_WITH_LEN("STARTS")};
1223   static const LEX_CSTRING alias_starts = {STRING_WITH_LEN("Starts")};
1224 
1225   static const LEX_CSTRING field_ends = {STRING_WITH_LEN("ENDS")};
1226   static const LEX_CSTRING alias_ends = {STRING_WITH_LEN("Ends")};
1227 
1228   static const LEX_CSTRING field_status = {STRING_WITH_LEN("STATUS")};
1229   static const LEX_CSTRING alias_status = {STRING_WITH_LEN("Status")};
1230 
1231   static const LEX_CSTRING field_originator = {STRING_WITH_LEN("ORIGINATOR")};
1232   static const LEX_CSTRING alias_originator = {STRING_WITH_LEN("Originator")};
1233 
1234   static const LEX_CSTRING field_client_cs = {
1235       STRING_WITH_LEN("CHARACTER_SET_CLIENT")};
1236   static const LEX_CSTRING alias_client_cs = {
1237       STRING_WITH_LEN("character_set_client")};
1238 
1239   static const LEX_CSTRING field_conn_coll = {
1240       STRING_WITH_LEN("COLLATION_CONNECTION")};
1241   static const LEX_CSTRING alias_conn_coll = {
1242       STRING_WITH_LEN("collation_connection")};
1243 
1244   static const LEX_CSTRING field_db_coll = {
1245       STRING_WITH_LEN("DATABASE_COLLATION")};
1246   static const LEX_CSTRING alias_db_coll = {
1247       STRING_WITH_LEN("Database Collation")};
1248 
1249   // Get the current logged in schema name
1250   size_t dummy;
1251   if (thd->lex->select_lex->db == nullptr &&
1252       thd->lex->copy_db_to(&thd->lex->select_lex->db, &dummy))
1253     return nullptr;
1254 
1255   // Convert IS db and table name to desired form.
1256   dd::info_schema::convert_table_name_case(thd->lex->select_lex->db,
1257                                            wild ? wild->ptr() : nullptr);
1258 
1259   LEX_STRING cur_db = {thd->lex->select_lex->db,
1260                        strlen(thd->lex->select_lex->db)};
1261 
1262   if (check_and_convert_db_name(&cur_db, false) != Ident_name_check::OK)
1263     return nullptr;
1264 
1265   /*
1266      Build sub query.
1267      ...
1268   */
1269   Select_lex_builder sub_query(&pos, thd);
1270   if (sub_query.add_select_item(field_db, alias_db) ||
1271       sub_query.add_select_item(field_name, alias_name) ||
1272       sub_query.add_select_item(field_definer, alias_definer) ||
1273       sub_query.add_select_item(field_zone, alias_zone) ||
1274       sub_query.add_select_item(field_type, alias_type) ||
1275       sub_query.add_select_item(field_execute_at, alias_execute_at) ||
1276       sub_query.add_select_item(field_interval_value, alias_interval_value) ||
1277       sub_query.add_select_item(field_interval_field, alias_interval_field) ||
1278       sub_query.add_select_item(field_starts, alias_starts) ||
1279       sub_query.add_select_item(field_ends, alias_ends) ||
1280       sub_query.add_select_item(field_status, alias_status) ||
1281       sub_query.add_select_item(field_originator, alias_originator) ||
1282       sub_query.add_select_item(field_client_cs, alias_client_cs) ||
1283       sub_query.add_select_item(field_conn_coll, alias_conn_coll) ||
1284       sub_query.add_select_item(field_db_coll, alias_db_coll))
1285     return nullptr;
1286 
1287   // ... FROM information_schema.tables ...
1288   if (sub_query.add_from_item(INFORMATION_SCHEMA_NAME, system_view_name))
1289     return nullptr;
1290 
1291   /*
1292     Build the top level query
1293   */
1294 
1295   Select_lex_builder top_query(&pos, thd);
1296 
1297   // SELECT * FROM <sub_query> ...
1298   if (top_query.add_star_select_item() ||
1299       top_query.add_from_item(
1300           sub_query.prepare_derived_table(system_view_name)))
1301     return nullptr;
1302 
1303   // ... WHERE 'Database' = <dbname> ...
1304   Item *database_condition =
1305       top_query.prepare_equal_item(alias_db, to_lex_cstring(cur_db));
1306   if (top_query.add_condition(database_condition)) return nullptr;
1307 
1308   // ... [ AND ] Name LIKE <value> ...
1309   if (wild) {
1310     Item *like = top_query.prepare_like_item(alias_name, wild);
1311     if (!like || top_query.add_condition(like)) return nullptr;
1312   }
1313 
1314   // ... [ AND ] <user provided condition> ...
1315   if (where_cond && top_query.add_condition(where_cond)) return nullptr;
1316 
1317   // ... ORDER BY 'Db, Name' ...
1318   if (top_query.add_order_by(alias_db) || top_query.add_order_by(alias_name))
1319     return nullptr;
1320 
1321   SELECT_LEX *sl = top_query.prepare_select_lex();
1322 
1323   // sql_command is set to SQL_QUERY after above call, so.
1324   thd->lex->sql_command = SQLCOM_SHOW_EVENTS;
1325 
1326   return sl;
1327 }
1328 
1329 }  // namespace info_schema
1330 }  // namespace dd
1331