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