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