1 /* Copyright (c) 2000, 2020, 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 
24 /* Function with list databases, tables or fields */
25 
26 #include "my_global.h"                          /* NO_EMBEDDED_ACCESS_CHECKS */
27 #include "sql_priv.h"
28 #include "unireg.h"
29 #include "sql_acl.h"                        // fill_schema_*_privileges
30 #include "sql_select.h"
31 #include "sql_base.h"                       // close_tables_for_reopen
32 #include "sql_show.h"
33 #include "sql_table.h"                        // filename_to_tablename,
34                                               // primary_key_name,
35                                               // build_table_filename
36 #include "sql_view.h"                           // mysql_frm_type
37 #include "sql_parse.h"             // check_access, check_table_access
38 #include "sql_partition.h"         // partition_element
39 #include "sql_derived.h"           // mysql_derived_prepare,
40                                    // mysql_handle_derived,
41 #include "sql_db.h"     // check_db_dir_existence, load_db_opt_by_name
42 #include "sql_time.h"   // interval_type_to_name
43 #include "tztime.h"                             // struct Time_zone
44 #include "sql_acl.h"     // TABLE_ACLS, check_grant, DB_ACLS, acl_get,
45                          // check_grant_db
46 #include "filesort.h"    // filesort_free_buffers
47 #include "sp.h"
48 #include "sp_head.h"
49 #include "sp_pcontext.h"
50 #include "set_var.h"
51 #include "sql_trigger.h"
52 #include "sql_derived.h"
53 #include "sql_partition.h"
54 #ifdef HAVE_EVENT_SCHEDULER
55 #include "events.h"
56 #include "event_data_objects.h"
57 #endif
58 #include <my_dir.h>
59 #include "lock.h"                           // MYSQL_OPEN_IGNORE_FLUSH
60 #include "debug_sync.h"
61 #include "datadict.h"   // dd_frm_type()
62 #include "opt_trace.h"     // Optimizer trace information schema tables
63 #include "sql_tmp_table.h" // Tmp tables
64 #include "sql_optimizer.h" // JOIN
65 #include "global_threads.h"
66 
67 #include <algorithm>
68 using std::max;
69 using std::min;
70 
71 #define STR_OR_NIL(S) ((S) ? (S) : "<nil>")
72 
73 #ifdef WITH_PARTITION_STORAGE_ENGINE
74 #include "ha_partition.h"
75 #endif
76 enum enum_i_s_events_fields
77 {
78   ISE_EVENT_CATALOG= 0,
79   ISE_EVENT_SCHEMA,
80   ISE_EVENT_NAME,
81   ISE_DEFINER,
82   ISE_TIME_ZONE,
83   ISE_EVENT_BODY,
84   ISE_EVENT_DEFINITION,
85   ISE_EVENT_TYPE,
86   ISE_EXECUTE_AT,
87   ISE_INTERVAL_VALUE,
88   ISE_INTERVAL_FIELD,
89   ISE_SQL_MODE,
90   ISE_STARTS,
91   ISE_ENDS,
92   ISE_STATUS,
93   ISE_ON_COMPLETION,
94   ISE_CREATED,
95   ISE_LAST_ALTERED,
96   ISE_LAST_EXECUTED,
97   ISE_EVENT_COMMENT,
98   ISE_ORIGINATOR,
99   ISE_CLIENT_CS,
100   ISE_CONNECTION_CL,
101   ISE_DB_CL
102 };
103 
104 #ifndef NO_EMBEDDED_ACCESS_CHECKS
105 static const char *grant_names[]={
106   "select","insert","update","delete","create","drop","reload","shutdown",
107   "process","file","grant","references","index","alter"};
108 
109 static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
110                                "grant_types",
111                                grant_names, NULL};
112 #endif
113 
114 static void store_key_options(THD *thd, String *packet, TABLE *table,
115                               KEY *key_info);
116 
117 #ifdef WITH_PARTITION_STORAGE_ENGINE
118 static void get_cs_converted_string_value(THD *thd,
119                                           String *input_str,
120                                           String *output_str,
121                                           const CHARSET_INFO *cs,
122                                           bool use_hex);
123 #endif
124 
125 static void
126 append_algorithm(TABLE_LIST *table, String *buff);
127 
128 static Item * make_cond_for_info_schema(Item *cond, TABLE_LIST *table);
129 
130 /***************************************************************************
131 ** List all table types supported
132 ***************************************************************************/
133 
make_version_string(char * buf,int buf_length,uint version)134 static int make_version_string(char *buf, int buf_length, uint version)
135 {
136   return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff);
137 }
138 
show_plugins(THD * thd,plugin_ref plugin,void * arg)139 static my_bool show_plugins(THD *thd, plugin_ref plugin,
140                             void *arg)
141 {
142   TABLE *table= (TABLE*) arg;
143   struct st_mysql_plugin *plug= plugin_decl(plugin);
144   struct st_plugin_dl *plugin_dl= plugin_dlib(plugin);
145   CHARSET_INFO *cs= system_charset_info;
146   char version_buf[20];
147 
148   restore_record(table, s->default_values);
149 
150   table->field[0]->store(plugin_name(plugin)->str,
151                          plugin_name(plugin)->length, cs);
152 
153   table->field[1]->store(version_buf,
154         make_version_string(version_buf, sizeof(version_buf), plug->version),
155         cs);
156 
157 
158   switch (plugin_state(plugin)) {
159   /* case PLUGIN_IS_FREED: does not happen */
160   case PLUGIN_IS_DELETED:
161     table->field[2]->store(STRING_WITH_LEN("DELETED"), cs);
162     break;
163   case PLUGIN_IS_UNINITIALIZED:
164     table->field[2]->store(STRING_WITH_LEN("INACTIVE"), cs);
165     break;
166   case PLUGIN_IS_READY:
167     table->field[2]->store(STRING_WITH_LEN("ACTIVE"), cs);
168     break;
169   case PLUGIN_IS_DISABLED:
170     table->field[2]->store(STRING_WITH_LEN("DISABLED"), cs);
171     break;
172   default:
173     DBUG_ASSERT(0);
174   }
175 
176   table->field[3]->store(plugin_type_names[plug->type].str,
177                          plugin_type_names[plug->type].length,
178                          cs);
179   table->field[4]->store(version_buf,
180         make_version_string(version_buf, sizeof(version_buf),
181                             *(uint *)plug->info), cs);
182 
183   if (plugin_dl)
184   {
185     table->field[5]->store(plugin_dl->dl.str, plugin_dl->dl.length, cs);
186     table->field[5]->set_notnull();
187     table->field[6]->store(version_buf,
188           make_version_string(version_buf, sizeof(version_buf),
189                               plugin_dl->version),
190           cs);
191     table->field[6]->set_notnull();
192   }
193   else
194   {
195     table->field[5]->set_null();
196     table->field[6]->set_null();
197   }
198 
199 
200   if (plug->author)
201   {
202     table->field[7]->store(plug->author, strlen(plug->author), cs);
203     table->field[7]->set_notnull();
204   }
205   else
206     table->field[7]->set_null();
207 
208   if (plug->descr)
209   {
210     table->field[8]->store(plug->descr, strlen(plug->descr), cs);
211     table->field[8]->set_notnull();
212   }
213   else
214     table->field[8]->set_null();
215 
216   switch (plug->license) {
217   case PLUGIN_LICENSE_GPL:
218     table->field[9]->store(PLUGIN_LICENSE_GPL_STRING,
219                            strlen(PLUGIN_LICENSE_GPL_STRING), cs);
220     break;
221   case PLUGIN_LICENSE_BSD:
222     table->field[9]->store(PLUGIN_LICENSE_BSD_STRING,
223                            strlen(PLUGIN_LICENSE_BSD_STRING), cs);
224     break;
225   default:
226     table->field[9]->store(PLUGIN_LICENSE_PROPRIETARY_STRING,
227                            strlen(PLUGIN_LICENSE_PROPRIETARY_STRING), cs);
228     break;
229   }
230   table->field[9]->set_notnull();
231 
232   table->field[10]->store(
233     global_plugin_typelib_names[plugin_load_option(plugin)],
234     strlen(global_plugin_typelib_names[plugin_load_option(plugin)]),
235     cs);
236 
237   return schema_table_store_record(thd, table);
238 }
239 
240 
fill_plugins(THD * thd,TABLE_LIST * tables,Item * cond)241 int fill_plugins(THD *thd, TABLE_LIST *tables, Item *cond)
242 {
243   DBUG_ENTER("fill_plugins");
244   TABLE *table= tables->table;
245 
246   if (plugin_foreach_with_mask(thd, show_plugins, MYSQL_ANY_PLUGIN,
247                                ~PLUGIN_IS_FREED, table))
248     DBUG_RETURN(1);
249 
250   DBUG_RETURN(0);
251 }
252 
253 
254 /***************************************************************************
255  List all privileges supported
256 ***************************************************************************/
257 
258 struct show_privileges_st {
259   const char *privilege;
260   const char *context;
261   const char *comment;
262 };
263 
264 static struct show_privileges_st sys_privileges[]=
265 {
266   {"Alter", "Tables",  "To alter the table"},
267   {"Alter routine", "Functions,Procedures",  "To alter or drop stored functions/procedures"},
268   {"Create", "Databases,Tables,Indexes",  "To create new databases and tables"},
269   {"Create routine","Databases","To use CREATE FUNCTION/PROCEDURE"},
270   {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"},
271   {"Create view", "Tables",  "To create new views"},
272   {"Create user", "Server Admin",  "To create new users"},
273   {"Delete", "Tables",  "To delete existing rows"},
274   {"Drop", "Databases,Tables", "To drop databases, tables, and views"},
275 #ifdef HAVE_EVENT_SCHEDULER
276   {"Event","Server Admin","To create, alter, drop and execute events"},
277 #endif
278   {"Execute", "Functions,Procedures", "To execute stored routines"},
279   {"File", "File access on server",   "To read and write files on the server"},
280   {"Grant option",  "Databases,Tables,Functions,Procedures", "To give to other users those privileges you possess"},
281   {"Index", "Tables",  "To create or drop indexes"},
282   {"Insert", "Tables",  "To insert data into tables"},
283   {"Lock tables","Databases","To use LOCK TABLES (together with SELECT privilege)"},
284   {"Process", "Server Admin", "To view the plain text of currently executing queries"},
285   {"Proxy", "Server Admin", "To make proxy user possible"},
286   {"References", "Databases,Tables", "To have references on tables"},
287   {"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"},
288   {"Replication client","Server Admin","To ask where the slave or master servers are"},
289   {"Replication slave","Server Admin","To read binary log events from the master"},
290   {"Select", "Tables",  "To retrieve rows from table"},
291   {"Show databases","Server Admin","To see all databases with SHOW DATABASES"},
292   {"Show view","Tables","To see views with SHOW CREATE VIEW"},
293   {"Shutdown","Server Admin", "To shut down the server"},
294   {"Super","Server Admin","To use KILL thread, SET GLOBAL, CHANGE MASTER, etc."},
295   {"Trigger","Tables", "To use triggers"},
296   {"Create tablespace", "Server Admin", "To create/alter/drop tablespaces"},
297   {"Update", "Tables",  "To update existing rows"},
298   {"Usage","Server Admin","No privileges - allow connect only"},
299   {NullS, NullS, NullS}
300 };
301 
mysqld_show_privileges(THD * thd)302 bool mysqld_show_privileges(THD *thd)
303 {
304   List<Item> field_list;
305   Protocol *protocol= thd->protocol;
306   DBUG_ENTER("mysqld_show_privileges");
307 
308   field_list.push_back(new Item_empty_string("Privilege",10));
309   field_list.push_back(new Item_empty_string("Context",15));
310   field_list.push_back(new Item_empty_string("Comment",NAME_CHAR_LEN));
311 
312   if (protocol->send_result_set_metadata(&field_list,
313                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
314     DBUG_RETURN(TRUE);
315 
316   show_privileges_st *privilege= sys_privileges;
317   for (privilege= sys_privileges; privilege->privilege ; privilege++)
318   {
319     protocol->prepare_for_resend();
320     protocol->store(privilege->privilege, system_charset_info);
321     protocol->store(privilege->context, system_charset_info);
322     protocol->store(privilege->comment, system_charset_info);
323     if (protocol->write())
324       DBUG_RETURN(TRUE);
325   }
326   my_eof(thd);
327   DBUG_RETURN(FALSE);
328 }
329 
330 
331 /** Hash of LEX_STRINGs used to search for ignored db directories. */
332 static HASH ignore_db_dirs_hash;
333 
334 /**
335   An array of LEX_STRING pointers to collect the options at
336   option parsing time.
337 */
338 static DYNAMIC_ARRAY ignore_db_dirs_array;
339 
340 /**
341   A value for the read only system variable to show a list of
342   ignored directories.
343 */
344 char *opt_ignore_db_dirs= NULL;
345 
346 
347 /**
348   Sets up the data structures for collection of directories at option
349   processing time.
350   We need to collect the directories in an array first, because
351   we need the character sets initialized before setting up the hash.
352 
353   @return state
354   @retval TRUE  failed
355   @retval FALSE success
356 */
357 
358 bool
ignore_db_dirs_init()359 ignore_db_dirs_init()
360 {
361   return my_init_dynamic_array(&ignore_db_dirs_array, sizeof(LEX_STRING *),
362                                0, 0);
363 }
364 
365 
366 /**
367   Retrieves the key (the string itself) from the LEX_STRING hash members.
368 
369   Needed by hash_init().
370 
371   @param     data         the data element from the hash
372   @param out len_ret      Placeholder to return the length of the key
373   @param                  unused
374   @return                 a pointer to the key
375 */
376 
377 static uchar *
db_dirs_hash_get_key(const uchar * data,size_t * len_ret,my_bool MY_ATTRIBUTE ((unused)))378 db_dirs_hash_get_key(const uchar *data, size_t *len_ret,
379                      my_bool MY_ATTRIBUTE((unused)))
380 {
381   LEX_STRING *e= (LEX_STRING *) data;
382 
383   *len_ret= e->length;
384   return (uchar *) e->str;
385 }
386 
387 
388 /**
389   Wrap a directory name into a LEX_STRING and push it to the array.
390 
391   Called at option processing time for each --ignore-db-dir option.
392 
393   @param    path  the name of the directory to push
394   @return state
395   @retval TRUE  failed
396   @retval FALSE success
397 */
398 
399 bool
push_ignored_db_dir(char * path)400 push_ignored_db_dir(char *path)
401 {
402   LEX_STRING *new_elt;
403   char *new_elt_buffer;
404   size_t path_len= strlen(path);
405 
406   if (!path_len || path_len >= FN_REFLEN)
407     return true;
408 
409   // No need to normalize, it's only a directory name, not a path.
410   if (!my_multi_malloc(0,
411                        &new_elt, sizeof(LEX_STRING),
412                        &new_elt_buffer, path_len + 1,
413                        NullS))
414     return true;
415   new_elt->str= new_elt_buffer;
416   memcpy(new_elt_buffer, path, path_len);
417   new_elt_buffer[path_len]= 0;
418   new_elt->length= path_len;
419   return insert_dynamic(&ignore_db_dirs_array, &new_elt);
420 }
421 
422 
423 /**
424   Clean up the directory ignore options accumulated so far.
425 
426   Called at option processing time for each --ignore-db-dir option
427   with an empty argument.
428 */
429 
430 void
ignore_db_dirs_reset()431 ignore_db_dirs_reset()
432 {
433   LEX_STRING **elt;
434   while (NULL!= (elt= (LEX_STRING **) pop_dynamic(&ignore_db_dirs_array)))
435     if (elt && *elt)
436       my_free(*elt);
437 }
438 
439 
440 /**
441   Free the directory ignore option variables.
442 
443   Called at server shutdown.
444 */
445 
446 void
ignore_db_dirs_free()447 ignore_db_dirs_free()
448 {
449   if (opt_ignore_db_dirs)
450   {
451     my_free(opt_ignore_db_dirs);
452     opt_ignore_db_dirs= NULL;
453   }
454   ignore_db_dirs_reset();
455   delete_dynamic(&ignore_db_dirs_array);
456   my_hash_free(&ignore_db_dirs_hash);
457 }
458 
459 
460 /**
461   Initialize the ignore db directories hash and status variable from
462   the options collected in the array.
463 
464   Called when option processing is over and the server's in-memory
465   structures are fully initialized.
466 
467   @return state
468   @retval TRUE  failed
469   @retval FALSE success
470 */
471 
472 bool
ignore_db_dirs_process_additions()473 ignore_db_dirs_process_additions()
474 {
475   ulong i;
476   size_t len;
477   char *ptr;
478   LEX_STRING *dir;
479 
480   DBUG_ASSERT(opt_ignore_db_dirs == NULL);
481 
482   if (my_hash_init(&ignore_db_dirs_hash,
483                    lower_case_table_names ?
484                      character_set_filesystem : &my_charset_bin,
485                    0, 0, 0, db_dirs_hash_get_key,
486                    my_free,
487                    HASH_UNIQUE))
488     return true;
489 
490   /* len starts from 1 because of the terminating zero. */
491   len= 1;
492   for (i= 0; i < ignore_db_dirs_array.elements; i++)
493   {
494     get_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
495     len+= dir->length + 1;                      // +1 for the comma
496   }
497 
498   /* No delimiter for the last directory. */
499   if (len > 1)
500     len--;
501 
502   /* +1 the terminating zero */
503   ptr= opt_ignore_db_dirs= (char *) my_malloc(len + 1, MYF(0));
504   if (!ptr)
505     return true;
506 
507   /* Make sure we have an empty string to start with. */
508   *ptr= 0;
509 
510   for (i= 0; i < ignore_db_dirs_array.elements; i++)
511   {
512     get_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
513     if (my_hash_insert(&ignore_db_dirs_hash, (uchar *) dir))
514       return true;
515     ptr= strnmov(ptr, dir->str, dir->length);
516     if (i + 1 < ignore_db_dirs_array.elements)
517       ptr= strmov(ptr, ",");
518 
519     /*
520       Set the transferred array element to NULL to avoid double free
521       in case of error.
522     */
523     dir= NULL;
524     set_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
525   }
526 
527   /* make sure the string is terminated */
528   DBUG_ASSERT(ptr - opt_ignore_db_dirs <= (ptrdiff_t) len);
529   *ptr= 0;
530 
531   /*
532     It's OK to empty the array here as the allocated elements are
533     referenced through the hash now.
534   */
535   reset_dynamic(&ignore_db_dirs_array);
536 
537   return false;
538 }
539 
540 
541 /**
542   Check if a directory name is in the hash of ignored directories.
543 
544   @return search result
545   @retval TRUE  found
546   @retval FALSE not found
547 */
548 
549 static inline bool
is_in_ignore_db_dirs_list(const char * directory)550 is_in_ignore_db_dirs_list(const char *directory)
551 {
552   return ignore_db_dirs_hash.records &&
553     NULL != my_hash_search(&ignore_db_dirs_hash, (const uchar *) directory,
554                            strlen(directory));
555 }
556 
557 
558 /*
559   find_files() - find files in a given directory.
560 
561   SYNOPSIS
562     find_files()
563     thd                 thread handler
564     files               put found files in this list
565     db                  database name to set in TABLE_LIST structure
566     path                path to database
567     wild                filter for found files
568     dir                 read databases in path if TRUE, read .frm files in
569                         database otherwise
570 
571   RETURN
572     FIND_FILES_OK       success
573     FIND_FILES_OOM      out of memory error
574     FIND_FILES_DIR      no such directory, or directory can't be read
575 */
576 
577 
578 find_files_result
find_files(THD * thd,List<LEX_STRING> * files,const char * db,const char * path,const char * wild,bool dir,MEM_ROOT * tmp_mem_root)579 find_files(THD *thd, List<LEX_STRING> *files, const char *db,
580            const char *path, const char *wild, bool dir, MEM_ROOT *tmp_mem_root)
581 {
582   uint i;
583   MY_DIR *dirp;
584   MEM_ROOT **root_ptr= NULL, *old_root= NULL;
585 #ifndef NO_EMBEDDED_ACCESS_CHECKS
586   uint col_access=thd->col_access;
587 #endif
588   uint wild_length= 0;
589   TABLE_LIST table_list;
590   DBUG_ENTER("find_files");
591 
592   if (wild)
593   {
594     if (!wild[0])
595       wild= 0;
596     else
597       wild_length= strlen(wild);
598   }
599 
600 
601 
602   memset(&table_list, 0, sizeof(table_list));
603 
604   if (!(dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0))))
605   {
606     if (my_errno == ENOENT)
607       my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db);
608     else
609     {
610       char errbuf[MYSYS_STRERROR_SIZE];
611       my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), path,
612                my_errno, my_strerror(errbuf, sizeof(errbuf), my_errno));
613     }
614     DBUG_RETURN(FIND_FILES_DIR);
615   }
616 
617   if (tmp_mem_root)
618   {
619     root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC);
620     old_root= *root_ptr;
621     *root_ptr= tmp_mem_root;
622   }
623 
624   for (i=0 ; i < (uint) dirp->number_off_files  ; i++)
625   {
626     char uname[NAME_LEN + 1];                   /* Unencoded name */
627     FILEINFO *file;
628     LEX_STRING *file_name= 0;
629     uint file_name_len;
630     char *ext;
631 
632     file=dirp->dir_entry+i;
633     if (dir)
634     {                                           /* Return databases */
635       /*
636         Ignore all the directories having names that start with a  dot (.).
637         This covers '.' and '..' and other cases like e.g. '.mysqlgui'.
638         Note that since 5.1 database directory names can't start with a
639         dot (.) thanks to table name encoding.
640       */
641       if (file->name[0]  == '.')
642         continue;
643 #ifdef USE_SYMDIR
644       char buff[FN_REFLEN];
645       if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym"))
646       {
647 	/* Only show the sym file if it points to a directory */
648 	char *end;
649         my_bool not_used;
650         *ext=0;                                 /* Remove extension */
651 	unpack_dirname(buff, file->name, &not_used);
652 	end= strend(buff);
653 	if (end != buff && end[-1] == FN_LIBCHAR)
654 	  end[-1]= 0;				// Remove end FN_LIBCHAR
655         if (!mysql_file_stat(key_file_misc, buff, file->mystat, MYF(0)))
656                continue;
657        }
658 #endif
659       if (!MY_S_ISDIR(file->mystat->st_mode))
660         continue;
661 
662       if (is_in_ignore_db_dirs_list(file->name))
663         continue;
664 
665     }
666     else
667     {
668         // Return only .frm files which aren't temp files.
669       if (my_strcasecmp(system_charset_info, ext=fn_rext(file->name),reg_ext) ||
670           is_prefix(file->name, tmp_file_prefix))
671         continue;
672       *ext=0;
673     }
674 
675     file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
676 
677     if (wild)
678     {
679       if (lower_case_table_names)
680       {
681         if (my_wildcmp(files_charset_info,
682                        uname, uname + file_name_len,
683                        wild, wild + wild_length,
684                        wild_prefix, wild_one,wild_many))
685           continue;
686       }
687       else if (wild_compare(uname, wild, 0))
688         continue;
689     }
690 
691 #ifndef NO_EMBEDDED_ACCESS_CHECKS
692     /* Don't show tables where we don't have any privileges */
693     if (db && !(col_access & TABLE_ACLS))
694     {
695       table_list.db= (char*) db;
696       table_list.db_length= strlen(db);
697       table_list.table_name= uname;
698       table_list.table_name_length= file_name_len;
699       table_list.grant.privilege=col_access;
700       if (check_grant(thd, TABLE_ACLS, &table_list, TRUE, 1, TRUE))
701         continue;
702     }
703 #endif
704     if (!(file_name= tmp_mem_root ?
705                      make_lex_string_root(tmp_mem_root, file_name, uname,
706                                           file_name_len, TRUE) :
707                      thd->make_lex_string(file_name, uname,
708                                           file_name_len, TRUE)) ||
709         files->push_back(file_name))
710     {
711       my_dirend(dirp);
712       DBUG_RETURN(FIND_FILES_OOM);
713     }
714   }
715   DBUG_PRINT("info",("found: %d files", files->elements));
716   my_dirend(dirp);
717 
718   (void) ha_find_files(thd, db, path, wild, dir, files);
719 
720   if (tmp_mem_root)
721     *root_ptr= old_root;
722 
723   DBUG_RETURN(FIND_FILES_OK);
724 }
725 
726 
727 /**
728    An Internal_error_handler that suppresses errors regarding views'
729    underlying tables that occur during privilege checking within SHOW CREATE
730    VIEW commands. This happens in the cases when
731 
732    - A view's underlying table (e.g. referenced in its SELECT list) does not
733      exist. There should not be an error as no attempt was made to access it
734      per se.
735 
736    - Access is denied for some table, column, function or stored procedure
737      such as mentioned above. This error gets raised automatically, since we
738      can't untangle its access checking from that of the view itself.
739  */
740 class Show_create_error_handler : public Internal_error_handler {
741 
742   TABLE_LIST *m_top_view;
743   bool m_handling;
744   Security_context *m_sctx;
745 
746   char m_view_access_denied_message[MYSQL_ERRMSG_SIZE];
747   char *m_view_access_denied_message_ptr;
748 
749 public:
750 
751   /**
752      Creates a new Show_create_error_handler for the particular security
753      context and view.
754 
755      @thd Thread context, used for security context information if needed.
756      @top_view The view. We do not verify at this point that top_view is in
757      fact a view since, alas, these things do not stay constant.
758   */
Show_create_error_handler(THD * thd,TABLE_LIST * top_view)759   explicit Show_create_error_handler(THD *thd, TABLE_LIST *top_view) :
760     m_top_view(top_view), m_handling(FALSE),
761     m_view_access_denied_message_ptr(NULL)
762   {
763 
764     m_sctx = MY_TEST(m_top_view->security_ctx) ?
765       m_top_view->security_ctx : thd->security_ctx;
766   }
767 
768   /**
769      Lazy instantiation of 'view access denied' message. The purpose of the
770      Show_create_error_handler is to hide details of underlying tables for
771      which we have no privileges behind ER_VIEW_INVALID messages. But this
772      obviously does not apply if we lack privileges on the view itself.
773      Unfortunately the information about for which table privilege checking
774      failed is not available at this point. The only way for us to check is by
775      reconstructing the actual error message and see if it's the same.
776   */
get_view_access_denied_message()777   char* get_view_access_denied_message()
778   {
779     if (!m_view_access_denied_message_ptr)
780     {
781       m_view_access_denied_message_ptr= m_view_access_denied_message;
782       my_snprintf(m_view_access_denied_message, MYSQL_ERRMSG_SIZE,
783                   ER(ER_TABLEACCESS_DENIED_ERROR), "SHOW VIEW",
784                   m_sctx->priv_user,
785                   m_sctx->host_or_ip, m_top_view->get_table_name());
786     }
787     return m_view_access_denied_message_ptr;
788   }
789 
handle_condition(THD * thd,uint sql_errno,const char *,Sql_condition::enum_warning_level level,const char * message,Sql_condition **)790   bool handle_condition(THD *thd, uint sql_errno, const char * /* sqlstate */,
791                         Sql_condition::enum_warning_level level,
792                         const char *message, Sql_condition ** /* cond_hdl */)
793   {
794     /*
795        The handler does not handle the errors raised by itself.
796        At this point we know if top_view is really a view.
797     */
798     if (m_handling || !m_top_view->view)
799       return FALSE;
800 
801     m_handling= TRUE;
802 
803     bool is_handled;
804 
805     switch (sql_errno)
806     {
807     case ER_TABLEACCESS_DENIED_ERROR:
808       if (!strcmp(get_view_access_denied_message(), message))
809       {
810         /* Access to top view is not granted, don't interfere. */
811         is_handled= FALSE;
812         break;
813       }
814     case ER_COLUMNACCESS_DENIED_ERROR:
815     case ER_VIEW_NO_EXPLAIN: /* Error was anonymized, ignore all the same. */
816     case ER_PROCACCESS_DENIED_ERROR:
817       is_handled= TRUE;
818       break;
819 
820     case ER_NO_SUCH_TABLE:
821       /* Established behavior: warn if underlying tables are missing. */
822       push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
823                           ER_VIEW_INVALID,
824                           ER(ER_VIEW_INVALID),
825                           m_top_view->get_db_name(),
826                           m_top_view->get_table_name());
827       is_handled= TRUE;
828       break;
829 
830     case ER_SP_DOES_NOT_EXIST:
831       /* Established behavior: warn if underlying functions are missing. */
832       push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
833                           ER_VIEW_INVALID,
834                           ER(ER_VIEW_INVALID),
835                           m_top_view->get_db_name(),
836                           m_top_view->get_table_name());
837       is_handled= TRUE;
838       break;
839     default:
840       is_handled= FALSE;
841     }
842 
843     m_handling= FALSE;
844     return is_handled;
845   }
846 };
847 
848 
849 bool
mysqld_show_create(THD * thd,TABLE_LIST * table_list)850 mysqld_show_create(THD *thd, TABLE_LIST *table_list)
851 {
852   Protocol *protocol= thd->protocol;
853   char buff[2048];
854   String buffer(buff, sizeof(buff), system_charset_info);
855   List<Item> field_list;
856   bool error= TRUE;
857   DBUG_ENTER("mysqld_show_create");
858   DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
859                       table_list->table_name));
860 
861   /*
862     Metadata locks taken during SHOW CREATE should be released when
863     the statmement completes as it is an information statement.
864   */
865   MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
866 
867   /* We want to preserve the tree for views. */
868   thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
869 
870   {
871     /*
872       Use open_tables() directly rather than open_normal_and_derived_tables().
873       This ensures that close_thread_tables() is not called if open tables fails
874       and the error is ignored. This allows us to handle broken views nicely.
875     */
876     uint counter;
877     Show_create_error_handler view_error_suppressor(thd, table_list);
878     thd->push_internal_handler(&view_error_suppressor);
879     bool open_error=
880       open_tables(thd, &table_list, &counter,
881                   MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL) ||
882                   mysql_handle_derived(thd->lex, &mysql_derived_prepare);
883     thd->pop_internal_handler();
884     if (open_error && (thd->killed || thd->is_error()))
885       goto exit;
886   }
887 
888   /* TODO: add environment variables show when it become possible */
889   if (thd->lex->only_view && !table_list->view)
890   {
891     my_error(ER_WRONG_OBJECT, MYF(0),
892              table_list->db, table_list->table_name, "VIEW");
893     goto exit;
894   }
895 
896   buffer.length(0);
897 
898   if (table_list->view)
899     buffer.set_charset(table_list->view_creation_ctx->get_client_cs());
900 
901   if ((table_list->view ?
902        view_store_create_info(thd, table_list, &buffer) :
903        store_create_info(thd, table_list, &buffer, NULL,
904                          FALSE /* show_database */)))
905     goto exit;
906 
907   if (table_list->view)
908   {
909     field_list.push_back(new Item_empty_string("View",NAME_CHAR_LEN));
910     field_list.push_back(new Item_empty_string("Create View",
911                                                max(buffer.length(), 1024U)));
912     field_list.push_back(new Item_empty_string("character_set_client",
913                                                MY_CS_NAME_SIZE));
914     field_list.push_back(new Item_empty_string("collation_connection",
915                                                MY_CS_NAME_SIZE));
916   }
917   else
918   {
919     field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN));
920     // 1024 is for not to confuse old clients
921     field_list.push_back(new Item_empty_string("Create Table",
922                                                max(buffer.length(), 1024U)));
923   }
924 
925   if (protocol->send_result_set_metadata(&field_list,
926                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
927     goto exit;
928 
929   protocol->prepare_for_resend();
930   if (table_list->view)
931     protocol->store(table_list->view_name.str, system_charset_info);
932   else
933   {
934     if (table_list->schema_table)
935       protocol->store(table_list->schema_table->table_name,
936                       system_charset_info);
937     else
938       protocol->store(table_list->table->alias, system_charset_info);
939   }
940 
941   if (table_list->view)
942   {
943     protocol->store(buffer.ptr(), buffer.length(),
944                     table_list->view_creation_ctx->get_client_cs());
945 
946     protocol->store(table_list->view_creation_ctx->get_client_cs()->csname,
947                     system_charset_info);
948 
949     protocol->store(table_list->view_creation_ctx->get_connection_cl()->name,
950                     system_charset_info);
951   }
952   else
953     protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
954 
955   if (protocol->write())
956     goto exit;
957 
958   error= FALSE;
959   my_eof(thd);
960 
961 exit:
962   close_thread_tables(thd);
963   /* Release any metadata locks taken during SHOW CREATE. */
964   thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
965   DBUG_RETURN(error);
966 }
967 
mysqld_show_create_db(THD * thd,char * dbname,HA_CREATE_INFO * create_info)968 bool mysqld_show_create_db(THD *thd, char *dbname,
969                            HA_CREATE_INFO *create_info)
970 {
971   char buff[2048], orig_dbname[NAME_LEN];
972   String buffer(buff, sizeof(buff), system_charset_info);
973 #ifndef NO_EMBEDDED_ACCESS_CHECKS
974   Security_context *sctx= thd->security_ctx;
975   uint db_access;
976 #endif
977   HA_CREATE_INFO create;
978   uint create_options = create_info ? create_info->options : 0;
979   Protocol *protocol=thd->protocol;
980   DBUG_ENTER("mysql_show_create_db");
981 
982   strcpy(orig_dbname, dbname);
983   if (lower_case_table_names && dbname != any_db)
984     my_casedn_str(files_charset_info, dbname);
985 
986 #ifndef NO_EMBEDDED_ACCESS_CHECKS
987   if (test_all_bits(sctx->master_access, DB_ACLS))
988     db_access=DB_ACLS;
989   else
990     db_access= (acl_get(sctx->get_host()->ptr(), sctx->get_ip()->ptr(),
991                         sctx->priv_user, dbname, 0) | sctx->master_access);
992   if (!(db_access & DB_ACLS) && check_grant_db(thd,dbname))
993   {
994     my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
995              sctx->priv_user, sctx->host_or_ip, dbname);
996     general_log_print(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
997                       sctx->priv_user, sctx->host_or_ip, dbname);
998     DBUG_RETURN(TRUE);
999   }
1000 #endif
1001   if (is_infoschema_db(dbname))
1002   {
1003     dbname= INFORMATION_SCHEMA_NAME.str;
1004     create.default_table_charset= system_charset_info;
1005   }
1006   else
1007   {
1008     if (check_db_dir_existence(dbname))
1009     {
1010       my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
1011       DBUG_RETURN(TRUE);
1012     }
1013 
1014     load_db_opt_by_name(thd, dbname, &create);
1015   }
1016   List<Item> field_list;
1017   field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
1018   field_list.push_back(new Item_empty_string("Create Database",1024));
1019 
1020   if (protocol->send_result_set_metadata(&field_list,
1021                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
1022     DBUG_RETURN(TRUE);
1023 
1024   protocol->prepare_for_resend();
1025   protocol->store(orig_dbname, strlen(orig_dbname), system_charset_info);
1026   buffer.length(0);
1027   buffer.append(STRING_WITH_LEN("CREATE DATABASE "));
1028   if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
1029     buffer.append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ "));
1030   append_identifier(thd, &buffer, orig_dbname, strlen(orig_dbname));
1031 
1032   if (create.default_table_charset)
1033   {
1034     buffer.append(STRING_WITH_LEN(" /*!40100"));
1035     buffer.append(STRING_WITH_LEN(" DEFAULT CHARACTER SET "));
1036     buffer.append(create.default_table_charset->csname);
1037     if (!(create.default_table_charset->state & MY_CS_PRIMARY))
1038     {
1039       buffer.append(STRING_WITH_LEN(" COLLATE "));
1040       buffer.append(create.default_table_charset->name);
1041     }
1042     buffer.append(STRING_WITH_LEN(" */"));
1043   }
1044   protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
1045 
1046   if (protocol->write())
1047     DBUG_RETURN(TRUE);
1048   my_eof(thd);
1049   DBUG_RETURN(FALSE);
1050 }
1051 
1052 
1053 
1054 /****************************************************************************
1055   Return only fields for API mysql_list_fields
1056   Use "show table wildcard" in mysql instead of this
1057 ****************************************************************************/
1058 
1059 void
mysqld_list_fields(THD * thd,TABLE_LIST * table_list,const char * wild)1060 mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
1061 {
1062   TABLE *table;
1063   DBUG_ENTER("mysqld_list_fields");
1064   DBUG_PRINT("enter",("table: %s",table_list->table_name));
1065 
1066   if (open_normal_and_derived_tables(thd, table_list,
1067                                      MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL))
1068     DBUG_VOID_RETURN;
1069   table= table_list->table;
1070   /* Create derived tables result table prior to reading it's fields list. */
1071   mysql_handle_single_derived(thd->lex, table_list, &mysql_derived_create);
1072   List<Item> field_list;
1073 
1074   Field **ptr,*field;
1075   for (ptr=table->field ; (field= *ptr); ptr++)
1076   {
1077     if (!wild || !wild[0] ||
1078         !wild_case_compare(system_charset_info, field->field_name,wild))
1079     {
1080       if (table_list->view)
1081         field_list.push_back(new Item_ident_for_show(field,
1082                                                      table_list->view_db.str,
1083                                                      table_list->view_name.str));
1084       else
1085         field_list.push_back(new Item_field(field));
1086     }
1087   }
1088   restore_record(table, s->default_values);              // Get empty record
1089   table->use_all_columns();
1090   if (thd->protocol->send_result_set_metadata(&field_list, Protocol::SEND_DEFAULTS))
1091     DBUG_VOID_RETURN;
1092   my_eof(thd);
1093   DBUG_VOID_RETURN;
1094 }
1095 
1096 /*
1097   Go through all character combinations and ensure that sql_lex.cc can
1098   parse it as an identifier.
1099 
1100   SYNOPSIS
1101   require_quotes()
1102   name			attribute name
1103   name_length		length of name
1104 
1105   RETURN
1106     #	Pointer to conflicting character
1107     0	No conflicting character
1108 */
1109 
require_quotes(const char * name,uint name_length)1110 static const char *require_quotes(const char *name, uint name_length)
1111 {
1112   bool pure_digit= TRUE;
1113   const char *end= name + name_length;
1114 
1115   for (; name < end ; name++)
1116   {
1117     uchar chr= (uchar) *name;
1118     uint length= my_mbcharlen(system_charset_info, chr);
1119     if (length == 0 || (length == 1 && !system_charset_info->ident_map[chr]))
1120       return name;
1121     if (length == 1 && (chr < '0' || chr > '9'))
1122       pure_digit= FALSE;
1123   }
1124   if (pure_digit)
1125     return name;
1126   return 0;
1127 }
1128 
1129 
1130 /**
1131   Convert and quote the given identifier if needed and append it to the
1132   target string. If the given identifier is empty, it will be quoted.
1133   @thd                         thread handler
1134   @packet                      target string
1135   @name                        the identifier to be appended
1136   @length                      length of the appending identifier
1137   @param from_cs               Charset information about the input string
1138   @param to_cs                 Charset information about the target string
1139 */
1140 
1141 void
append_identifier(THD * thd,String * packet,const char * name,uint length,const CHARSET_INFO * from_cs,const CHARSET_INFO * to_cs)1142 append_identifier(THD *thd, String *packet, const char *name, uint length,
1143                   const CHARSET_INFO *from_cs, const CHARSET_INFO *to_cs)
1144 {
1145   const char *name_end;
1146   char quote_char;
1147   int q;
1148 
1149   const CHARSET_INFO *cs_info= system_charset_info;
1150   const char *to_name= name;
1151   size_t to_length= length;
1152   String to_string(name,length, from_cs);
1153 
1154   if (from_cs != NULL && to_cs != NULL && from_cs != to_cs)
1155     thd->convert_string(&to_string, from_cs, to_cs);
1156 
1157   if (to_cs != NULL)
1158   {
1159     to_name= to_string.c_ptr();
1160     to_length= to_string.length();
1161     cs_info= to_cs;
1162   }
1163 
1164   q= thd ? get_quote_char_for_identifier(thd, to_name, to_length) : '`';
1165   if (q == EOF)
1166   {
1167     packet->append(to_name, to_length, packet->charset());
1168     return;
1169   }
1170 
1171   /*
1172     The identifier must be quoted as it includes a quote character or
1173    it's a keyword
1174   */
1175 
1176   (void) packet->reserve(to_length*2 + 2);
1177   quote_char= (char) q;
1178   packet->append(&quote_char, 1, system_charset_info);
1179 
1180   for (name_end= to_name+to_length ; to_name < name_end ; to_name+= to_length)
1181   {
1182     uchar chr= (uchar) *to_name;
1183     to_length= my_mbcharlen(cs_info, chr);
1184     /*
1185       my_mbcharlen can return 0 on a wrong multibyte
1186       sequence. It is possible when upgrading from 4.0,
1187       and identifier contains some accented characters.
1188       The manual says it does not work. So we'll just
1189       change length to 1 not to hang in the endless loop.
1190     */
1191     if (!to_length)
1192       to_length= 1;
1193     if (to_length == 1 && chr == (uchar) quote_char)
1194       packet->append(&quote_char, 1, system_charset_info);
1195     packet->append(to_name, to_length, system_charset_info);
1196   }
1197   packet->append(&quote_char, 1, system_charset_info);
1198 }
1199 
1200 
1201 /*
1202   Get the quote character for displaying an identifier.
1203 
1204   SYNOPSIS
1205     get_quote_char_for_identifier()
1206     thd		Thread handler
1207     name	name to quote
1208     length	length of name
1209 
1210   IMPLEMENTATION
1211     Force quoting in the following cases:
1212       - name is empty (for one, it is possible when we use this function for
1213         quoting user and host names for DEFINER clause);
1214       - name is a keyword;
1215       - name includes a special character;
1216     Otherwise identifier is quoted only if the option OPTION_QUOTE_SHOW_CREATE
1217     is set.
1218 
1219   RETURN
1220     EOF	  No quote character is needed
1221     #	  Quote character
1222 */
1223 
get_quote_char_for_identifier(THD * thd,const char * name,uint length)1224 int get_quote_char_for_identifier(THD *thd, const char *name, uint length)
1225 {
1226   if (length &&
1227       !is_keyword(name,length) &&
1228       !require_quotes(name, length) &&
1229       !(thd->variables.option_bits & OPTION_QUOTE_SHOW_CREATE))
1230     return EOF;
1231   if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
1232     return '"';
1233   return '`';
1234 }
1235 
1236 
1237 /* Append directory name (if exists) to CREATE INFO */
1238 
append_directory(THD * thd,String * packet,const char * dir_type,const char * filename)1239 static void append_directory(THD *thd, String *packet, const char *dir_type,
1240 			     const char *filename)
1241 {
1242   if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
1243   {
1244     uint length= dirname_length(filename);
1245     packet->append(' ');
1246     packet->append(dir_type);
1247     packet->append(STRING_WITH_LEN(" DIRECTORY='"));
1248 #ifdef __WIN__
1249     /* Convert \ to / to be able to create table on unix */
1250     char *winfilename= (char*) thd->memdup(filename, length);
1251     char *pos, *end;
1252     for (pos= winfilename, end= pos+length ; pos < end ; pos++)
1253     {
1254       if (*pos == '\\')
1255         *pos = '/';
1256     }
1257     filename= winfilename;
1258 #endif
1259     packet->append(filename, length);
1260     packet->append('\'');
1261   }
1262 }
1263 
1264 
1265 #define LIST_PROCESS_HOST_LEN 64
1266 
1267 /**
1268   Print "ON UPDATE" clause of a field into a string.
1269 
1270   @param timestamp_field   Pointer to timestamp field of a table.
1271   @param field             The field to generate ON UPDATE clause for.
1272   @bool  lcase             Whether to print in lower case.
1273   @return                  false on success, true on error.
1274 */
print_on_update_clause(Field * field,String * val,bool lcase)1275 static bool print_on_update_clause(Field *field, String *val, bool lcase)
1276 {
1277   DBUG_ASSERT(val->charset()->mbminlen == 1);
1278   val->length(0);
1279   if (field->has_update_default_function())
1280   {
1281     if (lcase)
1282       val->copy(STRING_WITH_LEN("on update "), val->charset());
1283     else
1284       val->copy(STRING_WITH_LEN("ON UPDATE "), val->charset());
1285     val->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
1286     if (field->decimals() > 0)
1287       val->append_parenthesized(field->decimals());
1288     return true;
1289   }
1290   return false;
1291 }
1292 
1293 
print_default_clause(THD * thd,Field * field,String * def_value,bool quoted)1294 static bool print_default_clause(THD *thd, Field *field, String *def_value,
1295                                  bool quoted)
1296 {
1297   enum enum_field_types field_type= field->type();
1298 
1299   const bool has_now_default= field->has_insert_default_function();
1300   const bool has_default=
1301     (field_type != FIELD_TYPE_BLOB &&
1302      !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
1303      field->unireg_check != Field::NEXT_NUMBER &&
1304      !((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
1305        && has_now_default));
1306 
1307   def_value->length(0);
1308   if (has_default)
1309   {
1310     if (has_now_default)
1311       /*
1312         We are using CURRENT_TIMESTAMP instead of NOW because it is the SQL
1313         standard.
1314       */
1315     {
1316       def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
1317       if (field->decimals() > 0)
1318         def_value->append_parenthesized(field->decimals());
1319     }
1320     else if (!field->is_null())
1321     {                                             // Not null by default
1322       char tmp[MAX_FIELD_WIDTH];
1323       String type(tmp, sizeof(tmp), field->charset());
1324       if (field_type == MYSQL_TYPE_BIT)
1325       {
1326         longlong dec= field->val_int();
1327         char *ptr= longlong2str(dec, tmp + 2, 2);
1328         uint32 length= (uint32) (ptr - tmp);
1329         tmp[0]= 'b';
1330         tmp[1]= '\'';
1331         tmp[length]= '\'';
1332         type.length(length + 1);
1333         quoted= 0;
1334       }
1335       else
1336         field->val_str(&type);
1337       if (type.length())
1338       {
1339         String def_val;
1340         uint dummy_errors;
1341         /* convert to system_charset_info == utf8 */
1342         def_val.copy(type.ptr(), type.length(), field->charset(),
1343                      system_charset_info, &dummy_errors);
1344         if (quoted)
1345           append_unescaped(def_value, def_val.ptr(), def_val.length());
1346         else
1347           def_value->append(def_val.ptr(), def_val.length());
1348       }
1349       else if (quoted)
1350         def_value->append(STRING_WITH_LEN("''"));
1351     }
1352     else if (field->maybe_null() && quoted)
1353       def_value->append(STRING_WITH_LEN("NULL"));    // Null as default
1354     else
1355       return 0;
1356 
1357   }
1358   return has_default;
1359 }
1360 
1361 
1362 /*
1363   Build a CREATE TABLE statement for a table.
1364 
1365   SYNOPSIS
1366     store_create_info()
1367     thd               The thread
1368     table_list        A list containing one table to write statement
1369                       for.
1370     packet            Pointer to a string where statement will be
1371                       written.
1372     create_info_arg   Pointer to create information that can be used
1373                       to tailor the format of the statement.  Can be
1374                       NULL, in which case only SQL_MODE is considered
1375                       when building the statement.
1376     show_database     If true, then print the database before the table
1377                       name. The database name is only printed in the event
1378                       that it is different from the current database.
1379                       If false, then do not print the database before
1380                       the table name.
1381 
1382   NOTE
1383     Currently always return 0, but might return error code in the
1384     future.
1385 
1386   RETURN
1387     0       OK
1388  */
1389 
store_create_info(THD * thd,TABLE_LIST * table_list,String * packet,HA_CREATE_INFO * create_info_arg,bool show_database)1390 int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
1391                       HA_CREATE_INFO *create_info_arg, bool show_database)
1392 {
1393   List<Item> field_list;
1394   char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], def_value_buf[MAX_FIELD_WIDTH];
1395   const char *alias;
1396   String type(tmp, sizeof(tmp), system_charset_info);
1397   String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
1398   Field **ptr,*field;
1399   uint primary_key;
1400   KEY *key_info;
1401   TABLE *table= table_list->table;
1402   handler *file= table->file;
1403   TABLE_SHARE *share= table->s;
1404   HA_CREATE_INFO create_info;
1405 #ifdef WITH_PARTITION_STORAGE_ENGINE
1406   bool show_table_options= FALSE;
1407 #endif /* WITH_PARTITION_STORAGE_ENGINE */
1408   bool foreign_db_mode=  (thd->variables.sql_mode & (MODE_POSTGRESQL |
1409                                                      MODE_ORACLE |
1410                                                      MODE_MSSQL |
1411                                                      MODE_DB2 |
1412                                                      MODE_MAXDB |
1413                                                      MODE_ANSI)) != 0;
1414   bool limited_mysql_mode= (thd->variables.sql_mode & (MODE_NO_FIELD_OPTIONS |
1415                                                        MODE_MYSQL323 |
1416                                                        MODE_MYSQL40)) != 0;
1417   my_bitmap_map *old_map;
1418   int error= 0;
1419   DBUG_ENTER("store_create_info");
1420   DBUG_PRINT("enter",("table: %s", table->s->table_name.str));
1421 
1422   restore_record(table, s->default_values); // Get empty record
1423 
1424   if (share->tmp_table)
1425     packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
1426   else
1427     packet->append(STRING_WITH_LEN("CREATE TABLE "));
1428   if (create_info_arg &&
1429       (create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS))
1430     packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
1431   if (table_list->schema_table)
1432     alias= table_list->schema_table->table_name;
1433   else
1434   {
1435     if (lower_case_table_names == 2)
1436       alias= table->alias;
1437     else
1438     {
1439       alias= share->table_name.str;
1440     }
1441   }
1442 
1443   /*
1444     Print the database before the table name if told to do that. The
1445     database name is only printed in the event that it is different
1446     from the current database.  The main reason for doing this is to
1447     avoid having to update gazillions of tests and result files, but
1448     it also saves a few bytes of the binary log.
1449    */
1450   if (show_database)
1451   {
1452     const LEX_STRING *const db=
1453       table_list->schema_table ? &INFORMATION_SCHEMA_NAME : &table->s->db;
1454     if (!thd->db || strcmp(db->str, thd->db))
1455     {
1456       append_identifier(thd, packet, db->str, db->length);
1457       packet->append(STRING_WITH_LEN("."));
1458     }
1459   }
1460 
1461   append_identifier(thd, packet, alias, strlen(alias));
1462   packet->append(STRING_WITH_LEN(" (\n"));
1463   /*
1464     We need this to get default values from the table
1465     We have to restore the read_set if we are called from insert in case
1466     of row based replication.
1467   */
1468   old_map= tmp_use_all_columns(table, table->read_set);
1469 
1470   for (ptr=table->field ; (field= *ptr); ptr++)
1471   {
1472     uint flags = field->flags;
1473     enum_field_types field_type= field->real_type();
1474 
1475     if (ptr != table->field)
1476       packet->append(STRING_WITH_LEN(",\n"));
1477 
1478     packet->append(STRING_WITH_LEN("  "));
1479     append_identifier(thd,packet,field->field_name, strlen(field->field_name));
1480     packet->append(' ');
1481     // check for surprises from the previous call to Field::sql_type()
1482     if (type.ptr() != tmp)
1483       type.set(tmp, sizeof(tmp), system_charset_info);
1484     else
1485       type.set_charset(system_charset_info);
1486 
1487     field->sql_type(type);
1488     /*
1489       If the session variable 'show_old_temporals' is enabled and the field
1490       is a temporal type of old format, add a comment to indicate the same.
1491     */
1492     if (thd->variables.show_old_temporals &&
1493         (field_type == MYSQL_TYPE_TIME || field_type == MYSQL_TYPE_DATETIME ||
1494          field_type == MYSQL_TYPE_TIMESTAMP))
1495       type.append(" /* 5.5 binary format */");
1496     packet->append(type.ptr(), type.length(), system_charset_info);
1497 
1498     if (field->has_charset() &&
1499         !(thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)))
1500     {
1501       if (field->charset() != share->table_charset)
1502       {
1503 	packet->append(STRING_WITH_LEN(" CHARACTER SET "));
1504 	packet->append(field->charset()->csname);
1505       }
1506       /*
1507 	For string types dump collation name only if
1508 	collation is not primary for the given charset
1509       */
1510       if (!(field->charset()->state & MY_CS_PRIMARY))
1511       {
1512 	packet->append(STRING_WITH_LEN(" COLLATE "));
1513 	packet->append(field->charset()->name);
1514       }
1515     }
1516 
1517     if (flags & NOT_NULL_FLAG)
1518       packet->append(STRING_WITH_LEN(" NOT NULL"));
1519     else if (field->type() == MYSQL_TYPE_TIMESTAMP)
1520     {
1521       /*
1522         TIMESTAMP field require explicit NULL flag, because unlike
1523         all other fields they are treated as NOT NULL by default.
1524       */
1525       packet->append(STRING_WITH_LEN(" NULL"));
1526     }
1527 
1528     switch(field->field_storage_type()){
1529     case HA_SM_DEFAULT:
1530       break;
1531     case HA_SM_DISK:
1532       packet->append(STRING_WITH_LEN(" /*!50606 STORAGE DISK */"));
1533       break;
1534     case HA_SM_MEMORY:
1535       packet->append(STRING_WITH_LEN(" /*!50606 STORAGE MEMORY */"));
1536       break;
1537     default:
1538       DBUG_ASSERT(0);
1539       break;
1540     }
1541 
1542     switch(field->column_format()){
1543     case COLUMN_FORMAT_TYPE_DEFAULT:
1544       break;
1545     case COLUMN_FORMAT_TYPE_FIXED:
1546       packet->append(STRING_WITH_LEN(" /*!50606 COLUMN_FORMAT FIXED */"));
1547       break;
1548     case COLUMN_FORMAT_TYPE_DYNAMIC:
1549       packet->append(STRING_WITH_LEN(" /*!50606 COLUMN_FORMAT DYNAMIC */"));
1550       break;
1551     default:
1552       DBUG_ASSERT(0);
1553       break;
1554     }
1555 
1556     if (print_default_clause(thd, field, &def_value, true))
1557     {
1558       packet->append(STRING_WITH_LEN(" DEFAULT "));
1559       packet->append(def_value.ptr(), def_value.length(), system_charset_info);
1560     }
1561 
1562     if (!limited_mysql_mode &&
1563         print_on_update_clause(field, &def_value, false))
1564     {
1565       packet->append(STRING_WITH_LEN(" "));
1566       packet->append(def_value);
1567     }
1568 
1569     if (field->unireg_check == Field::NEXT_NUMBER &&
1570         !(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS))
1571       packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
1572 
1573     if (field->comment.length)
1574     {
1575       packet->append(STRING_WITH_LEN(" COMMENT "));
1576       append_unescaped(packet, field->comment.str, field->comment.length);
1577     }
1578   }
1579 
1580   key_info= table->key_info;
1581   memset(&create_info, 0, sizeof(create_info));
1582   /* Allow update_create_info to update row type */
1583   create_info.row_type= share->row_type;
1584   file->update_create_info(&create_info);
1585   primary_key= share->primary_key;
1586 
1587   for (uint i=0 ; i < share->keys ; i++,key_info++)
1588   {
1589     KEY_PART_INFO *key_part= key_info->key_part;
1590     bool found_primary=0;
1591     packet->append(STRING_WITH_LEN(",\n  "));
1592 
1593     if (i == primary_key && !strcmp(key_info->name, primary_key_name))
1594     {
1595       found_primary=1;
1596       /*
1597         No space at end, because a space will be added after where the
1598         identifier would go, but that is not added for primary key.
1599       */
1600       packet->append(STRING_WITH_LEN("PRIMARY KEY"));
1601     }
1602     else if (key_info->flags & HA_NOSAME)
1603       packet->append(STRING_WITH_LEN("UNIQUE KEY "));
1604     else if (key_info->flags & HA_FULLTEXT)
1605       packet->append(STRING_WITH_LEN("FULLTEXT KEY "));
1606     else if (key_info->flags & HA_SPATIAL)
1607       packet->append(STRING_WITH_LEN("SPATIAL KEY "));
1608     else
1609       packet->append(STRING_WITH_LEN("KEY "));
1610 
1611     if (!found_primary)
1612      append_identifier(thd, packet, key_info->name, strlen(key_info->name));
1613 
1614     packet->append(STRING_WITH_LEN(" ("));
1615 
1616     for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++)
1617     {
1618       if (j)
1619         packet->append(',');
1620 
1621       if (key_part->field)
1622         append_identifier(thd,packet,key_part->field->field_name,
1623 			  strlen(key_part->field->field_name));
1624       if (key_part->field &&
1625           (key_part->length !=
1626            table->field[key_part->fieldnr-1]->key_length() &&
1627            !(key_info->flags & (HA_FULLTEXT | HA_SPATIAL))))
1628       {
1629         packet->append_parenthesized((long) key_part->length /
1630                                       key_part->field->charset()->mbmaxlen);
1631       }
1632     }
1633     packet->append(')');
1634     store_key_options(thd, packet, table, key_info);
1635     if (key_info->parser)
1636     {
1637       LEX_STRING *parser_name= plugin_name(key_info->parser);
1638       packet->append(STRING_WITH_LEN(" /*!50100 WITH PARSER "));
1639       append_identifier(thd, packet, parser_name->str, parser_name->length);
1640       packet->append(STRING_WITH_LEN(" */ "));
1641     }
1642   }
1643 
1644   /*
1645     Get possible foreign key definitions stored in InnoDB and append them
1646     to the CREATE TABLE statement
1647   */
1648 
1649   if ((for_str= file->get_foreign_key_create_info()))
1650   {
1651     packet->append(for_str, strlen(for_str));
1652     file->free_foreign_key_create_info(for_str);
1653   }
1654 
1655   packet->append(STRING_WITH_LEN("\n)"));
1656   if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
1657   {
1658 #ifdef WITH_PARTITION_STORAGE_ENGINE
1659     show_table_options= TRUE;
1660 #endif /* WITH_PARTITION_STORAGE_ENGINE */
1661 
1662     /* TABLESPACE and STORAGE */
1663     if (share->tablespace ||
1664         share->default_storage_media != HA_SM_DEFAULT)
1665     {
1666       packet->append(STRING_WITH_LEN(" /*!50100"));
1667       if (share->tablespace)
1668       {
1669         packet->append(STRING_WITH_LEN(" TABLESPACE "));
1670         packet->append(share->tablespace, strlen(share->tablespace));
1671       }
1672 
1673       if (share->default_storage_media == HA_SM_DISK)
1674         packet->append(STRING_WITH_LEN(" STORAGE DISK"));
1675       if (share->default_storage_media == HA_SM_MEMORY)
1676         packet->append(STRING_WITH_LEN(" STORAGE MEMORY"));
1677 
1678       packet->append(STRING_WITH_LEN(" */"));
1679     }
1680 
1681     /*
1682       IF   check_create_info
1683       THEN add ENGINE only if it was used when creating the table
1684     */
1685     if (!create_info_arg ||
1686         (create_info_arg->used_fields & HA_CREATE_USED_ENGINE))
1687     {
1688       if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
1689         packet->append(STRING_WITH_LEN(" TYPE="));
1690       else
1691         packet->append(STRING_WITH_LEN(" ENGINE="));
1692 #ifdef WITH_PARTITION_STORAGE_ENGINE
1693     if (table->part_info)
1694       packet->append(ha_resolve_storage_engine_name(
1695                         table->part_info->default_engine_type));
1696     else
1697       packet->append(file->table_type());
1698 #else
1699       packet->append(file->table_type());
1700 #endif
1701     }
1702 
1703     /*
1704       Add AUTO_INCREMENT=... if there is an AUTO_INCREMENT column,
1705       and NEXT_ID > 1 (the default).  We must not print the clause
1706       for engines that do not support this as it would break the
1707       import of dumps, but as of this writing, the test for whether
1708       AUTO_INCREMENT columns are allowed and wether AUTO_INCREMENT=...
1709       is supported is identical, !(file->table_flags() & HA_NO_AUTO_INCREMENT))
1710       Because of that, we do not explicitly test for the feature,
1711       but may extrapolate its existence from that of an AUTO_INCREMENT column.
1712     */
1713 
1714     if (create_info.auto_increment_value > 1)
1715     {
1716       char *end;
1717       packet->append(STRING_WITH_LEN(" AUTO_INCREMENT="));
1718       end= longlong10_to_str(create_info.auto_increment_value, buff,10);
1719       packet->append(buff, (uint) (end - buff));
1720     }
1721 
1722     if (share->table_charset &&
1723 	!(thd->variables.sql_mode & MODE_MYSQL323) &&
1724 	!(thd->variables.sql_mode & MODE_MYSQL40))
1725     {
1726       /*
1727         IF   check_create_info
1728         THEN add DEFAULT CHARSET only if it was used when creating the table
1729       */
1730       if (!create_info_arg ||
1731           (create_info_arg->used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
1732       {
1733         packet->append(STRING_WITH_LEN(" DEFAULT CHARSET="));
1734         packet->append(share->table_charset->csname);
1735         if (!(share->table_charset->state & MY_CS_PRIMARY))
1736         {
1737           packet->append(STRING_WITH_LEN(" COLLATE="));
1738           packet->append(table->s->table_charset->name);
1739         }
1740       }
1741     }
1742 
1743     if (share->min_rows)
1744     {
1745       char *end;
1746       packet->append(STRING_WITH_LEN(" MIN_ROWS="));
1747       end= longlong10_to_str(share->min_rows, buff, 10);
1748       packet->append(buff, (uint) (end- buff));
1749     }
1750 
1751     if (share->max_rows && !table_list->schema_table)
1752     {
1753       char *end;
1754       packet->append(STRING_WITH_LEN(" MAX_ROWS="));
1755       end= longlong10_to_str(share->max_rows, buff, 10);
1756       packet->append(buff, (uint) (end - buff));
1757     }
1758 
1759     if (share->avg_row_length)
1760     {
1761       char *end;
1762       packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH="));
1763       end= longlong10_to_str(share->avg_row_length, buff,10);
1764       packet->append(buff, (uint) (end - buff));
1765     }
1766 
1767     if (share->db_create_options & HA_OPTION_PACK_KEYS)
1768       packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
1769     if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
1770       packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
1771     if (share->db_create_options & HA_OPTION_STATS_PERSISTENT)
1772       packet->append(STRING_WITH_LEN(" STATS_PERSISTENT=1"));
1773     if (share->db_create_options & HA_OPTION_NO_STATS_PERSISTENT)
1774       packet->append(STRING_WITH_LEN(" STATS_PERSISTENT=0"));
1775     if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON)
1776       packet->append(STRING_WITH_LEN(" STATS_AUTO_RECALC=1"));
1777     else if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF)
1778       packet->append(STRING_WITH_LEN(" STATS_AUTO_RECALC=0"));
1779     if (share->stats_sample_pages != 0)
1780     {
1781       char *end;
1782       packet->append(STRING_WITH_LEN(" STATS_SAMPLE_PAGES="));
1783       end= longlong10_to_str(share->stats_sample_pages, buff, 10);
1784       packet->append(buff, (uint) (end - buff));
1785     }
1786     /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
1787     if (share->db_create_options & HA_OPTION_CHECKSUM)
1788       packet->append(STRING_WITH_LEN(" CHECKSUM=1"));
1789     if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
1790       packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1"));
1791     if (create_info.row_type != ROW_TYPE_DEFAULT)
1792     {
1793       packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
1794       packet->append(ha_row_type[(uint) create_info.row_type]);
1795     }
1796     if (table->s->key_block_size)
1797     {
1798       char *end;
1799       packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
1800       end= longlong10_to_str(table->s->key_block_size, buff, 10);
1801       packet->append(buff, (uint) (end - buff));
1802     }
1803     table->file->append_create_info(packet);
1804     if (share->comment.length)
1805     {
1806       packet->append(STRING_WITH_LEN(" COMMENT="));
1807       append_unescaped(packet, share->comment.str, share->comment.length);
1808     }
1809     if (share->connect_string.length)
1810     {
1811       packet->append(STRING_WITH_LEN(" CONNECTION="));
1812       append_unescaped(packet, share->connect_string.str, share->connect_string.length);
1813     }
1814     append_directory(thd, packet, "DATA",  create_info.data_file_name);
1815     append_directory(thd, packet, "INDEX", create_info.index_file_name);
1816   }
1817 #ifdef WITH_PARTITION_STORAGE_ENGINE
1818   {
1819     if (table->part_info &&
1820         !((table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION) &&
1821           table->part_info->is_auto_partitioned))
1822     {
1823       /*
1824         Partition syntax for CREATE TABLE is at the end of the syntax.
1825       */
1826       uint part_syntax_len;
1827       char *part_syntax;
1828       String comment_start;
1829       table->part_info->set_show_version_string(&comment_start);
1830       if ((part_syntax= generate_partition_syntax(table->part_info,
1831                                                   &part_syntax_len,
1832                                                   FALSE,
1833                                                   show_table_options,
1834                                                   NULL, NULL,
1835                                                   comment_start.c_ptr())))
1836       {
1837          packet->append(comment_start);
1838          if (packet->append(part_syntax, part_syntax_len) ||
1839              packet->append(STRING_WITH_LEN(" */")))
1840           error= 1;
1841          my_free(part_syntax);
1842       }
1843     }
1844   }
1845 #endif
1846   tmp_restore_column_map(table->read_set, old_map);
1847   DBUG_RETURN(error);
1848 }
1849 
1850 
store_key_options(THD * thd,String * packet,TABLE * table,KEY * key_info)1851 static void store_key_options(THD *thd, String *packet, TABLE *table,
1852                               KEY *key_info)
1853 {
1854   bool limited_mysql_mode= (thd->variables.sql_mode &
1855                             (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
1856                              MODE_MYSQL40)) != 0;
1857   bool foreign_db_mode=  (thd->variables.sql_mode & (MODE_POSTGRESQL |
1858                                                      MODE_ORACLE |
1859                                                      MODE_MSSQL |
1860                                                      MODE_DB2 |
1861                                                      MODE_MAXDB |
1862                                                      MODE_ANSI)) != 0;
1863   char *end, buff[32];
1864 
1865   if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) &&
1866       !limited_mysql_mode && !foreign_db_mode)
1867   {
1868 
1869     if (key_info->algorithm == HA_KEY_ALG_BTREE)
1870       packet->append(STRING_WITH_LEN(" USING BTREE"));
1871 
1872     if (key_info->algorithm == HA_KEY_ALG_HASH)
1873       packet->append(STRING_WITH_LEN(" USING HASH"));
1874 
1875     /* send USING only in non-default case: non-spatial rtree */
1876     if ((key_info->algorithm == HA_KEY_ALG_RTREE) &&
1877         !(key_info->flags & HA_SPATIAL))
1878       packet->append(STRING_WITH_LEN(" USING RTREE"));
1879 
1880     if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
1881         table->s->key_block_size != key_info->block_size)
1882     {
1883       packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
1884       end= longlong10_to_str(key_info->block_size, buff, 10);
1885       packet->append(buff, (uint) (end - buff));
1886     }
1887     DBUG_ASSERT(MY_TEST(key_info->flags & HA_USES_COMMENT) ==
1888                (key_info->comment.length > 0));
1889     if (key_info->flags & HA_USES_COMMENT)
1890     {
1891       packet->append(STRING_WITH_LEN(" COMMENT "));
1892       append_unescaped(packet, key_info->comment.str,
1893                        key_info->comment.length);
1894     }
1895   }
1896 }
1897 
1898 
1899 void
view_store_options(THD * thd,TABLE_LIST * table,String * buff)1900 view_store_options(THD *thd, TABLE_LIST *table, String *buff)
1901 {
1902   append_algorithm(table, buff);
1903   append_definer(thd, buff, &table->definer.user, &table->definer.host);
1904   if (table->view_suid)
1905     buff->append(STRING_WITH_LEN("SQL SECURITY DEFINER "));
1906   else
1907     buff->append(STRING_WITH_LEN("SQL SECURITY INVOKER "));
1908 }
1909 
1910 
1911 /*
1912   Append DEFINER clause to the given buffer.
1913 
1914   SYNOPSIS
1915     append_definer()
1916     thd           [in] thread handle
1917     buffer        [inout] buffer to hold DEFINER clause
1918     definer_user  [in] user name part of definer
1919     definer_host  [in] host name part of definer
1920 */
1921 
append_algorithm(TABLE_LIST * table,String * buff)1922 static void append_algorithm(TABLE_LIST *table, String *buff)
1923 {
1924   buff->append(STRING_WITH_LEN("ALGORITHM="));
1925   switch ((int8)table->algorithm) {
1926   case VIEW_ALGORITHM_UNDEFINED:
1927     buff->append(STRING_WITH_LEN("UNDEFINED "));
1928     break;
1929   case VIEW_ALGORITHM_TMPTABLE:
1930     buff->append(STRING_WITH_LEN("TEMPTABLE "));
1931     break;
1932   case VIEW_ALGORITHM_MERGE:
1933     buff->append(STRING_WITH_LEN("MERGE "));
1934     break;
1935   default:
1936     DBUG_ASSERT(0); // never should happen
1937   }
1938 }
1939 
1940 /*
1941   Append DEFINER clause to the given buffer.
1942 
1943   SYNOPSIS
1944     append_definer()
1945     thd           [in] thread handle
1946     buffer        [inout] buffer to hold DEFINER clause
1947     definer_user  [in] user name part of definer
1948     definer_host  [in] host name part of definer
1949 */
1950 
append_definer(THD * thd,String * buffer,const LEX_STRING * definer_user,const LEX_STRING * definer_host)1951 void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user,
1952                     const LEX_STRING *definer_host)
1953 {
1954   buffer->append(STRING_WITH_LEN("DEFINER="));
1955   append_identifier(thd, buffer, definer_user->str, definer_user->length);
1956   buffer->append('@');
1957   append_identifier(thd, buffer, definer_host->str, definer_host->length);
1958   buffer->append(' ');
1959 }
1960 
1961 
1962 int
view_store_create_info(THD * thd,TABLE_LIST * table,String * buff)1963 view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
1964 {
1965   my_bool compact_view_name= TRUE;
1966   my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
1967                                                        MODE_ORACLE |
1968                                                        MODE_MSSQL |
1969                                                        MODE_DB2 |
1970                                                        MODE_MAXDB |
1971                                                        MODE_ANSI)) != 0;
1972 
1973   if (!thd->db || strcmp(thd->db, table->view_db.str))
1974     /*
1975       print compact view name if the view belongs to the current database
1976     */
1977     compact_view_name= table->compact_view_format= FALSE;
1978   else
1979   {
1980     /*
1981       Compact output format for view body can be used
1982       if this view only references table inside it's own db
1983     */
1984     TABLE_LIST *tbl;
1985     table->compact_view_format= TRUE;
1986     for (tbl= thd->lex->query_tables;
1987          tbl;
1988          tbl= tbl->next_global)
1989     {
1990       if (strcmp(table->view_db.str, tbl->view ? tbl->view_db.str :tbl->db)!= 0)
1991       {
1992         table->compact_view_format= FALSE;
1993         break;
1994       }
1995     }
1996   }
1997 
1998   buff->append(STRING_WITH_LEN("CREATE "));
1999   if (!foreign_db_mode)
2000   {
2001     view_store_options(thd, table, buff);
2002   }
2003   buff->append(STRING_WITH_LEN("VIEW "));
2004   if (!compact_view_name)
2005   {
2006     append_identifier(thd, buff, table->view_db.str, table->view_db.length);
2007     buff->append('.');
2008   }
2009   append_identifier(thd, buff, table->view_name.str, table->view_name.length);
2010   buff->append(STRING_WITH_LEN(" AS "));
2011 
2012   /*
2013     We can't just use table->query, because our SQL_MODE may trigger
2014     a different syntax, like when ANSI_QUOTES is defined.
2015   */
2016   table->view->unit.print(buff, QT_ORDINARY);
2017 
2018   if (table->with_check != VIEW_CHECK_NONE)
2019   {
2020     if (table->with_check == VIEW_CHECK_LOCAL)
2021       buff->append(STRING_WITH_LEN(" WITH LOCAL CHECK OPTION"));
2022     else
2023       buff->append(STRING_WITH_LEN(" WITH CASCADED CHECK OPTION"));
2024   }
2025   return 0;
2026 }
2027 
2028 
2029 /****************************************************************************
2030   Return info about all processes
2031   returns for each thread: thread id, user, host, db, command, info
2032 ****************************************************************************/
2033 
2034 class thread_info
2035 {
2036 public:
operator new(size_t size)2037   static void *operator new(size_t size)
2038   {
2039     return (void*) sql_alloc((uint) size);
2040   }
operator delete(void * ptr MY_ATTRIBUTE ((unused)),size_t size MY_ATTRIBUTE ((unused)))2041   static void operator delete(void *ptr MY_ATTRIBUTE((unused)),
2042                               size_t size MY_ATTRIBUTE((unused)))
2043   { TRASH(ptr, size); }
2044 
2045   ulong thread_id;
2046   time_t start_time;
2047   uint   command;
2048   const char *user,*host,*db,*proc_info,*state_info;
2049   CSET_STRING query_string;
2050 };
2051 
2052 // For sorting by thread_id.
2053 class thread_info_compare :
2054   public std::binary_function<const thread_info*, const thread_info*, bool>
2055 {
2056 public:
operator ()(const thread_info * p1,const thread_info * p2)2057   bool operator() (const thread_info* p1, const thread_info* p2)
2058   {
2059     return p1->thread_id < p2->thread_id;
2060   }
2061 };
2062 
thread_state_info(THD * tmp)2063 static const char *thread_state_info(THD *tmp)
2064 {
2065 #ifndef EMBEDDED_LIBRARY
2066   if (tmp->net.reading_or_writing)
2067   {
2068     if (tmp->net.reading_or_writing == 2)
2069       return "Writing to net";
2070     else if (tmp->get_command() == COM_SLEEP)
2071       return "";
2072     else
2073       return "Reading from net";
2074   }
2075   else
2076 #endif
2077   {
2078     if (tmp->proc_info)
2079       return tmp->proc_info;
2080     else if (tmp->mysys_var && tmp->mysys_var->current_cond)
2081       return "Waiting on cond";
2082     else
2083       return NULL;
2084   }
2085 }
2086 
mysqld_list_processes(THD * thd,const char * user,bool verbose)2087 void mysqld_list_processes(THD *thd,const char *user, bool verbose)
2088 {
2089   Item *field;
2090   List<Item> field_list;
2091   Mem_root_array<thread_info*, true> thread_infos(thd->mem_root);
2092   ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
2093 			   PROCESS_LIST_WIDTH);
2094   Protocol *protocol= thd->protocol;
2095   DBUG_ENTER("mysqld_list_processes");
2096 
2097   field_list.push_back(new Item_int(NAME_STRING("Id"), 0, MY_INT64_NUM_DECIMAL_DIGITS));
2098   field_list.push_back(new Item_empty_string("User",16));
2099   field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
2100   field_list.push_back(field=new Item_empty_string("db",NAME_CHAR_LEN));
2101   field->maybe_null=1;
2102   field_list.push_back(new Item_empty_string("Command",16));
2103   field_list.push_back(field= new Item_return_int("Time",7, MYSQL_TYPE_LONG));
2104   field->unsigned_flag= 0;
2105   field_list.push_back(field=new Item_empty_string("State",30));
2106   field->maybe_null=1;
2107   field_list.push_back(field=new Item_empty_string("Info",max_query_length));
2108   field->maybe_null=1;
2109   if (protocol->send_result_set_metadata(&field_list,
2110                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
2111     DBUG_VOID_RETURN;
2112 
2113   if (!thd->killed)
2114   {
2115     /* take copy of global_thread_list */
2116     std::set<THD*> global_thread_list_copy;
2117     DEBUG_SYNC(thd,"before_copying_threads");
2118     /*
2119       Allow inserts to global_thread_list. Newly added thd
2120       will not be accounted for `show processlist` and
2121       removal from global_thread_list is blocked as LOCK_thd_remove
2122       mutex is not released yet
2123      */
2124     mysql_mutex_lock(&LOCK_thd_remove);
2125     copy_global_thread_list(&global_thread_list_copy);
2126 
2127     DEBUG_SYNC(thd,"after_copying_threads");
2128     thread_infos.reserve(get_thread_count());
2129     Thread_iterator it= global_thread_list_copy.begin();
2130     Thread_iterator end= global_thread_list_copy.end();
2131     for (; it != end; ++it)
2132     {
2133       THD *tmp= *it;
2134       Security_context *tmp_sctx= tmp->security_ctx;
2135       struct st_my_thread_var *mysys_var;
2136       if ((tmp->vio_ok() || tmp->system_thread) &&
2137           (!user || (!tmp->system_thread && tmp_sctx->user &&
2138                      !strcmp(tmp_sctx->user, user))))
2139       {
2140         thread_info *thd_info= new thread_info;
2141 
2142         thd_info->thread_id=tmp->thread_id;
2143         thd_info->user= thd->strdup(tmp_sctx->user ? tmp_sctx->user :
2144                                     (tmp->system_thread ?
2145                                      "system user" : "unauthenticated user"));
2146 	if (tmp->peer_port && (tmp_sctx->get_host()->length() ||
2147             tmp_sctx->get_ip()->length()) && thd->security_ctx->host_or_ip[0])
2148 	{
2149 	  if ((thd_info->host= (char*) thd->alloc(LIST_PROCESS_HOST_LEN+1)))
2150 	    my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN,
2151 			"%s:%u", tmp_sctx->host_or_ip, tmp->peer_port);
2152 	}
2153 	else
2154 	  thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ?
2155                                       tmp_sctx->host_or_ip :
2156                                       tmp_sctx->get_host()->length() ?
2157                                       tmp_sctx->get_host()->ptr() : "");
2158         thd_info->command=(int) tmp->get_command();
2159         DBUG_EXECUTE_IF("processlist_acquiring_dump_threads_LOCK_thd_data",
2160                         {
2161                          if (thd_info->command == COM_BINLOG_DUMP ||
2162                              thd_info->command == COM_BINLOG_DUMP_GTID)
2163                            DEBUG_SYNC(thd, "processlist_after_LOCK_thd_count_before_LOCK_thd_data");
2164                         });
2165         mysql_mutex_lock(&tmp->LOCK_thd_data);
2166         if ((thd_info->db= tmp->db))             // Safe test
2167           thd_info->db= thd->strdup(thd_info->db);
2168         if ((mysys_var= tmp->mysys_var))
2169           mysql_mutex_lock(&mysys_var->mutex);
2170         thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0);
2171         thd_info->state_info= thread_state_info(tmp);
2172         if (mysys_var)
2173           mysql_mutex_unlock(&mysys_var->mutex);
2174 
2175         /* Lock THD mutex that protects its data when looking at it. */
2176         if (tmp->query())
2177         {
2178           const char *query_str;
2179           size_t query_length;
2180           if ((query_length = tmp->rewritten_query.length()) > 0) {
2181             query_str = tmp->rewritten_query.c_ptr();
2182           } else {
2183             query_length = tmp->query_length();
2184             query_str = tmp->query();
2185           }
2186 
2187           uint length= min<uint>(max_query_length, query_length);
2188           char *q= thd->strmake(query_str, length);
2189           /* Safety: in case strmake failed, we set length to 0. */
2190           thd_info->query_string=
2191             CSET_STRING(q, q ? length : 0, tmp->query_charset());
2192         }
2193         mysql_mutex_unlock(&tmp->LOCK_thd_data);
2194         thd_info->start_time= tmp->start_time.tv_sec;
2195         thread_infos.push_back(thd_info);
2196       }
2197     }
2198     mysql_mutex_unlock(&LOCK_thd_remove);
2199   }
2200 
2201   // Return list sorted by thread_id.
2202   std::sort(thread_infos.begin(), thread_infos.end(), thread_info_compare());
2203 
2204   time_t now= my_time(0);
2205   for (size_t ix= 0; ix < thread_infos.size(); ++ix)
2206   {
2207     thread_info *thd_info= thread_infos.at(ix);
2208     protocol->prepare_for_resend();
2209     protocol->store((ulonglong) thd_info->thread_id);
2210     protocol->store(thd_info->user, system_charset_info);
2211     protocol->store(thd_info->host, system_charset_info);
2212     protocol->store(thd_info->db, system_charset_info);
2213     if (thd_info->proc_info)
2214       protocol->store(thd_info->proc_info, system_charset_info);
2215     else
2216       protocol->store(command_name[thd_info->command].str, system_charset_info);
2217     if (thd_info->start_time)
2218       protocol->store_long ((longlong) (now - thd_info->start_time));
2219     else
2220       protocol->store_null();
2221     protocol->store(thd_info->state_info, system_charset_info);
2222     protocol->store(thd_info->query_string.str(),
2223                     thd_info->query_string.charset());
2224     if (protocol->write())
2225       break; /* purecov: inspected */
2226   }
2227   my_eof(thd);
2228   DBUG_VOID_RETURN;
2229 }
2230 
fill_schema_processlist(THD * thd,TABLE_LIST * tables,Item * cond)2231 int fill_schema_processlist(THD* thd, TABLE_LIST* tables, Item* cond)
2232 {
2233   TABLE *table= tables->table;
2234   CHARSET_INFO *cs= system_charset_info;
2235   char *user;
2236   time_t now= my_time(0);
2237   DBUG_ENTER("fill_process_list");
2238 
2239   user= thd->security_ctx->master_access & PROCESS_ACL ?
2240         NullS : thd->security_ctx->priv_user;
2241 
2242   if (!thd->killed)
2243   {
2244     /* take copy of global_thread_list */
2245     std::set<THD*> global_thread_list_copy;
2246     /*
2247       Allow inserts to global_thread_list. Newly added thd
2248       will not be accounted for `fill schema processlist` and
2249       removal from global_thread_list is blocked as LOCK_thd_remove
2250       mutex is not released yet
2251      */
2252     mysql_mutex_lock(&LOCK_thd_remove);
2253     copy_global_thread_list(&global_thread_list_copy);
2254 
2255     DEBUG_SYNC(thd,"fill_schema_processlist_after_copying_threads");
2256 
2257     Thread_iterator it= global_thread_list_copy.begin();
2258     Thread_iterator end= global_thread_list_copy.end();
2259     for (; it != end; ++it)
2260     {
2261       THD* tmp= *it;
2262       Security_context *tmp_sctx= tmp->security_ctx;
2263       struct st_my_thread_var *mysys_var;
2264       const char *val, *db;
2265 
2266       if ((!tmp->vio_ok() && !tmp->system_thread) ||
2267           (user && (tmp->system_thread || !tmp_sctx->user ||
2268                     strcmp(tmp_sctx->user, user))))
2269         continue;
2270 
2271       restore_record(table, s->default_values);
2272       /* ID */
2273 
2274       table->field[0]->store((ulonglong) tmp->thread_id, TRUE);
2275       /* USER */
2276       val= tmp_sctx->user ? tmp_sctx->user :
2277             (tmp->system_thread ? "system user" : "unauthenticated user");
2278       table->field[1]->store(val, strlen(val), cs);
2279       /* HOST */
2280       if (tmp->peer_port && (tmp_sctx->get_host()->length() ||
2281           tmp_sctx->get_ip()->length()) && thd->security_ctx->host_or_ip[0])
2282       {
2283         char host[LIST_PROCESS_HOST_LEN + 1];
2284         my_snprintf(host, LIST_PROCESS_HOST_LEN, "%s:%u",
2285                     tmp_sctx->host_or_ip, tmp->peer_port);
2286         table->field[2]->store(host, strlen(host), cs);
2287       }
2288       else
2289         table->field[2]->store(tmp_sctx->host_or_ip,
2290                                strlen(tmp_sctx->host_or_ip), cs);
2291       DBUG_EXECUTE_IF("processlist_acquiring_dump_threads_LOCK_thd_data",
2292                       {
2293                       if (tmp->get_command() == COM_BINLOG_DUMP ||
2294                           tmp->get_command() == COM_BINLOG_DUMP_GTID)
2295                       DEBUG_SYNC(thd, "processlist_after_LOCK_thd_count_before_LOCK_thd_data");
2296                       });
2297       /* DB */
2298       mysql_mutex_lock(&tmp->LOCK_thd_data);
2299       if ((db= tmp->db))
2300       {
2301         table->field[3]->store(db, strlen(db), cs);
2302         table->field[3]->set_notnull();
2303       }
2304 
2305       if ((mysys_var= tmp->mysys_var))
2306         mysql_mutex_lock(&mysys_var->mutex);
2307       /* COMMAND */
2308       if ((val= (char *) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0)))
2309         table->field[4]->store(val, strlen(val), cs);
2310       else
2311         table->field[4]->store(command_name[tmp->get_command()].str,
2312                                command_name[tmp->get_command()].length, cs);
2313       /* MYSQL_TIME */
2314       table->field[5]->store((longlong)(tmp->start_time.tv_sec ?
2315                                       now - tmp->start_time.tv_sec : 0), FALSE);
2316       /* STATE */
2317       if ((val= thread_state_info(tmp)))
2318       {
2319         table->field[6]->store(val, strlen(val), cs);
2320         table->field[6]->set_notnull();
2321       }
2322 
2323       if (mysys_var)
2324         mysql_mutex_unlock(&mysys_var->mutex);
2325       /* INFO */
2326       if (tmp->query())
2327       {
2328         const char *query_str;
2329         size_t query_length;
2330 
2331         if ((query_length = tmp->rewritten_query.length()) > 0) {
2332           query_str = tmp->rewritten_query.c_ptr();
2333         } else {
2334           query_length = tmp->query_length();
2335           query_str = tmp->query();
2336         }
2337         size_t const width=
2338           min<size_t>(PROCESS_LIST_INFO_WIDTH, query_length);
2339         table->field[7]->store(query_str, width, cs);
2340         table->field[7]->set_notnull();
2341       }
2342       mysql_mutex_unlock(&tmp->LOCK_thd_data);
2343 
2344       if (schema_table_store_record(thd, table))
2345       {
2346         mysql_mutex_unlock(&LOCK_thd_remove);
2347         DBUG_RETURN(1);
2348       }
2349     }
2350     mysql_mutex_unlock(&LOCK_thd_remove);
2351   }
2352 
2353   DBUG_RETURN(0);
2354 }
2355 
2356 /*****************************************************************************
2357   Status functions
2358 *****************************************************************************/
2359 
2360 static DYNAMIC_ARRAY all_status_vars;
2361 static bool status_vars_inited= 0;
2362 
2363 C_MODE_START
show_var_cmp(const void * var1,const void * var2)2364 static int show_var_cmp(const void *var1, const void *var2)
2365 {
2366   return strcmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
2367 }
2368 C_MODE_END
2369 
2370 /*
2371   deletes all the SHOW_UNDEF elements from the array and calls
2372   delete_dynamic() if it's completely empty.
2373 */
shrink_var_array(DYNAMIC_ARRAY * array)2374 static void shrink_var_array(DYNAMIC_ARRAY *array)
2375 {
2376   uint a,b;
2377   SHOW_VAR *all= dynamic_element(array, 0, SHOW_VAR *);
2378 
2379   for (a= b= 0; b < array->elements; b++)
2380     if (all[b].type != SHOW_UNDEF)
2381       all[a++]= all[b];
2382   if (a)
2383   {
2384     memset(all+a, 0, sizeof(SHOW_VAR)); // writing NULL-element to the end
2385     array->elements= a;
2386   }
2387   else // array is completely empty - delete it
2388     delete_dynamic(array);
2389 }
2390 
2391 /*
2392   Adds an array of SHOW_VAR entries to the output of SHOW STATUS
2393 
2394   SYNOPSIS
2395     add_status_vars(SHOW_VAR *list)
2396     list - an array of SHOW_VAR entries to add to all_status_vars
2397            the last entry must be {0,0,SHOW_UNDEF}
2398 
2399   NOTE
2400     The handling of all_status_vars[] is completely internal, it's allocated
2401     automatically when something is added to it, and deleted completely when
2402     the last entry is removed.
2403 
2404     As a special optimization, if add_status_vars() is called before
2405     init_status_vars(), it assumes "startup mode" - neither concurrent access
2406     to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
2407 
2408     The last entry of the all_status_vars[] should always be {0,0,SHOW_UNDEF}
2409 */
add_status_vars(SHOW_VAR * list)2410 int add_status_vars(SHOW_VAR *list)
2411 {
2412   int res= 0;
2413   if (status_vars_inited)
2414     mysql_mutex_lock(&LOCK_status);
2415   if (!all_status_vars.buffer && // array is not allocated yet - do it now
2416       my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20))
2417   {
2418     res= 1;
2419     goto err;
2420   }
2421   while (list->name)
2422     res|= insert_dynamic(&all_status_vars, list++);
2423   res|= insert_dynamic(&all_status_vars, list); // appending NULL-element
2424   all_status_vars.elements--; // but next insert_dynamic should overwite it
2425   if (status_vars_inited)
2426     sort_dynamic(&all_status_vars, show_var_cmp);
2427 err:
2428   if (status_vars_inited)
2429     mysql_mutex_unlock(&LOCK_status);
2430   return res;
2431 }
2432 
2433 /*
2434   Make all_status_vars[] usable for SHOW STATUS
2435 
2436   NOTE
2437     See add_status_vars(). Before init_status_vars() call, add_status_vars()
2438     works in a special fast "startup" mode. Thus init_status_vars()
2439     should be called as late as possible but before enabling multi-threading.
2440 */
init_status_vars()2441 void init_status_vars()
2442 {
2443   status_vars_inited=1;
2444   sort_dynamic(&all_status_vars, show_var_cmp);
2445 }
2446 
reset_status_vars()2447 void reset_status_vars()
2448 {
2449   SHOW_VAR *ptr= (SHOW_VAR*) all_status_vars.buffer;
2450   SHOW_VAR *last= ptr + all_status_vars.elements;
2451   for (; ptr < last; ptr++)
2452   {
2453     /* Note that SHOW_LONG_NOFLUSH variables are not reset */
2454     if (ptr->type == SHOW_LONG || ptr->type == SHOW_SIGNED_LONG)
2455       *(ulong*) ptr->value= 0;
2456   }
2457 }
2458 
2459 /*
2460   catch-all cleanup function, cleans up everything no matter what
2461 
2462   DESCRIPTION
2463     This function is not strictly required if all add_to_status/
2464     remove_status_vars are properly paired, but it's a safety measure that
2465     deletes everything from the all_status_vars[] even if some
2466     remove_status_vars were forgotten
2467 */
free_status_vars()2468 void free_status_vars()
2469 {
2470   delete_dynamic(&all_status_vars);
2471 }
2472 
2473 /**
2474   @brief           Get the value of given status variable
2475 
2476   @param[in]       thd        thread handler
2477   @param[in]       list       list of SHOW_VAR objects in which function should
2478                               search
2479   @param[in]       name       name of the status variable
2480   @param[in/out]   value      buffer in which value of the status variable
2481                               needs to be filled in
2482 
2483   @return          status
2484     @retval        FALSE      if variable is not found in the list
2485     @retval        TRUE       if variable is found in the list
2486   NOTE: Currently this function is implemented just to support 'bool' status
2487   variables and 'long' status variables *only*. It can be extended very easily
2488   for further show_types in future if required.
2489   TODO: Currently show_status_arary switch case is tightly coupled with
2490   pos, end, buff, value variables and also it stores the values in a 'table'.
2491   Decouple the switch case to fill the buffer value so that it can be used
2492   in show_status_array() and get_status_var() to avoid duplicate code.
2493  */
2494 
get_status_var(THD * thd,SHOW_VAR * list,const char * name,char * const value)2495 bool get_status_var(THD* thd, SHOW_VAR *list, const char * name, char * const value)
2496 {
2497   for (; list->name; list++)
2498   {
2499     int res= strcmp(list->name, name);
2500     if (res == 0)
2501     {
2502       /*
2503         if var->type is SHOW_FUNC, call the function.
2504         Repeat as necessary, if new var is again SHOW_FUNC
2505       */
2506       SHOW_VAR tmp;
2507       for (; list->type == SHOW_FUNC; list= &tmp)
2508         ((mysql_show_var_func)(list->value))(thd, &tmp, value);
2509       switch (list->type) {
2510       case SHOW_BOOL:
2511         strmov(value, *(bool*) list->value ? "ON" : "OFF");
2512         break;
2513       case SHOW_LONG:
2514         int10_to_str(*(long*) list->value, value, 10);
2515         break;
2516       default:
2517         /* not supported type */
2518         DBUG_ASSERT(0);
2519       }
2520       return TRUE;
2521     }
2522   }
2523   return FALSE;
2524 }
2525 
2526 /*
2527   Removes an array of SHOW_VAR entries from the output of SHOW STATUS
2528 
2529   SYNOPSIS
2530     remove_status_vars(SHOW_VAR *list)
2531     list - an array of SHOW_VAR entries to remove to all_status_vars
2532            the last entry must be {0,0,SHOW_UNDEF}
2533 
2534   NOTE
2535     there's lots of room for optimizing this, especially in non-sorted mode,
2536     but nobody cares - it may be called only in case of failed plugin
2537     initialization in the mysqld startup.
2538 */
2539 
remove_status_vars(SHOW_VAR * list)2540 void remove_status_vars(SHOW_VAR *list)
2541 {
2542   if (status_vars_inited)
2543   {
2544     mysql_mutex_lock(&LOCK_status);
2545     SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
2546     int a= 0, b= all_status_vars.elements, c= (a+b)/2;
2547 
2548     for (; list->name; list++)
2549     {
2550       int res= 0;
2551       for (a= 0, b= all_status_vars.elements; b-a > 1; c= (a+b)/2)
2552       {
2553         res= show_var_cmp(list, all+c);
2554         if (res < 0)
2555           b= c;
2556         else if (res > 0)
2557           a= c;
2558         else
2559           break;
2560       }
2561       if (res == 0)
2562         all[c].type= SHOW_UNDEF;
2563     }
2564     shrink_var_array(&all_status_vars);
2565     mysql_mutex_unlock(&LOCK_status);
2566   }
2567   else
2568   {
2569     SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
2570     uint i;
2571     for (; list->name; list++)
2572     {
2573       for (i= 0; i < all_status_vars.elements; i++)
2574       {
2575         if (show_var_cmp(list, all+i))
2576           continue;
2577         all[i].type= SHOW_UNDEF;
2578         break;
2579       }
2580     }
2581     shrink_var_array(&all_status_vars);
2582   }
2583 }
2584 
make_upper(char * buf)2585 inline void make_upper(char *buf)
2586 {
2587   for (; *buf; buf++)
2588     *buf= my_toupper(system_charset_info, *buf);
2589 }
2590 
show_status_array(THD * thd,const char * wild,SHOW_VAR * variables,enum enum_var_type value_type,struct system_status_var * status_var,const char * prefix,TABLE * table,bool ucase_names,Item * cond)2591 static bool show_status_array(THD *thd, const char *wild,
2592                               SHOW_VAR *variables,
2593                               enum enum_var_type value_type,
2594                               struct system_status_var *status_var,
2595                               const char *prefix, TABLE *table,
2596                               bool ucase_names,
2597                               Item *cond)
2598 {
2599   my_aligned_storage<SHOW_VAR_FUNC_BUFF_SIZE, MY_ALIGNOF(long)> buffer;
2600   char * const buff= buffer.data;
2601   char *prefix_end;
2602   /* the variable name should not be longer than 64 characters */
2603   char name_buffer[64];
2604   int len;
2605   LEX_STRING null_lex_str;
2606   SHOW_VAR tmp, *var;
2607   Item *partial_cond= 0;
2608   enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
2609   bool res= FALSE;
2610   const CHARSET_INFO *charset= system_charset_info;
2611   DBUG_ENTER("show_status_array");
2612 
2613   thd->count_cuted_fields= CHECK_FIELD_WARN;
2614   null_lex_str.str= 0;				// For sys_var->value_ptr()
2615   null_lex_str.length= 0;
2616 
2617   prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1);
2618   if (*prefix)
2619     *prefix_end++= '_';
2620   len=name_buffer + sizeof(name_buffer) - prefix_end;
2621   partial_cond= make_cond_for_info_schema(cond, table->pos_in_table_list);
2622 
2623   for (; variables->name; variables++)
2624   {
2625     strnmov(prefix_end, variables->name, len);
2626     name_buffer[sizeof(name_buffer)-1]=0;       /* Safety */
2627     if (ucase_names)
2628       make_upper(name_buffer);
2629 
2630     restore_record(table, s->default_values);
2631     table->field[0]->store(name_buffer, strlen(name_buffer),
2632                            system_charset_info);
2633     /*
2634       if var->type is SHOW_FUNC, call the function.
2635       Repeat as necessary, if new var is again SHOW_FUNC
2636     */
2637     for (var=variables; var->type == SHOW_FUNC; var= &tmp)
2638       ((mysql_show_var_func)(var->value))(thd, &tmp, buff);
2639 
2640     SHOW_TYPE show_type=var->type;
2641     if (show_type == SHOW_ARRAY)
2642     {
2643       show_status_array(thd, wild, (SHOW_VAR *) var->value, value_type,
2644                         status_var, name_buffer, table, ucase_names, partial_cond);
2645     }
2646     else
2647     {
2648       if (!(wild && wild[0] && wild_case_compare(system_charset_info,
2649                                                  name_buffer, wild)) &&
2650           (!partial_cond || partial_cond->val_int()))
2651       {
2652         char *value=var->value;
2653         const char *pos, *end;                  // We assign a lot of const's
2654 
2655         mysql_mutex_lock(&LOCK_global_system_variables);
2656 
2657         if (show_type == SHOW_SYS)
2658         {
2659           sys_var *var= ((sys_var *) value);
2660           show_type= var->show_type();
2661           value= (char*) var->value_ptr(thd, value_type, &null_lex_str);
2662           charset= var->charset(thd);
2663         }
2664 
2665         pos= end= buff;
2666         /*
2667           note that value may be == buff. All SHOW_xxx code below
2668           should still work in this case
2669         */
2670         switch (show_type) {
2671         case SHOW_DOUBLE_STATUS:
2672           value= ((char *) status_var + (ulong) value);
2673           /* fall through */
2674         case SHOW_DOUBLE:
2675           /* 6 is the default precision for '%f' in sprintf() */
2676           end= buff + my_fcvt(*(double *) value, 6, buff, NULL);
2677           break;
2678         case SHOW_LONG_STATUS:
2679           value= ((char *) status_var + (ulong) value);
2680           /* fall through */
2681         case SHOW_LONG:
2682         case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status()
2683           end= int10_to_str(*(long*) value, buff, 10);
2684           break;
2685         case SHOW_SIGNED_LONG:
2686           end= int10_to_str(*(long*) value, buff, -10);
2687           break;
2688         case SHOW_LONGLONG_STATUS:
2689           value= ((char *) status_var + (ulong) value);
2690           /* fall through */
2691         case SHOW_LONGLONG:
2692           end= longlong10_to_str(*(longlong*) value, buff, 10);
2693           break;
2694         case SHOW_HA_ROWS:
2695           end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
2696           break;
2697         case SHOW_BOOL:
2698           end= strmov(buff, *(bool*) value ? "ON" : "OFF");
2699           break;
2700         case SHOW_MY_BOOL:
2701           end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
2702           break;
2703         case SHOW_INT:
2704           end= int10_to_str((long) *(uint32*) value, buff, 10);
2705           break;
2706         case SHOW_HAVE:
2707         {
2708           SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
2709           pos= show_comp_option_name[(int) tmp];
2710           end= strend(pos);
2711           break;
2712         }
2713         case SHOW_CHAR:
2714         {
2715           if (!(pos= value))
2716             pos= "";
2717           end= strend(pos);
2718           break;
2719         }
2720        case SHOW_CHAR_PTR:
2721         {
2722           if (!(pos= *(char**) value))
2723             pos= "";
2724 
2725           DBUG_EXECUTE_IF("alter_server_version_str",
2726                           if (!my_strcasecmp(system_charset_info,
2727                                              variables->name,
2728                                              "version")) {
2729                             pos= "some-other-version";
2730                           });
2731 
2732           end= strend(pos);
2733           break;
2734         }
2735         case SHOW_LEX_STRING:
2736         {
2737           LEX_STRING *ls=(LEX_STRING*)value;
2738           if (!(pos= ls->str))
2739             end= pos= "";
2740           else
2741             end= pos + ls->length;
2742           break;
2743         }
2744         case SHOW_KEY_CACHE_LONG:
2745           value= (char*) dflt_key_cache + (ulong)value;
2746           end= int10_to_str(*(long*) value, buff, 10);
2747           break;
2748         case SHOW_KEY_CACHE_LONGLONG:
2749           value= (char*) dflt_key_cache + (ulong)value;
2750 	  end= longlong10_to_str(*(longlong*) value, buff, 10);
2751 	  break;
2752         case SHOW_UNDEF:
2753           break;                                        // Return empty string
2754         case SHOW_SYS:                                  // Cannot happen
2755         default:
2756           DBUG_ASSERT(0);
2757           break;
2758         }
2759         table->field[1]->store(pos, (uint32) (end - pos), charset);
2760         thd->count_cuted_fields= CHECK_FIELD_IGNORE;
2761         table->field[1]->set_notnull();
2762 
2763         mysql_mutex_unlock(&LOCK_global_system_variables);
2764 
2765         if (schema_table_store_record(thd, table))
2766         {
2767           res= TRUE;
2768           goto end;
2769         }
2770       }
2771     }
2772   }
2773 end:
2774   thd->count_cuted_fields= save_count_cuted_fields;
2775   DBUG_RETURN(res);
2776 }
2777 
2778 
2779 /* collect status for all running threads */
2780 
calc_sum_of_all_status(STATUS_VAR * to)2781 void calc_sum_of_all_status(STATUS_VAR *to)
2782 {
2783   DBUG_ENTER("calc_sum_of_all_status");
2784 
2785   mysql_mutex_lock(&LOCK_thread_count);
2786 
2787   Thread_iterator it= global_thread_list_begin();
2788   Thread_iterator end= global_thread_list_end();
2789   /* Get global values as base */
2790   *to= global_status_var;
2791 
2792   /* Add to this status from existing threads */
2793   for (; it != end; ++it)
2794     add_to_status(to, &(*it)->status_var);
2795 
2796   mysql_mutex_unlock(&LOCK_thread_count);
2797   DBUG_VOID_RETURN;
2798 }
2799 
2800 
2801 /* This is only used internally, but we need it here as a forward reference */
2802 extern ST_SCHEMA_TABLE schema_tables[];
2803 
2804 /**
2805   Condition pushdown used for INFORMATION_SCHEMA / SHOW queries.
2806   This structure is to implement an optimization when
2807   accessing data dictionary data in the INFORMATION_SCHEMA
2808   or SHOW commands.
2809   When the query contain a TABLE_SCHEMA or TABLE_NAME clause,
2810   narrow the search for data based on the constraints given.
2811 */
2812 typedef struct st_lookup_field_values
2813 {
2814   /**
2815     Value of a TABLE_SCHEMA clause.
2816     Note that this value length may exceed @c NAME_LEN.
2817     @sa wild_db_value
2818   */
2819   LEX_STRING db_value;
2820   /**
2821     Value of a TABLE_NAME clause.
2822     Note that this value length may exceed @c NAME_LEN.
2823     @sa wild_table_value
2824   */
2825   LEX_STRING table_value;
2826   /**
2827     True when @c db_value is a LIKE clause,
2828     false when @c db_value is an '=' clause.
2829   */
2830   bool wild_db_value;
2831   /**
2832     True when @c table_value is a LIKE clause,
2833     false when @c table_value is an '=' clause.
2834   */
2835   bool wild_table_value;
2836 } LOOKUP_FIELD_VALUES;
2837 
2838 
2839 /*
2840   Store record to I_S table, convert HEAP table
2841   to MyISAM if necessary
2842 
2843   SYNOPSIS
2844     schema_table_store_record()
2845     thd                   thread handler
2846     table                 Information schema table to be updated
2847 
2848   RETURN
2849     0	                  success
2850     1	                  error
2851 */
2852 
schema_table_store_record(THD * thd,TABLE * table)2853 bool schema_table_store_record(THD *thd, TABLE *table)
2854 {
2855   int error;
2856   if ((error= table->file->ha_write_row(table->record[0])))
2857   {
2858     TMP_TABLE_PARAM *param= table->pos_in_table_list->schema_table_param;
2859 
2860     if (create_myisam_from_heap(thd, table, param->start_recinfo,
2861                                 &param->recinfo, error, FALSE, NULL))
2862       return 1;
2863   }
2864   return 0;
2865 }
2866 
2867 
make_table_list(THD * thd,SELECT_LEX * sel,LEX_STRING * db_name,LEX_STRING * table_name)2868 static int make_table_list(THD *thd, SELECT_LEX *sel,
2869                            LEX_STRING *db_name, LEX_STRING *table_name)
2870 {
2871   Table_ident *table_ident;
2872   table_ident= new Table_ident(thd, *db_name, *table_name, 1);
2873   if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ, MDL_SHARED_READ))
2874     return 1;
2875   return 0;
2876 }
2877 
2878 
2879 /**
2880   @brief    Get lookup value from the part of 'WHERE' condition
2881 
2882   @details This function gets lookup value from
2883            the part of 'WHERE' condition if it's possible and
2884            fill appropriate lookup_field_vals struct field
2885            with this value.
2886 
2887   @param[in]      thd                   thread handler
2888   @param[in]      item_func             part of WHERE condition
2889   @param[in]      table                 I_S table
2890   @param[in, out] lookup_field_vals     Struct which holds lookup values
2891 
2892   @return
2893     0             success
2894     1             error, there can be no matching records for the condition
2895 */
2896 
get_lookup_value(THD * thd,Item_func * item_func,TABLE_LIST * table,LOOKUP_FIELD_VALUES * lookup_field_vals)2897 bool get_lookup_value(THD *thd, Item_func *item_func,
2898                       TABLE_LIST *table,
2899                       LOOKUP_FIELD_VALUES *lookup_field_vals)
2900 {
2901   ST_SCHEMA_TABLE *schema_table= table->schema_table;
2902   ST_FIELD_INFO *field_info= schema_table->fields_info;
2903   const char *field_name1= schema_table->idx_field1 >= 0 ?
2904     field_info[schema_table->idx_field1].field_name : "";
2905   const char *field_name2= schema_table->idx_field2 >= 0 ?
2906     field_info[schema_table->idx_field2].field_name : "";
2907 
2908   if (item_func->functype() == Item_func::EQ_FUNC ||
2909       item_func->functype() == Item_func::EQUAL_FUNC)
2910   {
2911     int idx_field, idx_val;
2912     char tmp[MAX_FIELD_WIDTH];
2913     String *tmp_str, str_buff(tmp, sizeof(tmp), system_charset_info);
2914     Item_field *item_field;
2915     CHARSET_INFO *cs= system_charset_info;
2916 
2917     if (item_func->arguments()[0]->type() == Item::FIELD_ITEM &&
2918         item_func->arguments()[1]->const_item())
2919     {
2920       idx_field= 0;
2921       idx_val= 1;
2922     }
2923     else if (item_func->arguments()[1]->type() == Item::FIELD_ITEM &&
2924              item_func->arguments()[0]->const_item())
2925     {
2926       idx_field= 1;
2927       idx_val= 0;
2928     }
2929     else
2930       return 0;
2931 
2932     item_field= (Item_field*) item_func->arguments()[idx_field];
2933     if (table->table != item_field->field->table)
2934       return 0;
2935     tmp_str= item_func->arguments()[idx_val]->val_str(&str_buff);
2936 
2937     /* impossible value */
2938     if (!tmp_str)
2939       return 1;
2940 
2941     /* Lookup value is database name */
2942     if (!cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
2943                                (uchar *) item_field->field_name,
2944                                strlen(item_field->field_name), 0))
2945     {
2946       thd->make_lex_string(&lookup_field_vals->db_value, tmp_str->ptr(),
2947                            tmp_str->length(), FALSE);
2948     }
2949     /* Lookup value is table name */
2950     else if (!cs->coll->strnncollsp(cs, (uchar *) field_name2,
2951                                     strlen(field_name2),
2952                                     (uchar *) item_field->field_name,
2953                                     strlen(item_field->field_name), 0))
2954     {
2955       thd->make_lex_string(&lookup_field_vals->table_value, tmp_str->ptr(),
2956                            tmp_str->length(), FALSE);
2957     }
2958   }
2959   return 0;
2960 }
2961 
2962 
2963 /**
2964   @brief    Calculates lookup values from 'WHERE' condition
2965 
2966   @details This function calculates lookup value(database name, table name)
2967            from 'WHERE' condition if it's possible and
2968            fill lookup_field_vals struct fields with these values.
2969 
2970   @param[in]      thd                   thread handler
2971   @param[in]      cond                  WHERE condition
2972   @param[in]      table                 I_S table
2973   @param[in, out] lookup_field_vals     Struct which holds lookup values
2974 
2975   @return
2976     0             success
2977     1             error, there can be no matching records for the condition
2978 */
2979 
calc_lookup_values_from_cond(THD * thd,Item * cond,TABLE_LIST * table,LOOKUP_FIELD_VALUES * lookup_field_vals)2980 bool calc_lookup_values_from_cond(THD *thd, Item *cond, TABLE_LIST *table,
2981                                   LOOKUP_FIELD_VALUES *lookup_field_vals)
2982 {
2983   if (!cond)
2984     return 0;
2985 
2986   if (cond->type() == Item::COND_ITEM)
2987   {
2988     if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
2989     {
2990       List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
2991       Item *item;
2992       while ((item= li++))
2993       {
2994         if (item->type() == Item::FUNC_ITEM)
2995         {
2996           if (get_lookup_value(thd, (Item_func*)item, table, lookup_field_vals))
2997             return 1;
2998         }
2999         else
3000         {
3001           if (calc_lookup_values_from_cond(thd, item, table, lookup_field_vals))
3002             return 1;
3003         }
3004       }
3005     }
3006     return 0;
3007   }
3008   else if (cond->type() == Item::FUNC_ITEM &&
3009            get_lookup_value(thd, (Item_func*) cond, table, lookup_field_vals))
3010     return 1;
3011   return 0;
3012 }
3013 
3014 
uses_only_table_name_fields(Item * item,TABLE_LIST * table)3015 bool uses_only_table_name_fields(Item *item, TABLE_LIST *table)
3016 {
3017   if (item->type() == Item::FUNC_ITEM)
3018   {
3019     Item_func *item_func= (Item_func*)item;
3020     for (uint i=0; i<item_func->argument_count(); i++)
3021     {
3022       if (!uses_only_table_name_fields(item_func->arguments()[i], table))
3023         return 0;
3024     }
3025   }
3026   else if (item->type() == Item::FIELD_ITEM)
3027   {
3028     Item_field *item_field= (Item_field*)item;
3029     CHARSET_INFO *cs= system_charset_info;
3030     ST_SCHEMA_TABLE *schema_table= table->schema_table;
3031     ST_FIELD_INFO *field_info= schema_table->fields_info;
3032     const char *field_name1= schema_table->idx_field1 >= 0 ?
3033       field_info[schema_table->idx_field1].field_name : "";
3034     const char *field_name2= schema_table->idx_field2 >= 0 ?
3035       field_info[schema_table->idx_field2].field_name : "";
3036     if (table->table != item_field->field->table ||
3037         (cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
3038                                (uchar *) item_field->field_name,
3039                                strlen(item_field->field_name), 0) &&
3040          cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2),
3041                                (uchar *) item_field->field_name,
3042                                strlen(item_field->field_name), 0)))
3043       return 0;
3044   }
3045   else if (item->type() == Item::REF_ITEM)
3046     return uses_only_table_name_fields(item->real_item(), table);
3047 
3048   if (item->type() == Item::SUBSELECT_ITEM && !item->const_item())
3049     return 0;
3050 
3051   return 1;
3052 }
3053 
3054 
make_cond_for_info_schema(Item * cond,TABLE_LIST * table)3055 static Item * make_cond_for_info_schema(Item *cond, TABLE_LIST *table)
3056 {
3057   if (!cond)
3058     return (Item*) 0;
3059   if (cond->type() == Item::COND_ITEM)
3060   {
3061     if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
3062     {
3063       /* Create new top level AND item */
3064       Item_cond_and *new_cond=new Item_cond_and;
3065       if (!new_cond)
3066 	return (Item*) 0;
3067       List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
3068       Item *item;
3069       while ((item=li++))
3070       {
3071 	Item *fix= make_cond_for_info_schema(item, table);
3072 	if (fix)
3073 	  new_cond->argument_list()->push_back(fix);
3074       }
3075       switch (new_cond->argument_list()->elements) {
3076       case 0:
3077 	return (Item*) 0;
3078       case 1:
3079 	return new_cond->argument_list()->head();
3080       default:
3081 	new_cond->quick_fix_field();
3082 	return new_cond;
3083       }
3084     }
3085     else
3086     {						// Or list
3087       Item_cond_or *new_cond=new Item_cond_or;
3088       if (!new_cond)
3089 	return (Item*) 0;
3090       List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
3091       Item *item;
3092       while ((item=li++))
3093       {
3094 	Item *fix=make_cond_for_info_schema(item, table);
3095 	if (!fix)
3096 	  return (Item*) 0;
3097 	new_cond->argument_list()->push_back(fix);
3098       }
3099       new_cond->quick_fix_field();
3100       new_cond->top_level_item();
3101       return new_cond;
3102     }
3103   }
3104 
3105   if (!uses_only_table_name_fields(cond, table))
3106     return (Item*) 0;
3107   return cond;
3108 }
3109 
3110 
3111 /**
3112   @brief   Calculate lookup values(database name, table name)
3113 
3114   @details This function calculates lookup values(database name, table name)
3115            from 'WHERE' condition or wild values (for 'SHOW' commands only)
3116            from LEX struct and fill lookup_field_vals struct field
3117            with these values.
3118 
3119   @param[in]      thd                   thread handler
3120   @param[in]      cond                  WHERE condition
3121   @param[in]      tables                I_S table
3122   @param[in, out] lookup_field_values   Struct which holds lookup values
3123 
3124   @return
3125     0             success
3126     1             error, there can be no matching records for the condition
3127 */
3128 
get_lookup_field_values(THD * thd,Item * cond,TABLE_LIST * tables,LOOKUP_FIELD_VALUES * lookup_field_values)3129 bool get_lookup_field_values(THD *thd, Item *cond, TABLE_LIST *tables,
3130                              LOOKUP_FIELD_VALUES *lookup_field_values)
3131 {
3132   LEX *lex= thd->lex;
3133   const char *wild= lex->wild ? lex->wild->ptr() : NullS;
3134   bool rc= 0;
3135 
3136   memset(lookup_field_values, 0, sizeof(LOOKUP_FIELD_VALUES));
3137   switch (lex->sql_command) {
3138   case SQLCOM_SHOW_DATABASES:
3139     if (wild)
3140     {
3141       thd->make_lex_string(&lookup_field_values->db_value,
3142                            wild, strlen(wild), 0);
3143       lookup_field_values->wild_db_value= 1;
3144     }
3145     break;
3146   case SQLCOM_SHOW_TABLES:
3147   case SQLCOM_SHOW_TABLE_STATUS:
3148   case SQLCOM_SHOW_TRIGGERS:
3149   case SQLCOM_SHOW_EVENTS:
3150     thd->make_lex_string(&lookup_field_values->db_value,
3151                          lex->select_lex.db, strlen(lex->select_lex.db), 0);
3152     if (wild)
3153     {
3154       thd->make_lex_string(&lookup_field_values->table_value,
3155                            wild, strlen(wild), 0);
3156       lookup_field_values->wild_table_value= 1;
3157     }
3158     break;
3159   default:
3160     /*
3161       The "default" is for queries over I_S.
3162       All previous cases handle SHOW commands.
3163     */
3164     rc= calc_lookup_values_from_cond(thd, cond, tables, lookup_field_values);
3165     break;
3166   }
3167 
3168   if (lower_case_table_names && !rc)
3169   {
3170     /*
3171       We can safely do in-place upgrades here since all of the above cases
3172       are allocating a new memory buffer for these strings.
3173     */
3174     if (lookup_field_values->db_value.str && lookup_field_values->db_value.str[0])
3175       my_casedn_str(system_charset_info, lookup_field_values->db_value.str);
3176     if (lookup_field_values->table_value.str &&
3177         lookup_field_values->table_value.str[0])
3178       my_casedn_str(system_charset_info, lookup_field_values->table_value.str);
3179   }
3180 
3181   return rc;
3182 }
3183 
3184 
get_schema_table_idx(ST_SCHEMA_TABLE * schema_table)3185 enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table)
3186 {
3187   return (enum enum_schema_tables) (schema_table - &schema_tables[0]);
3188 }
3189 
3190 
3191 /*
3192   Create db names list. Information schema name always is first in list
3193 
3194   SYNOPSIS
3195     make_db_list()
3196     thd                   thread handler
3197     files                 list of db names
3198     wild                  wild string
3199     idx_field_vals        idx_field_vals->db_name contains db name or
3200                           wild string
3201     with_i_schema         returns 1 if we added 'IS' name to list
3202                           otherwise returns 0
3203 
3204   RETURN
3205     zero                  success
3206     non-zero              error
3207 */
3208 
make_db_list(THD * thd,List<LEX_STRING> * files,LOOKUP_FIELD_VALUES * lookup_field_vals,bool * with_i_schema,MEM_ROOT * tmp_mem_root)3209 int make_db_list(THD *thd, List<LEX_STRING> *files,
3210                  LOOKUP_FIELD_VALUES *lookup_field_vals,
3211                  bool *with_i_schema, MEM_ROOT *tmp_mem_root)
3212 {
3213   LEX_STRING *i_s_name_copy= 0;
3214   i_s_name_copy= thd->make_lex_string(i_s_name_copy,
3215                                       INFORMATION_SCHEMA_NAME.str,
3216                                       INFORMATION_SCHEMA_NAME.length, TRUE);
3217   *with_i_schema= 0;
3218   if (lookup_field_vals->wild_db_value)
3219   {
3220     /*
3221       This part of code is only for SHOW DATABASES command.
3222       idx_field_vals->db_value can be 0 when we don't use
3223       LIKE clause (see also get_index_field_values() function)
3224     */
3225     if (!lookup_field_vals->db_value.str ||
3226         !wild_case_compare(system_charset_info,
3227                            INFORMATION_SCHEMA_NAME.str,
3228                            lookup_field_vals->db_value.str))
3229     {
3230       *with_i_schema= 1;
3231       if (files->push_back(i_s_name_copy))
3232         return 1;
3233     }
3234     return (find_files(thd, files, NullS, mysql_data_home,
3235                        lookup_field_vals->db_value.str, 1, tmp_mem_root) !=
3236                       FIND_FILES_OK);
3237   }
3238 
3239 
3240   /*
3241     If we have db lookup value we just add it to list and
3242     exit from the function.
3243     We don't do this for database names longer than the maximum
3244     name length.
3245   */
3246   if (lookup_field_vals->db_value.str)
3247   {
3248     if (lookup_field_vals->db_value.length > NAME_LEN)
3249     {
3250       /*
3251         Impossible value for a database name,
3252         found in a WHERE DATABASE_NAME = 'xxx' clause.
3253       */
3254       return 0;
3255     }
3256 
3257     if (is_infoschema_db(lookup_field_vals->db_value.str,
3258                          lookup_field_vals->db_value.length))
3259     {
3260       *with_i_schema= 1;
3261       if (files->push_back(i_s_name_copy))
3262         return 1;
3263       return 0;
3264     }
3265     if (files->push_back(&lookup_field_vals->db_value))
3266       return 1;
3267     return 0;
3268   }
3269 
3270   /*
3271     Create list of existing databases. It is used in case
3272     of select from information schema table
3273   */
3274   if (files->push_back(i_s_name_copy))
3275     return 1;
3276   *with_i_schema= 1;
3277   return (find_files(thd, files, NullS,
3278                      mysql_data_home, NullS, 1, tmp_mem_root) != FIND_FILES_OK);
3279 }
3280 
3281 
3282 struct st_add_schema_table
3283 {
3284   List<LEX_STRING> *files;
3285   const char *wild;
3286 };
3287 
3288 
add_schema_table(THD * thd,plugin_ref plugin,void * p_data)3289 static my_bool add_schema_table(THD *thd, plugin_ref plugin,
3290                                 void* p_data)
3291 {
3292   LEX_STRING *file_name= 0;
3293   st_add_schema_table *data= (st_add_schema_table *)p_data;
3294   List<LEX_STRING> *file_list= data->files;
3295   const char *wild= data->wild;
3296   ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *);
3297   DBUG_ENTER("add_schema_table");
3298 
3299   if (schema_table->hidden)
3300       DBUG_RETURN(0);
3301   if (wild)
3302   {
3303     if (lower_case_table_names)
3304     {
3305       if (wild_case_compare(files_charset_info,
3306                             schema_table->table_name,
3307                             wild))
3308         DBUG_RETURN(0);
3309     }
3310     else if (wild_compare(schema_table->table_name, wild, 0))
3311       DBUG_RETURN(0);
3312   }
3313 
3314   if ((file_name= thd->make_lex_string(file_name, schema_table->table_name,
3315                                        strlen(schema_table->table_name),
3316                                        TRUE)) &&
3317       !file_list->push_back(file_name))
3318     DBUG_RETURN(0);
3319   DBUG_RETURN(1);
3320 }
3321 
3322 
schema_tables_add(THD * thd,List<LEX_STRING> * files,const char * wild)3323 int schema_tables_add(THD *thd, List<LEX_STRING> *files, const char *wild)
3324 {
3325   LEX_STRING *file_name= 0;
3326   ST_SCHEMA_TABLE *tmp_schema_table= schema_tables;
3327   st_add_schema_table add_data;
3328   DBUG_ENTER("schema_tables_add");
3329 
3330   for (; tmp_schema_table->table_name; tmp_schema_table++)
3331   {
3332     if (tmp_schema_table->hidden)
3333       continue;
3334     if (wild)
3335     {
3336       if (lower_case_table_names)
3337       {
3338         if (wild_case_compare(files_charset_info,
3339                               tmp_schema_table->table_name,
3340                               wild))
3341           continue;
3342       }
3343       else if (wild_compare(tmp_schema_table->table_name, wild, 0))
3344         continue;
3345     }
3346     if ((file_name=
3347          thd->make_lex_string(file_name, tmp_schema_table->table_name,
3348                               strlen(tmp_schema_table->table_name), TRUE)) &&
3349         !files->push_back(file_name))
3350       continue;
3351     DBUG_RETURN(1);
3352   }
3353 
3354   add_data.files= files;
3355   add_data.wild= wild;
3356   if (plugin_foreach(thd, add_schema_table,
3357                      MYSQL_INFORMATION_SCHEMA_PLUGIN, &add_data))
3358       DBUG_RETURN(1);
3359 
3360   DBUG_RETURN(0);
3361 }
3362 
3363 
3364 /**
3365   @brief          Create table names list
3366 
3367   @details        The function creates the list of table names in
3368                   database
3369 
3370   @param[in]      thd                   thread handler
3371   @param[in]      table_names           List of table names in database
3372   @param[in]      lex                   pointer to LEX struct
3373   @param[in]      lookup_field_vals     pointer to LOOKUP_FIELD_VALUE struct
3374   @param[in]      with_i_schema         TRUE means that we add I_S tables to list
3375   @param[in]      db_name               database name
3376 
3377   @return         Operation status
3378     @retval       0           ok
3379     @retval       1           fatal error
3380     @retval       2           Not fatal error; Safe to ignore this file list
3381 */
3382 
3383 static int
make_table_name_list(THD * thd,List<LEX_STRING> * table_names,LEX * lex,LOOKUP_FIELD_VALUES * lookup_field_vals,bool with_i_schema,LEX_STRING * db_name,MEM_ROOT * tmp_mem_root)3384 make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex,
3385                      LOOKUP_FIELD_VALUES *lookup_field_vals,
3386                      bool with_i_schema, LEX_STRING *db_name,
3387                      MEM_ROOT *tmp_mem_root)
3388 {
3389   char path[FN_REFLEN + 1];
3390   build_table_filename(path, sizeof(path) - 1, db_name->str, "", "", 0);
3391   if (!lookup_field_vals->wild_table_value &&
3392       lookup_field_vals->table_value.str)
3393   {
3394     if (lookup_field_vals->table_value.length > NAME_LEN)
3395     {
3396       /*
3397         Impossible value for a table name,
3398         found in a WHERE TABLE_NAME = 'xxx' clause.
3399       */
3400       return 0;
3401     }
3402 
3403     if (with_i_schema)
3404     {
3405       LEX_STRING *name;
3406       ST_SCHEMA_TABLE *schema_table=
3407         find_schema_table(thd, lookup_field_vals->table_value.str);
3408       if (schema_table && !schema_table->hidden)
3409       {
3410         if (!(name=
3411               thd->make_lex_string(NULL, schema_table->table_name,
3412                                    strlen(schema_table->table_name), TRUE)) ||
3413             table_names->push_back(name))
3414           return 1;
3415       }
3416     }
3417     else
3418     {
3419 #ifndef NO_EMBEDDED_ACCESS_CHECKS
3420       if (!(thd->col_access & TABLE_ACLS))
3421       {
3422         TABLE_LIST table_list;
3423         memset(&table_list, 0, sizeof(table_list));
3424 
3425         /*
3426           Database name and table name have already been converted to lowercase
3427           if lower_case_table_names is > 0. We can safely use lookup_field_vals
3428           here.
3429         */
3430         table_list.db= db_name->str;
3431         table_list.db_length= db_name->length;
3432         table_list.table_name_length= lookup_field_vals->table_value.length;
3433         table_list.table_name= lookup_field_vals->table_value.str;
3434         table_list.grant.privilege=thd->col_access;
3435 
3436         if (check_grant(thd, TABLE_ACLS, &table_list, TRUE, 1, TRUE))
3437           return 2;
3438       }
3439 #endif
3440       if (table_names->push_back(&lookup_field_vals->table_value))
3441         return 1;
3442       /*
3443         Check that table is relevant in current transaction.
3444         (used for ndb engine, see ndbcluster_find_files(), ha_ndbcluster.cc)
3445       */
3446       (void) ha_find_files(thd, db_name->str, path,
3447                          lookup_field_vals->table_value.str, 0,
3448                          table_names);
3449     }
3450     return 0;
3451   }
3452 
3453   /*
3454     This call will add all matching the wildcards (if specified) IS tables
3455     to the list
3456   */
3457   if (with_i_schema)
3458     return (schema_tables_add(thd, table_names,
3459                               lookup_field_vals->table_value.str));
3460 
3461   find_files_result res= find_files(thd, table_names, db_name->str, path,
3462                                     lookup_field_vals->table_value.str, 0,
3463                                     tmp_mem_root);
3464   if (res != FIND_FILES_OK)
3465   {
3466     /*
3467       Downgrade errors about problems with database directory to
3468       warnings if this is not a 'SHOW' command.  Another thread
3469       may have dropped database, and we may still have a name
3470       for that directory.
3471     */
3472     if (res == FIND_FILES_DIR)
3473     {
3474       if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
3475         return 1;
3476       thd->clear_error();
3477       return 2;
3478     }
3479     return 1;
3480   }
3481   return 0;
3482 }
3483 
3484 
3485 /**
3486   Fill I_S table with data obtained by performing full-blown table open.
3487 
3488   @param  thd                       Thread handler.
3489   @param  is_show_fields_or_keys    Indicates whether it is a legacy SHOW
3490                                     COLUMNS or SHOW KEYS statement.
3491   @param  table                     TABLE object for I_S table to be filled.
3492   @param  schema_table              I_S table description structure.
3493   @param  orig_db_name              Database name.
3494   @param  orig_table_name           Table name.
3495   @param  open_tables_state_backup  Open_tables_state object which is used
3496                                     to save/restore original status of
3497                                     variables related to open tables state.
3498   @param  can_deadlock              Indicates that deadlocks are possible
3499                                     due to metadata locks, so to avoid
3500                                     them we should not wait in case if
3501                                     conflicting lock is present.
3502 
3503   @retval FALSE - Success.
3504   @retval TRUE  - Failure.
3505 */
3506 static bool
fill_schema_table_by_open(THD * thd,bool is_show_fields_or_keys,TABLE * table,ST_SCHEMA_TABLE * schema_table,LEX_STRING * orig_db_name,LEX_STRING * orig_table_name,Open_tables_backup * open_tables_state_backup,bool can_deadlock)3507 fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
3508                           TABLE *table, ST_SCHEMA_TABLE *schema_table,
3509                           LEX_STRING *orig_db_name,
3510                           LEX_STRING *orig_table_name,
3511                           Open_tables_backup *open_tables_state_backup,
3512                           bool can_deadlock)
3513 {
3514   Query_arena i_s_arena(thd->mem_root,
3515                         Query_arena::STMT_CONVENTIONAL_EXECUTION),
3516               backup_arena, *old_arena;
3517   LEX *old_lex= thd->lex, temp_lex, *lex;
3518   LEX_STRING db_name, table_name;
3519   TABLE_LIST *table_list;
3520   bool result= true;
3521 
3522   DBUG_ENTER("fill_schema_table_by_open");
3523   /*
3524     When a view is opened its structures are allocated on a permanent
3525     statement arena and linked into the LEX tree for the current statement
3526     (this happens even in cases when view is handled through TEMPTABLE
3527     algorithm).
3528 
3529     To prevent this process from unnecessary hogging of memory in the permanent
3530     arena of our I_S query and to avoid damaging its LEX we use temporary
3531     arena and LEX for table/view opening.
3532 
3533     Use temporary arena instead of statement permanent arena. Also make
3534     it active arena and save original one for successive restoring.
3535   */
3536   old_arena= thd->stmt_arena;
3537   thd->stmt_arena= &i_s_arena;
3538   thd->set_n_backup_active_arena(&i_s_arena, &backup_arena);
3539 
3540   /* Prepare temporary LEX. */
3541   thd->lex= lex= &temp_lex;
3542   lex_start(thd);
3543 
3544   /* Disable constant subquery evaluation as we won't be locking tables. */
3545   lex->context_analysis_only= CONTEXT_ANALYSIS_ONLY_VIEW;
3546 
3547   /*
3548     Some of process_table() functions rely on wildcard being passed from
3549     old LEX (or at least being initialized).
3550   */
3551   lex->wild= old_lex->wild;
3552 
3553   /*
3554     Since make_table_list() might change database and table name passed
3555     to it we create copies of orig_db_name and orig_table_name here.
3556     These copies are used for make_table_list() while unaltered values
3557     are passed to process_table() functions.
3558   */
3559   if (!thd->make_lex_string(&db_name, orig_db_name->str,
3560                             orig_db_name->length, FALSE) ||
3561       !thd->make_lex_string(&table_name, orig_table_name->str,
3562                             orig_table_name->length, FALSE))
3563     goto end;
3564 
3565   /*
3566     Create table list element for table to be open. Link it with the
3567     temporary LEX. The latter is required to correctly open views and
3568     produce table describing their structure.
3569   */
3570   if (make_table_list(thd, &lex->select_lex, &db_name, &table_name))
3571     goto end;
3572 
3573   table_list= lex->select_lex.table_list.first;
3574 
3575   if (is_show_fields_or_keys)
3576   {
3577     /*
3578       Restore thd->temporary_tables to be able to process
3579       temporary tables (only for 'show index' & 'show columns').
3580       This should be changed when processing of temporary tables for
3581       I_S tables will be done.
3582     */
3583     thd->temporary_tables= open_tables_state_backup->temporary_tables;
3584   }
3585   else
3586   {
3587     /*
3588       Apply optimization flags for table opening which are relevant for
3589       this I_S table. We can't do this for SHOW COLUMNS/KEYS because of
3590       backward compatibility.
3591     */
3592     table_list->i_s_requested_object= schema_table->i_s_requested_object;
3593   }
3594 
3595   /*
3596     Let us set fake sql_command so views won't try to merge
3597     themselves into main statement. If we don't do this,
3598     SELECT * from information_schema.xxxx will cause problems.
3599     SQLCOM_SHOW_FIELDS is used because it satisfies
3600     'only_view_structure()'.
3601   */
3602   lex->sql_command= SQLCOM_SHOW_FIELDS;
3603 
3604   result= open_temporary_tables(thd, table_list);
3605 
3606   if (!result)
3607   {
3608     result= open_normal_and_derived_tables(thd, table_list,
3609                                            (MYSQL_OPEN_IGNORE_FLUSH |
3610                                             MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
3611                                             (can_deadlock ?
3612                                              MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)));
3613     lex->select_lex.handle_derived(lex, &mysql_derived_create);
3614   }
3615   /*
3616     Restore old value of sql_command back as it is being looked at in
3617     process_table() function.
3618   */
3619   lex->sql_command= old_lex->sql_command;
3620 
3621   DEBUG_SYNC(thd, "after_open_table_ignore_flush");
3622 
3623   /*
3624     XXX:  show_table_list has a flag i_is_requested,
3625     and when it's set, open_normal_and_derived_tables()
3626     can return an error without setting an error message
3627     in THD, which is a hack. This is why we have to
3628     check for res, then for thd->is_error() and only then
3629     for thd->main_da.sql_errno().
3630 
3631     Again we don't do this for SHOW COLUMNS/KEYS because
3632     of backward compatibility.
3633   */
3634   if (!is_show_fields_or_keys && result && thd->is_error() &&
3635       thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE)
3636   {
3637     /*
3638       Hide error for a non-existing table.
3639       For example, this error can occur when we use a where condition
3640       with a db name and table, but the table does not exist.
3641     */
3642     result= false;
3643     thd->clear_error();
3644   }
3645   else
3646   {
3647     result= schema_table->process_table(thd, table_list,
3648                                         table, result,
3649                                         orig_db_name,
3650                                         orig_table_name);
3651   }
3652 
3653 
3654 end:
3655   lex->unit.cleanup();
3656 
3657   /* Restore original LEX value, statement's arena and THD arena values. */
3658   lex_end(thd->lex);
3659 
3660   // Free items, before restoring backup_arena below.
3661   DBUG_ASSERT(i_s_arena.free_list == NULL);
3662   thd->free_items();
3663 
3664   /*
3665     For safety reset list of open temporary tables before closing
3666     all tables open within this Open_tables_state.
3667   */
3668   thd->temporary_tables= NULL;
3669   close_thread_tables(thd);
3670   /*
3671     Release metadata lock we might have acquired.
3672     See comment in fill_schema_table_from_frm() for details.
3673   */
3674   thd->mdl_context.rollback_to_savepoint(open_tables_state_backup->mdl_system_tables_svp);
3675 
3676   thd->lex= old_lex;
3677 
3678   thd->stmt_arena= old_arena;
3679   thd->restore_active_arena(&i_s_arena, &backup_arena);
3680 
3681   DBUG_RETURN(result);
3682 }
3683 
3684 
3685 /**
3686   @brief          Fill I_S table for SHOW TABLE NAMES commands
3687 
3688   @param[in]      thd                      thread handler
3689   @param[in]      table                    TABLE struct for I_S table
3690   @param[in]      db_name                  database name
3691   @param[in]      table_name               table name
3692   @param[in]      with_i_schema            I_S table if TRUE
3693 
3694   @return         Operation status
3695     @retval       0           success
3696     @retval       1           error
3697 */
3698 
fill_schema_table_names(THD * thd,TABLE * table,LEX_STRING * db_name,LEX_STRING * table_name,bool with_i_schema,bool need_table_type)3699 static int fill_schema_table_names(THD *thd, TABLE *table,
3700                                    LEX_STRING *db_name, LEX_STRING *table_name,
3701                                    bool with_i_schema,
3702                                    bool need_table_type)
3703 {
3704   /* Avoid opening FRM files if table type is not needed. */
3705   if (need_table_type)
3706   {
3707     if (with_i_schema)
3708     {
3709       table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"),
3710                              system_charset_info);
3711     }
3712     else
3713     {
3714       enum legacy_db_type not_used;
3715       char path[FN_REFLEN + 1];
3716       (void) build_table_filename(path, sizeof(path) - 1, db_name->str,
3717                                   table_name->str, reg_ext, 0);
3718       switch (dd_frm_type(thd, path, &not_used)) {
3719       case FRMTYPE_ERROR:
3720         table->field[3]->store(STRING_WITH_LEN("ERROR"),
3721                                system_charset_info);
3722         break;
3723       case FRMTYPE_TABLE:
3724         table->field[3]->store(STRING_WITH_LEN("BASE TABLE"),
3725                                system_charset_info);
3726         break;
3727       case FRMTYPE_VIEW:
3728         table->field[3]->store(STRING_WITH_LEN("VIEW"),
3729                                system_charset_info);
3730         break;
3731       default:
3732         DBUG_ASSERT(0);
3733       }
3734     if (thd->is_error() && thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE)
3735       {
3736         thd->clear_error();
3737         return 0;
3738       }
3739     }
3740   }
3741   if (schema_table_store_record(thd, table))
3742     return 1;
3743   return 0;
3744 }
3745 
3746 
3747 /**
3748   @brief          Get open table method
3749 
3750   @details        The function calculates the method which will be used
3751                   for table opening:
3752                   SKIP_OPEN_TABLE - do not open table
3753                   OPEN_FRM_ONLY   - open FRM file only
3754                   OPEN_FULL_TABLE - open FRM, data, index files
3755   @param[in]      tables               I_S table table_list
3756   @param[in]      schema_table         I_S table struct
3757   @param[in]      schema_table_idx     I_S table index
3758 
3759   @return         return a set of flags
3760     @retval       SKIP_OPEN_TABLE | OPEN_FRM_ONLY | OPEN_FULL_TABLE
3761 */
3762 
get_table_open_method(TABLE_LIST * tables,ST_SCHEMA_TABLE * schema_table,enum enum_schema_tables schema_table_idx)3763 uint get_table_open_method(TABLE_LIST *tables,
3764                                   ST_SCHEMA_TABLE *schema_table,
3765                                   enum enum_schema_tables schema_table_idx)
3766 {
3767   /*
3768     determine which method will be used for table opening
3769   */
3770   if (schema_table->i_s_requested_object & OPTIMIZE_I_S_TABLE)
3771   {
3772     Field **ptr, *field;
3773     int table_open_method= 0, field_indx= 0;
3774     uint star_table_open_method= OPEN_FULL_TABLE;
3775     bool used_star= true;                  // true if '*' is used in select
3776     for (ptr=tables->table->field; (field= *ptr) ; ptr++)
3777     {
3778       star_table_open_method=
3779         min(star_table_open_method,
3780             schema_table->fields_info[field_indx].open_method);
3781       if (bitmap_is_set(tables->table->read_set, field->field_index))
3782       {
3783         used_star= false;
3784         table_open_method|= schema_table->fields_info[field_indx].open_method;
3785       }
3786       field_indx++;
3787     }
3788     if (used_star)
3789       return star_table_open_method;
3790     return table_open_method;
3791   }
3792   /* I_S tables which use get_all_tables but can not be optimized */
3793   return (uint) OPEN_FULL_TABLE;
3794 }
3795 
3796 
3797 /**
3798    Try acquire high priority share metadata lock on a table (with
3799    optional wait for conflicting locks to go away).
3800 
3801    @param thd            Thread context.
3802    @param mdl_request    Pointer to memory to be used for MDL_request
3803                          object for a lock request.
3804    @param table          Table list element for the table
3805    @param can_deadlock   Indicates that deadlocks are possible due to
3806                          metadata locks, so to avoid them we should not
3807                          wait in case if conflicting lock is present.
3808 
3809    @note This is an auxiliary function to be used in cases when we want to
3810          access table's description by looking up info in TABLE_SHARE without
3811          going through full-blown table open.
3812    @note This function assumes that there are no other metadata lock requests
3813          in the current metadata locking context.
3814 
3815    @retval FALSE  No error, if lock was obtained TABLE_LIST::mdl_request::ticket
3816                   is set to non-NULL value.
3817    @retval TRUE   Some error occured (probably thread was killed).
3818 */
3819 
3820 static bool
try_acquire_high_prio_shared_mdl_lock(THD * thd,TABLE_LIST * table,bool can_deadlock)3821 try_acquire_high_prio_shared_mdl_lock(THD *thd, TABLE_LIST *table,
3822                                       bool can_deadlock)
3823 {
3824   bool error;
3825   table->mdl_request.init(MDL_key::TABLE, table->db, table->table_name,
3826                           MDL_SHARED_HIGH_PRIO, MDL_TRANSACTION);
3827 
3828   if (can_deadlock)
3829   {
3830     /*
3831       When .FRM is being open in order to get data for an I_S table,
3832       we might have some tables not only open but also locked.
3833       E.g. this happens when a SHOW or I_S statement is run
3834       under LOCK TABLES or inside a stored function.
3835       By waiting for the conflicting metadata lock to go away we
3836       might create a deadlock which won't entirely belong to the
3837       MDL subsystem and thus won't be detectable by this subsystem's
3838       deadlock detector. To avoid such situation, when there are
3839       other locked tables, we prefer not to wait on a conflicting
3840       lock.
3841     */
3842     error= thd->mdl_context.try_acquire_lock(&table->mdl_request);
3843   }
3844   else
3845     error= thd->mdl_context.acquire_lock(&table->mdl_request,
3846                                          thd->variables.lock_wait_timeout);
3847 
3848   return error;
3849 }
3850 
3851 
3852 /**
3853   @brief          Fill I_S table with data from FRM file only
3854 
3855   @param[in]      thd                      thread handler
3856   @param[in]      table                    TABLE struct for I_S table
3857   @param[in]      schema_table             I_S table struct
3858   @param[in]      db_name                  database name
3859   @param[in]      table_name               table name
3860   @param[in]      schema_table_idx         I_S table index
3861   @param[in]      open_tables_state_backup Open_tables_state object which is used
3862                                            to save/restore original state of metadata
3863                                            locks.
3864   @param[in]      can_deadlock             Indicates that deadlocks are possible
3865                                            due to metadata locks, so to avoid
3866                                            them we should not wait in case if
3867                                            conflicting lock is present.
3868 
3869   @return         Operation status
3870     @retval       0           Table is processed and we can continue
3871                               with new table
3872     @retval       1           It's view and we have to use
3873                               open_tables function for this table
3874 */
3875 
fill_schema_table_from_frm(THD * thd,TABLE_LIST * tables,ST_SCHEMA_TABLE * schema_table,LEX_STRING * db_name,LEX_STRING * table_name,enum enum_schema_tables schema_table_idx,Open_tables_backup * open_tables_state_backup,bool can_deadlock)3876 static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables,
3877                                       ST_SCHEMA_TABLE *schema_table,
3878                                       LEX_STRING *db_name,
3879                                       LEX_STRING *table_name,
3880                                       enum enum_schema_tables schema_table_idx,
3881                                       Open_tables_backup *open_tables_state_backup,
3882                                       bool can_deadlock)
3883 {
3884   TABLE *table= tables->table;
3885   TABLE_SHARE *share;
3886   TABLE tbl;
3887   TABLE_LIST table_list;
3888   uint res= 0;
3889   int not_used;
3890   my_hash_value_type hash_value;
3891   const char *key;
3892   uint key_length;
3893   char db_name_buff[NAME_LEN + 1], table_name_buff[NAME_LEN + 1];
3894 
3895   memset(&table_list, 0, sizeof(TABLE_LIST));
3896   memset(&tbl, 0, sizeof(TABLE));
3897 
3898   DBUG_ASSERT(db_name->length <= NAME_LEN);
3899   DBUG_ASSERT(table_name->length <= NAME_LEN);
3900 
3901   if (lower_case_table_names)
3902   {
3903     /*
3904       In lower_case_table_names > 0 metadata locking and table definition
3905       cache subsystems require normalized (lowercased) database and table
3906       names as input.
3907     */
3908     strmov(db_name_buff, db_name->str);
3909     strmov(table_name_buff, table_name->str);
3910     my_casedn_str(files_charset_info, db_name_buff);
3911     my_casedn_str(files_charset_info, table_name_buff);
3912     table_list.db= db_name_buff;
3913     table_list.table_name= table_name_buff;
3914   }
3915   else
3916   {
3917     table_list.table_name= table_name->str;
3918     table_list.db= db_name->str;
3919   }
3920 
3921   /*
3922     TODO: investigate if in this particular situation we can get by
3923           simply obtaining internal lock of the data-dictionary
3924           instead of obtaining full-blown metadata lock.
3925   */
3926   if (try_acquire_high_prio_shared_mdl_lock(thd, &table_list, can_deadlock))
3927   {
3928     /*
3929       Some error occured (most probably we have been killed while
3930       waiting for conflicting locks to go away), let the caller to
3931       handle the situation.
3932     */
3933     return 1;
3934   }
3935 
3936   if (! table_list.mdl_request.ticket)
3937   {
3938     /*
3939       We are in situation when we have encountered conflicting metadata
3940       lock and deadlocks can occur due to waiting for it to go away.
3941       So instead of waiting skip this table with an appropriate warning.
3942     */
3943     DBUG_ASSERT(can_deadlock);
3944 
3945     push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
3946                         ER_WARN_I_S_SKIPPED_TABLE,
3947                         ER(ER_WARN_I_S_SKIPPED_TABLE),
3948                         table_list.db, table_list.table_name);
3949     return 0;
3950   }
3951 
3952   if (schema_table->i_s_requested_object & OPEN_TRIGGER_ONLY)
3953   {
3954     init_sql_alloc(&tbl.mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
3955     if (!Table_triggers_list::check_n_load(thd, db_name->str,
3956                                            table_name->str, &tbl, 1))
3957     {
3958       table_list.table= &tbl;
3959       res= schema_table->process_table(thd, &table_list, table,
3960                                        res, db_name, table_name);
3961       delete tbl.triggers;
3962     }
3963     free_root(&tbl.mem_root, MYF(0));
3964     goto end;
3965   }
3966 
3967   key_length= get_table_def_key(&table_list, &key);
3968   hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length);
3969   mysql_mutex_lock(&LOCK_open);
3970   share= get_table_share(thd, &table_list, key,
3971                          key_length, OPEN_VIEW, &not_used, hash_value);
3972   if (!share)
3973   {
3974     res= 0;
3975     goto end_unlock;
3976   }
3977 
3978   if (share->is_view)
3979   {
3980     if (schema_table->i_s_requested_object & OPEN_TABLE_ONLY)
3981     {
3982       /* skip view processing */
3983       res= 0;
3984       goto end_share;
3985     }
3986     else if (schema_table->i_s_requested_object & OPEN_VIEW_FULL)
3987     {
3988       /*
3989         tell get_all_tables() to fall back to
3990         open_normal_and_derived_tables()
3991       */
3992       res= 1;
3993       goto end_share;
3994     }
3995   }
3996 
3997   if (share->is_view)
3998   {
3999     if (mysql_make_view(thd, share, &table_list, true))
4000       goto end_share;
4001     table_list.view= (LEX*) share->is_view;
4002     res= schema_table->process_table(thd, &table_list, table,
4003                                      res, db_name, table_name);
4004     goto end_share;
4005   }
4006 
4007   if (!open_table_from_share(thd, share, table_name->str, 0,
4008                              (EXTRA_RECORD | OPEN_FRM_FILE_ONLY),
4009                              thd->open_options, &tbl, FALSE))
4010   {
4011     tbl.s= share;
4012     table_list.table= &tbl;
4013     table_list.view= (LEX*) share->is_view;
4014     res= schema_table->process_table(thd, &table_list, table,
4015                                      res, db_name, table_name);
4016     free_root(&tbl.mem_root, MYF(0));
4017     my_free((void *) tbl.alias);
4018   }
4019 
4020 end_share:
4021   release_table_share(share);
4022 
4023 end_unlock:
4024   mysql_mutex_unlock(&LOCK_open);
4025 
4026 end:
4027   /*
4028     Release metadata lock we might have acquired.
4029 
4030     Without this step metadata locks acquired for each table processed
4031     will be accumulated. In situation when a lot of tables are processed
4032     by I_S query this will result in transaction with too many metadata
4033     locks. As result performance of acquisition of new lock will suffer.
4034 
4035     Of course, the fact that we don't hold metadata lock on tables which
4036     were processed till the end of I_S query makes execution less isolated
4037     from concurrent DDL. Consequently one might get 'dirty' results from
4038     such a query. But we have never promised serializability of I_S queries
4039     anyway.
4040 
4041     We don't have any tables open since we took backup, so rolling back to
4042     savepoint is safe.
4043   */
4044   DBUG_ASSERT(thd->open_tables == NULL);
4045   thd->mdl_context.rollback_to_savepoint(open_tables_state_backup->mdl_system_tables_svp);
4046   thd->clear_error();
4047   return res;
4048 }
4049 
4050 
4051 /**
4052   Trigger_error_handler is intended to intercept and silence SQL conditions
4053   that might happen during trigger loading for SHOW statements.
4054   The potential SQL conditions are:
4055 
4056     - ER_PARSE_ERROR -- this error is thrown if a trigger definition file
4057       is damaged or contains invalid CREATE TRIGGER statement. That should
4058       not happen in normal life.
4059 
4060     - ER_TRG_NO_DEFINER -- this warning is thrown when we're loading a
4061       trigger created/imported in/from the version of MySQL, which does not
4062       support trigger definers.
4063 
4064     - ER_TRG_NO_CREATION_CTX -- this warning is thrown when we're loading a
4065       trigger created/imported in/from the version of MySQL, which does not
4066       support trigger creation contexts.
4067 */
4068 
4069 class Trigger_error_handler : public Internal_error_handler
4070 {
4071 public:
handle_condition(THD * thd,uint sql_errno,const char * sqlstate,Sql_condition::enum_warning_level level,const char * msg,Sql_condition ** cond_hdl)4072   bool handle_condition(THD *thd,
4073                         uint sql_errno,
4074                         const char* sqlstate,
4075                         Sql_condition::enum_warning_level level,
4076                         const char* msg,
4077                         Sql_condition ** cond_hdl)
4078   {
4079     if (sql_errno == ER_PARSE_ERROR ||
4080         sql_errno == ER_TRG_NO_DEFINER ||
4081         sql_errno == ER_TRG_NO_CREATION_CTX)
4082       return true;
4083 
4084     return false;
4085   }
4086 };
4087 
4088 
4089 
4090 /**
4091   @brief          Fill I_S tables whose data are retrieved
4092                   from frm files and storage engine
4093 
4094   @details        The information schema tables are internally represented as
4095                   temporary tables that are filled at query execution time.
4096                   Those I_S tables whose data are retrieved
4097                   from frm files and storage engine are filled by the function
4098                   get_all_tables().
4099 
4100   @param[in]      thd                      thread handler
4101   @param[in]      tables                   I_S table
4102   @param[in]      cond                     'WHERE' condition
4103 
4104   @return         Operation status
4105     @retval       0                        success
4106     @retval       1                        error
4107 */
4108 
get_all_tables(THD * thd,TABLE_LIST * tables,Item * cond)4109 int get_all_tables(THD *thd, TABLE_LIST *tables, Item *cond)
4110 {
4111   LEX *lex= thd->lex;
4112   TABLE *table= tables->table;
4113   SELECT_LEX *lsel= tables->schema_select_lex;
4114   ST_SCHEMA_TABLE *schema_table= tables->schema_table;
4115   LOOKUP_FIELD_VALUES lookup_field_vals;
4116   LEX_STRING *db_name, *table_name;
4117   bool with_i_schema;
4118   enum enum_schema_tables schema_table_idx;
4119   List<LEX_STRING> db_names;
4120   List_iterator_fast<LEX_STRING> it(db_names);
4121   Item *partial_cond= 0;
4122   int error= 1;
4123   Open_tables_backup open_tables_state_backup;
4124 #ifndef NO_EMBEDDED_ACCESS_CHECKS
4125   Security_context *sctx= thd->security_ctx;
4126 #endif
4127   uint table_open_method;
4128   bool can_deadlock;
4129   DBUG_ENTER("get_all_tables");
4130 
4131   MEM_ROOT tmp_mem_root;
4132   init_sql_alloc(&tmp_mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
4133 
4134   /*
4135     In cases when SELECT from I_S table being filled by this call is
4136     part of statement which also uses other tables or is being executed
4137     under LOCK TABLES or is part of transaction which also uses other
4138     tables waiting for metadata locks which happens below might result
4139     in deadlocks.
4140     To avoid them we don't wait if conflicting metadata lock is
4141     encountered and skip table with emitting an appropriate warning.
4142   */
4143   can_deadlock= thd->mdl_context.has_locks();
4144 
4145   /*
4146     We should not introduce deadlocks even if we already have some
4147     tables open and locked, since we won't lock tables which we will
4148     open and will ignore pending exclusive metadata locks for these
4149     tables by using high-priority requests for shared metadata locks.
4150   */
4151   thd->reset_n_backup_open_tables_state(&open_tables_state_backup);
4152 
4153   schema_table_idx= get_schema_table_idx(schema_table);
4154   tables->table_open_method= table_open_method=
4155     get_table_open_method(tables, schema_table, schema_table_idx);
4156   DBUG_PRINT("open_method", ("%d", tables->table_open_method));
4157   /*
4158     this branch processes SHOW FIELDS, SHOW INDEXES commands.
4159     see sql_parse.cc, prepare_schema_table() function where
4160     this values are initialized
4161   */
4162   if (lsel && lsel->table_list.first)
4163   {
4164     LEX_STRING db_name, table_name;
4165 
4166     db_name.str= lsel->table_list.first->db;
4167     db_name.length= lsel->table_list.first->db_length;
4168 
4169     table_name.str= lsel->table_list.first->table_name;
4170     table_name.length= lsel->table_list.first->table_name_length;
4171 
4172     error= fill_schema_table_by_open(thd, TRUE,
4173                                      table, schema_table,
4174                                      &db_name, &table_name,
4175                                      &open_tables_state_backup,
4176                                      can_deadlock);
4177     goto err;
4178   }
4179 
4180   if (get_lookup_field_values(thd, cond, tables, &lookup_field_vals))
4181   {
4182     error= 0;
4183     goto err;
4184   }
4185 
4186   DBUG_PRINT("INDEX VALUES",("db_name='%s', table_name='%s'",
4187                              STR_OR_NIL(lookup_field_vals.db_value.str),
4188                              STR_OR_NIL(lookup_field_vals.table_value.str)));
4189 
4190   if (!lookup_field_vals.wild_db_value && !lookup_field_vals.wild_table_value)
4191   {
4192     /*
4193       if lookup value is empty string then
4194       it's impossible table name or db name
4195     */
4196     if ((lookup_field_vals.db_value.str &&
4197          !lookup_field_vals.db_value.str[0]) ||
4198         (lookup_field_vals.table_value.str &&
4199          !lookup_field_vals.table_value.str[0]))
4200     {
4201       error= 0;
4202       goto err;
4203     }
4204   }
4205 
4206   if (lookup_field_vals.db_value.length &&
4207       !lookup_field_vals.wild_db_value)
4208     tables->has_db_lookup_value= TRUE;
4209   if (lookup_field_vals.table_value.length &&
4210       !lookup_field_vals.wild_table_value)
4211     tables->has_table_lookup_value= TRUE;
4212 
4213   if (tables->has_db_lookup_value && tables->has_table_lookup_value)
4214     partial_cond= 0;
4215   else
4216     partial_cond= make_cond_for_info_schema(cond, tables);
4217 
4218   if (lex->describe)
4219   {
4220     /* EXPLAIN SELECT */
4221     error= 0;
4222     goto err;
4223   }
4224 
4225   if (make_db_list(thd, &db_names, &lookup_field_vals, &with_i_schema, &tmp_mem_root))
4226     goto err;
4227   it.rewind(); /* To get access to new elements in basis list */
4228   while ((db_name= it++))
4229   {
4230     DBUG_ASSERT(db_name->length <= NAME_LEN);
4231 #ifndef NO_EMBEDDED_ACCESS_CHECKS
4232     if (!(check_access(thd, SELECT_ACL, db_name->str,
4233                        &thd->col_access, NULL, 0, 1) ||
4234           (!thd->col_access && check_grant_db(thd, db_name->str))) ||
4235         sctx->master_access & (DB_ACLS | SHOW_DB_ACL) ||
4236         acl_get(sctx->get_host()->ptr(), sctx->get_ip()->ptr(),
4237                 sctx->priv_user, db_name->str, 0))
4238 #endif
4239     {
4240       List<LEX_STRING> table_names;
4241       int res= make_table_name_list(thd, &table_names, lex,
4242                                     &lookup_field_vals,
4243                                     with_i_schema, db_name, &tmp_mem_root);
4244       if (res == 2)   /* Not fatal error, continue */
4245         continue;
4246       if (res)
4247         goto err;
4248 
4249       List_iterator_fast<LEX_STRING> it_files(table_names);
4250       while ((table_name= it_files++))
4251       {
4252         DBUG_ASSERT(table_name->length <= NAME_LEN);
4253 	restore_record(table, s->default_values);
4254         table->field[schema_table->idx_field1]->
4255           store(db_name->str, db_name->length, system_charset_info);
4256         table->field[schema_table->idx_field2]->
4257           store(table_name->str, table_name->length, system_charset_info);
4258 
4259         if (!partial_cond || partial_cond->val_int())
4260         {
4261           /*
4262             If table is I_S.tables and open_table_method is 0 (eg SKIP_OPEN)
4263             we can skip table opening and we don't have lookup value for
4264             table name or lookup value is wild string(table name list is
4265             already created by make_table_name_list() function).
4266           */
4267           if (!table_open_method && schema_table_idx == SCH_TABLES &&
4268               (!lookup_field_vals.table_value.length ||
4269                lookup_field_vals.wild_table_value))
4270           {
4271             table->field[0]->store(STRING_WITH_LEN("def"), system_charset_info);
4272             if (schema_table_store_record(thd, table))
4273               goto err;      /* Out of space in temporary table */
4274             continue;
4275           }
4276 
4277           /* SHOW TABLE NAMES command */
4278           if (schema_table_idx == SCH_TABLE_NAMES)
4279           {
4280             if (fill_schema_table_names(thd, tables->table, db_name,
4281                                         table_name, with_i_schema,
4282                                         lex->verbose))
4283               continue;
4284           }
4285           else
4286           {
4287             if (!(table_open_method & ~OPEN_FRM_ONLY) &&
4288                 !with_i_schema)
4289             {
4290               /*
4291                 Here we need to filter out warnings, which can happen
4292                 during loading of triggers in fill_schema_table_from_frm(),
4293                 because we don't need those warnings to pollute output of
4294                 SELECT from I_S / SHOW-statements.
4295               */
4296 
4297               Trigger_error_handler err_handler;
4298               thd->push_internal_handler(&err_handler);
4299 
4300               int res= fill_schema_table_from_frm(thd, tables, schema_table,
4301                                                   db_name, table_name,
4302                                                   schema_table_idx,
4303                                                   &open_tables_state_backup,
4304                                                   can_deadlock);
4305 
4306               thd->pop_internal_handler();
4307 
4308               if (!res)
4309                 continue;
4310             }
4311 
4312             DEBUG_SYNC(thd, "before_open_in_get_all_tables");
4313 
4314             if (fill_schema_table_by_open(thd, FALSE,
4315                                           table, schema_table,
4316                                           db_name, table_name,
4317                                           &open_tables_state_backup,
4318                                           can_deadlock))
4319               goto err;
4320           }
4321         }
4322       }
4323       /*
4324         If we have information schema its always the first table and only
4325         the first table. Reset for other tables.
4326       */
4327       with_i_schema= 0;
4328     }
4329   }
4330   error= 0;
4331 err:
4332 
4333   free_root(&tmp_mem_root, MYF(0));
4334   thd->restore_backup_open_tables_state(&open_tables_state_backup);
4335 
4336   DBUG_RETURN(error);
4337 }
4338 
4339 
store_schema_shemata(THD * thd,TABLE * table,LEX_STRING * db_name,const CHARSET_INFO * cs)4340 bool store_schema_shemata(THD* thd, TABLE *table, LEX_STRING *db_name,
4341                           const CHARSET_INFO *cs)
4342 {
4343   restore_record(table, s->default_values);
4344   table->field[0]->store(STRING_WITH_LEN("def"), system_charset_info);
4345   table->field[1]->store(db_name->str, db_name->length, system_charset_info);
4346   table->field[2]->store(cs->csname, strlen(cs->csname), system_charset_info);
4347   table->field[3]->store(cs->name, strlen(cs->name), system_charset_info);
4348   return schema_table_store_record(thd, table);
4349 }
4350 
4351 
fill_schema_schemata(THD * thd,TABLE_LIST * tables,Item * cond)4352 int fill_schema_schemata(THD *thd, TABLE_LIST *tables, Item *cond)
4353 {
4354   /*
4355     TODO: fill_schema_shemata() is called when new client is connected.
4356     Returning error status in this case leads to client hangup.
4357   */
4358 
4359   /*
4360    * A temporary class is created to free tmp_mem_root when we return from
4361    * this function, since we have 'return' from this function from many
4362    * places. This is just to avoid goto.
4363    */
4364   class free_tmp_mem_root
4365   {
4366   public:
4367     free_tmp_mem_root()
4368     {
4369       init_sql_alloc(&tmp_mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
4370     }
4371     ~free_tmp_mem_root()
4372     {
4373       free_root(&tmp_mem_root, MYF(0));
4374     }
4375     MEM_ROOT tmp_mem_root;
4376   };
4377 
4378   free_tmp_mem_root dummy_member;
4379 
4380   LOOKUP_FIELD_VALUES lookup_field_vals;
4381   List<LEX_STRING> db_names;
4382   LEX_STRING *db_name;
4383   bool with_i_schema;
4384   HA_CREATE_INFO create;
4385   TABLE *table= tables->table;
4386 #ifndef NO_EMBEDDED_ACCESS_CHECKS
4387   Security_context *sctx= thd->security_ctx;
4388 #endif
4389   DBUG_ENTER("fill_schema_shemata");
4390 
4391   if (get_lookup_field_values(thd, cond, tables, &lookup_field_vals))
4392     DBUG_RETURN(0);
4393 
4394   DBUG_PRINT("INDEX VALUES",("db_name='%s', table_name='%s'",
4395                              lookup_field_vals.db_value.str,
4396                              lookup_field_vals.table_value.str));
4397   if (make_db_list(thd, &db_names, &lookup_field_vals,
4398                    &with_i_schema, &dummy_member.tmp_mem_root))
4399     DBUG_RETURN(1);
4400 
4401   /*
4402     If we have lookup db value we should check that the database exists
4403   */
4404   if(lookup_field_vals.db_value.str && !lookup_field_vals.wild_db_value &&
4405      !with_i_schema)
4406   {
4407     char path[FN_REFLEN+16];
4408     uint path_len;
4409     MY_STAT stat_info;
4410     if (!lookup_field_vals.db_value.str[0])
4411       DBUG_RETURN(0);
4412     path_len= build_table_filename(path, sizeof(path) - 1,
4413                                    lookup_field_vals.db_value.str, "", "", 0);
4414     path[path_len-1]= 0;
4415     if (!mysql_file_stat(key_file_misc, path, &stat_info, MYF(0)))
4416       DBUG_RETURN(0);
4417   }
4418 
4419   List_iterator_fast<LEX_STRING> it(db_names);
4420   while ((db_name=it++))
4421   {
4422     DBUG_ASSERT(db_name->length <= NAME_LEN);
4423     if (with_i_schema)       // information schema name is always first in list
4424     {
4425       if (store_schema_shemata(thd, table, db_name,
4426                                system_charset_info))
4427         DBUG_RETURN(1);
4428       with_i_schema= 0;
4429       continue;
4430     }
4431 #ifndef NO_EMBEDDED_ACCESS_CHECKS
4432     if (sctx->master_access & (DB_ACLS | SHOW_DB_ACL) ||
4433 	acl_get(sctx->get_host()->ptr(), sctx->get_ip()->ptr(),
4434                 sctx->priv_user, db_name->str, 0) ||
4435 	!check_grant_db(thd, db_name->str))
4436 #endif
4437     {
4438       load_db_opt_by_name(thd, db_name->str, &create);
4439       if (store_schema_shemata(thd, table, db_name,
4440                                create.default_table_charset))
4441         DBUG_RETURN(1);
4442     }
4443   }
4444   DBUG_RETURN(0);
4445 }
4446 
4447 
get_schema_tables_record(THD * thd,TABLE_LIST * tables,TABLE * table,bool res,LEX_STRING * db_name,LEX_STRING * table_name)4448 static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
4449 				    TABLE *table, bool res,
4450 				    LEX_STRING *db_name,
4451 				    LEX_STRING *table_name)
4452 {
4453   const char *tmp_buff;
4454   MYSQL_TIME time;
4455   int info_error= 0;
4456   CHARSET_INFO *cs= system_charset_info;
4457   DBUG_ENTER("get_schema_tables_record");
4458 
4459   restore_record(table, s->default_values);
4460   table->field[0]->store(STRING_WITH_LEN("def"), cs);
4461   table->field[1]->store(db_name->str, db_name->length, cs);
4462   table->field[2]->store(table_name->str, table_name->length, cs);
4463 
4464   if (res)
4465   {
4466     /* There was a table open error, so set the table type and return */
4467     if (tables->view)
4468       table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
4469     else if (tables->schema_table)
4470       table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
4471     else
4472       table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
4473 
4474     goto err;
4475   }
4476 
4477   if (tables->view)
4478   {
4479     table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
4480     table->field[20]->store(STRING_WITH_LEN("VIEW"), cs);
4481   }
4482   else
4483   {
4484     char option_buff[350],*ptr;
4485     TABLE *show_table= tables->table;
4486     TABLE_SHARE *share= show_table->s;
4487     handler *file= show_table->file;
4488     handlerton *tmp_db_type= share->db_type();
4489 #ifdef WITH_PARTITION_STORAGE_ENGINE
4490     bool is_partitioned= FALSE;
4491 #endif
4492 
4493     if (share->tmp_table == SYSTEM_TMP_TABLE)
4494       table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
4495     else if (share->tmp_table)
4496       table->field[3]->store(STRING_WITH_LEN("LOCAL TEMPORARY"), cs);
4497     else
4498       table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
4499 
4500     for (int i= 4; i < 20; i++)
4501     {
4502       if (i == 7 || (i > 12 && i < 17) || i == 18)
4503         continue;
4504       table->field[i]->set_notnull();
4505     }
4506 
4507     /* Collect table info from the table share */
4508 
4509 #ifdef WITH_PARTITION_STORAGE_ENGINE
4510     if (share->db_type() == partition_hton &&
4511         share->partition_info_str_len)
4512     {
4513       tmp_db_type= share->default_part_db_type;
4514       is_partitioned= TRUE;
4515     }
4516 #endif
4517 
4518     tmp_buff= (char *) ha_resolve_storage_engine_name(tmp_db_type);
4519     table->field[4]->store(tmp_buff, strlen(tmp_buff), cs);
4520     table->field[5]->store((longlong) share->frm_version, TRUE);
4521 
4522     ptr=option_buff;
4523 
4524     if (share->min_rows)
4525     {
4526       ptr=strmov(ptr," min_rows=");
4527       ptr=longlong10_to_str(share->min_rows,ptr,10);
4528     }
4529 
4530     if (share->max_rows)
4531     {
4532       ptr=strmov(ptr," max_rows=");
4533       ptr=longlong10_to_str(share->max_rows,ptr,10);
4534     }
4535 
4536     if (share->avg_row_length)
4537     {
4538       ptr=strmov(ptr," avg_row_length=");
4539       ptr=longlong10_to_str(share->avg_row_length,ptr,10);
4540     }
4541 
4542     if (share->db_create_options & HA_OPTION_PACK_KEYS)
4543       ptr=strmov(ptr," pack_keys=1");
4544 
4545     if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
4546       ptr=strmov(ptr," pack_keys=0");
4547 
4548     if (share->db_create_options & HA_OPTION_STATS_PERSISTENT)
4549       ptr=strmov(ptr," stats_persistent=1");
4550 
4551     if (share->db_create_options & HA_OPTION_NO_STATS_PERSISTENT)
4552       ptr=strmov(ptr," stats_persistent=0");
4553 
4554     if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON)
4555       ptr=strmov(ptr," stats_auto_recalc=1");
4556     else if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF)
4557       ptr=strmov(ptr," stats_auto_recalc=0");
4558 
4559     if (share->stats_sample_pages != 0)
4560     {
4561       ptr= strmov(ptr, " stats_sample_pages=");
4562       ptr= longlong10_to_str(share->stats_sample_pages, ptr, 10);
4563     }
4564 
4565     /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
4566     if (share->db_create_options & HA_OPTION_CHECKSUM)
4567       ptr=strmov(ptr," checksum=1");
4568 
4569     if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
4570       ptr=strmov(ptr," delay_key_write=1");
4571 
4572     if (share->row_type != ROW_TYPE_DEFAULT)
4573       ptr=strxmov(ptr, " row_format=",
4574                   ha_row_type[(uint) share->row_type],
4575                   NullS);
4576 
4577     if (share->key_block_size)
4578     {
4579       ptr= strmov(ptr, " KEY_BLOCK_SIZE=");
4580       ptr= longlong10_to_str(share->key_block_size, ptr, 10);
4581     }
4582 
4583 #ifdef WITH_PARTITION_STORAGE_ENGINE
4584     if (is_partitioned)
4585       ptr= strmov(ptr, " partitioned");
4586 #endif
4587 
4588     table->field[19]->store(option_buff+1,
4589                             (ptr == option_buff ? 0 :
4590                              (uint) (ptr-option_buff)-1), cs);
4591 
4592     tmp_buff= (share->table_charset ?
4593                share->table_charset->name : "default");
4594 
4595     table->field[17]->store(tmp_buff, strlen(tmp_buff), cs);
4596 
4597     if (share->comment.str)
4598       table->field[20]->store(share->comment.str, share->comment.length, cs);
4599 
4600     /* Collect table info from the storage engine  */
4601 
4602     if(file)
4603     {
4604       /* If info() fails, then there's nothing else to do */
4605       if ((info_error= file->info(HA_STATUS_VARIABLE |
4606                                   HA_STATUS_TIME |
4607                                   HA_STATUS_VARIABLE_EXTRA |
4608                                   HA_STATUS_AUTO)) != 0)
4609         goto err;
4610 
4611       enum row_type row_type = file->get_row_type();
4612       switch (row_type) {
4613       case ROW_TYPE_NOT_USED:
4614       case ROW_TYPE_DEFAULT:
4615         tmp_buff= ((share->db_options_in_use &
4616                     HA_OPTION_COMPRESS_RECORD) ? "Compressed" :
4617                    (share->db_options_in_use & HA_OPTION_PACK_RECORD) ?
4618                    "Dynamic" : "Fixed");
4619         break;
4620       case ROW_TYPE_FIXED:
4621         tmp_buff= "Fixed";
4622         break;
4623       case ROW_TYPE_DYNAMIC:
4624         tmp_buff= "Dynamic";
4625         break;
4626       case ROW_TYPE_COMPRESSED:
4627         tmp_buff= "Compressed";
4628         break;
4629       case ROW_TYPE_REDUNDANT:
4630         tmp_buff= "Redundant";
4631         break;
4632       case ROW_TYPE_COMPACT:
4633         tmp_buff= "Compact";
4634         break;
4635       case ROW_TYPE_PAGE:
4636         tmp_buff= "Paged";
4637         break;
4638       }
4639 
4640       table->field[6]->store(tmp_buff, strlen(tmp_buff), cs);
4641 
4642       if (!tables->schema_table)
4643       {
4644         table->field[7]->store((longlong) file->stats.records, TRUE);
4645         table->field[7]->set_notnull();
4646       }
4647       table->field[8]->store((longlong) file->stats.mean_rec_length, TRUE);
4648       table->field[9]->store((longlong) file->stats.data_file_length, TRUE);
4649       if (file->stats.max_data_file_length)
4650       {
4651         table->field[10]->store((longlong) file->stats.max_data_file_length,
4652                                 TRUE);
4653       }
4654       table->field[11]->store((longlong) file->stats.index_file_length, TRUE);
4655       table->field[12]->store((longlong) file->stats.delete_length, TRUE);
4656       if (show_table->found_next_number_field)
4657       {
4658         table->field[13]->store((longlong) file->stats.auto_increment_value,
4659                                 TRUE);
4660         table->field[13]->set_notnull();
4661       }
4662       if (file->stats.create_time)
4663       {
4664         thd->variables.time_zone->gmt_sec_to_TIME(&time,
4665                                                   (my_time_t) file->stats.create_time);
4666         table->field[14]->store_time(&time);
4667         table->field[14]->set_notnull();
4668       }
4669       if (file->stats.update_time)
4670       {
4671         thd->variables.time_zone->gmt_sec_to_TIME(&time,
4672                                                   (my_time_t) file->stats.update_time);
4673         table->field[15]->store_time(&time);
4674         table->field[15]->set_notnull();
4675       }
4676       if (file->stats.check_time)
4677       {
4678         thd->variables.time_zone->gmt_sec_to_TIME(&time,
4679                                                   (my_time_t) file->stats.check_time);
4680         table->field[16]->store_time(&time);
4681         table->field[16]->set_notnull();
4682       }
4683       if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM)
4684       {
4685         table->field[18]->store((longlong) file->checksum(), TRUE);
4686         table->field[18]->set_notnull();
4687       }
4688     }
4689   }
4690 
4691 err:
4692   if (res || info_error)
4693   {
4694     /*
4695       If an error was encountered, push a warning, set the TABLE COMMENT
4696       column with the error text, and clear the error so that the operation
4697       can continue.
4698     */
4699     const char *error= thd->is_error() ? thd->get_stmt_da()->message() : "";
4700     table->field[20]->store(error, strlen(error), cs);
4701 
4702     if (thd->is_error())
4703     {
4704       push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
4705                    thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message());
4706       thd->clear_error();
4707     }
4708   }
4709 
4710   DBUG_RETURN(schema_table_store_record(thd, table));
4711 }
4712 
4713 
4714 /**
4715   @brief    Store field characteristics into appropriate I_S table columns
4716             starting from DATA_TYPE column till DTD_IDENTIFIER column.
4717 
4718   @param[in]      thd               Thread context.
4719   @param[in]      table             I_S table
4720   @param[in]      field             processed field
4721   @param[in]      cs                I_S table charset
4722   @param[in]      offset            offset from beginning of table
4723                                     to DATE_TYPE column in I_S table
4724   @return         void
4725 */
4726 
store_column_type(THD * thd,TABLE * table,Field * field,CHARSET_INFO * cs,uint offset)4727 void store_column_type(THD *thd, TABLE *table, Field *field, CHARSET_INFO *cs,
4728                        uint offset)
4729 {
4730   bool is_blob;
4731   int decimals, field_length;
4732   const char *tmp_buff;
4733   char column_type_buff[MAX_FIELD_WIDTH];
4734   String column_type(column_type_buff, sizeof(column_type_buff), cs);
4735   enum_field_types field_type= field->real_type();
4736   uint32 orig_column_type_length;
4737 
4738   field->sql_type(column_type);
4739   orig_column_type_length= column_type.length();
4740 
4741   /*
4742     If the session variable 'show_old_temporals' is enabled and the field
4743     is a temporal type of old format, add a comment to the COLUMN_TYPE
4744     indicate the same.
4745   */
4746   if (thd->variables.show_old_temporals &&
4747       (field_type == MYSQL_TYPE_TIME || field_type == MYSQL_TYPE_DATETIME ||
4748        field_type == MYSQL_TYPE_TIMESTAMP))
4749     column_type.append(" /* 5.5 binary format */");
4750 
4751   /* DTD_IDENTIFIER column */
4752   table->field[offset + 8]->store(column_type.ptr(), column_type.length(), cs);
4753   column_type.length(orig_column_type_length);
4754   table->field[offset + 8]->set_notnull();
4755   /*
4756     DATA_TYPE column:
4757     MySQL column type has the following format:
4758     base_type [(dimension)] [unsigned] [zerofill].
4759     For DATA_TYPE column we extract only base type.
4760   */
4761   tmp_buff= strchr(column_type.ptr(), '(');
4762   if (!tmp_buff)
4763     /*
4764       if there is no dimention part then check the presence of
4765       [unsigned] [zerofill] attributes and cut them of if exist.
4766     */
4767     tmp_buff= strchr(column_type.ptr(), ' ');
4768   table->field[offset]->store(column_type.ptr(),
4769                               (tmp_buff ? tmp_buff - column_type.ptr() :
4770                                column_type.length()), cs);
4771 
4772   is_blob= (field->type() == MYSQL_TYPE_BLOB);
4773   if (field->has_charset() || is_blob ||
4774       field->real_type() == MYSQL_TYPE_VARCHAR ||  // For varbinary type
4775       field->real_type() == MYSQL_TYPE_STRING)     // For binary type
4776   {
4777     uint32 octet_max_length= field->max_display_length();
4778     if (is_blob && octet_max_length != (uint32) 4294967295U)
4779       octet_max_length /= field->charset()->mbmaxlen;
4780     longlong char_max_len= is_blob ?
4781       (longlong) octet_max_length / field->charset()->mbminlen :
4782       (longlong) octet_max_length / field->charset()->mbmaxlen;
4783     /* CHARACTER_MAXIMUM_LENGTH column*/
4784     table->field[offset + 1]->store(char_max_len, TRUE);
4785     table->field[offset + 1]->set_notnull();
4786     /* CHARACTER_OCTET_LENGTH column */
4787     table->field[offset + 2]->store((longlong) octet_max_length, TRUE);
4788     table->field[offset + 2]->set_notnull();
4789   }
4790 
4791   /*
4792     Calculate field_length and decimals.
4793     They are set to -1 if they should not be set (we should return NULL)
4794   */
4795 
4796   decimals= field->decimals();
4797   switch (field->type()) {
4798   case MYSQL_TYPE_NEWDECIMAL:
4799     field_length= ((Field_new_decimal*) field)->precision;
4800     break;
4801   case MYSQL_TYPE_DECIMAL:
4802     field_length= field->field_length - (decimals  ? 2 : 1);
4803     break;
4804   case MYSQL_TYPE_TINY:
4805   case MYSQL_TYPE_SHORT:
4806   case MYSQL_TYPE_LONG:
4807   case MYSQL_TYPE_INT24:
4808     field_length= field->max_display_length() - 1;
4809     break;
4810   case MYSQL_TYPE_LONGLONG:
4811     field_length= field->max_display_length() -
4812       ((field->flags & UNSIGNED_FLAG) ? 0 : 1);
4813     break;
4814   case MYSQL_TYPE_BIT:
4815     field_length= field->max_display_length();
4816     decimals= -1;                             // return NULL
4817     break;
4818   case MYSQL_TYPE_FLOAT:
4819   case MYSQL_TYPE_DOUBLE:
4820     field_length= field->field_length;
4821     if (decimals == NOT_FIXED_DEC)
4822       decimals= -1;                           // return NULL
4823     break;
4824   case MYSQL_TYPE_DATETIME:
4825   case MYSQL_TYPE_TIMESTAMP:
4826   case MYSQL_TYPE_TIME:
4827     /* DATETIME_PRECISION column */
4828     table->field[offset + 5]->store(field->decimals(), TRUE);
4829     table->field[offset + 5]->set_notnull();
4830     field_length= decimals= -1;
4831     break;
4832   default:
4833     field_length= decimals= -1;
4834     break;
4835   }
4836 
4837   /* NUMERIC_PRECISION column */
4838   if (field_length >= 0)
4839   {
4840     table->field[offset + 3]->store((longlong) field_length, TRUE);
4841     table->field[offset + 3]->set_notnull();
4842   }
4843   /* NUMERIC_SCALE column */
4844   if (decimals >= 0)
4845   {
4846     table->field[offset + 4]->store((longlong) decimals, TRUE);
4847     table->field[offset + 4]->set_notnull();
4848   }
4849   if (field->has_charset())
4850   {
4851     /* CHARACTER_SET_NAME column*/
4852     tmp_buff= field->charset()->csname;
4853     table->field[offset + 6]->store(tmp_buff, strlen(tmp_buff), cs);
4854     table->field[offset + 6]->set_notnull();
4855     /* COLLATION_NAME column */
4856     tmp_buff= field->charset()->name;
4857     table->field[offset + 7]->store(tmp_buff, strlen(tmp_buff), cs);
4858     table->field[offset + 7]->set_notnull();
4859   }
4860 }
4861 
4862 
get_schema_column_record(THD * thd,TABLE_LIST * tables,TABLE * table,bool res,LEX_STRING * db_name,LEX_STRING * table_name)4863 static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
4864 				    TABLE *table, bool res,
4865 				    LEX_STRING *db_name,
4866 				    LEX_STRING *table_name)
4867 {
4868   LEX *lex= thd->lex;
4869   const char *wild= lex->wild ? lex->wild->ptr() : NullS;
4870   CHARSET_INFO *cs= system_charset_info;
4871   TABLE *show_table;
4872   Field **ptr, *field;
4873   int count;
4874   DBUG_ENTER("get_schema_column_record");
4875 
4876   if (res)
4877   {
4878     if (lex->sql_command != SQLCOM_SHOW_FIELDS)
4879     {
4880       /*
4881         I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
4882         rather than in SHOW COLUMNS
4883       */
4884       if (thd->is_error())
4885         push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
4886                      thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message());
4887       thd->clear_error();
4888       res= 0;
4889     }
4890     DBUG_RETURN(res);
4891   }
4892 
4893   show_table= tables->table;
4894   count= 0;
4895   ptr= show_table->field;
4896   show_table->use_all_columns();               // Required for default
4897   restore_record(show_table, s->default_values);
4898 
4899   for (; (field= *ptr) ; ptr++)
4900   {
4901     uchar *pos;
4902     char tmp[MAX_FIELD_WIDTH];
4903     String type(tmp,sizeof(tmp), system_charset_info);
4904 
4905     DEBUG_SYNC(thd, "get_schema_column");
4906 
4907     if (wild && wild[0] &&
4908         wild_case_compare(system_charset_info, field->field_name,wild))
4909       continue;
4910 
4911     count++;
4912     /* Get default row, with all NULL fields set to NULL */
4913     restore_record(table, s->default_values);
4914 
4915 #ifndef NO_EMBEDDED_ACCESS_CHECKS
4916     uint col_access;
4917     check_access(thd,SELECT_ACL, db_name->str,
4918                  &tables->grant.privilege, 0, 0, MY_TEST(tables->schema_table));
4919     col_access= get_column_grant(thd, &tables->grant,
4920                                  db_name->str, table_name->str,
4921                                  field->field_name) & COL_ACLS;
4922     if (!tables->schema_table && !col_access)
4923       continue;
4924     char *end= tmp;
4925     for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
4926     {
4927       if (col_access & 1)
4928       {
4929         *end++=',';
4930         end=strmov(end,grant_types.type_names[bitnr]);
4931       }
4932     }
4933     table->field[IS_COLUMNS_PRIVILEGES]->store(tmp+1,
4934                                                end == tmp ? 0 :
4935                                                (uint) (end-tmp-1), cs);
4936 
4937 #endif
4938     table->field[IS_COLUMNS_TABLE_CATALOG]->store(STRING_WITH_LEN("def"), cs);
4939     table->field[IS_COLUMNS_TABLE_SCHEMA]->store(db_name->str,
4940                                                  db_name->length, cs);
4941     table->field[IS_COLUMNS_TABLE_NAME]->store(table_name->str,
4942                                                table_name->length, cs);
4943     table->field[IS_COLUMNS_COLUMN_NAME]->store(field->field_name,
4944                                                 strlen(field->field_name), cs);
4945     table->field[IS_COLUMNS_ORDINAL_POSITION]->store((longlong) count, TRUE);
4946     field->sql_type(type);
4947     table->field[IS_COLUMNS_COLUMN_TYPE]->store(type.ptr(), type.length(), cs);
4948 
4949     if (print_default_clause(thd, field, &type, false))
4950     {
4951       table->field[IS_COLUMNS_COLUMN_DEFAULT]->store(type.ptr(), type.length(),
4952                                                     cs);
4953       table->field[IS_COLUMNS_COLUMN_DEFAULT]->set_notnull();
4954     }
4955     pos=(uchar*) ((field->flags & NOT_NULL_FLAG) ?  "NO" : "YES");
4956     table->field[IS_COLUMNS_IS_NULLABLE]->store((const char*) pos,
4957                            strlen((const char*) pos), cs);
4958     store_column_type(thd, table, field, cs, IS_COLUMNS_DATA_TYPE);
4959     pos=(uchar*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
4960                  (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
4961                  (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
4962     table->field[IS_COLUMNS_COLUMN_KEY]->store((const char*) pos,
4963                             strlen((const char*) pos), cs);
4964 
4965     if (field->unireg_check == Field::NEXT_NUMBER)
4966       table->field[IS_COLUMNS_EXTRA]->store(STRING_WITH_LEN("auto_increment"),
4967                                             cs);
4968     if (print_on_update_clause(field, &type, true))
4969       table->field[IS_COLUMNS_EXTRA]->store(type.ptr(), type.length(), cs);
4970     table->field[IS_COLUMNS_COLUMN_COMMENT]->store(field->comment.str,
4971                                                    field->comment.length, cs);
4972     if (schema_table_store_record(thd, table))
4973       DBUG_RETURN(1);
4974   }
4975   DBUG_RETURN(0);
4976 }
4977 
4978 
fill_schema_charsets(THD * thd,TABLE_LIST * tables,Item * cond)4979 int fill_schema_charsets(THD *thd, TABLE_LIST *tables, Item *cond)
4980 {
4981   CHARSET_INFO **cs;
4982   const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
4983   TABLE *table= tables->table;
4984   CHARSET_INFO *scs= system_charset_info;
4985 
4986   for (cs= all_charsets ;
4987        cs < all_charsets + array_elements(all_charsets) ;
4988        cs++)
4989   {
4990     CHARSET_INFO *tmp_cs= cs[0];
4991     if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) &&
4992         (tmp_cs->state & MY_CS_AVAILABLE) &&
4993         !(tmp_cs->state & MY_CS_HIDDEN) &&
4994         !(wild && wild[0] &&
4995 	  wild_case_compare(scs, tmp_cs->csname,wild)))
4996     {
4997       const char *comment;
4998       restore_record(table, s->default_values);
4999       table->field[0]->store(tmp_cs->csname, strlen(tmp_cs->csname), scs);
5000       table->field[1]->store(tmp_cs->name, strlen(tmp_cs->name), scs);
5001       comment= tmp_cs->comment ? tmp_cs->comment : "";
5002       table->field[2]->store(comment, strlen(comment), scs);
5003       table->field[3]->store((longlong) tmp_cs->mbmaxlen, TRUE);
5004       if (schema_table_store_record(thd, table))
5005         return 1;
5006     }
5007   }
5008   return 0;
5009 }
5010 
5011 
iter_schema_engines(THD * thd,plugin_ref plugin,void * ptable)5012 static my_bool iter_schema_engines(THD *thd, plugin_ref plugin,
5013                                    void *ptable)
5014 {
5015   TABLE *table= (TABLE *) ptable;
5016   handlerton *hton= plugin_data(plugin, handlerton *);
5017   const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
5018   CHARSET_INFO *scs= system_charset_info;
5019   handlerton *default_type= ha_default_handlerton(thd);
5020   DBUG_ENTER("iter_schema_engines");
5021 
5022 
5023   /* Disabled plugins */
5024   if (plugin_state(plugin) != PLUGIN_IS_READY)
5025   {
5026 
5027     struct st_mysql_plugin *plug= plugin_decl(plugin);
5028     if (!(wild && wild[0] &&
5029           wild_case_compare(scs, plug->name,wild)))
5030     {
5031       restore_record(table, s->default_values);
5032       table->field[0]->store(plug->name, strlen(plug->name), scs);
5033       table->field[1]->store(C_STRING_WITH_LEN("NO"), scs);
5034       table->field[2]->store(plug->descr, strlen(plug->descr), scs);
5035       if (schema_table_store_record(thd, table))
5036         DBUG_RETURN(1);
5037     }
5038     DBUG_RETURN(0);
5039   }
5040 
5041   if (!(hton->flags & HTON_HIDDEN))
5042   {
5043     LEX_STRING *name= plugin_name(plugin);
5044     if (!(wild && wild[0] &&
5045           wild_case_compare(scs, name->str,wild)))
5046     {
5047       LEX_STRING yesno[2]= {{ C_STRING_WITH_LEN("NO") },
5048                             { C_STRING_WITH_LEN("YES") }};
5049       LEX_STRING *tmp;
5050       const char *option_name= show_comp_option_name[(int) hton->state];
5051       restore_record(table, s->default_values);
5052 
5053       table->field[0]->store(name->str, name->length, scs);
5054       if (hton->state == SHOW_OPTION_YES && default_type == hton)
5055         option_name= "DEFAULT";
5056       table->field[1]->store(option_name, strlen(option_name), scs);
5057       table->field[2]->store(plugin_decl(plugin)->descr,
5058                              strlen(plugin_decl(plugin)->descr), scs);
5059       tmp= &yesno[MY_TEST(hton->commit)];
5060       table->field[3]->store(tmp->str, tmp->length, scs);
5061       table->field[3]->set_notnull();
5062       tmp= &yesno[MY_TEST(hton->prepare)];
5063       table->field[4]->store(tmp->str, tmp->length, scs);
5064       table->field[4]->set_notnull();
5065       tmp= &yesno[MY_TEST(hton->savepoint_set)];
5066       table->field[5]->store(tmp->str, tmp->length, scs);
5067       table->field[5]->set_notnull();
5068 
5069       if (schema_table_store_record(thd, table))
5070         DBUG_RETURN(1);
5071     }
5072   }
5073   DBUG_RETURN(0);
5074 }
5075 
fill_schema_engines(THD * thd,TABLE_LIST * tables,Item * cond)5076 int fill_schema_engines(THD *thd, TABLE_LIST *tables, Item *cond)
5077 {
5078   DBUG_ENTER("fill_schema_engines");
5079   if (plugin_foreach_with_mask(thd, iter_schema_engines,
5080                                MYSQL_STORAGE_ENGINE_PLUGIN,
5081                                ~PLUGIN_IS_FREED, tables->table))
5082     DBUG_RETURN(1);
5083   DBUG_RETURN(0);
5084 }
5085 
5086 
fill_schema_collation(THD * thd,TABLE_LIST * tables,Item * cond)5087 int fill_schema_collation(THD *thd, TABLE_LIST *tables, Item *cond)
5088 {
5089   CHARSET_INFO **cs;
5090   const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
5091   TABLE *table= tables->table;
5092   CHARSET_INFO *scs= system_charset_info;
5093   for (cs= all_charsets ;
5094        cs < all_charsets + array_elements(all_charsets)  ;
5095        cs++ )
5096   {
5097     CHARSET_INFO **cl;
5098     CHARSET_INFO *tmp_cs= cs[0];
5099     if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
5100          (tmp_cs->state & MY_CS_HIDDEN) ||
5101         !(tmp_cs->state & MY_CS_PRIMARY))
5102       continue;
5103     for (cl= all_charsets;
5104          cl < all_charsets + array_elements(all_charsets)  ;
5105          cl ++)
5106     {
5107       CHARSET_INFO *tmp_cl= cl[0];
5108       if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) ||
5109           !my_charset_same(tmp_cs, tmp_cl))
5110 	continue;
5111       if (!(wild && wild[0] &&
5112 	  wild_case_compare(scs, tmp_cl->name,wild)))
5113       {
5114 	const char *tmp_buff;
5115 	restore_record(table, s->default_values);
5116 	table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
5117         table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
5118         table->field[2]->store((longlong) tmp_cl->number, TRUE);
5119         tmp_buff= (tmp_cl->state & MY_CS_PRIMARY) ? "Yes" : "";
5120 	table->field[3]->store(tmp_buff, strlen(tmp_buff), scs);
5121         tmp_buff= (tmp_cl->state & MY_CS_COMPILED)? "Yes" : "";
5122 	table->field[4]->store(tmp_buff, strlen(tmp_buff), scs);
5123         table->field[5]->store((longlong) tmp_cl->strxfrm_multiply, TRUE);
5124         if (schema_table_store_record(thd, table))
5125           return 1;
5126       }
5127     }
5128   }
5129   return 0;
5130 }
5131 
5132 
fill_schema_coll_charset_app(THD * thd,TABLE_LIST * tables,Item * cond)5133 int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, Item *cond)
5134 {
5135   CHARSET_INFO **cs;
5136   TABLE *table= tables->table;
5137   CHARSET_INFO *scs= system_charset_info;
5138   for (cs= all_charsets ;
5139        cs < all_charsets + array_elements(all_charsets) ;
5140        cs++ )
5141   {
5142     CHARSET_INFO **cl;
5143     CHARSET_INFO *tmp_cs= cs[0];
5144     if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
5145         !(tmp_cs->state & MY_CS_PRIMARY))
5146       continue;
5147     for (cl= all_charsets;
5148          cl < all_charsets + array_elements(all_charsets) ;
5149          cl ++)
5150     {
5151       CHARSET_INFO *tmp_cl= cl[0];
5152       if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) ||
5153           (tmp_cl->state & MY_CS_HIDDEN) ||
5154           !my_charset_same(tmp_cs,tmp_cl))
5155 	continue;
5156       restore_record(table, s->default_values);
5157       table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
5158       table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
5159       if (schema_table_store_record(thd, table))
5160         return 1;
5161     }
5162   }
5163   return 0;
5164 }
5165 
5166 
copy_field_as_string(Field * to_field,Field * from_field)5167 static inline void copy_field_as_string(Field *to_field, Field *from_field)
5168 {
5169   char buff[MAX_FIELD_WIDTH];
5170   String tmp_str(buff, sizeof(buff), system_charset_info);
5171   from_field->val_str(&tmp_str);
5172   to_field->store(tmp_str.ptr(), tmp_str.length(), system_charset_info);
5173 }
5174 
5175 
5176 /**
5177   @brief Store record into I_S.PARAMETERS table
5178 
5179   @param[in]      thd                   thread handler
5180   @param[in]      table                 I_S table
5181   @param[in]      proc_table            'mysql.proc' table
5182   @param[in]      wild                  wild string, not used for now,
5183                                         will be useful
5184                                         if we add 'SHOW PARAMETERs'
5185   @param[in]      full_access           if 1 user has privileges on the routine
5186   @param[in]      sp_user               user in 'user@host' format
5187 
5188   @return         Operation status
5189     @retval       0                     ok
5190     @retval       1                     error
5191 */
5192 
store_schema_params(THD * thd,TABLE * table,TABLE * proc_table,const char * wild,bool full_access,const char * sp_user)5193 bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
5194                          const char *wild, bool full_access,
5195                          const char *sp_user)
5196 {
5197   TABLE_SHARE share;
5198   TABLE tbl;
5199   CHARSET_INFO *cs= system_charset_info;
5200   char params_buff[MAX_FIELD_WIDTH], returns_buff[MAX_FIELD_WIDTH],
5201     sp_db_buff[NAME_LEN], sp_name_buff[NAME_LEN], path[FN_REFLEN],
5202     definer_buff[USERNAME_LENGTH + HOSTNAME_LENGTH + 1];
5203   String params(params_buff, sizeof(params_buff), cs);
5204   String returns(returns_buff, sizeof(returns_buff), cs);
5205   String sp_db(sp_db_buff, sizeof(sp_db_buff), cs);
5206   String sp_name(sp_name_buff, sizeof(sp_name_buff), cs);
5207   String definer(definer_buff, sizeof(definer_buff), cs);
5208   sp_head *sp;
5209   enum_sp_type routine_type;
5210   bool free_sp_head;
5211   DBUG_ENTER("store_schema_params");
5212 
5213   memset(&tbl, 0, sizeof(TABLE));
5214   (void) build_table_filename(path, sizeof(path), "", "", "", 0);
5215   init_tmp_table_share(thd, &share, "", 0, "", path);
5216 
5217   get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_DB], &sp_db);
5218   get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_NAME], &sp_name);
5219   get_field(thd->mem_root,proc_table->field[MYSQL_PROC_FIELD_DEFINER],&definer);
5220   routine_type= (enum_sp_type) proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int();
5221 
5222   if (!full_access)
5223     full_access= !strcmp(sp_user, definer.ptr());
5224   if (!full_access &&
5225       check_some_routine_access(thd, sp_db.ptr(),sp_name.ptr(),
5226                                 routine_type == SP_TYPE_PROCEDURE))
5227     DBUG_RETURN(0);
5228 
5229   params.length(0);
5230   get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_PARAM_LIST],
5231             &params);
5232   returns.length(0);
5233   if (routine_type == SP_TYPE_FUNCTION)
5234     get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_RETURNS],
5235               &returns);
5236 
5237   sp= sp_load_for_information_schema(thd, proc_table, &sp_db, &sp_name,
5238                                      (sql_mode_t) proc_table->
5239                                      field[MYSQL_PROC_FIELD_SQL_MODE]->val_int(),
5240                                      routine_type,
5241                                      returns.c_ptr_safe(),
5242                                      params.c_ptr_safe(),
5243                                      &free_sp_head);
5244 
5245   if (sp)
5246   {
5247     Field *field;
5248     Create_field *field_def;
5249     String tmp_string;
5250     if (routine_type == SP_TYPE_FUNCTION)
5251     {
5252       restore_record(table, s->default_values);
5253       table->field[IS_PARAMETERS_SPECIFIC_CATALOG]->store(STRING_WITH_LEN
5254                                                           ("def"), cs);
5255       table->field[IS_PARAMETERS_SPECIFIC_SCHEMA]->store(sp_db.ptr(),
5256                                                          sp_db.length(), cs);
5257       table->field[IS_PARAMETERS_SPECIFIC_NAME]->store(sp_name.ptr(),
5258                                                        sp_name.length(), cs);
5259       table->field[IS_PARAMETERS_ORDINAL_POSITION]->store((longlong) 0, TRUE);
5260       get_field(thd->mem_root, proc_table->field[MYSQL_PROC_MYSQL_TYPE],
5261                 &tmp_string);
5262       table->field[IS_PARAMETERS_ROUTINE_TYPE]->store(tmp_string.ptr(),
5263                                                       tmp_string.length(), cs);
5264       field_def= &sp->m_return_field_def;
5265       field= make_field(&share, (uchar*) 0, field_def->length,
5266                         (uchar*) "", 0, field_def->pack_flag,
5267                         field_def->sql_type, field_def->charset,
5268                         field_def->geom_type, Field::NONE,
5269                         field_def->interval, "");
5270 
5271       field->table= &tbl;
5272       tbl.in_use= thd;
5273       store_column_type(thd, table, field, cs, IS_PARAMETERS_DATA_TYPE);
5274       if (schema_table_store_record(thd, table))
5275       {
5276         free_table_share(&share);
5277         if (free_sp_head)
5278           delete sp;
5279         DBUG_RETURN(1);
5280       }
5281     }
5282 
5283     sp_pcontext *sp_root_parsing_ctx= sp->get_root_parsing_context();
5284 
5285     for (uint i= 0; i < sp_root_parsing_ctx->context_var_count(); i++)
5286     {
5287       const char *tmp_buff;
5288       sp_variable *spvar= sp_root_parsing_ctx->find_variable(i);
5289       field_def= &spvar->field_def;
5290       switch (spvar->mode) {
5291       case sp_variable::MODE_IN:
5292         tmp_buff= "IN";
5293         break;
5294       case sp_variable::MODE_OUT:
5295         tmp_buff= "OUT";
5296         break;
5297       case sp_variable::MODE_INOUT:
5298         tmp_buff= "INOUT";
5299         break;
5300       default:
5301         tmp_buff= "";
5302         break;
5303       }
5304 
5305       restore_record(table, s->default_values);
5306       table->field[IS_PARAMETERS_SPECIFIC_CATALOG]->store(STRING_WITH_LEN
5307                                                           ("def"), cs);
5308       table->field[IS_PARAMETERS_SPECIFIC_SCHEMA]->store(sp_db.ptr(),
5309                                                          sp_db.length(), cs);
5310       table->field[IS_PARAMETERS_SPECIFIC_NAME]->store(sp_name.ptr(),
5311                                                        sp_name.length(), cs);
5312       table->field[IS_PARAMETERS_ORDINAL_POSITION]->store((longlong) i + 1,
5313                                                           TRUE);
5314       table->field[IS_PARAMETERS_PARAMETER_MODE]->store(tmp_buff,
5315                                                         strlen(tmp_buff), cs);
5316       table->field[IS_PARAMETERS_PARAMETER_MODE]->set_notnull();
5317       table->field[IS_PARAMETERS_PARAMETER_NAME]->store(spvar->name.str,
5318                                                         spvar->name.length, cs);
5319       table->field[IS_PARAMETERS_PARAMETER_NAME]->set_notnull();
5320       get_field(thd->mem_root, proc_table->field[MYSQL_PROC_MYSQL_TYPE],
5321                 &tmp_string);
5322       table->field[IS_PARAMETERS_ROUTINE_TYPE]->store(tmp_string.ptr(),
5323                                                       tmp_string.length(), cs);
5324 
5325       field= make_field(&share, (uchar*) 0, field_def->length,
5326                         (uchar*) "", 0, field_def->pack_flag,
5327                         field_def->sql_type, field_def->charset,
5328                         field_def->geom_type, Field::NONE,
5329                         field_def->interval, spvar->name.str);
5330 
5331       field->table= &tbl;
5332       tbl.in_use= thd;
5333       store_column_type(thd, table, field, cs, IS_PARAMETERS_DATA_TYPE);
5334       if (schema_table_store_record(thd, table))
5335       {
5336         free_table_share(&share);
5337         if (free_sp_head)
5338           delete sp;
5339         DBUG_RETURN(1);
5340       }
5341     }
5342     if (free_sp_head)
5343       delete sp;
5344   }
5345   free_table_share(&share);
5346   DBUG_RETURN(0);
5347 }
5348 
5349 
store_schema_proc(THD * thd,TABLE * table,TABLE * proc_table,const char * wild,bool full_access,const char * sp_user)5350 bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
5351                        const char *wild, bool full_access, const char *sp_user)
5352 {
5353   MYSQL_TIME time;
5354   LEX *lex= thd->lex;
5355   CHARSET_INFO *cs= system_charset_info;
5356   char sp_db_buff[NAME_LEN + 1], sp_name_buff[NAME_LEN + 1],
5357     definer_buff[USERNAME_LENGTH + HOSTNAME_LENGTH + 2],
5358     returns_buff[MAX_FIELD_WIDTH];
5359 
5360   String sp_db(sp_db_buff, sizeof(sp_db_buff), cs);
5361   String sp_name(sp_name_buff, sizeof(sp_name_buff), cs);
5362   String definer(definer_buff, sizeof(definer_buff), cs);
5363   String returns(returns_buff, sizeof(returns_buff), cs);
5364 
5365   proc_table->field[MYSQL_PROC_FIELD_DB]->val_str(&sp_db);
5366   proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str(&sp_name);
5367   proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str(&definer);
5368 
5369   enum_sp_type sp_type=
5370     (enum_sp_type) proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int();
5371 
5372   if (!full_access)
5373     full_access= !strcmp(sp_user, definer.c_ptr_safe());
5374   if (!full_access &&
5375       check_some_routine_access(thd, sp_db.c_ptr_safe(), sp_name.c_ptr_safe(),
5376                                 sp_type == SP_TYPE_PROCEDURE))
5377     return 0;
5378 
5379   if ((lex->sql_command == SQLCOM_SHOW_STATUS_PROC &&
5380       sp_type == SP_TYPE_PROCEDURE) ||
5381       (lex->sql_command == SQLCOM_SHOW_STATUS_FUNC &&
5382       sp_type == SP_TYPE_FUNCTION) ||
5383       (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0)
5384   {
5385     restore_record(table, s->default_values);
5386     if (!wild || !wild[0] || !wild_case_compare(system_charset_info,
5387                                                 sp_name.c_ptr_safe(), wild))
5388     {
5389       int enum_idx= (int) proc_table->field[MYSQL_PROC_FIELD_ACCESS]->val_int();
5390       table->field[IS_ROUTINES_ROUTINE_NAME]->store(sp_name.ptr(),
5391                                                     sp_name.length(), cs);
5392 
5393       copy_field_as_string(table->field[IS_ROUTINES_SPECIFIC_NAME],
5394                            proc_table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]);
5395       table->field[IS_ROUTINES_ROUTINE_CATALOG]->store(STRING_WITH_LEN("def"),
5396                                                        cs);
5397       table->field[IS_ROUTINES_ROUTINE_SCHEMA]->store(sp_db.ptr(), sp_db.length(), cs);
5398       copy_field_as_string(table->field[IS_ROUTINES_ROUTINE_TYPE],
5399                            proc_table->field[MYSQL_PROC_MYSQL_TYPE]);
5400 
5401       if (sp_type == SP_TYPE_FUNCTION)
5402       {
5403         sp_head *sp;
5404         bool free_sp_head;
5405         proc_table->field[MYSQL_PROC_FIELD_RETURNS]->val_str(&returns);
5406         sp= sp_load_for_information_schema(thd, proc_table, &sp_db, &sp_name,
5407                                            (sql_mode_t) proc_table->
5408                                            field[MYSQL_PROC_FIELD_SQL_MODE]->
5409                                            val_int(),
5410                                            SP_TYPE_FUNCTION,
5411                                            returns.c_ptr_safe(),
5412                                            "", &free_sp_head);
5413 
5414         if (sp)
5415         {
5416           char path[FN_REFLEN];
5417           TABLE_SHARE share;
5418           TABLE tbl;
5419           Field *field;
5420           Create_field *field_def= &sp->m_return_field_def;
5421 
5422           memset(&tbl, 0, sizeof(TABLE));
5423           (void) build_table_filename(path, sizeof(path), "", "", "", 0);
5424           init_tmp_table_share(thd, &share, "", 0, "", path);
5425           field= make_field(&share, (uchar*) 0, field_def->length,
5426                             (uchar*) "", 0, field_def->pack_flag,
5427                             field_def->sql_type, field_def->charset,
5428                             field_def->geom_type, Field::NONE,
5429                             field_def->interval, "");
5430 
5431           field->table= &tbl;
5432           tbl.in_use= thd;
5433           store_column_type(thd, table, field, cs, IS_ROUTINES_DATA_TYPE);
5434           free_table_share(&share);
5435           if (free_sp_head)
5436             delete sp;
5437         }
5438       }
5439 
5440       if (full_access)
5441       {
5442         copy_field_as_string(table->field[IS_ROUTINES_ROUTINE_DEFINITION],
5443                              proc_table->field[MYSQL_PROC_FIELD_BODY_UTF8]);
5444         table->field[IS_ROUTINES_ROUTINE_DEFINITION]->set_notnull();
5445       }
5446       table->field[IS_ROUTINES_ROUTINE_BODY]->store(STRING_WITH_LEN("SQL"), cs);
5447       table->field[IS_ROUTINES_PARAMETER_STYLE]->store(STRING_WITH_LEN("SQL"),
5448                                                        cs);
5449       copy_field_as_string(table->field[IS_ROUTINES_IS_DETERMINISTIC],
5450                            proc_table->field[MYSQL_PROC_FIELD_DETERMINISTIC]);
5451       table->field[IS_ROUTINES_SQL_DATA_ACCESS]->
5452                    store(sp_data_access_name[enum_idx].str,
5453                          sp_data_access_name[enum_idx].length , cs);
5454       copy_field_as_string(table->field[IS_ROUTINES_SECURITY_TYPE],
5455                            proc_table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]);
5456 
5457       memset(&time, 0, sizeof(time));
5458       proc_table->field[MYSQL_PROC_FIELD_CREATED]->get_time(&time);
5459       table->field[IS_ROUTINES_CREATED]->store_time(&time);
5460       memset(&time, 0, sizeof(time));
5461       proc_table->field[MYSQL_PROC_FIELD_MODIFIED]->get_time(&time);
5462       table->field[IS_ROUTINES_LAST_ALTERED]->store_time(&time);
5463       copy_field_as_string(table->field[IS_ROUTINES_SQL_MODE],
5464                            proc_table->field[MYSQL_PROC_FIELD_SQL_MODE]);
5465       copy_field_as_string(table->field[IS_ROUTINES_ROUTINE_COMMENT],
5466                            proc_table->field[MYSQL_PROC_FIELD_COMMENT]);
5467 
5468       table->field[IS_ROUTINES_DEFINER]->store(definer.ptr(),
5469                                                definer.length(), cs);
5470       copy_field_as_string(table->field[IS_ROUTINES_CHARACTER_SET_CLIENT],
5471                            proc_table->
5472                            field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT]);
5473       copy_field_as_string(table->field[IS_ROUTINES_COLLATION_CONNECTION],
5474                            proc_table->
5475                            field[MYSQL_PROC_FIELD_COLLATION_CONNECTION]);
5476       copy_field_as_string(table->field[IS_ROUTINES_DATABASE_COLLATION],
5477 			   proc_table->field[MYSQL_PROC_FIELD_DB_COLLATION]);
5478 
5479       return schema_table_store_record(thd, table);
5480     }
5481   }
5482   return 0;
5483 }
5484 
5485 
fill_schema_proc(THD * thd,TABLE_LIST * tables,Item * cond)5486 int fill_schema_proc(THD *thd, TABLE_LIST *tables, Item *cond)
5487 {
5488   TABLE *proc_table;
5489   TABLE_LIST proc_tables;
5490   const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
5491   int error, res= 0;
5492   TABLE *table= tables->table;
5493   bool full_access;
5494   char definer[USER_HOST_BUFF_SIZE];
5495   Open_tables_backup open_tables_state_backup;
5496   enum enum_schema_tables schema_table_idx=
5497     get_schema_table_idx(tables->schema_table);
5498   DBUG_ENTER("fill_schema_proc");
5499 
5500   strxmov(definer, thd->security_ctx->priv_user, "@",
5501           thd->security_ctx->priv_host, NullS);
5502   /* We use this TABLE_LIST instance only for checking of privileges. */
5503   memset(&proc_tables, 0, sizeof(proc_tables));
5504   proc_tables.db= (char*) "mysql";
5505   proc_tables.db_length= 5;
5506   proc_tables.table_name= proc_tables.alias= (char*) "proc";
5507   proc_tables.table_name_length= 4;
5508   proc_tables.lock_type= TL_READ;
5509   full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, FALSE,
5510                                    1, TRUE);
5511   if (!(proc_table= open_proc_table_for_read(thd, &open_tables_state_backup)))
5512   {
5513     DBUG_RETURN(1);
5514   }
5515   if ((error= proc_table->file->ha_index_init(0, 1)))
5516   {
5517     proc_table->file->print_error(error, MYF(0));
5518     res= 1;
5519     goto err;
5520   }
5521   if ((error= proc_table->file->ha_index_first(proc_table->record[0])))
5522   {
5523     res= (error == HA_ERR_END_OF_FILE) ? 0 : 1;
5524     if (res)
5525       proc_table->file->print_error(error, MYF(0));
5526     goto err;
5527   }
5528 
5529   if (schema_table_idx == SCH_PROCEDURES ?
5530       store_schema_proc(thd, table, proc_table, wild, full_access, definer) :
5531       store_schema_params(thd, table, proc_table, wild, full_access, definer))
5532   {
5533     res= 1;
5534     goto err;
5535   }
5536   while (!proc_table->file->ha_index_next(proc_table->record[0]))
5537   {
5538     if (schema_table_idx == SCH_PROCEDURES ?
5539         store_schema_proc(thd, table, proc_table, wild, full_access, definer):
5540         store_schema_params(thd, table, proc_table, wild, full_access, definer))
5541     {
5542       res= 1;
5543       goto err;
5544     }
5545   }
5546 
5547 err:
5548   if (proc_table->file->inited)
5549     (void) proc_table->file->ha_index_end();
5550   close_system_tables(thd, &open_tables_state_backup);
5551   DBUG_RETURN(res);
5552 }
5553 
5554 
get_schema_stat_record(THD * thd,TABLE_LIST * tables,TABLE * table,bool res,LEX_STRING * db_name,LEX_STRING * table_name)5555 static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
5556 				  TABLE *table, bool res,
5557 				  LEX_STRING *db_name,
5558 				  LEX_STRING *table_name)
5559 {
5560   CHARSET_INFO *cs= system_charset_info;
5561   DBUG_ENTER("get_schema_stat_record");
5562   if (res)
5563   {
5564     if (thd->lex->sql_command != SQLCOM_SHOW_KEYS)
5565     {
5566       /*
5567         I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS
5568         rather than in SHOW KEYS
5569       */
5570       if (thd->is_error())
5571         push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
5572                      thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message());
5573       thd->clear_error();
5574       res= 0;
5575     }
5576     DBUG_RETURN(res);
5577   }
5578   else if (!tables->view)
5579   {
5580     TABLE *show_table= tables->table;
5581     KEY *key_info=show_table->s->key_info;
5582     if (show_table->file)
5583       show_table->file->info(HA_STATUS_VARIABLE |
5584                              HA_STATUS_NO_LOCK |
5585                              HA_STATUS_TIME);
5586     for (uint i=0 ; i < show_table->s->keys ; i++,key_info++)
5587     {
5588       KEY_PART_INFO *key_part= key_info->key_part;
5589       const char *str;
5590       for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++)
5591       {
5592         restore_record(table, s->default_values);
5593         table->field[0]->store(STRING_WITH_LEN("def"), cs);
5594         table->field[1]->store(db_name->str, db_name->length, cs);
5595         table->field[2]->store(table_name->str, table_name->length, cs);
5596         table->field[3]->store((longlong) ((key_info->flags &
5597                                             HA_NOSAME) ? 0 : 1), TRUE);
5598         table->field[4]->store(db_name->str, db_name->length, cs);
5599         table->field[5]->store(key_info->name, strlen(key_info->name), cs);
5600         table->field[6]->store((longlong) (j+1), TRUE);
5601         str=(key_part->field ? key_part->field->field_name :
5602              "?unknown field?");
5603         table->field[7]->store(str, strlen(str), cs);
5604         if (show_table->file)
5605         {
5606           if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER)
5607           {
5608             table->field[8]->store(((key_part->key_part_flag &
5609                                      HA_REVERSE_SORT) ?
5610                                     "D" : "A"), 1, cs);
5611             table->field[8]->set_notnull();
5612           }
5613           KEY *key=show_table->key_info+i;
5614           if (key->rec_per_key[j])
5615           {
5616             ha_rows records=(show_table->file->stats.records /
5617                              key->rec_per_key[j]);
5618             table->field[9]->store((longlong) records, TRUE);
5619             table->field[9]->set_notnull();
5620           }
5621           str= show_table->file->index_type(i);
5622           table->field[13]->store(str, strlen(str), cs);
5623         }
5624         if (!(key_info->flags & HA_FULLTEXT) &&
5625             (key_part->field &&
5626              key_part->length !=
5627              show_table->s->field[key_part->fieldnr-1]->key_length()))
5628         {
5629           table->field[10]->store((longlong) key_part->length /
5630                                   key_part->field->charset()->mbmaxlen, TRUE);
5631           table->field[10]->set_notnull();
5632         }
5633         uint flags= key_part->field ? key_part->field->flags : 0;
5634         const char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
5635         table->field[12]->store(pos, strlen(pos), cs);
5636         if (!show_table->s->keys_in_use.is_set(i))
5637           table->field[14]->store(STRING_WITH_LEN("disabled"), cs);
5638         else
5639           table->field[14]->store("", 0, cs);
5640         table->field[14]->set_notnull();
5641         DBUG_ASSERT(MY_TEST(key_info->flags & HA_USES_COMMENT) ==
5642                    (key_info->comment.length > 0));
5643         if (key_info->flags & HA_USES_COMMENT)
5644           table->field[15]->store(key_info->comment.str,
5645                                   key_info->comment.length, cs);
5646         if (schema_table_store_record(thd, table))
5647           DBUG_RETURN(1);
5648       }
5649     }
5650   }
5651   DBUG_RETURN(res);
5652 }
5653 
5654 
get_schema_views_record(THD * thd,TABLE_LIST * tables,TABLE * table,bool res,LEX_STRING * db_name,LEX_STRING * table_name)5655 static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
5656 				   TABLE *table, bool res,
5657 				   LEX_STRING *db_name,
5658 				   LEX_STRING *table_name)
5659 {
5660   CHARSET_INFO *cs= system_charset_info;
5661   char definer[USER_HOST_BUFF_SIZE];
5662   uint definer_len;
5663   bool updatable_view;
5664   DBUG_ENTER("get_schema_views_record");
5665 
5666   if (tables->view)
5667   {
5668     Security_context *sctx= thd->security_ctx;
5669     if (!tables->allowed_show)
5670     {
5671       if (!my_strcasecmp(system_charset_info, tables->definer.user.str,
5672                          sctx->priv_user) &&
5673           !my_strcasecmp(system_charset_info, tables->definer.host.str,
5674                          sctx->priv_host))
5675         tables->allowed_show= TRUE;
5676 #ifndef NO_EMBEDDED_ACCESS_CHECKS
5677       else
5678       {
5679         if ((thd->col_access & (SHOW_VIEW_ACL|SELECT_ACL)) ==
5680             (SHOW_VIEW_ACL|SELECT_ACL))
5681           tables->allowed_show= TRUE;
5682         else
5683         {
5684           TABLE_LIST table_list;
5685           uint view_access;
5686           memset(&table_list, 0, sizeof(table_list));
5687           table_list.db= tables->db;
5688           table_list.table_name= tables->table_name;
5689           table_list.grant.privilege= thd->col_access;
5690           view_access= get_table_grant(thd, &table_list);
5691 	  if ((view_access & (SHOW_VIEW_ACL|SELECT_ACL)) ==
5692 	      (SHOW_VIEW_ACL|SELECT_ACL))
5693 	    tables->allowed_show= TRUE;
5694         }
5695       }
5696 #endif
5697     }
5698     restore_record(table, s->default_values);
5699     table->field[0]->store(STRING_WITH_LEN("def"), cs);
5700     table->field[1]->store(db_name->str, db_name->length, cs);
5701     table->field[2]->store(table_name->str, table_name->length, cs);
5702 
5703     if (tables->allowed_show)
5704     {
5705       table->field[3]->store(tables->view_body_utf8.str,
5706                              tables->view_body_utf8.length,
5707                              cs);
5708     }
5709 
5710     if (tables->with_check != VIEW_CHECK_NONE)
5711     {
5712       if (tables->with_check == VIEW_CHECK_LOCAL)
5713         table->field[4]->store(STRING_WITH_LEN("LOCAL"), cs);
5714       else
5715         table->field[4]->store(STRING_WITH_LEN("CASCADED"), cs);
5716     }
5717     else
5718       table->field[4]->store(STRING_WITH_LEN("NONE"), cs);
5719 
5720     /*
5721       Only try to fill in the information about view updatability
5722       if it is requested as part of the top-level query (i.e.
5723       it's select * from i_s.views, as opposed to, say, select
5724       security_type from i_s.views).  Do not try to access the
5725       underlying tables if there was an error when opening the
5726       view: all underlying tables are released back to the table
5727       definition cache on error inside open_normal_and_derived_tables().
5728       If a field is not assigned explicitly, it defaults to NULL.
5729     */
5730     if (res == FALSE &&
5731         table->pos_in_table_list->table_open_method & OPEN_FULL_TABLE)
5732     {
5733       updatable_view= 0;
5734       if (tables->algorithm != VIEW_ALGORITHM_TMPTABLE)
5735       {
5736         /*
5737           We should use tables->view->select_lex.item_list here
5738           and can not use Field_iterator_view because the view
5739           always uses temporary algorithm during opening for I_S
5740           and TABLE_LIST fields 'field_translation'
5741           & 'field_translation_end' are uninitialized is this
5742           case.
5743         */
5744         List<Item> *fields= &tables->view->select_lex.item_list;
5745         List_iterator<Item> it(*fields);
5746         Item *item;
5747         Item_field *field;
5748         /*
5749           check that at least one column in view is updatable
5750         */
5751         while ((item= it++))
5752         {
5753           if ((field= item->field_for_view_update()) && field->field &&
5754               !field->field->table->pos_in_table_list->schema_table)
5755           {
5756             updatable_view= 1;
5757             break;
5758           }
5759         }
5760         if (updatable_view && !tables->view->can_be_merged())
5761           updatable_view= 0;
5762       }
5763       if (updatable_view)
5764         table->field[5]->store(STRING_WITH_LEN("YES"), cs);
5765       else
5766         table->field[5]->store(STRING_WITH_LEN("NO"), cs);
5767     }
5768 
5769     definer_len= (strxmov(definer, tables->definer.user.str, "@",
5770                           tables->definer.host.str, NullS) - definer);
5771     table->field[6]->store(definer, definer_len, cs);
5772     if (tables->view_suid)
5773       table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs);
5774     else
5775       table->field[7]->store(STRING_WITH_LEN("INVOKER"), cs);
5776 
5777     table->field[8]->store(tables->view_creation_ctx->get_client_cs()->csname,
5778                            strlen(tables->view_creation_ctx->
5779                                   get_client_cs()->csname), cs);
5780 
5781     table->field[9]->store(tables->view_creation_ctx->
5782                            get_connection_cl()->name,
5783                            strlen(tables->view_creation_ctx->
5784                                   get_connection_cl()->name), cs);
5785 
5786 
5787     if (schema_table_store_record(thd, table))
5788       DBUG_RETURN(1);
5789     if (res && thd->is_error())
5790       push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
5791                    thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message());
5792   }
5793   if (res)
5794     thd->clear_error();
5795   DBUG_RETURN(0);
5796 }
5797 
5798 
store_constraints(THD * thd,TABLE * table,LEX_STRING * db_name,LEX_STRING * table_name,const char * key_name,uint key_len,const char * con_type,uint con_len)5799 bool store_constraints(THD *thd, TABLE *table, LEX_STRING *db_name,
5800                        LEX_STRING *table_name, const char *key_name,
5801                        uint key_len, const char *con_type, uint con_len)
5802 {
5803   CHARSET_INFO *cs= system_charset_info;
5804   restore_record(table, s->default_values);
5805   table->field[0]->store(STRING_WITH_LEN("def"), cs);
5806   table->field[1]->store(db_name->str, db_name->length, cs);
5807   table->field[2]->store(key_name, key_len, cs);
5808   table->field[3]->store(db_name->str, db_name->length, cs);
5809   table->field[4]->store(table_name->str, table_name->length, cs);
5810   table->field[5]->store(con_type, con_len, cs);
5811   return schema_table_store_record(thd, table);
5812 }
5813 
5814 
get_schema_constraints_record(THD * thd,TABLE_LIST * tables,TABLE * table,bool res,LEX_STRING * db_name,LEX_STRING * table_name)5815 static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
5816 					 TABLE *table, bool res,
5817 					 LEX_STRING *db_name,
5818 					 LEX_STRING *table_name)
5819 {
5820   DBUG_ENTER("get_schema_constraints_record");
5821   if (res)
5822   {
5823     if (thd->is_error())
5824       push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
5825                    thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message());
5826     thd->clear_error();
5827     DBUG_RETURN(0);
5828   }
5829   else if (!tables->view)
5830   {
5831     List<FOREIGN_KEY_INFO> f_key_list;
5832     TABLE *show_table= tables->table;
5833     KEY *key_info=show_table->key_info;
5834     uint primary_key= show_table->s->primary_key;
5835     for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
5836     {
5837       if (i != primary_key && !(key_info->flags & HA_NOSAME))
5838         continue;
5839 
5840       if (i == primary_key && !strcmp(key_info->name, primary_key_name))
5841       {
5842         if (store_constraints(thd, table, db_name, table_name, key_info->name,
5843                               strlen(key_info->name),
5844                               STRING_WITH_LEN("PRIMARY KEY")))
5845           DBUG_RETURN(1);
5846       }
5847       else if (key_info->flags & HA_NOSAME)
5848       {
5849         if (store_constraints(thd, table, db_name, table_name, key_info->name,
5850                               strlen(key_info->name),
5851                               STRING_WITH_LEN("UNIQUE")))
5852           DBUG_RETURN(1);
5853       }
5854     }
5855 
5856     show_table->file->get_foreign_key_list(thd, &f_key_list);
5857     FOREIGN_KEY_INFO *f_key_info;
5858     List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
5859     while ((f_key_info=it++))
5860     {
5861       if (store_constraints(thd, table, db_name, table_name,
5862                             f_key_info->foreign_id->str,
5863                             strlen(f_key_info->foreign_id->str),
5864                             "FOREIGN KEY", 11))
5865         DBUG_RETURN(1);
5866     }
5867   }
5868   DBUG_RETURN(res);
5869 }
5870 
5871 
store_trigger(THD * thd,TABLE * table,LEX_STRING * db_name,LEX_STRING * table_name,LEX_STRING * trigger_name,enum trg_event_type event,enum trg_action_time_type timing,LEX_STRING * trigger_stmt,sql_mode_t sql_mode,LEX_STRING * definer_buffer,LEX_STRING * client_cs_name,LEX_STRING * connection_cl_name,LEX_STRING * db_cl_name)5872 static bool store_trigger(THD *thd, TABLE *table, LEX_STRING *db_name,
5873                           LEX_STRING *table_name, LEX_STRING *trigger_name,
5874                           enum trg_event_type event,
5875                           enum trg_action_time_type timing,
5876                           LEX_STRING *trigger_stmt,
5877                           sql_mode_t sql_mode,
5878                           LEX_STRING *definer_buffer,
5879                           LEX_STRING *client_cs_name,
5880                           LEX_STRING *connection_cl_name,
5881                           LEX_STRING *db_cl_name)
5882 {
5883   CHARSET_INFO *cs= system_charset_info;
5884   LEX_STRING sql_mode_rep;
5885 
5886   restore_record(table, s->default_values);
5887   table->field[0]->store(STRING_WITH_LEN("def"), cs);
5888   table->field[1]->store(db_name->str, db_name->length, cs);
5889   table->field[2]->store(trigger_name->str, trigger_name->length, cs);
5890   table->field[3]->store(trg_event_type_names[event].str,
5891                          trg_event_type_names[event].length, cs);
5892   table->field[4]->store(STRING_WITH_LEN("def"), cs);
5893   table->field[5]->store(db_name->str, db_name->length, cs);
5894   table->field[6]->store(table_name->str, table_name->length, cs);
5895   table->field[9]->store(trigger_stmt->str, trigger_stmt->length, cs);
5896   table->field[10]->store(STRING_WITH_LEN("ROW"), cs);
5897   table->field[11]->store(trg_action_time_type_names[timing].str,
5898                           trg_action_time_type_names[timing].length, cs);
5899   table->field[14]->store(STRING_WITH_LEN("OLD"), cs);
5900   table->field[15]->store(STRING_WITH_LEN("NEW"), cs);
5901 
5902   sql_mode_string_representation(thd, sql_mode, &sql_mode_rep);
5903   table->field[17]->store(sql_mode_rep.str, sql_mode_rep.length, cs);
5904   table->field[18]->store(definer_buffer->str, definer_buffer->length, cs);
5905   table->field[19]->store(client_cs_name->str, client_cs_name->length, cs);
5906   table->field[20]->store(connection_cl_name->str,
5907                           connection_cl_name->length, cs);
5908   table->field[21]->store(db_cl_name->str, db_cl_name->length, cs);
5909 
5910   return schema_table_store_record(thd, table);
5911 }
5912 
5913 
get_schema_triggers_record(THD * thd,TABLE_LIST * tables,TABLE * table,bool res,LEX_STRING * db_name,LEX_STRING * table_name)5914 static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables,
5915 				      TABLE *table, bool res,
5916 				      LEX_STRING *db_name,
5917 				      LEX_STRING *table_name)
5918 {
5919   DBUG_ENTER("get_schema_triggers_record");
5920   /*
5921     res can be non zero value when processed table is a view or
5922     error happened during opening of processed table.
5923   */
5924   if (res)
5925   {
5926     if (thd->is_error())
5927       push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
5928                    thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message());
5929     thd->clear_error();
5930     DBUG_RETURN(0);
5931   }
5932   if (!tables->view && tables->table->triggers)
5933   {
5934     Table_triggers_list *triggers= tables->table->triggers;
5935     int event, timing;
5936 
5937     if (check_table_access(thd, TRIGGER_ACL, tables, FALSE, 1, TRUE))
5938       goto ret;
5939 
5940     for (event= 0; event < (int)TRG_EVENT_MAX; event++)
5941     {
5942       for (timing= 0; timing < (int)TRG_ACTION_MAX; timing++)
5943       {
5944         LEX_STRING trigger_name;
5945         LEX_STRING trigger_stmt;
5946         sql_mode_t sql_mode;
5947         char definer_holder[USER_HOST_BUFF_SIZE];
5948         LEX_STRING definer_buffer;
5949         LEX_STRING client_cs_name;
5950         LEX_STRING connection_cl_name;
5951         LEX_STRING db_cl_name;
5952 
5953         definer_buffer.str= definer_holder;
5954         if (triggers->get_trigger_info(thd, (enum trg_event_type) event,
5955                                        (enum trg_action_time_type)timing,
5956                                        &trigger_name, &trigger_stmt,
5957                                        &sql_mode,
5958                                        &definer_buffer,
5959                                        &client_cs_name,
5960                                        &connection_cl_name,
5961                                        &db_cl_name))
5962           continue;
5963 
5964         if (store_trigger(thd, table, db_name, table_name, &trigger_name,
5965                          (enum trg_event_type) event,
5966                          (enum trg_action_time_type) timing, &trigger_stmt,
5967                          sql_mode,
5968                          &definer_buffer,
5969                          &client_cs_name,
5970                          &connection_cl_name,
5971                          &db_cl_name))
5972           DBUG_RETURN(1);
5973       }
5974     }
5975   }
5976 ret:
5977   DBUG_RETURN(0);
5978 }
5979 
5980 
store_key_column_usage(TABLE * table,LEX_STRING * db_name,LEX_STRING * table_name,const char * key_name,uint key_len,const char * con_type,uint con_len,longlong idx)5981 void store_key_column_usage(TABLE *table, LEX_STRING *db_name,
5982                             LEX_STRING *table_name, const char *key_name,
5983                             uint key_len, const char *con_type, uint con_len,
5984                             longlong idx)
5985 {
5986   CHARSET_INFO *cs= system_charset_info;
5987   table->field[0]->store(STRING_WITH_LEN("def"), cs);
5988   table->field[1]->store(db_name->str, db_name->length, cs);
5989   table->field[2]->store(key_name, key_len, cs);
5990   table->field[3]->store(STRING_WITH_LEN("def"), cs);
5991   table->field[4]->store(db_name->str, db_name->length, cs);
5992   table->field[5]->store(table_name->str, table_name->length, cs);
5993   table->field[6]->store(con_type, con_len, cs);
5994   table->field[7]->store((longlong) idx, TRUE);
5995 }
5996 
5997 
get_schema_key_column_usage_record(THD * thd,TABLE_LIST * tables,TABLE * table,bool res,LEX_STRING * db_name,LEX_STRING * table_name)5998 static int get_schema_key_column_usage_record(THD *thd,
5999 					      TABLE_LIST *tables,
6000 					      TABLE *table, bool res,
6001 					      LEX_STRING *db_name,
6002 					      LEX_STRING *table_name)
6003 {
6004   DBUG_ENTER("get_schema_key_column_usage_record");
6005   if (res)
6006   {
6007     if (thd->is_error())
6008       push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
6009                    thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message());
6010     thd->clear_error();
6011     DBUG_RETURN(0);
6012   }
6013   else if (!tables->view)
6014   {
6015     List<FOREIGN_KEY_INFO> f_key_list;
6016     TABLE *show_table= tables->table;
6017     KEY *key_info=show_table->key_info;
6018     uint primary_key= show_table->s->primary_key;
6019     for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
6020     {
6021       if (i != primary_key && !(key_info->flags & HA_NOSAME))
6022         continue;
6023       uint f_idx= 0;
6024       KEY_PART_INFO *key_part= key_info->key_part;
6025       for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++)
6026       {
6027         if (key_part->field)
6028         {
6029           f_idx++;
6030           restore_record(table, s->default_values);
6031           store_key_column_usage(table, db_name, table_name,
6032                                  key_info->name,
6033                                  strlen(key_info->name),
6034                                  key_part->field->field_name,
6035                                  strlen(key_part->field->field_name),
6036                                  (longlong) f_idx);
6037           if (schema_table_store_record(thd, table))
6038             DBUG_RETURN(1);
6039         }
6040       }
6041     }
6042 
6043     show_table->file->get_foreign_key_list(thd, &f_key_list);
6044     FOREIGN_KEY_INFO *f_key_info;
6045     List_iterator_fast<FOREIGN_KEY_INFO> fkey_it(f_key_list);
6046     while ((f_key_info= fkey_it++))
6047     {
6048       LEX_STRING *f_info;
6049       LEX_STRING *r_info;
6050       List_iterator_fast<LEX_STRING> it(f_key_info->foreign_fields),
6051         it1(f_key_info->referenced_fields);
6052       uint f_idx= 0;
6053       while ((f_info= it++))
6054       {
6055         r_info= it1++;
6056         f_idx++;
6057         restore_record(table, s->default_values);
6058         store_key_column_usage(table, db_name, table_name,
6059                                f_key_info->foreign_id->str,
6060                                f_key_info->foreign_id->length,
6061                                f_info->str, f_info->length,
6062                                (longlong) f_idx);
6063         table->field[8]->store((longlong) f_idx, TRUE);
6064         table->field[8]->set_notnull();
6065         table->field[9]->store(f_key_info->referenced_db->str,
6066                                f_key_info->referenced_db->length,
6067                                system_charset_info);
6068         table->field[9]->set_notnull();
6069         table->field[10]->store(f_key_info->referenced_table->str,
6070                                 f_key_info->referenced_table->length,
6071                                 system_charset_info);
6072         table->field[10]->set_notnull();
6073         table->field[11]->store(r_info->str, r_info->length,
6074                                 system_charset_info);
6075         table->field[11]->set_notnull();
6076         if (schema_table_store_record(thd, table))
6077           DBUG_RETURN(1);
6078       }
6079     }
6080   }
6081   DBUG_RETURN(res);
6082 }
6083 
6084 
6085 #ifdef WITH_PARTITION_STORAGE_ENGINE
collect_partition_expr(THD * thd,List<char> & field_list,String * str)6086 static void collect_partition_expr(THD *thd, List<char> &field_list,
6087                                    String *str)
6088 {
6089   List_iterator<char> part_it(field_list);
6090   ulong no_fields= field_list.elements;
6091   const char *field_str;
6092   str->length(0);
6093   while ((field_str= part_it++))
6094   {
6095     append_identifier(thd, str, field_str, strlen(field_str));
6096     if (--no_fields != 0)
6097       str->append(",");
6098   }
6099   return;
6100 }
6101 
6102 
6103 /*
6104   Convert a string in a given character set to a string which can be
6105   used for FRM file storage in which case use_hex is TRUE and we store
6106   the character constants as hex strings in the character set encoding
6107   their field have. In the case of SHOW CREATE TABLE and the
6108   PARTITIONS information schema table we instead provide utf8 strings
6109   to the user and convert to the utf8 character set.
6110 
6111   SYNOPSIS
6112     get_cs_converted_part_value_from_string()
6113     item                           Item from which constant comes
6114     input_str                      String as provided by val_str after
6115                                    conversion to character set
6116     output_str                     Out value: The string created
6117     cs                             Character set string is encoded in
6118                                    NULL for INT_RESULT's here
6119     use_hex                        TRUE => hex string created
6120                                    FALSE => utf8 constant string created
6121 
6122   RETURN VALUES
6123     TRUE                           Error
6124     FALSE                          Ok
6125 */
6126 
get_cs_converted_part_value_from_string(THD * thd,Item * item,String * input_str,String * output_str,const CHARSET_INFO * cs,bool use_hex)6127 int get_cs_converted_part_value_from_string(THD *thd,
6128                                             Item *item,
6129                                             String *input_str,
6130                                             String *output_str,
6131                                             const CHARSET_INFO *cs,
6132                                             bool use_hex)
6133 {
6134   if (item->result_type() == INT_RESULT)
6135   {
6136     longlong value= item->val_int();
6137     output_str->set(value, system_charset_info);
6138     return FALSE;
6139   }
6140   if (!input_str)
6141   {
6142     my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
6143     return TRUE;
6144   }
6145   get_cs_converted_string_value(thd,
6146                                 input_str,
6147                                 output_str,
6148                                 cs,
6149                                 use_hex);
6150   return FALSE;
6151 }
6152 #endif
6153 
6154 
store_schema_partitions_record(THD * thd,TABLE * schema_table,TABLE * showing_table,partition_element * part_elem,handler * file,uint part_id)6155 static void store_schema_partitions_record(THD *thd, TABLE *schema_table,
6156                                            TABLE *showing_table,
6157                                            partition_element *part_elem,
6158                                            handler *file, uint part_id)
6159 {
6160   TABLE* table= schema_table;
6161   CHARSET_INFO *cs= system_charset_info;
6162   PARTITION_STATS stat_info;
6163   MYSQL_TIME time;
6164   file->get_dynamic_partition_info(&stat_info, part_id);
6165   table->field[0]->store(STRING_WITH_LEN("def"), cs);
6166   table->field[12]->store((longlong) stat_info.records, TRUE);
6167   table->field[13]->store((longlong) stat_info.mean_rec_length, TRUE);
6168   table->field[14]->store((longlong) stat_info.data_file_length, TRUE);
6169   if (stat_info.max_data_file_length)
6170   {
6171     table->field[15]->store((longlong) stat_info.max_data_file_length, TRUE);
6172     table->field[15]->set_notnull();
6173   }
6174   table->field[16]->store((longlong) stat_info.index_file_length, TRUE);
6175   table->field[17]->store((longlong) stat_info.delete_length, TRUE);
6176   if (stat_info.create_time)
6177   {
6178     thd->variables.time_zone->gmt_sec_to_TIME(&time,
6179                                               (my_time_t)stat_info.create_time);
6180     table->field[18]->store_time(&time);
6181     table->field[18]->set_notnull();
6182   }
6183   if (stat_info.update_time)
6184   {
6185     thd->variables.time_zone->gmt_sec_to_TIME(&time,
6186                                               (my_time_t)stat_info.update_time);
6187     table->field[19]->store_time(&time);
6188     table->field[19]->set_notnull();
6189   }
6190   if (stat_info.check_time)
6191   {
6192     thd->variables.time_zone->gmt_sec_to_TIME(&time,
6193                                               (my_time_t)stat_info.check_time);
6194     table->field[20]->store_time(&time);
6195     table->field[20]->set_notnull();
6196   }
6197   if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM)
6198   {
6199     table->field[21]->store((longlong) stat_info.check_sum, TRUE);
6200     table->field[21]->set_notnull();
6201   }
6202   if (part_elem)
6203   {
6204     if (part_elem->part_comment)
6205       table->field[22]->store(part_elem->part_comment,
6206                               strlen(part_elem->part_comment), cs);
6207     else
6208       table->field[22]->store(STRING_WITH_LEN(""), cs);
6209     if (part_elem->nodegroup_id != UNDEF_NODEGROUP)
6210       table->field[23]->store((longlong) part_elem->nodegroup_id, TRUE);
6211     else
6212       table->field[23]->store(STRING_WITH_LEN("default"), cs);
6213 
6214     table->field[24]->set_notnull();
6215     if (part_elem->tablespace_name)
6216       table->field[24]->store(part_elem->tablespace_name,
6217                               strlen(part_elem->tablespace_name), cs);
6218     else
6219     {
6220       char *ts= showing_table->s->tablespace;
6221       if(ts)
6222         table->field[24]->store(ts, strlen(ts), cs);
6223       else
6224         table->field[24]->set_null();
6225     }
6226   }
6227   return;
6228 }
6229 
6230 #ifdef WITH_PARTITION_STORAGE_ENGINE
6231 static int
get_partition_column_description(THD * thd,partition_info * part_info,part_elem_value * list_value,String & tmp_str)6232 get_partition_column_description(THD *thd,
6233                                  partition_info *part_info,
6234                                  part_elem_value *list_value,
6235                                  String &tmp_str)
6236 {
6237   uint num_elements= part_info->part_field_list.elements;
6238   uint i;
6239   DBUG_ENTER("get_partition_column_description");
6240 
6241   for (i= 0; i < num_elements; i++)
6242   {
6243     part_column_list_val *col_val= &list_value->col_val_array[i];
6244     if (col_val->max_value)
6245       tmp_str.append(partition_keywords[PKW_MAXVALUE].str);
6246     else if (col_val->null_value)
6247       tmp_str.append("NULL");
6248     else
6249     {
6250       char buffer[MAX_KEY_LENGTH];
6251       String str(buffer, sizeof(buffer), &my_charset_bin);
6252       String val_conv;
6253       Item *item= col_val->item_expression;
6254 
6255       if (!(item= part_info->get_column_item(item,
6256                               part_info->part_field_array[i])))
6257       {
6258         DBUG_RETURN(1);
6259       }
6260       String *res= item->val_str(&str);
6261       if (get_cs_converted_part_value_from_string(thd, item, res, &val_conv,
6262                               part_info->part_field_array[i]->charset(),
6263                               FALSE))
6264       {
6265         DBUG_RETURN(1);
6266       }
6267       tmp_str.append(val_conv);
6268     }
6269     if (i != num_elements - 1)
6270       tmp_str.append(",");
6271   }
6272   DBUG_RETURN(0);
6273 }
6274 #endif /* WITH_PARTITION_STORAGE_ENGINE */
6275 
get_schema_partitions_record(THD * thd,TABLE_LIST * tables,TABLE * table,bool res,LEX_STRING * db_name,LEX_STRING * table_name)6276 static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
6277                                         TABLE *table, bool res,
6278                                         LEX_STRING *db_name,
6279                                         LEX_STRING *table_name)
6280 {
6281   CHARSET_INFO *cs= system_charset_info;
6282   char buff[61];
6283   String tmp_res(buff, sizeof(buff), cs);
6284   String tmp_str;
6285   TABLE *show_table= tables->table;
6286   handler *file;
6287 #ifdef WITH_PARTITION_STORAGE_ENGINE
6288   partition_info *part_info;
6289 #endif
6290   DBUG_ENTER("get_schema_partitions_record");
6291 
6292   if (res)
6293   {
6294     if (thd->is_error())
6295       push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
6296                    thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message());
6297     thd->clear_error();
6298     DBUG_RETURN(0);
6299   }
6300   file= show_table->file;
6301 #ifdef WITH_PARTITION_STORAGE_ENGINE
6302   part_info= show_table->part_info;
6303   if (part_info)
6304   {
6305     partition_element *part_elem;
6306     List_iterator<partition_element> part_it(part_info->partitions);
6307     uint part_pos= 0, part_id= 0;
6308 
6309     restore_record(table, s->default_values);
6310     table->field[0]->store(STRING_WITH_LEN("def"), cs);
6311     table->field[1]->store(db_name->str, db_name->length, cs);
6312     table->field[2]->store(table_name->str, table_name->length, cs);
6313 
6314 
6315     /* Partition method*/
6316     switch (part_info->part_type) {
6317     case RANGE_PARTITION:
6318     case LIST_PARTITION:
6319       tmp_res.length(0);
6320       if (part_info->part_type == RANGE_PARTITION)
6321         tmp_res.append(partition_keywords[PKW_RANGE].str,
6322                        partition_keywords[PKW_RANGE].length);
6323       else
6324         tmp_res.append(partition_keywords[PKW_LIST].str,
6325                        partition_keywords[PKW_LIST].length);
6326       if (part_info->column_list)
6327         tmp_res.append(partition_keywords[PKW_COLUMNS].str,
6328                        partition_keywords[PKW_COLUMNS].length);
6329       table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs);
6330       break;
6331     case HASH_PARTITION:
6332       tmp_res.length(0);
6333       if (part_info->linear_hash_ind)
6334         tmp_res.append(partition_keywords[PKW_LINEAR].str,
6335                        partition_keywords[PKW_LINEAR].length);
6336       if (part_info->list_of_part_fields)
6337         tmp_res.append(partition_keywords[PKW_KEY].str,
6338                        partition_keywords[PKW_KEY].length);
6339       else
6340         tmp_res.append(partition_keywords[PKW_HASH].str,
6341                        partition_keywords[PKW_HASH].length);
6342       table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs);
6343       break;
6344     default:
6345       DBUG_ASSERT(0);
6346       my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
6347       DBUG_RETURN(1);
6348     }
6349     table->field[7]->set_notnull();
6350 
6351     /* Partition expression */
6352     if (part_info->part_expr)
6353     {
6354       table->field[9]->store(part_info->part_func_string,
6355                              part_info->part_func_len, cs);
6356     }
6357     else if (part_info->list_of_part_fields)
6358     {
6359       collect_partition_expr(thd, part_info->part_field_list, &tmp_str);
6360       table->field[9]->store(tmp_str.ptr(), tmp_str.length(), cs);
6361     }
6362     table->field[9]->set_notnull();
6363 
6364     if (part_info->is_sub_partitioned())
6365     {
6366       /* Subpartition method */
6367       tmp_res.length(0);
6368       if (part_info->linear_hash_ind)
6369         tmp_res.append(partition_keywords[PKW_LINEAR].str,
6370                        partition_keywords[PKW_LINEAR].length);
6371       if (part_info->list_of_subpart_fields)
6372         tmp_res.append(partition_keywords[PKW_KEY].str,
6373                        partition_keywords[PKW_KEY].length);
6374       else
6375         tmp_res.append(partition_keywords[PKW_HASH].str,
6376                        partition_keywords[PKW_HASH].length);
6377       table->field[8]->store(tmp_res.ptr(), tmp_res.length(), cs);
6378       table->field[8]->set_notnull();
6379 
6380       /* Subpartition expression */
6381       if (part_info->subpart_expr)
6382       {
6383         table->field[10]->store(part_info->subpart_func_string,
6384                                 part_info->subpart_func_len, cs);
6385       }
6386       else if (part_info->list_of_subpart_fields)
6387       {
6388         collect_partition_expr(thd, part_info->subpart_field_list, &tmp_str);
6389         table->field[10]->store(tmp_str.ptr(), tmp_str.length(), cs);
6390       }
6391       table->field[10]->set_notnull();
6392     }
6393 
6394     while ((part_elem= part_it++))
6395     {
6396       table->field[3]->store(part_elem->partition_name,
6397                              strlen(part_elem->partition_name), cs);
6398       table->field[3]->set_notnull();
6399       /* PARTITION_ORDINAL_POSITION */
6400       table->field[5]->store((longlong) ++part_pos, TRUE);
6401       table->field[5]->set_notnull();
6402 
6403       /* Partition description */
6404       if (part_info->part_type == RANGE_PARTITION)
6405       {
6406         if (part_info->column_list)
6407         {
6408           List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
6409           part_elem_value *list_value= list_val_it++;
6410           tmp_str.length(0);
6411           if (get_partition_column_description(thd,
6412                                                part_info,
6413                                                list_value,
6414                                                tmp_str))
6415           {
6416             DBUG_RETURN(1);
6417           }
6418           table->field[11]->store(tmp_str.ptr(), tmp_str.length(), cs);
6419         }
6420         else
6421         {
6422           if (part_elem->range_value != LONGLONG_MAX)
6423             table->field[11]->store((longlong) part_elem->range_value, FALSE);
6424           else
6425             table->field[11]->store(partition_keywords[PKW_MAXVALUE].str,
6426                                  partition_keywords[PKW_MAXVALUE].length, cs);
6427         }
6428         table->field[11]->set_notnull();
6429       }
6430       else if (part_info->part_type == LIST_PARTITION)
6431       {
6432         List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
6433         part_elem_value *list_value;
6434         uint num_items= part_elem->list_val_list.elements;
6435         tmp_str.length(0);
6436         tmp_res.length(0);
6437         if (part_elem->has_null_value)
6438         {
6439           tmp_str.append("NULL");
6440           if (num_items > 0)
6441             tmp_str.append(",");
6442         }
6443         while ((list_value= list_val_it++))
6444         {
6445           if (part_info->column_list)
6446           {
6447             if (part_info->part_field_list.elements > 1U)
6448               tmp_str.append("(");
6449             if (get_partition_column_description(thd,
6450                                                  part_info,
6451                                                  list_value,
6452                                                  tmp_str))
6453             {
6454               DBUG_RETURN(1);
6455             }
6456             if (part_info->part_field_list.elements > 1U)
6457               tmp_str.append(")");
6458           }
6459           else
6460           {
6461             if (!list_value->unsigned_flag)
6462               tmp_res.set(list_value->value, cs);
6463             else
6464               tmp_res.set((ulonglong)list_value->value, cs);
6465             tmp_str.append(tmp_res);
6466           }
6467           if (--num_items != 0)
6468             tmp_str.append(",");
6469         }
6470         table->field[11]->store(tmp_str.ptr(), tmp_str.length(), cs);
6471         table->field[11]->set_notnull();
6472       }
6473 
6474       if (part_elem->subpartitions.elements)
6475       {
6476         List_iterator<partition_element> sub_it(part_elem->subpartitions);
6477         partition_element *subpart_elem;
6478         uint subpart_pos= 0;
6479 
6480         while ((subpart_elem= sub_it++))
6481         {
6482           table->field[4]->store(subpart_elem->partition_name,
6483                                  strlen(subpart_elem->partition_name), cs);
6484           table->field[4]->set_notnull();
6485           /* SUBPARTITION_ORDINAL_POSITION */
6486           table->field[6]->store((longlong) ++subpart_pos, TRUE);
6487           table->field[6]->set_notnull();
6488 
6489           store_schema_partitions_record(thd, table, show_table, subpart_elem,
6490                                          file, part_id);
6491           part_id++;
6492           if(schema_table_store_record(thd, table))
6493             DBUG_RETURN(1);
6494         }
6495       }
6496       else
6497       {
6498         store_schema_partitions_record(thd, table, show_table, part_elem,
6499                                        file, part_id);
6500         part_id++;
6501         if(schema_table_store_record(thd, table))
6502           DBUG_RETURN(1);
6503       }
6504     }
6505     DBUG_RETURN(0);
6506   }
6507   else
6508 #endif
6509   {
6510     store_schema_partitions_record(thd, table, show_table, 0, file, 0);
6511     if(schema_table_store_record(thd, table))
6512       DBUG_RETURN(1);
6513   }
6514   DBUG_RETURN(0);
6515 }
6516 
6517 
6518 #ifdef HAVE_EVENT_SCHEDULER
6519 /*
6520   Loads an event from mysql.event and copies it's data to a row of
6521   I_S.EVENTS
6522 
6523   Synopsis
6524     copy_event_to_schema_table()
6525       thd         Thread
6526       sch_table   The schema table (information_schema.event)
6527       event_table The event table to use for loading (mysql.event).
6528 
6529   Returns
6530     0  OK
6531     1  Error
6532 */
6533 
6534 int
copy_event_to_schema_table(THD * thd,TABLE * sch_table,TABLE * event_table)6535 copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
6536 {
6537   const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
6538   CHARSET_INFO *scs= system_charset_info;
6539   MYSQL_TIME time;
6540   Event_timed et;
6541   DBUG_ENTER("copy_event_to_schema_table");
6542 
6543   restore_record(sch_table, s->default_values);
6544 
6545   if (et.load_from_row(thd, event_table))
6546   {
6547     my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0), "mysql", "event");
6548     DBUG_RETURN(1);
6549   }
6550 
6551   if (!(!wild || !wild[0] || !wild_case_compare(scs, et.name.str, wild)))
6552     DBUG_RETURN(0);
6553 
6554   /*
6555     Skip events in schemas one does not have access to. The check is
6556     optimized. It's guaranteed in case of SHOW EVENTS that the user
6557     has access.
6558   */
6559   if (thd->lex->sql_command != SQLCOM_SHOW_EVENTS &&
6560       check_access(thd, EVENT_ACL, et.dbname.str, NULL, NULL, 0, 1))
6561     DBUG_RETURN(0);
6562 
6563   sch_table->field[ISE_EVENT_CATALOG]->store(STRING_WITH_LEN("def"), scs);
6564   sch_table->field[ISE_EVENT_SCHEMA]->
6565                                 store(et.dbname.str, et.dbname.length,scs);
6566   sch_table->field[ISE_EVENT_NAME]->
6567                                 store(et.name.str, et.name.length, scs);
6568   sch_table->field[ISE_DEFINER]->
6569                                 store(et.definer.str, et.definer.length, scs);
6570   const String *tz_name= et.time_zone->get_name();
6571   sch_table->field[ISE_TIME_ZONE]->
6572                                 store(tz_name->ptr(), tz_name->length(), scs);
6573   sch_table->field[ISE_EVENT_BODY]->
6574                                 store(STRING_WITH_LEN("SQL"), scs);
6575   sch_table->field[ISE_EVENT_DEFINITION]->store(
6576     et.body_utf8.str, et.body_utf8.length, scs);
6577 
6578   /* SQL_MODE */
6579   {
6580     LEX_STRING sql_mode;
6581     sql_mode_string_representation(thd, et.sql_mode, &sql_mode);
6582     sch_table->field[ISE_SQL_MODE]->
6583                                 store(sql_mode.str, sql_mode.length, scs);
6584   }
6585 
6586   int not_used=0;
6587 
6588   if (et.expression)
6589   {
6590     String show_str;
6591     /* type */
6592     sch_table->field[ISE_EVENT_TYPE]->store(STRING_WITH_LEN("RECURRING"), scs);
6593 
6594     if (Events::reconstruct_interval_expression(&show_str, et.interval,
6595                                                 et.expression))
6596       DBUG_RETURN(1);
6597 
6598     sch_table->field[ISE_INTERVAL_VALUE]->set_notnull();
6599     sch_table->field[ISE_INTERVAL_VALUE]->
6600                                 store(show_str.ptr(), show_str.length(), scs);
6601 
6602     LEX_STRING *ival= &interval_type_to_name[et.interval];
6603     sch_table->field[ISE_INTERVAL_FIELD]->set_notnull();
6604     sch_table->field[ISE_INTERVAL_FIELD]->store(ival->str, ival->length, scs);
6605 
6606     /* starts & ends . STARTS is always set - see sql_yacc.yy */
6607     et.time_zone->gmt_sec_to_TIME(&time, et.starts);
6608     sch_table->field[ISE_STARTS]->set_notnull();
6609     sch_table->field[ISE_STARTS]->store_time(&time);
6610 
6611     if (!et.ends_null)
6612     {
6613       et.time_zone->gmt_sec_to_TIME(&time, et.ends);
6614       sch_table->field[ISE_ENDS]->set_notnull();
6615       sch_table->field[ISE_ENDS]->store_time(&time);
6616     }
6617   }
6618   else
6619   {
6620     /* type */
6621     sch_table->field[ISE_EVENT_TYPE]->store(STRING_WITH_LEN("ONE TIME"), scs);
6622 
6623     et.time_zone->gmt_sec_to_TIME(&time, et.execute_at);
6624     sch_table->field[ISE_EXECUTE_AT]->set_notnull();
6625     sch_table->field[ISE_EXECUTE_AT]->store_time(&time);
6626   }
6627 
6628   /* status */
6629 
6630   switch (et.status)
6631   {
6632     case Event_parse_data::ENABLED:
6633       sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("ENABLED"), scs);
6634       break;
6635     case Event_parse_data::SLAVESIDE_DISABLED:
6636       sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("SLAVESIDE_DISABLED"),
6637                                           scs);
6638       break;
6639     case Event_parse_data::DISABLED:
6640       sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("DISABLED"), scs);
6641       break;
6642     default:
6643       DBUG_ASSERT(0);
6644   }
6645   sch_table->field[ISE_ORIGINATOR]->store(et.originator, TRUE);
6646 
6647   /* on_completion */
6648   if (et.on_completion == Event_parse_data::ON_COMPLETION_DROP)
6649     sch_table->field[ISE_ON_COMPLETION]->
6650                                 store(STRING_WITH_LEN("NOT PRESERVE"), scs);
6651   else
6652     sch_table->field[ISE_ON_COMPLETION]->
6653                                 store(STRING_WITH_LEN("PRESERVE"), scs);
6654 
6655   number_to_datetime(et.created, &time, 0, &not_used);
6656   DBUG_ASSERT(not_used==0);
6657   sch_table->field[ISE_CREATED]->store_time(&time);
6658 
6659   number_to_datetime(et.modified, &time, 0, &not_used);
6660   DBUG_ASSERT(not_used==0);
6661   sch_table->field[ISE_LAST_ALTERED]->store_time(&time);
6662 
6663   if (et.last_executed)
6664   {
6665     et.time_zone->gmt_sec_to_TIME(&time, et.last_executed);
6666     sch_table->field[ISE_LAST_EXECUTED]->set_notnull();
6667     sch_table->field[ISE_LAST_EXECUTED]->store_time(&time);
6668   }
6669 
6670   sch_table->field[ISE_EVENT_COMMENT]->
6671                       store(et.comment.str, et.comment.length, scs);
6672 
6673   sch_table->field[ISE_CLIENT_CS]->set_notnull();
6674   sch_table->field[ISE_CLIENT_CS]->store(
6675     et.creation_ctx->get_client_cs()->csname,
6676     strlen(et.creation_ctx->get_client_cs()->csname),
6677     scs);
6678 
6679   sch_table->field[ISE_CONNECTION_CL]->set_notnull();
6680   sch_table->field[ISE_CONNECTION_CL]->store(
6681     et.creation_ctx->get_connection_cl()->name,
6682     strlen(et.creation_ctx->get_connection_cl()->name),
6683     scs);
6684 
6685   sch_table->field[ISE_DB_CL]->set_notnull();
6686   sch_table->field[ISE_DB_CL]->store(
6687     et.creation_ctx->get_db_cl()->name,
6688     strlen(et.creation_ctx->get_db_cl()->name),
6689     scs);
6690 
6691   if (schema_table_store_record(thd, sch_table))
6692     DBUG_RETURN(1);
6693 
6694   DBUG_RETURN(0);
6695 }
6696 #endif
6697 
fill_open_tables(THD * thd,TABLE_LIST * tables,Item * cond)6698 int fill_open_tables(THD *thd, TABLE_LIST *tables, Item *cond)
6699 {
6700   DBUG_ENTER("fill_open_tables");
6701   const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
6702   TABLE *table= tables->table;
6703   CHARSET_INFO *cs= system_charset_info;
6704   OPEN_TABLE_LIST *open_list;
6705   if (!(open_list=list_open_tables(thd,thd->lex->select_lex.db, wild))
6706             && thd->is_fatal_error)
6707     DBUG_RETURN(1);
6708 
6709   for (; open_list ; open_list=open_list->next)
6710   {
6711     restore_record(table, s->default_values);
6712     table->field[0]->store(open_list->db, strlen(open_list->db), cs);
6713     table->field[1]->store(open_list->table, strlen(open_list->table), cs);
6714     table->field[2]->store((longlong) open_list->in_use, TRUE);
6715     table->field[3]->store((longlong) open_list->locked, TRUE);
6716     if (schema_table_store_record(thd, table))
6717       DBUG_RETURN(1);
6718   }
6719   DBUG_RETURN(0);
6720 }
6721 
6722 
fill_variables(THD * thd,TABLE_LIST * tables,Item * cond)6723 int fill_variables(THD *thd, TABLE_LIST *tables, Item *cond)
6724 {
6725   DBUG_ENTER("fill_variables");
6726   SHOW_VAR *sys_var_array;
6727   int res= 0;
6728   LEX *lex= thd->lex;
6729   const char *wild= lex->wild ? lex->wild->ptr() : NullS;
6730   enum enum_schema_tables schema_table_idx=
6731     get_schema_table_idx(tables->schema_table);
6732   enum enum_var_type option_type= OPT_SESSION;
6733   bool upper_case_names= (schema_table_idx != SCH_VARIABLES);
6734   bool sorted_vars= (schema_table_idx == SCH_VARIABLES);
6735 
6736   if (lex->option_type == OPT_GLOBAL ||
6737       schema_table_idx == SCH_GLOBAL_VARIABLES)
6738     option_type= OPT_GLOBAL;
6739 
6740   /*
6741     Lock LOCK_plugin_delete to avoid deletion of any plugins while creating
6742     SHOW_VAR array and hold it until all variables are stored in the table.
6743   */
6744   if (thd->fill_variables_recursion_level++ == 0)
6745   {
6746     mysql_mutex_lock(&LOCK_plugin_delete);
6747   }
6748 
6749   // Lock LOCK_system_variables_hash to prepare SHOW_VARs array.
6750   mysql_rwlock_rdlock(&LOCK_system_variables_hash);
6751   DEBUG_SYNC(thd, "acquired_LOCK_system_variables_hash");
6752   sys_var_array= enumerate_sys_vars(thd, sorted_vars, option_type);
6753   mysql_rwlock_unlock(&LOCK_system_variables_hash);
6754 
6755   res= show_status_array(thd, wild, sys_var_array, option_type, NULL, "",
6756                          tables->table, upper_case_names, cond);
6757 
6758   if (thd->fill_variables_recursion_level-- == 1)
6759   {
6760     mysql_mutex_unlock(&LOCK_plugin_delete);
6761   }
6762 
6763   DBUG_RETURN(res);
6764 }
6765 
6766 
fill_status(THD * thd,TABLE_LIST * tables,Item * cond)6767 int fill_status(THD *thd, TABLE_LIST *tables, Item *cond)
6768 {
6769   DBUG_ENTER("fill_status");
6770   LEX *lex= thd->lex;
6771   const char *wild= lex->wild ? lex->wild->ptr() : NullS;
6772   int res= 0;
6773   STATUS_VAR *tmp1, tmp;
6774   enum enum_schema_tables schema_table_idx=
6775     get_schema_table_idx(tables->schema_table);
6776   enum enum_var_type option_type;
6777   bool upper_case_names= (schema_table_idx != SCH_STATUS);
6778 
6779   if (schema_table_idx == SCH_STATUS)
6780   {
6781     option_type= lex->option_type;
6782     if (option_type == OPT_GLOBAL)
6783       tmp1= &tmp;
6784     else
6785       tmp1= thd->initial_status_var;
6786   }
6787   else if (schema_table_idx == SCH_GLOBAL_STATUS)
6788   {
6789     option_type= OPT_GLOBAL;
6790     tmp1= &tmp;
6791   }
6792   else
6793   {
6794     option_type= OPT_SESSION;
6795     tmp1= &thd->status_var;
6796   }
6797 
6798   /*
6799     Avoid recursive acquisition of LOCK_status in cases when WHERE clause
6800     represented by "cond" contains subquery on I_S.SESSION/GLOBAL_STATUS.
6801   */
6802   DEBUG_SYNC(thd, "before_preparing_global_status_array");
6803 
6804   if (thd->fill_status_recursion_level++ == 0)
6805     mysql_mutex_lock(&LOCK_status);
6806   if (option_type == OPT_GLOBAL)
6807     calc_sum_of_all_status(&tmp);
6808   res= show_status_array(thd, wild,
6809                          (SHOW_VAR *)all_status_vars.buffer,
6810                          option_type, tmp1, "", tables->table,
6811                          upper_case_names, cond);
6812   if (thd->fill_status_recursion_level-- == 1)
6813     mysql_mutex_unlock(&LOCK_status);
6814 
6815   DEBUG_SYNC(thd, "after_preparing_global_status_array");
6816   DBUG_RETURN(res);
6817 }
6818 
6819 
6820 /*
6821   Fill and store records into I_S.referential_constraints table
6822 
6823   SYNOPSIS
6824     get_referential_constraints_record()
6825     thd                 thread handle
6826     tables              table list struct(processed table)
6827     table               I_S table
6828     res                 1 means the error during opening of the processed table
6829                         0 means processed table is opened without error
6830     base_name           db name
6831     file_name           table name
6832 
6833   RETURN
6834     0	ok
6835     #   error
6836 */
6837 
6838 static int
get_referential_constraints_record(THD * thd,TABLE_LIST * tables,TABLE * table,bool res,LEX_STRING * db_name,LEX_STRING * table_name)6839 get_referential_constraints_record(THD *thd, TABLE_LIST *tables,
6840                                    TABLE *table, bool res,
6841                                    LEX_STRING *db_name, LEX_STRING *table_name)
6842 {
6843   CHARSET_INFO *cs= system_charset_info;
6844   DBUG_ENTER("get_referential_constraints_record");
6845 
6846   if (res)
6847   {
6848     if (thd->is_error())
6849       push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
6850                    thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message());
6851     thd->clear_error();
6852     DBUG_RETURN(0);
6853   }
6854   if (!tables->view)
6855   {
6856     List<FOREIGN_KEY_INFO> f_key_list;
6857     TABLE *show_table= tables->table;
6858 
6859     show_table->file->get_foreign_key_list(thd, &f_key_list);
6860     FOREIGN_KEY_INFO *f_key_info;
6861     List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
6862     while ((f_key_info= it++))
6863     {
6864       restore_record(table, s->default_values);
6865       table->field[0]->store(STRING_WITH_LEN("def"), cs);
6866       table->field[1]->store(db_name->str, db_name->length, cs);
6867       table->field[9]->store(table_name->str, table_name->length, cs);
6868       table->field[2]->store(f_key_info->foreign_id->str,
6869                              f_key_info->foreign_id->length, cs);
6870       table->field[3]->store(STRING_WITH_LEN("def"), cs);
6871       table->field[4]->store(f_key_info->referenced_db->str,
6872                              f_key_info->referenced_db->length, cs);
6873       table->field[10]->store(f_key_info->referenced_table->str,
6874                              f_key_info->referenced_table->length, cs);
6875       if (f_key_info->referenced_key_name)
6876       {
6877         table->field[5]->store(f_key_info->referenced_key_name->str,
6878                                f_key_info->referenced_key_name->length, cs);
6879         table->field[5]->set_notnull();
6880       }
6881       else
6882         table->field[5]->set_null();
6883       table->field[6]->store(STRING_WITH_LEN("NONE"), cs);
6884       table->field[7]->store(f_key_info->update_method->str,
6885                              f_key_info->update_method->length, cs);
6886       table->field[8]->store(f_key_info->delete_method->str,
6887                              f_key_info->delete_method->length, cs);
6888       if (schema_table_store_record(thd, table))
6889         DBUG_RETURN(1);
6890     }
6891   }
6892   DBUG_RETURN(0);
6893 }
6894 
6895 struct schema_table_ref
6896 {
6897   const char *table_name;
6898   ST_SCHEMA_TABLE *schema_table;
6899 };
6900 
6901 
6902 /*
6903   Find schema_tables elment by name
6904 
6905   SYNOPSIS
6906     find_schema_table_in_plugin()
6907     thd                 thread handler
6908     plugin              plugin
6909     table_name          table name
6910 
6911   RETURN
6912     0	table not found
6913     1   found the schema table
6914 */
find_schema_table_in_plugin(THD * thd,plugin_ref plugin,void * p_table)6915 static my_bool find_schema_table_in_plugin(THD *thd, plugin_ref plugin,
6916                                            void* p_table)
6917 {
6918   schema_table_ref *p_schema_table= (schema_table_ref *)p_table;
6919   const char* table_name= p_schema_table->table_name;
6920   ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *);
6921   DBUG_ENTER("find_schema_table_in_plugin");
6922 
6923   if (!my_strcasecmp(system_charset_info,
6924                      schema_table->table_name,
6925                      table_name)) {
6926     p_schema_table->schema_table= schema_table;
6927     DBUG_RETURN(1);
6928   }
6929 
6930   DBUG_RETURN(0);
6931 }
6932 
6933 
6934 /*
6935   Find schema_tables elment by name
6936 
6937   SYNOPSIS
6938     find_schema_table()
6939     thd                 thread handler
6940     table_name          table name
6941 
6942   RETURN
6943     0	table not found
6944     #   pointer to 'schema_tables' element
6945 */
6946 
find_schema_table(THD * thd,const char * table_name)6947 ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name)
6948 {
6949   schema_table_ref schema_table_a;
6950   ST_SCHEMA_TABLE *schema_table= schema_tables;
6951   DBUG_ENTER("find_schema_table");
6952 
6953   for (; schema_table->table_name; schema_table++)
6954   {
6955     if (!my_strcasecmp(system_charset_info,
6956                        schema_table->table_name,
6957                        table_name))
6958       DBUG_RETURN(schema_table);
6959   }
6960 
6961   schema_table_a.table_name= table_name;
6962   if (plugin_foreach(thd, find_schema_table_in_plugin,
6963                      MYSQL_INFORMATION_SCHEMA_PLUGIN, &schema_table_a))
6964     DBUG_RETURN(schema_table_a.schema_table);
6965 
6966   DBUG_RETURN(NULL);
6967 }
6968 
6969 
get_schema_table(enum enum_schema_tables schema_table_idx)6970 ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx)
6971 {
6972   return &schema_tables[schema_table_idx];
6973 }
6974 
6975 
6976 /**
6977   Create information_schema table using schema_table data.
6978 
6979   @note
6980     For MYSQL_TYPE_DECIMAL fields only, the field_length member has encoded
6981     into it two numbers, based on modulus of base-10 numbers.  In the ones
6982     position is the number of decimals.  Tens position is unused.  In the
6983     hundreds and thousands position is a two-digit decimal number representing
6984     length.  Encode this value with  (decimals*100)+length  , where
6985     0<decimals<10 and 0<=length<100 .
6986 
6987   @param
6988     thd	       	          thread handler
6989 
6990   @param table_list Used to pass I_S table information(fields info, tables
6991   parameters etc) and table name.
6992 
6993   @retval  \#             Pointer to created table
6994   @retval  NULL           Can't create table
6995 */
6996 
create_schema_table(THD * thd,TABLE_LIST * table_list)6997 TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
6998 {
6999   int field_count= 0;
7000   Item *item;
7001   TABLE *table;
7002   List<Item> field_list;
7003   ST_SCHEMA_TABLE *schema_table= table_list->schema_table;
7004   ST_FIELD_INFO *fields_info= schema_table->fields_info;
7005   CHARSET_INFO *cs= system_charset_info;
7006   DBUG_ENTER("create_schema_table");
7007 
7008   for (; fields_info->field_name; fields_info++)
7009   {
7010     switch (fields_info->field_type) {
7011     case MYSQL_TYPE_TINY:
7012     case MYSQL_TYPE_LONG:
7013     case MYSQL_TYPE_SHORT:
7014     case MYSQL_TYPE_LONGLONG:
7015     case MYSQL_TYPE_INT24:
7016       if (!(item= new Item_return_int(fields_info->field_name,
7017                                       fields_info->field_length,
7018                                       fields_info->field_type,
7019                                       fields_info->value)))
7020       {
7021         DBUG_RETURN(0);
7022       }
7023       item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED);
7024       break;
7025     case MYSQL_TYPE_DATE:
7026     case MYSQL_TYPE_TIME:
7027     case MYSQL_TYPE_TIMESTAMP:
7028     case MYSQL_TYPE_DATETIME:
7029     {
7030       const Name_string field_name(fields_info->field_name,
7031                                    strlen(fields_info->field_name));
7032       if (!(item=new Item_temporal(fields_info->field_type, field_name, 0, 0)))
7033         DBUG_RETURN(0);
7034       break;
7035     }
7036     case MYSQL_TYPE_FLOAT:
7037     case MYSQL_TYPE_DOUBLE:
7038     {
7039       const Name_string field_name(fields_info->field_name,
7040                                    strlen(fields_info->field_name));
7041       if ((item= new Item_float(field_name, 0.0, NOT_FIXED_DEC,
7042                                 fields_info->field_length)) == NULL)
7043         DBUG_RETURN(NULL);
7044       break;
7045     }
7046     case MYSQL_TYPE_DECIMAL:
7047     case MYSQL_TYPE_NEWDECIMAL:
7048       if (!(item= new Item_decimal((longlong) fields_info->value, false)))
7049       {
7050         DBUG_RETURN(0);
7051       }
7052       item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED);
7053       item->decimals= fields_info->field_length%10;
7054       item->max_length= (fields_info->field_length/100)%100;
7055       if (item->unsigned_flag == 0)
7056         item->max_length+= 1;
7057       if (item->decimals > 0)
7058         item->max_length+= 1;
7059       item->item_name.copy(fields_info->field_name);
7060       break;
7061     case MYSQL_TYPE_TINY_BLOB:
7062     case MYSQL_TYPE_MEDIUM_BLOB:
7063     case MYSQL_TYPE_LONG_BLOB:
7064     case MYSQL_TYPE_BLOB:
7065       if (!(item= new Item_blob(fields_info->field_name,
7066                                 fields_info->field_length)))
7067       {
7068         DBUG_RETURN(0);
7069       }
7070       break;
7071     default:
7072       /* Don't let unimplemented types pass through. Could be a grave error. */
7073       DBUG_ASSERT(fields_info->field_type == MYSQL_TYPE_STRING);
7074 
7075       if (!(item= new Item_empty_string("", fields_info->field_length, cs)))
7076       {
7077         DBUG_RETURN(0);
7078       }
7079       item->item_name.copy(fields_info->field_name);
7080       break;
7081     }
7082     field_list.push_back(item);
7083     item->maybe_null= (fields_info->field_flags & MY_I_S_MAYBE_NULL);
7084     field_count++;
7085   }
7086   TMP_TABLE_PARAM *tmp_table_param =
7087     (TMP_TABLE_PARAM*) (thd->alloc(sizeof(TMP_TABLE_PARAM)));
7088   tmp_table_param->init();
7089   tmp_table_param->table_charset= cs;
7090   tmp_table_param->field_count= field_count;
7091   tmp_table_param->schema_table= 1;
7092   SELECT_LEX *select_lex= thd->lex->current_select;
7093   if (!(table= create_tmp_table(thd, tmp_table_param,
7094                                 field_list, (ORDER*) 0, 0, 0,
7095                                 (select_lex->options | thd->variables.option_bits |
7096                                  TMP_TABLE_ALL_COLUMNS),
7097                                 HA_POS_ERROR, table_list->alias)))
7098     DBUG_RETURN(0);
7099   my_bitmap_map* bitmaps=
7100     (my_bitmap_map*) thd->alloc(bitmap_buffer_size(field_count));
7101   bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count,
7102               FALSE);
7103   table->read_set= &table->def_read_set;
7104   bitmap_clear_all(table->read_set);
7105   table_list->schema_table_param= tmp_table_param;
7106   DBUG_RETURN(table);
7107 }
7108 
7109 
7110 /*
7111   For old SHOW compatibility. It is used when
7112   old SHOW doesn't have generated column names
7113   Make list of fields for SHOW
7114 
7115   SYNOPSIS
7116     make_old_format()
7117     thd			thread handler
7118     schema_table        pointer to 'schema_tables' element
7119 
7120   RETURN
7121    1	error
7122    0	success
7123 */
7124 
make_old_format(THD * thd,ST_SCHEMA_TABLE * schema_table)7125 int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
7126 {
7127   ST_FIELD_INFO *field_info= schema_table->fields_info;
7128   Name_resolution_context *context= &thd->lex->select_lex.context;
7129   for (; field_info->field_name; field_info++)
7130   {
7131     if (field_info->old_name)
7132     {
7133       Item_field *field= new Item_field(context,
7134                                         NullS, NullS, field_info->field_name);
7135       if (field)
7136       {
7137         field->item_name.copy(field_info->old_name);
7138         if (add_item_to_list(thd, field))
7139           return 1;
7140       }
7141     }
7142   }
7143   return 0;
7144 }
7145 
7146 
make_schemata_old_format(THD * thd,ST_SCHEMA_TABLE * schema_table)7147 int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
7148 {
7149   char tmp[128];
7150   LEX *lex= thd->lex;
7151   SELECT_LEX *sel= lex->current_select;
7152   Name_resolution_context *context= &sel->context;
7153 
7154   if (!sel->item_list.elements)
7155   {
7156     ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
7157     String buffer(tmp,sizeof(tmp), system_charset_info);
7158     Item_field *field= new Item_field(context,
7159                                       NullS, NullS, field_info->field_name);
7160     if (!field || add_item_to_list(thd, field))
7161       return 1;
7162     buffer.length(0);
7163     buffer.append(field_info->old_name);
7164     if (lex->wild && lex->wild->ptr())
7165     {
7166       buffer.append(STRING_WITH_LEN(" ("));
7167       buffer.append(lex->wild->ptr());
7168       buffer.append(')');
7169     }
7170     field->item_name.copy(buffer.ptr(), buffer.length(), system_charset_info);
7171   }
7172   return 0;
7173 }
7174 
7175 
make_table_names_old_format(THD * thd,ST_SCHEMA_TABLE * schema_table)7176 int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
7177 {
7178   char tmp[128];
7179   String buffer(tmp,sizeof(tmp), thd->charset());
7180   LEX *lex= thd->lex;
7181   Name_resolution_context *context= &lex->select_lex.context;
7182 
7183   ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
7184   buffer.length(0);
7185   buffer.append(field_info->old_name);
7186   buffer.append(lex->select_lex.db);
7187   if (lex->wild && lex->wild->ptr())
7188   {
7189     buffer.append(STRING_WITH_LEN(" ("));
7190     buffer.append(lex->wild->ptr());
7191     buffer.append(')');
7192   }
7193   Item_field *field= new Item_field(context,
7194                                     NullS, NullS, field_info->field_name);
7195   if (add_item_to_list(thd, field))
7196     return 1;
7197   field->item_name.copy(buffer.ptr(), buffer.length(), system_charset_info);
7198   if (thd->lex->verbose)
7199   {
7200     field->item_name.copy(buffer.ptr(), buffer.length(), system_charset_info);
7201     field_info= &schema_table->fields_info[3];
7202     field= new Item_field(context, NullS, NullS, field_info->field_name);
7203     if (add_item_to_list(thd, field))
7204       return 1;
7205     field->item_name.copy(field_info->old_name);
7206   }
7207   return 0;
7208 }
7209 
7210 
make_columns_old_format(THD * thd,ST_SCHEMA_TABLE * schema_table)7211 int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
7212 {
7213   int fields_arr[]= {IS_COLUMNS_COLUMN_NAME,
7214                      IS_COLUMNS_COLUMN_TYPE,
7215                      IS_COLUMNS_COLLATION_NAME,
7216                      IS_COLUMNS_IS_NULLABLE,
7217                      IS_COLUMNS_COLUMN_KEY,
7218                      IS_COLUMNS_COLUMN_DEFAULT,
7219                      IS_COLUMNS_EXTRA,
7220                      IS_COLUMNS_PRIVILEGES,
7221                      IS_COLUMNS_COLUMN_COMMENT,
7222                      -1};
7223   int *field_num= fields_arr;
7224   ST_FIELD_INFO *field_info;
7225   Name_resolution_context *context= &thd->lex->select_lex.context;
7226 
7227   for (; *field_num >= 0; field_num++)
7228   {
7229     field_info= &schema_table->fields_info[*field_num];
7230     if (!thd->lex->verbose && (*field_num == IS_COLUMNS_COLLATION_NAME ||
7231                                *field_num == IS_COLUMNS_PRIVILEGES     ||
7232                                *field_num == IS_COLUMNS_COLUMN_COMMENT))
7233       continue;
7234     Item_field *field= new Item_field(context,
7235                                       NullS, NullS, field_info->field_name);
7236     if (field)
7237     {
7238       field->item_name.copy(field_info->old_name);
7239       if (add_item_to_list(thd, field))
7240         return 1;
7241     }
7242   }
7243   return 0;
7244 }
7245 
7246 
make_character_sets_old_format(THD * thd,ST_SCHEMA_TABLE * schema_table)7247 int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
7248 {
7249   int fields_arr[]= {0, 2, 1, 3, -1};
7250   int *field_num= fields_arr;
7251   ST_FIELD_INFO *field_info;
7252   Name_resolution_context *context= &thd->lex->select_lex.context;
7253 
7254   for (; *field_num >= 0; field_num++)
7255   {
7256     field_info= &schema_table->fields_info[*field_num];
7257     Item_field *field= new Item_field(context,
7258                                       NullS, NullS, field_info->field_name);
7259     if (field)
7260     {
7261       field->item_name.copy(field_info->old_name);
7262       if (add_item_to_list(thd, field))
7263         return 1;
7264     }
7265   }
7266   return 0;
7267 }
7268 
7269 
make_proc_old_format(THD * thd,ST_SCHEMA_TABLE * schema_table)7270 int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
7271 {
7272   int fields_arr[]= {IS_ROUTINES_ROUTINE_SCHEMA,
7273                      IS_ROUTINES_ROUTINE_NAME,
7274                      IS_ROUTINES_ROUTINE_TYPE,
7275                      IS_ROUTINES_DEFINER,
7276                      IS_ROUTINES_LAST_ALTERED,
7277                      IS_ROUTINES_CREATED,
7278                      IS_ROUTINES_SECURITY_TYPE,
7279                      IS_ROUTINES_ROUTINE_COMMENT,
7280                      IS_ROUTINES_CHARACTER_SET_CLIENT,
7281                      IS_ROUTINES_COLLATION_CONNECTION,
7282                      IS_ROUTINES_DATABASE_COLLATION,
7283                      -1};
7284   int *field_num= fields_arr;
7285   ST_FIELD_INFO *field_info;
7286   Name_resolution_context *context= &thd->lex->select_lex.context;
7287 
7288   for (; *field_num >= 0; field_num++)
7289   {
7290     field_info= &schema_table->fields_info[*field_num];
7291     Item_field *field= new Item_field(context,
7292                                       NullS, NullS, field_info->field_name);
7293     if (field)
7294     {
7295       field->item_name.copy(field_info->old_name);
7296       if (add_item_to_list(thd, field))
7297         return 1;
7298     }
7299   }
7300   return 0;
7301 }
7302 
7303 
7304 /*
7305   Create information_schema table
7306 
7307   SYNOPSIS
7308   mysql_schema_table()
7309     thd                thread handler
7310     lex                pointer to LEX
7311     table_list         pointer to table_list
7312 
7313   RETURN
7314     0	success
7315     1   error
7316 */
7317 
mysql_schema_table(THD * thd,LEX * lex,TABLE_LIST * table_list)7318 int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
7319 {
7320   TABLE *table;
7321   DBUG_ENTER("mysql_schema_table");
7322   if (!(table= table_list->schema_table->create_table(thd, table_list)))
7323     DBUG_RETURN(1);
7324   table->s->tmp_table= SYSTEM_TMP_TABLE;
7325   table->grant.privilege= SELECT_ACL;
7326   /*
7327     This test is necessary to make
7328     case insensitive file systems +
7329     upper case table names(information schema tables) +
7330     views
7331     working correctly
7332   */
7333   if (table_list->schema_table_name)
7334     table->alias_name_used= my_strcasecmp(table_alias_charset,
7335                                           table_list->schema_table_name,
7336                                           table_list->alias);
7337   table_list->table_name= table->s->table_name.str;
7338   table_list->table_name_length= table->s->table_name.length;
7339   table_list->table= table;
7340   table->next= thd->derived_tables;
7341   thd->derived_tables= table;
7342   table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
7343   lex->safe_to_cache_query= 0;
7344 
7345   if (table_list->schema_table_reformed) // show command
7346   {
7347     SELECT_LEX *sel= lex->current_select;
7348     Item *item;
7349     Field_translator *transl, *org_transl;
7350 
7351     if (table_list->field_translation)
7352     {
7353       Field_translator *end= table_list->field_translation_end;
7354       for (transl= table_list->field_translation; transl < end; transl++)
7355       {
7356         if (!transl->item->fixed &&
7357             transl->item->fix_fields(thd, &transl->item))
7358           DBUG_RETURN(1);
7359       }
7360       DBUG_RETURN(0);
7361     }
7362     List_iterator_fast<Item> it(sel->item_list);
7363     if (!(transl=
7364           (Field_translator*)(thd->stmt_arena->
7365                               alloc(sel->item_list.elements *
7366                                     sizeof(Field_translator)))))
7367     {
7368       DBUG_RETURN(1);
7369     }
7370     for (org_transl= transl; (item= it++); transl++)
7371     {
7372       transl->item= item;
7373       transl->name= item->item_name.ptr();
7374       if (!item->fixed && item->fix_fields(thd, &transl->item))
7375       {
7376         DBUG_RETURN(1);
7377       }
7378     }
7379     table_list->field_translation= org_transl;
7380     table_list->field_translation_end= transl;
7381   }
7382 
7383   DBUG_RETURN(0);
7384 }
7385 
7386 
7387 /*
7388   Generate select from information_schema table
7389 
7390   SYNOPSIS
7391     make_schema_select()
7392     thd                  thread handler
7393     sel                  pointer to SELECT_LEX
7394     schema_table_idx     index of 'schema_tables' element
7395 
7396   RETURN
7397     0	success
7398     1   error
7399 */
7400 
make_schema_select(THD * thd,SELECT_LEX * sel,enum enum_schema_tables schema_table_idx)7401 int make_schema_select(THD *thd, SELECT_LEX *sel,
7402 		       enum enum_schema_tables schema_table_idx)
7403 {
7404   ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx);
7405   LEX_STRING db, table;
7406   DBUG_ENTER("make_schema_select");
7407   DBUG_PRINT("enter", ("mysql_schema_select: %s", schema_table->table_name));
7408   /*
7409      We have to make non const db_name & table_name
7410      because of lower_case_table_names
7411   */
7412   thd->make_lex_string(&db, INFORMATION_SCHEMA_NAME.str,
7413                        INFORMATION_SCHEMA_NAME.length, 0);
7414   thd->make_lex_string(&table, schema_table->table_name,
7415                        strlen(schema_table->table_name), 0);
7416   if (schema_table->old_format(thd, schema_table) ||   /* Handle old syntax */
7417       !sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
7418                               0, 0, TL_READ, MDL_SHARED_READ))
7419   {
7420     DBUG_RETURN(1);
7421   }
7422   DBUG_RETURN(0);
7423 }
7424 
7425 
7426 /**
7427   Fill INFORMATION_SCHEMA-table, leave correct Diagnostics_area /
7428   Warning_info state after itself.
7429 
7430   This function is a wrapper around ST_SCHEMA_TABLE::fill_table(), which
7431   may "partially silence" some errors. The thing is that during
7432   fill_table() many errors might be emitted. These errors stem from the
7433   nature of fill_table().
7434 
7435   For example, SELECT ... FROM INFORMATION_SCHEMA.xxx WHERE TABLE_NAME = 'xxx'
7436   results in a number of 'Table <db name>.xxx does not exist' errors,
7437   because fill_table() tries to open the 'xxx' table in every possible
7438   database.
7439 
7440   Those errors are cleared (the error status is cleared from
7441   Diagnostics_area) inside fill_table(), but they remain in Warning_info
7442   (Warning_info is not cleared because it may contain useful warnings).
7443 
7444   This function is responsible for making sure that Warning_info does not
7445   contain warnings corresponding to the cleared errors.
7446 
7447   @note: THD::no_warnings_for_error used to be set before calling
7448   fill_table(), thus those errors didn't go to Warning_info. This is not
7449   the case now (THD::no_warnings_for_error was eliminated as a hack), so we
7450   need to take care of those warnings here.
7451 
7452   @param thd            Thread context.
7453   @param table_list     I_S table.
7454   @param join_table     JOIN/SELECT table.
7455 
7456   @return Error status.
7457   @retval TRUE Error.
7458   @retval FALSE Success.
7459 */
do_fill_table(THD * thd,TABLE_LIST * table_list,JOIN_TAB * join_table)7460 static bool do_fill_table(THD *thd,
7461                           TABLE_LIST *table_list,
7462                           JOIN_TAB *join_table)
7463 {
7464   // NOTE: fill_table() may generate many "useless" warnings, which will be
7465   // ignored afterwards. On the other hand, there might be "useful"
7466   // warnings, which should be presented to the user. Warning_info usually
7467   // stores no more than THD::variables.max_error_count warnings.
7468   // The problem is that "useless warnings" may occupy all the slots in the
7469   // Warning_info, so "useful warnings" get rejected. In order to avoid
7470   // that problem we create a Warning_info instance, which is capable of
7471   // storing "unlimited" number of warnings.
7472   Diagnostics_area *da= thd->get_stmt_da();
7473   Warning_info wi_tmp(thd->query_id, true);
7474 
7475   da->push_warning_info(&wi_tmp);
7476 
7477   bool res= table_list->schema_table->fill_table(
7478     thd, table_list, join_table->unified_condition());
7479 
7480   da->pop_warning_info();
7481 
7482   // Pass an error if any.
7483 
7484   if (da->is_error())
7485   {
7486     da->push_warning(thd,
7487                      da->sql_errno(),
7488                      da->get_sqlstate(),
7489                      Sql_condition::WARN_LEVEL_ERROR,
7490                      da->message());
7491   }
7492 
7493   // Pass warnings (if any).
7494   //
7495   // Filter out warnings with WARN_LEVEL_ERROR level, because they
7496   // correspond to the errors which were filtered out in fill_table().
7497   da->copy_non_errors_from_wi(thd, &wi_tmp);
7498 
7499   return res;
7500 }
7501 
7502 
7503 /*
7504   Fill temporary schema tables before SELECT
7505 
7506   SYNOPSIS
7507     get_schema_tables_result()
7508     join  join which use schema tables
7509     executed_place place where I_S table processed
7510 
7511   RETURN
7512     FALSE success
7513     TRUE  error
7514 */
7515 
get_schema_tables_result(JOIN * join,enum enum_schema_table_state executed_place)7516 bool get_schema_tables_result(JOIN *join,
7517                               enum enum_schema_table_state executed_place)
7518 {
7519   THD *thd= join->thd;
7520   LEX *lex= thd->lex;
7521   bool result= 0;
7522   DBUG_ENTER("get_schema_tables_result");
7523 
7524   /* Check if the schema table is optimized away */
7525   if (!join->join_tab)
7526     DBUG_RETURN(result);
7527 
7528   for (uint i= 0; i < join->tables; i++)
7529   {
7530     JOIN_TAB *const tab= join->join_tab + i;
7531     if (!tab->table || !tab->table->pos_in_table_list)
7532       continue;
7533 
7534     TABLE_LIST *table_list= tab->table->pos_in_table_list;
7535     if (table_list->schema_table && thd->fill_information_schema_tables())
7536     {
7537       bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
7538                           lex->current_select->master_unit()->item);
7539 
7540       /* A value of 0 indicates a dummy implementation */
7541       if (table_list->schema_table->fill_table == 0)
7542         continue;
7543 
7544       /* skip I_S optimizations specific to get_all_tables */
7545       if (thd->lex->describe &&
7546           (table_list->schema_table->fill_table != get_all_tables))
7547         continue;
7548 
7549       /*
7550         If schema table is already processed and
7551         the statement is not a subselect then
7552         we don't need to fill this table again.
7553         If schema table is already processed and
7554         schema_table_state != executed_place then
7555         table is already processed and
7556         we should skip second data processing.
7557       */
7558       if (table_list->schema_table_state &&
7559           (!is_subselect || table_list->schema_table_state != executed_place))
7560         continue;
7561 
7562       /*
7563         if table is used in a subselect and
7564         table has been processed earlier with the same
7565         'executed_place' value then we should refresh the table.
7566       */
7567       if (table_list->schema_table_state && is_subselect)
7568       {
7569         table_list->table->file->extra(HA_EXTRA_NO_CACHE);
7570         table_list->table->file->extra(HA_EXTRA_RESET_STATE);
7571         table_list->table->file->ha_delete_all_rows();
7572         free_io_cache(table_list->table);
7573         filesort_free_buffers(table_list->table,1);
7574         table_list->table->null_row= 0;
7575       }
7576       else
7577         table_list->table->file->stats.records= 0;
7578 
7579       if (do_fill_table(thd, table_list, tab))
7580       {
7581         result= 1;
7582         join->error= 1;
7583         table_list->schema_table_state= executed_place;
7584         break;
7585       }
7586       table_list->schema_table_state= executed_place;
7587     }
7588   }
7589   DBUG_RETURN(result);
7590 }
7591 
7592 struct run_hton_fill_schema_table_args
7593 {
7594   TABLE_LIST *tables;
7595   Item *cond;
7596 };
7597 
run_hton_fill_schema_table(THD * thd,plugin_ref plugin,void * arg)7598 static my_bool run_hton_fill_schema_table(THD *thd, plugin_ref plugin,
7599                                           void *arg)
7600 {
7601   struct run_hton_fill_schema_table_args *args=
7602     (run_hton_fill_schema_table_args *) arg;
7603   handlerton *hton= plugin_data(plugin, handlerton *);
7604   if (hton->fill_is_table && hton->state == SHOW_OPTION_YES)
7605       hton->fill_is_table(hton, thd, args->tables, args->cond,
7606             get_schema_table_idx(args->tables->schema_table));
7607   return false;
7608 }
7609 
hton_fill_schema_table(THD * thd,TABLE_LIST * tables,Item * cond)7610 int hton_fill_schema_table(THD *thd, TABLE_LIST *tables, Item *cond)
7611 {
7612   DBUG_ENTER("hton_fill_schema_table");
7613 
7614   struct run_hton_fill_schema_table_args args;
7615   args.tables= tables;
7616   args.cond= cond;
7617 
7618   if (check_global_access(thd, PROCESS_ACL))
7619     DBUG_RETURN(1);
7620 
7621   plugin_foreach(thd, run_hton_fill_schema_table,
7622                  MYSQL_STORAGE_ENGINE_PLUGIN, &args);
7623 
7624   DBUG_RETURN(0);
7625 }
7626 
7627 
7628 ST_FIELD_INFO schema_fields_info[]=
7629 {
7630   {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7631   {"SCHEMA_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Database",
7632    SKIP_OPEN_TABLE},
7633   {"DEFAULT_CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
7634    SKIP_OPEN_TABLE},
7635   {"DEFAULT_COLLATION_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
7636    SKIP_OPEN_TABLE},
7637   {"SQL_PATH", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
7638   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7639 };
7640 
7641 
7642 ST_FIELD_INFO tables_fields_info[]=
7643 {
7644   {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7645   {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7646   {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
7647    SKIP_OPEN_TABLE},
7648   {"TABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7649   {"ENGINE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine", OPEN_FRM_ONLY},
7650   {"VERSION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
7651    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Version", OPEN_FRM_ONLY},
7652   {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format", OPEN_FULL_TABLE},
7653   {"TABLE_ROWS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
7654    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Rows", OPEN_FULL_TABLE},
7655   {"AVG_ROW_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
7656    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Avg_row_length", OPEN_FULL_TABLE},
7657   {"DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
7658    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_length", OPEN_FULL_TABLE},
7659   {"MAX_DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
7660    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Max_data_length", OPEN_FULL_TABLE},
7661   {"INDEX_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
7662    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Index_length", OPEN_FULL_TABLE},
7663   {"DATA_FREE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
7664    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_free", OPEN_FULL_TABLE},
7665   {"AUTO_INCREMENT", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG, 0,
7666    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Auto_increment", OPEN_FULL_TABLE},
7667   {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Create_time", OPEN_FULL_TABLE},
7668   {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Update_time", OPEN_FULL_TABLE},
7669   {"CHECK_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Check_time", OPEN_FULL_TABLE},
7670   {"TABLE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 1, "Collation",
7671    OPEN_FRM_ONLY},
7672   {"CHECKSUM", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
7673    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Checksum", OPEN_FULL_TABLE},
7674   {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options",
7675    OPEN_FRM_ONLY},
7676   {"TABLE_COMMENT", TABLE_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0,
7677    "Comment", OPEN_FRM_ONLY},
7678   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7679 };
7680 
7681 
7682 ST_FIELD_INFO columns_fields_info[]=
7683 {
7684   {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7685   {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7686   {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7687   {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Field",
7688    OPEN_FRM_ONLY},
7689   {"ORDINAL_POSITION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
7690    MY_I_S_UNSIGNED, 0, OPEN_FRM_ONLY},
7691   {"COLUMN_DEFAULT", MAX_FIELD_VARCHARLENGTH, MYSQL_TYPE_STRING, 0,
7692    1, "Default", OPEN_FRM_ONLY},
7693   {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null", OPEN_FRM_ONLY},
7694   {"DATA_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7695   {"CHARACTER_MAXIMUM_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
7696    0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
7697   {"CHARACTER_OCTET_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
7698    0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
7699   {"NUMERIC_PRECISION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
7700    0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
7701   {"NUMERIC_SCALE", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
7702    0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
7703   {"DATETIME_PRECISION", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
7704    0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
7705   {"CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 1, 0,
7706    OPEN_FRM_ONLY},
7707   {"COLLATION_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 1, "Collation",
7708    OPEN_FRM_ONLY},
7709   {"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type", OPEN_FRM_ONLY},
7710   {"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key", OPEN_FRM_ONLY},
7711   {"EXTRA", 30, MYSQL_TYPE_STRING, 0, 0, "Extra", OPEN_FRM_ONLY},
7712   {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges", OPEN_FRM_ONLY},
7713   {"COLUMN_COMMENT", COLUMN_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0,
7714    "Comment", OPEN_FRM_ONLY},
7715   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7716 };
7717 
7718 
7719 ST_FIELD_INFO charsets_fields_info[]=
7720 {
7721   {"CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, "Charset",
7722    SKIP_OPEN_TABLE},
7723   {"DEFAULT_COLLATE_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
7724    "Default collation", SKIP_OPEN_TABLE},
7725   {"DESCRIPTION", 60, MYSQL_TYPE_STRING, 0, 0, "Description",
7726    SKIP_OPEN_TABLE},
7727   {"MAXLEN", 3, MYSQL_TYPE_LONGLONG, 0, 0, "Maxlen", SKIP_OPEN_TABLE},
7728   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7729 };
7730 
7731 
7732 ST_FIELD_INFO collation_fields_info[]=
7733 {
7734   {"COLLATION_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, "Collation",
7735    SKIP_OPEN_TABLE},
7736   {"CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, "Charset",
7737    SKIP_OPEN_TABLE},
7738   {"ID", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Id",
7739    SKIP_OPEN_TABLE},
7740   {"IS_DEFAULT", 3, MYSQL_TYPE_STRING, 0, 0, "Default", SKIP_OPEN_TABLE},
7741   {"IS_COMPILED", 3, MYSQL_TYPE_STRING, 0, 0, "Compiled", SKIP_OPEN_TABLE},
7742   {"SORTLEN", 3, MYSQL_TYPE_LONGLONG, 0, 0, "Sortlen", SKIP_OPEN_TABLE},
7743   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7744 };
7745 
7746 
7747 ST_FIELD_INFO engines_fields_info[]=
7748 {
7749   {"ENGINE", 64, MYSQL_TYPE_STRING, 0, 0, "Engine", SKIP_OPEN_TABLE},
7750   {"SUPPORT", 8, MYSQL_TYPE_STRING, 0, 0, "Support", SKIP_OPEN_TABLE},
7751   {"COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment", SKIP_OPEN_TABLE},
7752   {"TRANSACTIONS", 3, MYSQL_TYPE_STRING, 0, 1, "Transactions", SKIP_OPEN_TABLE},
7753   {"XA", 3, MYSQL_TYPE_STRING, 0, 1, "XA", SKIP_OPEN_TABLE},
7754   {"SAVEPOINTS", 3 ,MYSQL_TYPE_STRING, 0, 1, "Savepoints", SKIP_OPEN_TABLE},
7755   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7756 };
7757 
7758 
7759 ST_FIELD_INFO events_fields_info[]=
7760 {
7761   {"EVENT_CATALOG", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7762   {"EVENT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Db",
7763    SKIP_OPEN_TABLE},
7764   {"EVENT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
7765    SKIP_OPEN_TABLE},
7766   {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", SKIP_OPEN_TABLE},
7767   {"TIME_ZONE", 64, MYSQL_TYPE_STRING, 0, 0, "Time zone", SKIP_OPEN_TABLE},
7768   {"EVENT_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7769   {"EVENT_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7770   {"EVENT_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
7771   {"EXECUTE_AT", 0, MYSQL_TYPE_DATETIME, 0, 1, "Execute at", SKIP_OPEN_TABLE},
7772   {"INTERVAL_VALUE", 256, MYSQL_TYPE_STRING, 0, 1, "Interval value",
7773    SKIP_OPEN_TABLE},
7774   {"INTERVAL_FIELD", 18, MYSQL_TYPE_STRING, 0, 1, "Interval field",
7775    SKIP_OPEN_TABLE},
7776   {"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7777   {"STARTS", 0, MYSQL_TYPE_DATETIME, 0, 1, "Starts", SKIP_OPEN_TABLE},
7778   {"ENDS", 0, MYSQL_TYPE_DATETIME, 0, 1, "Ends", SKIP_OPEN_TABLE},
7779   {"STATUS", 18, MYSQL_TYPE_STRING, 0, 0, "Status", SKIP_OPEN_TABLE},
7780   {"ON_COMPLETION", 12, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7781   {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 0, 0, SKIP_OPEN_TABLE},
7782   {"LAST_ALTERED", 0, MYSQL_TYPE_DATETIME, 0, 0, 0, SKIP_OPEN_TABLE},
7783   {"LAST_EXECUTED", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
7784   {"EVENT_COMMENT", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7785   {"ORIGINATOR", 10, MYSQL_TYPE_LONGLONG, 0, 0, "Originator", SKIP_OPEN_TABLE},
7786   {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
7787    "character_set_client", SKIP_OPEN_TABLE},
7788   {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
7789    "collation_connection", SKIP_OPEN_TABLE},
7790   {"DATABASE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
7791    "Database Collation", SKIP_OPEN_TABLE},
7792   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7793 };
7794 
7795 
7796 
7797 ST_FIELD_INFO coll_charset_app_fields_info[]=
7798 {
7799   {"COLLATION_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
7800    SKIP_OPEN_TABLE},
7801   {"CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
7802    SKIP_OPEN_TABLE},
7803   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7804 };
7805 
7806 
7807 ST_FIELD_INFO proc_fields_info[]=
7808 {
7809   {"SPECIFIC_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7810   {"ROUTINE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7811   {"ROUTINE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Db",
7812    SKIP_OPEN_TABLE},
7813   {"ROUTINE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
7814    SKIP_OPEN_TABLE},
7815   {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
7816   {"DATA_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7817   {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, SKIP_OPEN_TABLE},
7818   {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, SKIP_OPEN_TABLE},
7819   {"NUMERIC_PRECISION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
7820    0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
7821   {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0, SKIP_OPEN_TABLE},
7822   {"DATETIME_PRECISION", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
7823    0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
7824   {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
7825   {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
7826   {"DTD_IDENTIFIER", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
7827   {"ROUTINE_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7828   {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
7829   {"EXTERNAL_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
7830   {"EXTERNAL_LANGUAGE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
7831    SKIP_OPEN_TABLE},
7832   {"PARAMETER_STYLE", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7833   {"IS_DETERMINISTIC", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7834   {"SQL_DATA_ACCESS", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
7835    SKIP_OPEN_TABLE},
7836   {"SQL_PATH", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
7837   {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, "Security_type",
7838    SKIP_OPEN_TABLE},
7839   {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 0, "Created", SKIP_OPEN_TABLE},
7840   {"LAST_ALTERED", 0, MYSQL_TYPE_DATETIME, 0, 0, "Modified", SKIP_OPEN_TABLE},
7841   {"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7842   {"ROUTINE_COMMENT", 65535, MYSQL_TYPE_STRING, 0, 0, "Comment",
7843    SKIP_OPEN_TABLE},
7844   {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", SKIP_OPEN_TABLE},
7845   {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
7846    "character_set_client", SKIP_OPEN_TABLE},
7847   {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
7848    "collation_connection", SKIP_OPEN_TABLE},
7849   {"DATABASE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
7850    "Database Collation", SKIP_OPEN_TABLE},
7851   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7852 };
7853 
7854 
7855 ST_FIELD_INFO stat_fields_info[]=
7856 {
7857   {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7858   {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7859   {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", OPEN_FRM_ONLY},
7860   {"NON_UNIQUE", 1, MYSQL_TYPE_LONGLONG, 0, 0, "Non_unique", OPEN_FRM_ONLY},
7861   {"INDEX_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7862   {"INDEX_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Key_name",
7863    OPEN_FRM_ONLY},
7864   {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONGLONG, 0, 0, "Seq_in_index", OPEN_FRM_ONLY},
7865   {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name",
7866    OPEN_FRM_ONLY},
7867   {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY},
7868   {"CARDINALITY", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 1,
7869    "Cardinality", OPEN_FULL_TABLE},
7870   {"SUB_PART", 3, MYSQL_TYPE_LONGLONG, 0, 1, "Sub_part", OPEN_FRM_ONLY},
7871   {"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, "Packed", OPEN_FRM_ONLY},
7872   {"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null", OPEN_FRM_ONLY},
7873   {"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, "Index_type", OPEN_FULL_TABLE},
7874   {"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, "Comment", OPEN_FRM_ONLY},
7875   {"INDEX_COMMENT", INDEX_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0,
7876    "Index_comment", OPEN_FRM_ONLY},
7877   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7878 };
7879 
7880 
7881 ST_FIELD_INFO view_fields_info[]=
7882 {
7883   {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7884   {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7885   {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7886   {"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7887   {"CHECK_OPTION", 8, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7888   {"IS_UPDATABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
7889   {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7890   {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
7891   {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
7892    OPEN_FRM_ONLY},
7893   {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
7894    OPEN_FRM_ONLY},
7895   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7896 };
7897 
7898 
7899 ST_FIELD_INFO user_privileges_fields_info[]=
7900 {
7901   {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7902   {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7903   {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7904   {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7905   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7906 };
7907 
7908 
7909 ST_FIELD_INFO schema_privileges_fields_info[]=
7910 {
7911   {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7912   {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7913   {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7914   {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7915   {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7916   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7917 };
7918 
7919 
7920 ST_FIELD_INFO table_privileges_fields_info[]=
7921 {
7922   {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7923   {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7924   {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7925   {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7926   {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7927   {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7928   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7929 };
7930 
7931 
7932 ST_FIELD_INFO column_privileges_fields_info[]=
7933 {
7934   {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7935   {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7936   {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7937   {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7938   {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7939   {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7940   {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7941   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7942 };
7943 
7944 
7945 ST_FIELD_INFO table_constraints_fields_info[]=
7946 {
7947   {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
7948   {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
7949    OPEN_FULL_TABLE},
7950   {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
7951    OPEN_FULL_TABLE},
7952   {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
7953   {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
7954   {"CONSTRAINT_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
7955    OPEN_FULL_TABLE},
7956   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7957 };
7958 
7959 
7960 ST_FIELD_INFO key_column_usage_fields_info[]=
7961 {
7962   {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
7963   {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
7964    OPEN_FULL_TABLE},
7965   {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
7966    OPEN_FULL_TABLE},
7967   {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
7968   {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
7969   {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
7970   {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
7971   {"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONGLONG, 0, 0, 0, OPEN_FULL_TABLE},
7972   {"POSITION_IN_UNIQUE_CONSTRAINT", 10 ,MYSQL_TYPE_LONGLONG, 0, 1, 0,
7973    OPEN_FULL_TABLE},
7974   {"REFERENCED_TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
7975    OPEN_FULL_TABLE},
7976   {"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
7977    OPEN_FULL_TABLE},
7978   {"REFERENCED_COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
7979    OPEN_FULL_TABLE},
7980   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7981 };
7982 
7983 
7984 ST_FIELD_INFO table_names_fields_info[]=
7985 {
7986   {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7987   {"TABLE_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
7988   {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_",
7989    SKIP_OPEN_TABLE},
7990   {"TABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type",
7991    OPEN_FRM_ONLY},
7992   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
7993 };
7994 
7995 
7996 ST_FIELD_INFO open_tables_fields_info[]=
7997 {
7998   {"Database", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Database",
7999    SKIP_OPEN_TABLE},
8000   {"Table",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", SKIP_OPEN_TABLE},
8001   {"In_use", 1, MYSQL_TYPE_LONGLONG, 0, 0, "In_use", SKIP_OPEN_TABLE},
8002   {"Name_locked", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Name_locked", SKIP_OPEN_TABLE},
8003   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
8004 };
8005 
8006 
8007 ST_FIELD_INFO triggers_fields_info[]=
8008 {
8009   {"TRIGGER_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
8010   {"TRIGGER_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
8011   {"TRIGGER_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Trigger",
8012    OPEN_FRM_ONLY},
8013   {"EVENT_MANIPULATION", 6, MYSQL_TYPE_STRING, 0, 0, "Event", OPEN_FRM_ONLY},
8014   {"EVENT_OBJECT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0,
8015    OPEN_FRM_ONLY},
8016   {"EVENT_OBJECT_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
8017    OPEN_FRM_ONLY},
8018   {"EVENT_OBJECT_TABLE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table",
8019    OPEN_FRM_ONLY},
8020   {"ACTION_ORDER", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, OPEN_FRM_ONLY},
8021   {"ACTION_CONDITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
8022   {"ACTION_STATEMENT", 65535, MYSQL_TYPE_STRING, 0, 0, "Statement",
8023    OPEN_FRM_ONLY},
8024   {"ACTION_ORIENTATION", 9, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
8025   {"ACTION_TIMING", 6, MYSQL_TYPE_STRING, 0, 0, "Timing", OPEN_FRM_ONLY},
8026   {"ACTION_REFERENCE_OLD_TABLE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
8027    OPEN_FRM_ONLY},
8028   {"ACTION_REFERENCE_NEW_TABLE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
8029    OPEN_FRM_ONLY},
8030   {"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
8031   {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
8032   {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 1, "Created", OPEN_FRM_ONLY},
8033   {"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, "sql_mode", OPEN_FRM_ONLY},
8034   {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", OPEN_FRM_ONLY},
8035   {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
8036    "character_set_client", OPEN_FRM_ONLY},
8037   {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
8038    "collation_connection", OPEN_FRM_ONLY},
8039   {"DATABASE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
8040    "Database Collation", OPEN_FRM_ONLY},
8041   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
8042 };
8043 
8044 
8045 ST_FIELD_INFO partitions_fields_info[]=
8046 {
8047   {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8048   {"TABLE_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8049   {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8050   {"PARTITION_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
8051   {"SUBPARTITION_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
8052    OPEN_FULL_TABLE},
8053   {"PARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONGLONG, 0,
8054    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
8055   {"SUBPARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONGLONG, 0,
8056    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
8057   {"PARTITION_METHOD", 18, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
8058   {"SUBPARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
8059   {"PARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
8060   {"SUBPARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0,
8061    OPEN_FULL_TABLE},
8062   {"PARTITION_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
8063   {"TABLE_ROWS", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
8064    OPEN_FULL_TABLE},
8065   {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
8066    OPEN_FULL_TABLE},
8067   {"DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
8068    OPEN_FULL_TABLE},
8069   {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0,
8070    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
8071   {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
8072    OPEN_FULL_TABLE},
8073   {"DATA_FREE", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
8074    OPEN_FULL_TABLE},
8075   {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, OPEN_FULL_TABLE},
8076   {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, OPEN_FULL_TABLE},
8077   {"CHECK_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, OPEN_FULL_TABLE},
8078   {"CHECKSUM", 21 , MYSQL_TYPE_LONGLONG, 0,
8079    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
8080   {"PARTITION_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8081   {"NODEGROUP", 12 , MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8082   {"TABLESPACE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
8083    OPEN_FULL_TABLE},
8084   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
8085 };
8086 
8087 
8088 ST_FIELD_INFO variables_fields_info[]=
8089 {
8090   {"VARIABLE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Variable_name",
8091    SKIP_OPEN_TABLE},
8092   {"VARIABLE_VALUE", 1024, MYSQL_TYPE_STRING, 0, 1, "Value", SKIP_OPEN_TABLE},
8093   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
8094 };
8095 
8096 
8097 ST_FIELD_INFO processlist_fields_info[]=
8098 {
8099   {"ID", 21, MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, "Id", SKIP_OPEN_TABLE},
8100   {"USER", 16, MYSQL_TYPE_STRING, 0, 0, "User", SKIP_OPEN_TABLE},
8101   {"HOST", LIST_PROCESS_HOST_LEN,  MYSQL_TYPE_STRING, 0, 0, "Host",
8102    SKIP_OPEN_TABLE},
8103   {"DB", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Db", SKIP_OPEN_TABLE},
8104   {"COMMAND", 16, MYSQL_TYPE_STRING, 0, 0, "Command", SKIP_OPEN_TABLE},
8105   {"TIME", 7, MYSQL_TYPE_LONG, 0, 0, "Time", SKIP_OPEN_TABLE},
8106   {"STATE", 64, MYSQL_TYPE_STRING, 0, 1, "State", SKIP_OPEN_TABLE},
8107   {"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info",
8108    SKIP_OPEN_TABLE},
8109   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
8110 };
8111 
8112 
8113 ST_FIELD_INFO plugin_fields_info[]=
8114 {
8115   {"PLUGIN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
8116    SKIP_OPEN_TABLE},
8117   {"PLUGIN_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
8118   {"PLUGIN_STATUS", 10, MYSQL_TYPE_STRING, 0, 0, "Status", SKIP_OPEN_TABLE},
8119   {"PLUGIN_TYPE", 80, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
8120   {"PLUGIN_TYPE_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
8121   {"PLUGIN_LIBRARY", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Library",
8122    SKIP_OPEN_TABLE},
8123   {"PLUGIN_LIBRARY_VERSION", 20, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
8124   {"PLUGIN_AUTHOR", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
8125   {"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
8126   {"PLUGIN_LICENSE", 80, MYSQL_TYPE_STRING, 0, 1, "License", SKIP_OPEN_TABLE},
8127   {"LOAD_OPTION", 64, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
8128   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
8129 };
8130 
8131 ST_FIELD_INFO files_fields_info[]=
8132 {
8133   {"FILE_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE},
8134   {"FILE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
8135   {"FILE_TYPE", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
8136   {"TABLESPACE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
8137    SKIP_OPEN_TABLE},
8138   {"TABLE_CATALOG", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
8139   {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
8140   {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
8141   {"LOGFILE_GROUP_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
8142    SKIP_OPEN_TABLE},
8143   {"LOGFILE_GROUP_NUMBER", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
8144   {"ENGINE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
8145   {"FULLTEXT_KEYS", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
8146   {"DELETED_ROWS", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
8147   {"UPDATE_COUNT", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
8148   {"FREE_EXTENTS", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
8149   {"TOTAL_EXTENTS", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
8150   {"EXTENT_SIZE", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE},
8151   {"INITIAL_SIZE", 21, MYSQL_TYPE_LONGLONG, 0,
8152    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
8153   {"MAXIMUM_SIZE", 21, MYSQL_TYPE_LONGLONG, 0,
8154    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
8155   {"AUTOEXTEND_SIZE", 21, MYSQL_TYPE_LONGLONG, 0,
8156    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
8157   {"CREATION_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
8158   {"LAST_UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
8159   {"LAST_ACCESS_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
8160   {"RECOVER_TIME", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
8161   {"TRANSACTION_COUNTER", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
8162   {"VERSION", 21 , MYSQL_TYPE_LONGLONG, 0,
8163    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Version", SKIP_OPEN_TABLE},
8164   {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format", SKIP_OPEN_TABLE},
8165   {"TABLE_ROWS", 21 , MYSQL_TYPE_LONGLONG, 0,
8166    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Rows", SKIP_OPEN_TABLE},
8167   {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0,
8168    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Avg_row_length", SKIP_OPEN_TABLE},
8169   {"DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0,
8170    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_length", SKIP_OPEN_TABLE},
8171   {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0,
8172    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Max_data_length", SKIP_OPEN_TABLE},
8173   {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0,
8174    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Index_length", SKIP_OPEN_TABLE},
8175   {"DATA_FREE", 21 , MYSQL_TYPE_LONGLONG, 0,
8176    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_free", SKIP_OPEN_TABLE},
8177   {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Create_time", SKIP_OPEN_TABLE},
8178   {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Update_time", SKIP_OPEN_TABLE},
8179   {"CHECK_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Check_time", SKIP_OPEN_TABLE},
8180   {"CHECKSUM", 21 , MYSQL_TYPE_LONGLONG, 0,
8181    (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Checksum", SKIP_OPEN_TABLE},
8182   {"STATUS", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
8183   {"EXTRA", 255, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
8184   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
8185 };
8186 
init_fill_schema_files_row(TABLE * table)8187 void init_fill_schema_files_row(TABLE* table)
8188 {
8189   int i;
8190   for(i=0; files_fields_info[i].field_name!=NULL; i++)
8191     table->field[i]->set_null();
8192 
8193   table->field[IS_FILES_STATUS]->set_notnull();
8194   table->field[IS_FILES_STATUS]->store("NORMAL", 6, system_charset_info);
8195 }
8196 
8197 ST_FIELD_INFO referential_constraints_fields_info[]=
8198 {
8199   {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8200   {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
8201    OPEN_FULL_TABLE},
8202   {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
8203    OPEN_FULL_TABLE},
8204   {"UNIQUE_CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0,
8205    OPEN_FULL_TABLE},
8206   {"UNIQUE_CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
8207    OPEN_FULL_TABLE},
8208   {"UNIQUE_CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0,
8209    MY_I_S_MAYBE_NULL, 0, OPEN_FULL_TABLE},
8210   {"MATCH_OPTION", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8211   {"UPDATE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8212   {"DELETE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8213   {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8214   {"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
8215    OPEN_FULL_TABLE},
8216   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
8217 };
8218 
8219 
8220 ST_FIELD_INFO parameters_fields_info[]=
8221 {
8222   {"SPECIFIC_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8223   {"SPECIFIC_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
8224    OPEN_FULL_TABLE},
8225   {"SPECIFIC_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8226   {"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0, OPEN_FULL_TABLE},
8227   {"PARAMETER_MODE", 5, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
8228   {"PARAMETER_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
8229   {"DATA_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8230   {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE},
8231   {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE},
8232   {"NUMERIC_PRECISION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
8233    0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
8234   {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE},
8235   {"DATETIME_PRECISION", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
8236    0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
8237   {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
8238   {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
8239   {"DTD_IDENTIFIER", 65535, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8240   {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
8241   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}
8242 };
8243 
8244 
8245 ST_FIELD_INFO tablespaces_fields_info[]=
8246 {
8247   {"TABLESPACE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
8248    SKIP_OPEN_TABLE},
8249   {"ENGINE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
8250   {"TABLESPACE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL,
8251    0, SKIP_OPEN_TABLE},
8252   {"LOGFILE_GROUP_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL,
8253    0, SKIP_OPEN_TABLE},
8254   {"EXTENT_SIZE", 21, MYSQL_TYPE_LONGLONG, 0,
8255    MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED, 0, SKIP_OPEN_TABLE},
8256   {"AUTOEXTEND_SIZE", 21, MYSQL_TYPE_LONGLONG, 0,
8257    MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED, 0, SKIP_OPEN_TABLE},
8258   {"MAXIMUM_SIZE", 21, MYSQL_TYPE_LONGLONG, 0,
8259    MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED, 0, SKIP_OPEN_TABLE},
8260   {"NODEGROUP_ID", 21, MYSQL_TYPE_LONGLONG, 0,
8261    MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED, 0, SKIP_OPEN_TABLE},
8262   {"TABLESPACE_COMMENT", 2048, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, 0,
8263    SKIP_OPEN_TABLE},
8264   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
8265 };
8266 
8267 
8268 /** For creating fields of information_schema.OPTIMIZER_TRACE */
8269 extern ST_FIELD_INFO optimizer_trace_info[];
8270 
8271 /*
8272   Description of ST_FIELD_INFO in table.h
8273 
8274   Make sure that the order of schema_tables and enum_schema_tables are the same.
8275 
8276 */
8277 
8278 ST_SCHEMA_TABLE schema_tables[]=
8279 {
8280   {"CHARACTER_SETS", charsets_fields_info, create_schema_table,
8281    fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0, 0},
8282   {"COLLATIONS", collation_fields_info, create_schema_table,
8283    fill_schema_collation, make_old_format, 0, -1, -1, 0, 0},
8284   {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info,
8285    create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1, 0, 0},
8286   {"COLUMNS", columns_fields_info, create_schema_table,
8287    get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2, 0,
8288    OPTIMIZE_I_S_TABLE|OPEN_VIEW_FULL},
8289   {"COLUMN_PRIVILEGES", column_privileges_fields_info, create_schema_table,
8290    fill_schema_column_privileges, 0, 0, -1, -1, 0, 0},
8291   {"ENGINES", engines_fields_info, create_schema_table,
8292    fill_schema_engines, make_old_format, 0, -1, -1, 0, 0},
8293 #ifdef HAVE_EVENT_SCHEDULER
8294   {"EVENTS", events_fields_info, create_schema_table,
8295    Events::fill_schema_events, make_old_format, 0, -1, -1, 0, 0},
8296 #else // for alignment with enum_schema_tables
8297   {"EVENTS", events_fields_info, create_schema_table,
8298    0, make_old_format, 0, -1, -1, 0, 0},
8299 #endif
8300   {"FILES", files_fields_info, create_schema_table,
8301    hton_fill_schema_table, 0, 0, -1, -1, 0, 0},
8302   {"GLOBAL_STATUS", variables_fields_info, create_schema_table,
8303    fill_status, make_old_format, 0, 0, -1, 0, 0},
8304   {"GLOBAL_VARIABLES", variables_fields_info, create_schema_table,
8305    fill_variables, make_old_format, 0, 0, -1, 0, 0},
8306   {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
8307    get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
8308    OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
8309   {"OPEN_TABLES", open_tables_fields_info, create_schema_table,
8310    fill_open_tables, make_old_format, 0, -1, -1, 1, 0},
8311 #ifdef OPTIMIZER_TRACE
8312   {"OPTIMIZER_TRACE", optimizer_trace_info, create_schema_table,
8313    fill_optimizer_trace_info, NULL, NULL, -1, -1, false, 0},
8314 #else // for alignment with enum_schema_tables
8315   {"OPTIMIZER_TRACE", optimizer_trace_info, create_schema_table,
8316    NULL, NULL, NULL, -1, -1, false, 0},
8317 #endif
8318   {"PARAMETERS", parameters_fields_info, create_schema_table,
8319    fill_schema_proc, 0, 0, -1, -1, 0, 0},
8320   {"PARTITIONS", partitions_fields_info, create_schema_table,
8321    get_all_tables, 0, get_schema_partitions_record, 1, 2, 0,
8322    OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
8323   {"PLUGINS", plugin_fields_info, create_schema_table,
8324    fill_plugins, make_old_format, 0, -1, -1, 0, 0},
8325   {"PROCESSLIST", processlist_fields_info, create_schema_table,
8326    fill_schema_processlist, make_old_format, 0, -1, -1, 0, 0},
8327   {"PROFILING", query_profile_statistics_info, create_schema_table,
8328     fill_query_profile_statistics_info, make_profile_table_for_show,
8329     NULL, -1, -1, false, 0},
8330   {"REFERENTIAL_CONSTRAINTS", referential_constraints_fields_info,
8331    create_schema_table, get_all_tables, 0, get_referential_constraints_record,
8332    1, 9, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
8333   {"ROUTINES", proc_fields_info, create_schema_table,
8334    fill_schema_proc, make_proc_old_format, 0, -1, -1, 0, 0},
8335   {"SCHEMATA", schema_fields_info, create_schema_table,
8336    fill_schema_schemata, make_schemata_old_format, 0, 1, -1, 0, 0},
8337   {"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table,
8338    fill_schema_schema_privileges, 0, 0, -1, -1, 0, 0},
8339   {"SESSION_STATUS", variables_fields_info, create_schema_table,
8340    fill_status, make_old_format, 0, 0, -1, 0, 0},
8341   {"SESSION_VARIABLES", variables_fields_info, create_schema_table,
8342    fill_variables, make_old_format, 0, 0, -1, 0, 0},
8343   {"STATISTICS", stat_fields_info, create_schema_table,
8344    get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0,
8345    OPEN_TABLE_ONLY|OPTIMIZE_I_S_TABLE},
8346   {"STATUS", variables_fields_info, create_schema_table, fill_status,
8347    make_old_format, 0, 0, -1, 1, 0},
8348   {"TABLES", tables_fields_info, create_schema_table,
8349    get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0,
8350    OPTIMIZE_I_S_TABLE},
8351   {"TABLESPACES", tablespaces_fields_info, create_schema_table,
8352    hton_fill_schema_table, 0, 0, -1, -1, 0, 0},
8353   {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table,
8354    get_all_tables, 0, get_schema_constraints_record, 3, 4, 0,
8355    OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
8356   {"TABLE_NAMES", table_names_fields_info, create_schema_table,
8357    get_all_tables, make_table_names_old_format, 0, 1, 2, 1, 0},
8358   {"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table,
8359    fill_schema_table_privileges, 0, 0, -1, -1, 0, 0},
8360   {"TRIGGERS", triggers_fields_info, create_schema_table,
8361    get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0,
8362    OPEN_TRIGGER_ONLY|OPTIMIZE_I_S_TABLE},
8363   {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table,
8364    fill_schema_user_privileges, 0, 0, -1, -1, 0, 0},
8365   {"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
8366    make_old_format, 0, 0, -1, 1, 0},
8367   {"VIEWS", view_fields_info, create_schema_table,
8368    get_all_tables, 0, get_schema_views_record, 1, 2, 0,
8369    OPEN_VIEW_ONLY|OPTIMIZE_I_S_TABLE},
8370   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
8371 };
8372 
8373 
initialize_schema_table(st_plugin_int * plugin)8374 int initialize_schema_table(st_plugin_int *plugin)
8375 {
8376   ST_SCHEMA_TABLE *schema_table;
8377   DBUG_ENTER("initialize_schema_table");
8378 
8379   if (!(schema_table= (ST_SCHEMA_TABLE *)my_malloc(sizeof(ST_SCHEMA_TABLE),
8380                                 MYF(MY_WME | MY_ZEROFILL))))
8381       DBUG_RETURN(1);
8382   /* Historical Requirement */
8383   plugin->data= schema_table; // shortcut for the future
8384   if (plugin->plugin->init)
8385   {
8386     schema_table->create_table= create_schema_table;
8387     schema_table->old_format= make_old_format;
8388     schema_table->idx_field1= -1,
8389     schema_table->idx_field2= -1;
8390 
8391     /* Make the name available to the init() function. */
8392     schema_table->table_name= plugin->name.str;
8393 
8394     if (plugin->plugin->init(schema_table))
8395     {
8396       sql_print_error("Plugin '%s' init function returned error.",
8397                       plugin->name.str);
8398       plugin->data= NULL;
8399       my_free(schema_table);
8400       DBUG_RETURN(1);
8401     }
8402 
8403     /* Make sure the plugin name is not set inside the init() function. */
8404     schema_table->table_name= plugin->name.str;
8405   }
8406   DBUG_RETURN(0);
8407 }
8408 
finalize_schema_table(st_plugin_int * plugin)8409 int finalize_schema_table(st_plugin_int *plugin)
8410 {
8411   ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data;
8412   DBUG_ENTER("finalize_schema_table");
8413 
8414   if (schema_table)
8415   {
8416     if (plugin->plugin->deinit)
8417     {
8418       DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str));
8419       if (plugin->plugin->deinit(NULL))
8420       {
8421         DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.",
8422                                plugin->name.str));
8423       }
8424     }
8425     my_free(schema_table);
8426   }
8427   DBUG_RETURN(0);
8428 }
8429 
8430 
8431 /**
8432   Output trigger information (SHOW CREATE TRIGGER) to the client.
8433 
8434   @param thd          Thread context.
8435   @param triggers     List of triggers for the table.
8436   @param trigger_idx  Index of the trigger to dump.
8437 
8438   @return Operation status
8439     @retval TRUE Error.
8440     @retval FALSE Success.
8441 */
8442 
show_create_trigger_impl(THD * thd,Table_triggers_list * triggers,int trigger_idx)8443 static bool show_create_trigger_impl(THD *thd,
8444                                      Table_triggers_list *triggers,
8445                                      int trigger_idx)
8446 {
8447   int ret_code;
8448 
8449   Protocol *p= thd->protocol;
8450   List<Item> fields;
8451 
8452   LEX_STRING trg_name;
8453   sql_mode_t trg_sql_mode;
8454   LEX_STRING trg_sql_mode_str;
8455   LEX_STRING trg_sql_original_stmt;
8456   LEX_STRING trg_client_cs_name;
8457   LEX_STRING trg_connection_cl_name;
8458   LEX_STRING trg_db_cl_name;
8459 
8460   const CHARSET_INFO *trg_client_cs;
8461 
8462   /*
8463     TODO: Check privileges here. This functionality will be added by
8464     implementation of the following WL items:
8465       - WL#2227: New privileges for new objects
8466       - WL#3482: Protect SHOW CREATE PROCEDURE | FUNCTION | VIEW | TRIGGER
8467         properly
8468 
8469     SHOW TRIGGERS and I_S.TRIGGERS will be affected too.
8470   */
8471 
8472   /* Prepare trigger "object". */
8473 
8474   triggers->get_trigger_info(thd,
8475                              trigger_idx,
8476                              &trg_name,
8477                              &trg_sql_mode,
8478                              &trg_sql_original_stmt,
8479                              &trg_client_cs_name,
8480                              &trg_connection_cl_name,
8481                              &trg_db_cl_name);
8482 
8483   sql_mode_string_representation(thd, trg_sql_mode, &trg_sql_mode_str);
8484 
8485   /* Resolve trigger client character set. */
8486 
8487   if (resolve_charset(trg_client_cs_name.str, NULL, &trg_client_cs))
8488     return TRUE;
8489 
8490   /* Send header. */
8491 
8492   fields.push_back(new Item_empty_string("Trigger", NAME_LEN));
8493   fields.push_back(new Item_empty_string("sql_mode", trg_sql_mode_str.length));
8494 
8495   {
8496     /*
8497       NOTE: SQL statement field must be not less than 1024 in order not to
8498       confuse old clients.
8499     */
8500 
8501     Item_empty_string *stmt_fld=
8502       new Item_empty_string("SQL Original Statement",
8503                             max<size_t>(trg_sql_original_stmt.length, 1024));
8504 
8505     stmt_fld->maybe_null= TRUE;
8506 
8507     fields.push_back(stmt_fld);
8508   }
8509 
8510   fields.push_back(new Item_empty_string("character_set_client",
8511                                          MY_CS_NAME_SIZE));
8512 
8513   fields.push_back(new Item_empty_string("collation_connection",
8514                                          MY_CS_NAME_SIZE));
8515 
8516   fields.push_back(new Item_empty_string("Database Collation",
8517                                          MY_CS_NAME_SIZE));
8518 
8519   if (p->send_result_set_metadata(&fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
8520     return TRUE;
8521 
8522   /* Send data. */
8523 
8524   p->prepare_for_resend();
8525 
8526   p->store(trg_name.str,
8527            trg_name.length,
8528            system_charset_info);
8529 
8530   p->store(trg_sql_mode_str.str,
8531            trg_sql_mode_str.length,
8532            system_charset_info);
8533 
8534   p->store(trg_sql_original_stmt.str,
8535            trg_sql_original_stmt.length,
8536            trg_client_cs);
8537 
8538   p->store(trg_client_cs_name.str,
8539            trg_client_cs_name.length,
8540            system_charset_info);
8541 
8542   p->store(trg_connection_cl_name.str,
8543            trg_connection_cl_name.length,
8544            system_charset_info);
8545 
8546   p->store(trg_db_cl_name.str,
8547            trg_db_cl_name.length,
8548            system_charset_info);
8549 
8550   ret_code= p->write();
8551 
8552   if (!ret_code)
8553     my_eof(thd);
8554 
8555   return ret_code != 0;
8556 }
8557 
8558 
8559 /**
8560   Read TRN and TRG files to obtain base table name for the specified
8561   trigger name and construct TABE_LIST object for the base table.
8562 
8563   @param thd      Thread context.
8564   @param trg_name Trigger name.
8565 
8566   @return TABLE_LIST object corresponding to the base table.
8567 
8568   TODO: This function is a copy&paste from add_table_to_list() and
8569   sp_add_to_query_tables(). The problem is that in order to be compatible
8570   with Stored Programs (Prepared Statements), we should not touch thd->lex.
8571   The "source" functions also add created TABLE_LIST object to the
8572   thd->lex->query_tables.
8573 
8574   The plan to eliminate this copy&paste is to:
8575 
8576     - get rid of sp_add_to_query_tables() and use Lex::add_table_to_list().
8577       Only add_table_to_list() must be used to add tables from the parser
8578       into Lex::query_tables list.
8579 
8580     - do not update Lex::query_tables in add_table_to_list().
8581 */
8582 
8583 static
get_trigger_table(THD * thd,const sp_name * trg_name)8584 TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name)
8585 {
8586   char trn_path_buff[FN_REFLEN];
8587   LEX_STRING trn_path= { trn_path_buff, 0 };
8588   LEX_STRING db;
8589   LEX_STRING tbl_name;
8590   TABLE_LIST *table;
8591 
8592   build_trn_path(thd, trg_name, &trn_path);
8593 
8594   if (check_trn_exists(&trn_path))
8595   {
8596     my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
8597     return NULL;
8598   }
8599 
8600   if (load_table_name_for_trigger(thd, trg_name, &trn_path, &tbl_name))
8601     return NULL;
8602 
8603   /* We need to reset statement table list to be PS/SP friendly. */
8604   if (!(table= (TABLE_LIST*) thd->alloc(sizeof(TABLE_LIST))))
8605     return NULL;
8606 
8607   db= trg_name->m_db;
8608 
8609   db.str= thd->strmake(db.str, db.length);
8610   tbl_name.str= thd->strmake(tbl_name.str, tbl_name.length);
8611 
8612   if (db.str == NULL || tbl_name.str == NULL)
8613     return NULL;
8614 
8615   table->init_one_table(db.str, db.length, tbl_name.str, tbl_name.length,
8616                         tbl_name.str, TL_IGNORE);
8617 
8618   return table;
8619 }
8620 
8621 
8622 /**
8623   SHOW CREATE TRIGGER high-level implementation.
8624 
8625   @param thd      Thread context.
8626   @param trg_name Trigger name.
8627 
8628   @return Operation status
8629     @retval TRUE Error.
8630     @retval FALSE Success.
8631 */
8632 
show_create_trigger(THD * thd,const sp_name * trg_name)8633 bool show_create_trigger(THD *thd, const sp_name *trg_name)
8634 {
8635   TABLE_LIST *lst= get_trigger_table(thd, trg_name);
8636   uint num_tables; /* NOTE: unused, only to pass to open_tables(). */
8637   Table_triggers_list *triggers;
8638   int trigger_idx;
8639   bool error= TRUE;
8640 
8641   if (!lst)
8642     return TRUE;
8643 
8644   if (check_table_access(thd, TRIGGER_ACL, lst, FALSE, 1, TRUE))
8645   {
8646     my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "TRIGGER");
8647     return TRUE;
8648   }
8649 
8650   /*
8651     Metadata locks taken during SHOW CREATE TRIGGER should be released when
8652     the statement completes as it is an information statement.
8653   */
8654   MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
8655 
8656   /*
8657     Open the table by name in order to load Table_triggers_list object.
8658   */
8659   if (open_tables(thd, &lst, &num_tables,
8660                   MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL))
8661   {
8662     my_error(ER_TRG_CANT_OPEN_TABLE, MYF(0),
8663              (const char *) trg_name->m_db.str,
8664              (const char *) lst->table_name);
8665 
8666     goto exit;
8667 
8668     /* Perform closing actions and return error status. */
8669   }
8670 
8671   triggers= lst->table->triggers;
8672 
8673   if (!triggers)
8674   {
8675     my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
8676     goto exit;
8677   }
8678 
8679   trigger_idx= triggers->find_trigger_by_name(&trg_name->m_name);
8680 
8681   if (trigger_idx < 0)
8682   {
8683     my_error(ER_TRG_CORRUPTED_FILE, MYF(0),
8684              (const char *) trg_name->m_db.str,
8685              (const char *) lst->table_name);
8686 
8687     goto exit;
8688   }
8689 
8690   error= show_create_trigger_impl(thd, triggers, trigger_idx);
8691 
8692   /*
8693     NOTE: if show_create_trigger_impl() failed, that means we could not
8694     send data to the client. In this case we simply raise the error
8695     status and client connection will be closed.
8696   */
8697 
8698 exit:
8699   close_thread_tables(thd);
8700   /* Release any metadata locks taken during SHOW CREATE TRIGGER. */
8701   thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
8702   return error;
8703 }
8704 
8705 class IS_internal_schema_access : public ACL_internal_schema_access
8706 {
8707 public:
IS_internal_schema_access()8708   IS_internal_schema_access()
8709   {}
8710 
~IS_internal_schema_access()8711   ~IS_internal_schema_access()
8712   {}
8713 
8714   ACL_internal_access_result check(ulong want_access,
8715                                    ulong *save_priv) const;
8716 
8717   const ACL_internal_table_access *lookup(const char *name) const;
8718 };
8719 
8720 ACL_internal_access_result
check(ulong want_access,ulong * save_priv) const8721 IS_internal_schema_access::check(ulong want_access,
8722                                  ulong *save_priv) const
8723 {
8724   want_access &= ~SELECT_ACL;
8725 
8726   /*
8727     We don't allow any simple privileges but SELECT_ACL on
8728     the information_schema database.
8729   */
8730   if (unlikely(want_access & DB_ACLS))
8731     return ACL_INTERNAL_ACCESS_DENIED;
8732 
8733   /* Always grant SELECT for the information schema. */
8734   *save_priv|= SELECT_ACL;
8735 
8736   return want_access ? ACL_INTERNAL_ACCESS_CHECK_GRANT :
8737                        ACL_INTERNAL_ACCESS_GRANTED;
8738 }
8739 
8740 const ACL_internal_table_access *
lookup(const char * name) const8741 IS_internal_schema_access::lookup(const char *name) const
8742 {
8743   /* There are no per table rules for the information schema. */
8744   return NULL;
8745 }
8746 
8747 static IS_internal_schema_access is_internal_schema_access;
8748 
initialize_information_schema_acl()8749 void initialize_information_schema_acl()
8750 {
8751   ACL_internal_schema_registry::register_schema(&INFORMATION_SCHEMA_NAME,
8752                                                 &is_internal_schema_access);
8753 }
8754 
8755 #ifdef WITH_PARTITION_STORAGE_ENGINE
8756 /*
8757   Convert a string in character set in column character set format
8758   to utf8 character set if possible, the utf8 character set string
8759   will later possibly be converted to character set used by client.
8760   Thus we attempt conversion from column character set to both
8761   utf8 and to character set client.
8762 
8763   Examples of strings that should fail conversion to utf8 are unassigned
8764   characters as e.g. 0x81 in cp1250 (Windows character set for for countries
8765   like Czech and Poland). Example of string that should fail conversion to
8766   character set on client (e.g. if this is latin1) is 0x2020 (daggger) in
8767   ucs2.
8768 
8769   If the conversion fails we will as a fall back convert the string to
8770   hex encoded format. The caller of the function can also ask for hex
8771   encoded format of output string unconditionally.
8772 
8773   SYNOPSIS
8774     get_cs_converted_string_value()
8775     thd                             Thread object
8776     input_str                       Input string in cs character set
8777     output_str                      Output string to be produced in utf8
8778     cs                              Character set of input string
8779     use_hex                         Use hex string unconditionally
8780 
8781 
8782   RETURN VALUES
8783     No return value
8784 */
8785 
get_cs_converted_string_value(THD * thd,String * input_str,String * output_str,const CHARSET_INFO * cs,bool use_hex)8786 static void get_cs_converted_string_value(THD *thd,
8787                                           String *input_str,
8788                                           String *output_str,
8789                                           const CHARSET_INFO *cs,
8790                                           bool use_hex)
8791 {
8792 
8793   output_str->length(0);
8794   if (input_str->length() == 0)
8795   {
8796     output_str->append("''");
8797     return;
8798   }
8799   if (!use_hex)
8800   {
8801     String try_val;
8802     uint try_conv_error= 0;
8803 
8804     try_val.copy(input_str->ptr(), input_str->length(), cs,
8805                  thd->variables.character_set_client, &try_conv_error);
8806     if (!try_conv_error)
8807     {
8808       String val;
8809       uint conv_error= 0;
8810 
8811       val.copy(input_str->ptr(), input_str->length(), cs,
8812                system_charset_info, &conv_error);
8813       if (!conv_error)
8814       {
8815         append_unescaped(output_str, val.ptr(), val.length());
8816         return;
8817       }
8818     }
8819     /* We had a conversion error, use hex encoded string for safety */
8820   }
8821   {
8822     const uchar *ptr;
8823     uint i, len;
8824     char buf[3];
8825 
8826     output_str->append("_");
8827     output_str->append(cs->csname);
8828     output_str->append(" ");
8829     output_str->append("0x");
8830     len= input_str->length();
8831     ptr= (uchar*)input_str->ptr();
8832     for (i= 0; i < len; i++)
8833     {
8834       uint high, low;
8835 
8836       high= (*ptr) >> 4;
8837       low= (*ptr) & 0x0F;
8838       buf[0]= _dig_vec_upper[high];
8839       buf[1]= _dig_vec_upper[low];
8840       buf[2]= 0;
8841       output_str->append((const char*)buf);
8842       ptr++;
8843     }
8844   }
8845   return;
8846 }
8847 #endif
8848