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