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