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