The world's most popular open source database
00001 /* Copyright (C) 2000-2004 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 00018 /* Function with list databases, tables or fields */ 00019 00020 #include "mysql_priv.h" 00021 #include "sql_select.h" // For select_describe 00022 #include "sql_show.h" 00023 #include "repl_failsafe.h" 00024 #include "sp.h" 00025 #include "sp_head.h" 00026 #include "sql_trigger.h" 00027 #include "authors.h" 00028 #include "contributors.h" 00029 #include "events.h" 00030 #include "event_timed.h" 00031 #include <my_dir.h> 00032 00033 #ifdef WITH_PARTITION_STORAGE_ENGINE 00034 #include "ha_partition.h" 00035 #endif 00036 00037 enum enum_i_s_events_fields 00038 { 00039 ISE_EVENT_CATALOG= 0, 00040 ISE_EVENT_SCHEMA, 00041 ISE_EVENT_NAME, 00042 ISE_DEFINER, 00043 ISE_EVENT_BODY, 00044 ISE_EVENT_DEFINITION, 00045 ISE_EVENT_TYPE, 00046 ISE_EXECUTE_AT, 00047 ISE_INTERVAL_VALUE, 00048 ISE_INTERVAL_FIELD, 00049 ISE_SQL_MODE, 00050 ISE_STARTS, 00051 ISE_ENDS, 00052 ISE_STATUS, 00053 ISE_ON_COMPLETION, 00054 ISE_CREATED, 00055 ISE_LAST_ALTERED, 00056 ISE_LAST_EXECUTED, 00057 ISE_EVENT_COMMENT 00058 }; 00059 00060 00061 static const char *grant_names[]={ 00062 "select","insert","update","delete","create","drop","reload","shutdown", 00063 "process","file","grant","references","index","alter"}; 00064 00065 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00066 static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **), 00067 "grant_types", 00068 grant_names, NULL}; 00069 #endif 00070 00071 static void store_key_options(THD *thd, String *packet, TABLE *table, 00072 KEY *key_info); 00073 00074 static void 00075 append_algorithm(TABLE_LIST *table, String *buff); 00076 00077 00078 /*************************************************************************** 00079 ** List all table types supported 00080 ***************************************************************************/ 00081 00082 static my_bool show_handlerton(THD *thd, st_plugin_int *plugin, 00083 void *arg) 00084 { 00085 handlerton *default_type= (handlerton *) arg; 00086 Protocol *protocol= thd->protocol; 00087 handlerton *hton= (handlerton *)plugin->data; 00088 00089 if (!(hton->flags & HTON_HIDDEN)) 00090 { 00091 protocol->prepare_for_resend(); 00092 protocol->store(plugin->name.str, plugin->name.length, 00093 system_charset_info); 00094 const char *option_name= show_comp_option_name[(int) hton->state]; 00095 00096 if (hton->state == SHOW_OPTION_YES && default_type == hton) 00097 option_name= "DEFAULT"; 00098 protocol->store(option_name, system_charset_info); 00099 protocol->store(plugin->plugin->descr, system_charset_info); 00100 protocol->store(hton->commit ? "YES" : "NO", system_charset_info); 00101 protocol->store(hton->prepare ? "YES" : "NO", system_charset_info); 00102 protocol->store(hton->savepoint_set ? "YES" : "NO", system_charset_info); 00103 00104 return protocol->write() ? 1 : 0; 00105 } 00106 return 0; 00107 } 00108 00109 bool mysqld_show_storage_engines(THD *thd) 00110 { 00111 List<Item> field_list; 00112 Protocol *protocol= thd->protocol; 00113 DBUG_ENTER("mysqld_show_storage_engines"); 00114 00115 field_list.push_back(new Item_empty_string("Engine",10)); 00116 field_list.push_back(new Item_empty_string("Support",10)); 00117 field_list.push_back(new Item_empty_string("Comment",80)); 00118 field_list.push_back(new Item_empty_string("Transactions",3)); 00119 field_list.push_back(new Item_empty_string("XA",3)); 00120 field_list.push_back(new Item_empty_string("Savepoints",3)); 00121 00122 if (protocol->send_fields(&field_list, 00123 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) 00124 DBUG_RETURN(TRUE); 00125 00126 if (plugin_foreach(thd, show_handlerton, 00127 MYSQL_STORAGE_ENGINE_PLUGIN, thd->variables.table_type)) 00128 DBUG_RETURN(TRUE); 00129 00130 send_eof(thd); 00131 DBUG_RETURN(FALSE); 00132 } 00133 00134 static int make_version_string(char *buf, int buf_length, uint version) 00135 { 00136 return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff); 00137 } 00138 00139 static my_bool show_plugins(THD *thd, st_plugin_int *plugin, 00140 void *arg) 00141 { 00142 TABLE *table= (TABLE*) arg; 00143 struct st_mysql_plugin *plug= plugin->plugin; 00144 Protocol *protocol= thd->protocol; 00145 CHARSET_INFO *cs= system_charset_info; 00146 char version_buf[20]; 00147 00148 restore_record(table, s->default_values); 00149 00150 table->field[0]->store(plugin->name.str, plugin->name.length, cs); 00151 00152 table->field[1]->store(version_buf, 00153 make_version_string(version_buf, sizeof(version_buf), plug->version), 00154 cs); 00155 00156 00157 switch (plugin->state) 00158 { 00159 /* case PLUGIN_IS_FREED: does not happen */ 00160 case PLUGIN_IS_DELETED: 00161 table->field[2]->store(STRING_WITH_LEN("DELETED"), cs); 00162 break; 00163 case PLUGIN_IS_UNINITIALIZED: 00164 table->field[2]->store(STRING_WITH_LEN("INACTIVE"), cs); 00165 break; 00166 case PLUGIN_IS_READY: 00167 table->field[2]->store(STRING_WITH_LEN("ACTIVE"), cs); 00168 break; 00169 default: 00170 DBUG_ASSERT(0); 00171 } 00172 00173 table->field[3]->store(plugin_type_names[plug->type].str, 00174 plugin_type_names[plug->type].length, 00175 cs); 00176 table->field[4]->store(version_buf, 00177 make_version_string(version_buf, sizeof(version_buf), 00178 *(uint *)plug->info), cs); 00179 00180 if (plugin->plugin_dl) 00181 { 00182 table->field[5]->store(plugin->plugin_dl->dl.str, 00183 plugin->plugin_dl->dl.length, cs); 00184 table->field[5]->set_notnull(); 00185 table->field[6]->store(version_buf, 00186 make_version_string(version_buf, sizeof(version_buf), 00187 plugin->plugin_dl->version), 00188 cs); 00189 table->field[6]->set_notnull(); 00190 } 00191 else 00192 { 00193 table->field[5]->set_null(); 00194 table->field[6]->set_null(); 00195 } 00196 00197 00198 if (plug->author) 00199 { 00200 table->field[7]->store(plug->author, strlen(plug->author), cs); 00201 table->field[7]->set_notnull(); 00202 } 00203 else 00204 table->field[7]->set_null(); 00205 00206 if (plug->descr) 00207 { 00208 table->field[8]->store(plug->descr, strlen(plug->descr), cs); 00209 table->field[8]->set_notnull(); 00210 } 00211 else 00212 table->field[8]->set_null(); 00213 00214 return schema_table_store_record(thd, table); 00215 } 00216 00217 00218 int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond) 00219 { 00220 DBUG_ENTER("fill_plugins"); 00221 TABLE *table= tables->table; 00222 00223 if (plugin_foreach(thd, show_plugins, MYSQL_ANY_PLUGIN, table)) 00224 DBUG_RETURN(1); 00225 00226 DBUG_RETURN(0); 00227 } 00228 00229 00230 /*************************************************************************** 00231 ** List all Authors. 00232 ** If you can update it, you get to be in it :) 00233 ***************************************************************************/ 00234 00235 bool mysqld_show_authors(THD *thd) 00236 { 00237 List<Item> field_list; 00238 Protocol *protocol= thd->protocol; 00239 DBUG_ENTER("mysqld_show_authors"); 00240 00241 field_list.push_back(new Item_empty_string("Name",40)); 00242 field_list.push_back(new Item_empty_string("Location",40)); 00243 field_list.push_back(new Item_empty_string("Comment",80)); 00244 00245 if (protocol->send_fields(&field_list, 00246 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) 00247 DBUG_RETURN(TRUE); 00248 00249 show_table_authors_st *authors; 00250 for (authors= show_table_authors; authors->name; authors++) 00251 { 00252 protocol->prepare_for_resend(); 00253 protocol->store(authors->name, system_charset_info); 00254 protocol->store(authors->location, system_charset_info); 00255 protocol->store(authors->comment, system_charset_info); 00256 if (protocol->write()) 00257 DBUG_RETURN(TRUE); 00258 } 00259 send_eof(thd); 00260 DBUG_RETURN(FALSE); 00261 } 00262 00263 00264 /*************************************************************************** 00265 ** List all Contributors. 00266 ** Please get permission before updating 00267 ***************************************************************************/ 00268 00269 bool mysqld_show_contributors(THD *thd) 00270 { 00271 List<Item> field_list; 00272 Protocol *protocol= thd->protocol; 00273 DBUG_ENTER("mysqld_show_contributors"); 00274 00275 field_list.push_back(new Item_empty_string("Name",40)); 00276 field_list.push_back(new Item_empty_string("Location",40)); 00277 field_list.push_back(new Item_empty_string("Comment",80)); 00278 00279 if (protocol->send_fields(&field_list, 00280 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) 00281 DBUG_RETURN(TRUE); 00282 00283 show_table_contributors_st *contributors; 00284 for (contributors= show_table_contributors; contributors->name; contributors++) 00285 { 00286 protocol->prepare_for_resend(); 00287 protocol->store(contributors->name, system_charset_info); 00288 protocol->store(contributors->location, system_charset_info); 00289 protocol->store(contributors->comment, system_charset_info); 00290 if (protocol->write()) 00291 DBUG_RETURN(TRUE); 00292 } 00293 send_eof(thd); 00294 DBUG_RETURN(FALSE); 00295 } 00296 00297 00298 /*************************************************************************** 00299 List all privileges supported 00300 ***************************************************************************/ 00301 00302 struct show_privileges_st { 00303 const char *privilege; 00304 const char *context; 00305 const char *comment; 00306 }; 00307 00308 static struct show_privileges_st sys_privileges[]= 00309 { 00310 {"Alter", "Tables", "To alter the table"}, 00311 {"Alter routine", "Functions,Procedures", "To alter or drop stored functions/procedures"}, 00312 {"Create", "Databases,Tables,Indexes", "To create new databases and tables"}, 00313 {"Create routine","Functions,Procedures","To use CREATE FUNCTION/PROCEDURE"}, 00314 {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"}, 00315 {"Create view", "Tables", "To create new views"}, 00316 {"Create user", "Server Admin", "To create new users"}, 00317 {"Delete", "Tables", "To delete existing rows"}, 00318 {"Drop", "Databases,Tables", "To drop databases, tables, and views"}, 00319 {"Event","Server Admin","To create, alter, drop and execute events"}, 00320 {"Execute", "Functions,Procedures", "To execute stored routines"}, 00321 {"File", "File access on server", "To read and write files on the server"}, 00322 {"Grant option", "Databases,Tables,Functions,Procedures", "To give to other users those privileges you possess"}, 00323 {"Index", "Tables", "To create or drop indexes"}, 00324 {"Insert", "Tables", "To insert data into tables"}, 00325 {"Lock tables","Databases","To use LOCK TABLES (together with SELECT privilege)"}, 00326 {"Process", "Server Admin", "To view the plain text of currently executing queries"}, 00327 {"References", "Databases,Tables", "To have references on tables"}, 00328 {"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"}, 00329 {"Replication client","Server Admin","To ask where the slave or master servers are"}, 00330 {"Replication slave","Server Admin","To read binary log events from the master"}, 00331 {"Select", "Tables", "To retrieve rows from table"}, 00332 {"Show databases","Server Admin","To see all databases with SHOW DATABASES"}, 00333 {"Show view","Tables","To see views with SHOW CREATE VIEW"}, 00334 {"Shutdown","Server Admin", "To shut down the server"}, 00335 {"Super","Server Admin","To use KILL thread, SET GLOBAL, CHANGE MASTER, etc."}, 00336 {"Trigger","Tables", "To use triggers"}, 00337 {"Update", "Tables", "To update existing rows"}, 00338 {"Usage","Server Admin","No privileges - allow connect only"}, 00339 {NullS, NullS, NullS} 00340 }; 00341 00342 bool mysqld_show_privileges(THD *thd) 00343 { 00344 List<Item> field_list; 00345 Protocol *protocol= thd->protocol; 00346 DBUG_ENTER("mysqld_show_privileges"); 00347 00348 field_list.push_back(new Item_empty_string("Privilege",10)); 00349 field_list.push_back(new Item_empty_string("Context",15)); 00350 field_list.push_back(new Item_empty_string("Comment",NAME_LEN)); 00351 00352 if (protocol->send_fields(&field_list, 00353 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) 00354 DBUG_RETURN(TRUE); 00355 00356 show_privileges_st *privilege= sys_privileges; 00357 for (privilege= sys_privileges; privilege->privilege ; privilege++) 00358 { 00359 protocol->prepare_for_resend(); 00360 protocol->store(privilege->privilege, system_charset_info); 00361 protocol->store(privilege->context, system_charset_info); 00362 protocol->store(privilege->comment, system_charset_info); 00363 if (protocol->write()) 00364 DBUG_RETURN(TRUE); 00365 } 00366 send_eof(thd); 00367 DBUG_RETURN(FALSE); 00368 } 00369 00370 00371 /*************************************************************************** 00372 List all column types 00373 ***************************************************************************/ 00374 00375 struct show_column_type_st 00376 { 00377 const char *type; 00378 uint size; 00379 const char *min_value; 00380 const char *max_value; 00381 uint precision; 00382 uint scale; 00383 const char *nullable; 00384 const char *auto_increment; 00385 const char *unsigned_attr; 00386 const char *zerofill; 00387 const char *searchable; 00388 const char *case_sensitivity; 00389 const char *default_value; 00390 const char *comment; 00391 }; 00392 00393 /* TODO: Add remaning types */ 00394 00395 static struct show_column_type_st sys_column_types[]= 00396 { 00397 {"tinyint", 00398 1, "-128", "127", 0, 0, "YES", "YES", 00399 "NO", "YES", "YES", "NO", "NULL,0", 00400 "A very small integer"}, 00401 {"tinyint unsigned", 00402 1, "0" , "255", 0, 0, "YES", "YES", 00403 "YES", "YES", "YES", "NO", "NULL,0", 00404 "A very small integer"}, 00405 }; 00406 00407 bool mysqld_show_column_types(THD *thd) 00408 { 00409 List<Item> field_list; 00410 Protocol *protocol= thd->protocol; 00411 DBUG_ENTER("mysqld_show_column_types"); 00412 00413 field_list.push_back(new Item_empty_string("Type",30)); 00414 field_list.push_back(new Item_int("Size",(longlong) 1,21)); 00415 field_list.push_back(new Item_empty_string("Min_Value",20)); 00416 field_list.push_back(new Item_empty_string("Max_Value",20)); 00417 field_list.push_back(new Item_return_int("Prec", 4, MYSQL_TYPE_SHORT)); 00418 field_list.push_back(new Item_return_int("Scale", 4, MYSQL_TYPE_SHORT)); 00419 field_list.push_back(new Item_empty_string("Nullable",4)); 00420 field_list.push_back(new Item_empty_string("Auto_Increment",4)); 00421 field_list.push_back(new Item_empty_string("Unsigned",4)); 00422 field_list.push_back(new Item_empty_string("Zerofill",4)); 00423 field_list.push_back(new Item_empty_string("Searchable",4)); 00424 field_list.push_back(new Item_empty_string("Case_Sensitive",4)); 00425 field_list.push_back(new Item_empty_string("Default",NAME_LEN)); 00426 field_list.push_back(new Item_empty_string("Comment",NAME_LEN)); 00427 00428 if (protocol->send_fields(&field_list, 00429 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) 00430 DBUG_RETURN(TRUE); 00431 00432 /* TODO: Change the loop to not use 'i' */ 00433 for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++) 00434 { 00435 protocol->prepare_for_resend(); 00436 protocol->store(sys_column_types[i].type, system_charset_info); 00437 protocol->store((ulonglong) sys_column_types[i].size); 00438 protocol->store(sys_column_types[i].min_value, system_charset_info); 00439 protocol->store(sys_column_types[i].max_value, system_charset_info); 00440 protocol->store_short((longlong) sys_column_types[i].precision); 00441 protocol->store_short((longlong) sys_column_types[i].scale); 00442 protocol->store(sys_column_types[i].nullable, system_charset_info); 00443 protocol->store(sys_column_types[i].auto_increment, system_charset_info); 00444 protocol->store(sys_column_types[i].unsigned_attr, system_charset_info); 00445 protocol->store(sys_column_types[i].zerofill, system_charset_info); 00446 protocol->store(sys_column_types[i].searchable, system_charset_info); 00447 protocol->store(sys_column_types[i].case_sensitivity, system_charset_info); 00448 protocol->store(sys_column_types[i].default_value, system_charset_info); 00449 protocol->store(sys_column_types[i].comment, system_charset_info); 00450 if (protocol->write()) 00451 DBUG_RETURN(TRUE); 00452 } 00453 send_eof(thd); 00454 DBUG_RETURN(FALSE); 00455 } 00456 00457 00458 /* 00459 find_files() - find files in a given directory. 00460 00461 SYNOPSIS 00462 find_files() 00463 thd thread handler 00464 files put found files in this list 00465 db database name to set in TABLE_LIST structure 00466 path path to database 00467 wild filter for found files 00468 dir read databases in path if TRUE, read .frm files in 00469 database otherwise 00470 00471 RETURN 00472 FIND_FILES_OK success 00473 FIND_FILES_OOM out of memory error 00474 FIND_FILES_DIR no such directory, or directory can't be read 00475 */ 00476 00477 enum find_files_result { 00478 FIND_FILES_OK, 00479 FIND_FILES_OOM, 00480 FIND_FILES_DIR 00481 }; 00482 00483 static 00484 find_files_result 00485 find_files(THD *thd, List<char> *files, const char *db, 00486 const char *path, const char *wild, bool dir) 00487 { 00488 uint i; 00489 char *ext; 00490 MY_DIR *dirp; 00491 FILEINFO *file; 00492 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00493 uint col_access=thd->col_access; 00494 #endif 00495 TABLE_LIST table_list; 00496 DBUG_ENTER("find_files"); 00497 00498 if (wild && !wild[0]) 00499 wild=0; 00500 00501 bzero((char*) &table_list,sizeof(table_list)); 00502 00503 if (!(dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0)))) 00504 { 00505 if (my_errno == ENOENT) 00506 my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db); 00507 else 00508 my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), path, my_errno); 00509 DBUG_RETURN(FIND_FILES_DIR); 00510 } 00511 00512 for (i=0 ; i < (uint) dirp->number_off_files ; i++) 00513 { 00514 char uname[NAME_LEN*3+1]; /* Unencoded name */ 00515 file=dirp->dir_entry+i; 00516 if (dir) 00517 { /* Return databases */ 00518 if ((file->name[0] == '.' && 00519 ((file->name[1] == '.' && file->name[2] == '\0') || 00520 file->name[1] == '\0'))) 00521 continue; /* . or .. */ 00522 #ifdef USE_SYMDIR 00523 char *ext; 00524 char buff[FN_REFLEN]; 00525 if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym")) 00526 { 00527 /* Only show the sym file if it points to a directory */ 00528 char *end; 00529 *ext=0; /* Remove extension */ 00530 unpack_dirname(buff, file->name); 00531 end= strend(buff); 00532 if (end != buff && end[-1] == FN_LIBCHAR) 00533 end[-1]= 0; // Remove end FN_LIBCHAR 00534 if (!my_stat(buff, file->mystat, MYF(0))) 00535 continue; 00536 } 00537 #endif 00538 if (!MY_S_ISDIR(file->mystat->st_mode)) 00539 continue; 00540 VOID(filename_to_tablename(file->name, uname, sizeof(uname))); 00541 if (wild && wild_compare(uname, wild, 0)) 00542 continue; 00543 file->name= uname; 00544 } 00545 else 00546 { 00547 // Return only .frm files which aren't temp files. 00548 if (my_strcasecmp(system_charset_info, ext=fn_rext(file->name),reg_ext) || 00549 is_prefix(file->name, tmp_file_prefix)) 00550 continue; 00551 *ext=0; 00552 VOID(filename_to_tablename(file->name, uname, sizeof(uname))); 00553 file->name= uname; 00554 if (wild) 00555 { 00556 if (lower_case_table_names) 00557 { 00558 if (wild_case_compare(files_charset_info, file->name, wild)) 00559 continue; 00560 } 00561 else if (wild_compare(file->name,wild,0)) 00562 continue; 00563 } 00564 } 00565 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00566 /* Don't show tables where we don't have any privileges */ 00567 if (db && !(col_access & TABLE_ACLS)) 00568 { 00569 table_list.db= (char*) db; 00570 table_list.db_length= strlen(db); 00571 table_list.table_name= file->name; 00572 table_list.table_name_length= strlen(file->name); 00573 table_list.grant.privilege=col_access; 00574 if (check_grant(thd, TABLE_ACLS, &table_list, 1, 1, 1)) 00575 continue; 00576 } 00577 #endif 00578 if (files->push_back(thd->strdup(file->name))) 00579 { 00580 my_dirend(dirp); 00581 DBUG_RETURN(FIND_FILES_OOM); 00582 } 00583 } 00584 DBUG_PRINT("info",("found: %d files", files->elements)); 00585 my_dirend(dirp); 00586 00587 VOID(ha_find_files(thd,db,path,wild,dir,files)); 00588 00589 DBUG_RETURN(FIND_FILES_OK); 00590 } 00591 00592 00593 bool 00594 mysqld_show_create(THD *thd, TABLE_LIST *table_list) 00595 { 00596 Protocol *protocol= thd->protocol; 00597 char buff[2048]; 00598 String buffer(buff, sizeof(buff), system_charset_info); 00599 DBUG_ENTER("mysqld_show_create"); 00600 DBUG_PRINT("enter",("db: %s table: %s",table_list->db, 00601 table_list->table_name)); 00602 00603 /* We want to preserve the tree for views. */ 00604 thd->lex->view_prepare_mode= TRUE; 00605 00606 /* Only one table for now, but VIEW can involve several tables */ 00607 if (open_normal_and_derived_tables(thd, table_list, 0)) 00608 { 00609 if (!table_list->view || thd->net.last_errno != ER_VIEW_INVALID) 00610 DBUG_RETURN(TRUE); 00611 00612 /* 00613 Clear all messages with 'error' level status and 00614 issue a warning with 'warning' level status in 00615 case of invalid view and last error is ER_VIEW_INVALID 00616 */ 00617 mysql_reset_errors(thd, true); 00618 thd->clear_error(); 00619 00620 push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN, 00621 ER_VIEW_INVALID, 00622 ER(ER_VIEW_INVALID), 00623 table_list->view_db.str, 00624 table_list->view_name.str); 00625 } 00626 00627 /* TODO: add environment variables show when it become possible */ 00628 if (thd->lex->only_view && !table_list->view) 00629 { 00630 my_error(ER_WRONG_OBJECT, MYF(0), 00631 table_list->db, table_list->table_name, "VIEW"); 00632 DBUG_RETURN(TRUE); 00633 } 00634 00635 buffer.length(0); 00636 if ((table_list->view ? 00637 view_store_create_info(thd, table_list, &buffer) : 00638 store_create_info(thd, table_list, &buffer, NULL))) 00639 DBUG_RETURN(TRUE); 00640 00641 List<Item> field_list; 00642 if (table_list->view) 00643 { 00644 field_list.push_back(new Item_empty_string("View",NAME_LEN)); 00645 field_list.push_back(new Item_empty_string("Create View", 00646 max(buffer.length(),1024))); 00647 } 00648 else 00649 { 00650 field_list.push_back(new Item_empty_string("Table",NAME_LEN)); 00651 // 1024 is for not to confuse old clients 00652 field_list.push_back(new Item_empty_string("Create Table", 00653 max(buffer.length(),1024))); 00654 } 00655 00656 if (protocol->send_fields(&field_list, 00657 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) 00658 DBUG_RETURN(TRUE); 00659 protocol->prepare_for_resend(); 00660 if (table_list->view) 00661 protocol->store(table_list->view_name.str, system_charset_info); 00662 else 00663 { 00664 if (table_list->schema_table) 00665 protocol->store(table_list->schema_table->table_name, 00666 system_charset_info); 00667 else 00668 protocol->store(table_list->table->alias, system_charset_info); 00669 } 00670 protocol->store(buffer.ptr(), buffer.length(), buffer.charset()); 00671 00672 if (protocol->write()) 00673 DBUG_RETURN(TRUE); 00674 send_eof(thd); 00675 DBUG_RETURN(FALSE); 00676 } 00677 00678 bool mysqld_show_create_db(THD *thd, char *dbname, 00679 HA_CREATE_INFO *create_info) 00680 { 00681 Security_context *sctx= thd->security_ctx; 00682 int length; 00683 char buff[2048]; 00684 String buffer(buff, sizeof(buff), system_charset_info); 00685 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00686 uint db_access; 00687 #endif 00688 HA_CREATE_INFO create; 00689 uint create_options = create_info ? create_info->options : 0; 00690 Protocol *protocol=thd->protocol; 00691 DBUG_ENTER("mysql_show_create_db"); 00692 00693 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00694 if (test_all_bits(sctx->master_access, DB_ACLS)) 00695 db_access=DB_ACLS; 00696 else 00697 db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, dbname, 0) | 00698 sctx->master_access); 00699 if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) 00700 { 00701 my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), 00702 sctx->priv_user, sctx->host_or_ip, dbname); 00703 general_log_print(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), 00704 sctx->priv_user, sctx->host_or_ip, dbname); 00705 DBUG_RETURN(TRUE); 00706 } 00707 #endif 00708 if (!my_strcasecmp(system_charset_info, dbname, 00709 information_schema_name.str)) 00710 { 00711 dbname= information_schema_name.str; 00712 create.default_table_charset= system_charset_info; 00713 } 00714 else 00715 { 00716 if (check_db_dir_existence(dbname)) 00717 { 00718 my_error(ER_BAD_DB_ERROR, MYF(0), dbname); 00719 DBUG_RETURN(TRUE); 00720 } 00721 00722 load_db_opt_by_name(thd, dbname, &create); 00723 } 00724 List<Item> field_list; 00725 field_list.push_back(new Item_empty_string("Database",NAME_LEN)); 00726 field_list.push_back(new Item_empty_string("Create Database",1024)); 00727 00728 if (protocol->send_fields(&field_list, 00729 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) 00730 DBUG_RETURN(TRUE); 00731 00732 protocol->prepare_for_resend(); 00733 protocol->store(dbname, strlen(dbname), system_charset_info); 00734 buffer.length(0); 00735 buffer.append(STRING_WITH_LEN("CREATE DATABASE ")); 00736 if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS) 00737 buffer.append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ ")); 00738 append_identifier(thd, &buffer, dbname, strlen(dbname)); 00739 00740 if (create.default_table_charset) 00741 { 00742 buffer.append(STRING_WITH_LEN(" /*!40100")); 00743 buffer.append(STRING_WITH_LEN(" DEFAULT CHARACTER SET ")); 00744 buffer.append(create.default_table_charset->csname); 00745 if (!(create.default_table_charset->state & MY_CS_PRIMARY)) 00746 { 00747 buffer.append(STRING_WITH_LEN(" COLLATE ")); 00748 buffer.append(create.default_table_charset->name); 00749 } 00750 buffer.append(STRING_WITH_LEN(" */")); 00751 } 00752 protocol->store(buffer.ptr(), buffer.length(), buffer.charset()); 00753 00754 if (protocol->write()) 00755 DBUG_RETURN(TRUE); 00756 send_eof(thd); 00757 DBUG_RETURN(FALSE); 00758 } 00759 00760 00761 00762 /**************************************************************************** 00763 Return only fields for API mysql_list_fields 00764 Use "show table wildcard" in mysql instead of this 00765 ****************************************************************************/ 00766 00767 void 00768 mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) 00769 { 00770 TABLE *table; 00771 DBUG_ENTER("mysqld_list_fields"); 00772 DBUG_PRINT("enter",("table: %s",table_list->table_name)); 00773 00774 if (open_normal_and_derived_tables(thd, table_list, 0)) 00775 DBUG_VOID_RETURN; 00776 table= table_list->table; 00777 00778 List<Item> field_list; 00779 00780 Field **ptr,*field; 00781 for (ptr=table->field ; (field= *ptr); ptr++) 00782 { 00783 if (!wild || !wild[0] || 00784 !wild_case_compare(system_charset_info, field->field_name,wild)) 00785 { 00786 if (table_list->view) 00787 field_list.push_back(new Item_ident_for_show(field, 00788 table_list->view_db.str, 00789 table_list->view_name.str)); 00790 else 00791 field_list.push_back(new Item_field(field)); 00792 } 00793 } 00794 restore_record(table, s->default_values); // Get empty record 00795 table->use_all_columns(); 00796 if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS | 00797 Protocol::SEND_EOF)) 00798 DBUG_VOID_RETURN; 00799 thd->protocol->flush(); 00800 DBUG_VOID_RETURN; 00801 } 00802 00803 00804 int 00805 mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd) 00806 { 00807 Protocol *protocol= thd->protocol; 00808 String *packet= protocol->storage_packet(); 00809 DBUG_ENTER("mysqld_dump_create_info"); 00810 DBUG_PRINT("enter",("table: %s",table_list->table->s->table_name.str)); 00811 00812 protocol->prepare_for_resend(); 00813 if (store_create_info(thd, table_list, packet, NULL)) 00814 DBUG_RETURN(-1); 00815 00816 if (fd < 0) 00817 { 00818 if (protocol->write()) 00819 DBUG_RETURN(-1); 00820 protocol->flush(); 00821 } 00822 else 00823 { 00824 if (my_write(fd, (const byte*) packet->ptr(), packet->length(), 00825 MYF(MY_WME))) 00826 DBUG_RETURN(-1); 00827 } 00828 DBUG_RETURN(0); 00829 } 00830 00831 /* 00832 Go through all character combinations and ensure that sql_lex.cc can 00833 parse it as an identifier. 00834 00835 SYNOPSIS 00836 require_quotes() 00837 name attribute name 00838 name_length length of name 00839 00840 RETURN 00841 # Pointer to conflicting character 00842 0 No conflicting character 00843 */ 00844 00845 static const char *require_quotes(const char *name, uint name_length) 00846 { 00847 uint length; 00848 bool pure_digit= TRUE; 00849 const char *end= name + name_length; 00850 00851 for (; name < end ; name++) 00852 { 00853 uchar chr= (uchar) *name; 00854 length= my_mbcharlen(system_charset_info, chr); 00855 if (length == 1 && !system_charset_info->ident_map[chr]) 00856 return name; 00857 if (length == 1 && (chr < '0' || chr > '9')) 00858 pure_digit= FALSE; 00859 } 00860 if (pure_digit) 00861 return name; 00862 return 0; 00863 } 00864 00865 00866 /* 00867 Quote the given identifier if needed and append it to the target string. 00868 If the given identifier is empty, it will be quoted. 00869 00870 SYNOPSIS 00871 append_identifier() 00872 thd thread handler 00873 packet target string 00874 name the identifier to be appended 00875 name_length length of the appending identifier 00876 */ 00877 00878 void 00879 append_identifier(THD *thd, String *packet, const char *name, uint length) 00880 { 00881 const char *name_end; 00882 char quote_char; 00883 int q= get_quote_char_for_identifier(thd, name, length); 00884 00885 if (q == EOF) 00886 { 00887 packet->append(name, length, system_charset_info); 00888 return; 00889 } 00890 00891 /* 00892 The identifier must be quoted as it includes a quote character or 00893 it's a keyword 00894 */ 00895 00896 VOID(packet->reserve(length*2 + 2)); 00897 quote_char= (char) q; 00898 packet->append("e_char, 1, system_charset_info); 00899 00900 for (name_end= name+length ; name < name_end ; name+= length) 00901 { 00902 uchar chr= (uchar) *name; 00903 length= my_mbcharlen(system_charset_info, chr); 00904 /* 00905 my_mbcharlen can retur 0 on a wrong multibyte 00906 sequence. It is possible when upgrading from 4.0, 00907 and identifier contains some accented characters. 00908 The manual says it does not work. So we'll just 00909 change length to 1 not to hang in the endless loop. 00910 */ 00911 if (!length) 00912 length= 1; 00913 if (length == 1 && chr == (uchar) quote_char) 00914 packet->append("e_char, 1, system_charset_info); 00915 packet->append(name, length, packet->charset()); 00916 } 00917 packet->append("e_char, 1, system_charset_info); 00918 } 00919 00920 00921 /* 00922 Get the quote character for displaying an identifier. 00923 00924 SYNOPSIS 00925 get_quote_char_for_identifier() 00926 thd Thread handler 00927 name name to quote 00928 length length of name 00929 00930 IMPLEMENTATION 00931 Force quoting in the following cases: 00932 - name is empty (for one, it is possible when we use this function for 00933 quoting user and host names for DEFINER clause); 00934 - name is a keyword; 00935 - name includes a special character; 00936 Otherwise identifier is quoted only if the option OPTION_QUOTE_SHOW_CREATE 00937 is set. 00938 00939 RETURN 00940 EOF No quote character is needed 00941 # Quote character 00942 */ 00943 00944 int get_quote_char_for_identifier(THD *thd, const char *name, uint length) 00945 { 00946 if (length && 00947 !is_keyword(name,length) && 00948 !require_quotes(name, length) && 00949 !(thd->options & OPTION_QUOTE_SHOW_CREATE)) 00950 return EOF; 00951 if (thd->variables.sql_mode & MODE_ANSI_QUOTES) 00952 return '"'; 00953 return '`'; 00954 } 00955 00956 00957 /* Append directory name (if exists) to CREATE INFO */ 00958 00959 static void append_directory(THD *thd, String *packet, const char *dir_type, 00960 const char *filename) 00961 { 00962 if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)) 00963 { 00964 uint length= dirname_length(filename); 00965 packet->append(' '); 00966 packet->append(dir_type); 00967 packet->append(STRING_WITH_LEN(" DIRECTORY='")); 00968 #ifdef __WIN__ 00969 /* Convert \ to / to be able to create table on unix */ 00970 char *winfilename= (char*) thd->memdup(filename, length); 00971 char *pos, *end; 00972 for (pos= winfilename, end= pos+length ; pos < end ; pos++) 00973 { 00974 if (*pos == '\\') 00975 *pos = '/'; 00976 } 00977 filename= winfilename; 00978 #endif 00979 packet->append(filename, length); 00980 packet->append('\''); 00981 } 00982 } 00983 00984 00985 #define LIST_PROCESS_HOST_LEN 64 00986 00987 /* 00988 Build a CREATE TABLE statement for a table. 00989 00990 SYNOPSIS 00991 store_create_info() 00992 thd The thread 00993 table_list A list containing one table to write statement 00994 for. 00995 packet Pointer to a string where statement will be 00996 written. 00997 create_info_arg Pointer to create information that can be used 00998 to tailor the format of the statement. Can be 00999 NULL, in which case only SQL_MODE is considered 01000 when building the statement. 01001 01002 NOTE 01003 Currently always return 0, but might return error code in the 01004 future. 01005 01006 RETURN 01007 0 OK 01008 */ 01009 01010 int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, 01011 HA_CREATE_INFO *create_info_arg) 01012 { 01013 List<Item> field_list; 01014 char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end, uname[NAME_LEN*3+1]; 01015 const char *alias; 01016 String type(tmp, sizeof(tmp), system_charset_info); 01017 Field **ptr,*field; 01018 uint primary_key; 01019 KEY *key_info; 01020 TABLE *table= table_list->table; 01021 handler *file= table->file; 01022 TABLE_SHARE *share= table->s; 01023 HA_CREATE_INFO create_info; 01024 bool show_table_options= FALSE; 01025 bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL | 01026 MODE_ORACLE | 01027 MODE_MSSQL | 01028 MODE_DB2 | 01029 MODE_MAXDB | 01030 MODE_ANSI)) != 0; 01031 bool limited_mysql_mode= (thd->variables.sql_mode & (MODE_NO_FIELD_OPTIONS | 01032 MODE_MYSQL323 | 01033 MODE_MYSQL40)) != 0; 01034 my_bitmap_map *old_map; 01035 DBUG_ENTER("store_create_info"); 01036 DBUG_PRINT("enter",("table: %s", table->s->table_name.str)); 01037 01038 restore_record(table, s->default_values); // Get empty record 01039 01040 if (share->tmp_table) 01041 packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE ")); 01042 else 01043 packet->append(STRING_WITH_LEN("CREATE TABLE ")); 01044 if (table_list->schema_table) 01045 alias= table_list->schema_table->table_name; 01046 else 01047 { 01048 if (lower_case_table_names == 2) 01049 alias= table->alias; 01050 else 01051 { 01052 alias= share->table_name.str; 01053 } 01054 } 01055 append_identifier(thd, packet, alias, strlen(alias)); 01056 packet->append(STRING_WITH_LEN(" (\n")); 01057 /* 01058 We need this to get default values from the table 01059 We have to restore the read_set if we are called from insert in case 01060 of row based replication. 01061 */ 01062 old_map= tmp_use_all_columns(table, table->read_set); 01063 01064 for (ptr=table->field ; (field= *ptr); ptr++) 01065 { 01066 bool has_default; 01067 bool has_now_default; 01068 uint flags = field->flags; 01069 01070 if (ptr != table->field) 01071 packet->append(STRING_WITH_LEN(",\n")); 01072 01073 packet->append(STRING_WITH_LEN(" ")); 01074 append_identifier(thd,packet,field->field_name, strlen(field->field_name)); 01075 packet->append(' '); 01076 // check for surprises from the previous call to Field::sql_type() 01077 if (type.ptr() != tmp) 01078 type.set(tmp, sizeof(tmp), system_charset_info); 01079 else 01080 type.set_charset(system_charset_info); 01081 01082 field->sql_type(type); 01083 packet->append(type.ptr(), type.length(), system_charset_info); 01084 01085 if (field->has_charset() && 01086 !(thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))) 01087 { 01088 if (field->charset() != share->table_charset) 01089 { 01090 packet->append(STRING_WITH_LEN(" CHARACTER SET ")); 01091 packet->append(field->charset()->csname); 01092 } 01093 /* 01094 For string types dump collation name only if 01095 collation is not primary for the given charset 01096 */ 01097 if (!(field->charset()->state & MY_CS_PRIMARY)) 01098 { 01099 packet->append(STRING_WITH_LEN(" COLLATE ")); 01100 packet->append(field->charset()->name); 01101 } 01102 } 01103 01104 if (flags & NOT_NULL_FLAG) 01105 packet->append(STRING_WITH_LEN(" NOT NULL")); 01106 else if (field->type() == FIELD_TYPE_TIMESTAMP) 01107 { 01108 /* 01109 TIMESTAMP field require explicit NULL flag, because unlike 01110 all other fields they are treated as NOT NULL by default. 01111 */ 01112 packet->append(STRING_WITH_LEN(" NULL")); 01113 } 01114 01115 /* 01116 Again we are using CURRENT_TIMESTAMP instead of NOW because it is 01117 more standard 01118 */ 01119 has_now_default= table->timestamp_field == field && 01120 field->unireg_check != Field::TIMESTAMP_UN_FIELD; 01121 01122 has_default= (field->type() != FIELD_TYPE_BLOB && 01123 !(field->flags & NO_DEFAULT_VALUE_FLAG) && 01124 field->unireg_check != Field::NEXT_NUMBER && 01125 !((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) 01126 && has_now_default)); 01127 01128 if (has_default) 01129 { 01130 packet->append(STRING_WITH_LEN(" DEFAULT ")); 01131 if (has_now_default) 01132 packet->append(STRING_WITH_LEN("CURRENT_TIMESTAMP")); 01133 else if (!field->is_null()) 01134 { // Not null by default 01135 type.set(tmp, sizeof(tmp), field->charset()); 01136 field->val_str(&type); 01137 if (type.length()) 01138 { 01139 String def_val; 01140 uint dummy_errors; 01141 /* convert to system_charset_info == utf8 */ 01142 def_val.copy(type.ptr(), type.length(), field->charset(), 01143 system_charset_info, &dummy_errors); 01144 append_unescaped(packet, def_val.ptr(), def_val.length()); 01145 } 01146 else 01147 packet->append(STRING_WITH_LEN("''")); 01148 } 01149 else if (field->maybe_null()) 01150 packet->append(STRING_WITH_LEN("NULL")); // Null as default 01151 else 01152 packet->append(tmp); 01153 } 01154 01155 if (!limited_mysql_mode && table->timestamp_field == field && 01156 field->unireg_check != Field::TIMESTAMP_DN_FIELD) 01157 packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP")); 01158 01159 if (field->unireg_check == Field::NEXT_NUMBER && 01160 !(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS)) 01161 packet->append(STRING_WITH_LEN(" AUTO_INCREMENT")); 01162 01163 if (field->comment.length) 01164 { 01165 packet->append(STRING_WITH_LEN(" COMMENT ")); 01166 append_unescaped(packet, field->comment.str, field->comment.length); 01167 } 01168 } 01169 01170 key_info= table->key_info; 01171 bzero((char*) &create_info, sizeof(create_info)); 01172 file->update_create_info(&create_info); 01173 primary_key= share->primary_key; 01174 01175 for (uint i=0 ; i < share->keys ; i++,key_info++) 01176 { 01177 KEY_PART_INFO *key_part= key_info->key_part; 01178 bool found_primary=0; 01179 packet->append(STRING_WITH_LEN(",\n ")); 01180 01181 if (i == primary_key && !strcmp(key_info->name, primary_key_name)) 01182 { 01183 found_primary=1; 01184 /* 01185 No space at end, because a space will be added after where the 01186 identifier would go, but that is not added for primary key. 01187 */ 01188 packet->append(STRING_WITH_LEN("PRIMARY KEY")); 01189 } 01190 else if (key_info->flags & HA_NOSAME) 01191 packet->append(STRING_WITH_LEN("UNIQUE KEY ")); 01192 else if (key_info->flags & HA_FULLTEXT) 01193 packet->append(STRING_WITH_LEN("FULLTEXT KEY ")); 01194 else if (key_info->flags & HA_SPATIAL) 01195 packet->append(STRING_WITH_LEN("SPATIAL KEY ")); 01196 else 01197 packet->append(STRING_WITH_LEN("KEY ")); 01198 01199 if (!found_primary) 01200 append_identifier(thd, packet, key_info->name, strlen(key_info->name)); 01201 01202 packet->append(STRING_WITH_LEN(" (")); 01203 01204 for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) 01205 { 01206 if (j) 01207 packet->append(','); 01208 01209 if (key_part->field) 01210 append_identifier(thd,packet,key_part->field->field_name, 01211 strlen(key_part->field->field_name)); 01212 if (key_part->field && 01213 (key_part->length != 01214 table->field[key_part->fieldnr-1]->key_length() && 01215 !(key_info->flags & HA_FULLTEXT))) 01216 { 01217 char *end; 01218 buff[0] = '('; 01219 end= int10_to_str((long) key_part->length / 01220 key_part->field->charset()->mbmaxlen, 01221 buff + 1,10); 01222 *end++ = ')'; 01223 packet->append(buff,(uint) (end-buff)); 01224 } 01225 } 01226 packet->append(')'); 01227 store_key_options(thd, packet, table, key_info); 01228 if (key_info->parser) 01229 { 01230 packet->append(" WITH PARSER ", 13); 01231 append_identifier(thd, packet, key_info->parser->name.str, 01232 key_info->parser->name.length); 01233 } 01234 } 01235 01236 /* 01237 Get possible foreign key definitions stored in InnoDB and append them 01238 to the CREATE TABLE statement 01239 */ 01240 01241 if ((for_str= file->get_foreign_key_create_info())) 01242 { 01243 packet->append(for_str, strlen(for_str)); 01244 file->free_foreign_key_create_info(for_str); 01245 } 01246 01247 packet->append(STRING_WITH_LEN("\n)")); 01248 if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode) 01249 { 01250 show_table_options= TRUE; 01251 /* 01252 Get possible table space definitions and append them 01253 to the CREATE TABLE statement 01254 */ 01255 01256 if ((for_str= file->get_tablespace_name(thd))) 01257 { 01258 packet->append(" TABLESPACE "); 01259 packet->append(for_str, strlen(for_str)); 01260 packet->append(" STORAGE DISK"); 01261 my_free(for_str, MYF(0)); 01262 } 01263 01264 /* 01265 IF check_create_info 01266 THEN add ENGINE only if it was used when creating the table 01267 */ 01268 if (!create_info_arg || 01269 (create_info_arg->used_fields & HA_CREATE_USED_ENGINE)) 01270 { 01271 if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) 01272 packet->append(STRING_WITH_LEN(" TYPE=")); 01273 else 01274 packet->append(STRING_WITH_LEN(" ENGINE=")); 01275 #ifdef WITH_PARTITION_STORAGE_ENGINE 01276 if (table->part_info) 01277 packet->append(ha_resolve_storage_engine_name( 01278 table->part_info->default_engine_type)); 01279 else 01280 packet->append(file->table_type()); 01281 #else 01282 packet->append(file->table_type()); 01283 #endif 01284 } 01285 01286 /* 01287 Add AUTO_INCREMENT=... if there is an AUTO_INCREMENT column, 01288 and NEXT_ID > 1 (the default). We must not print the clause 01289 for engines that do not support this as it would break the 01290 import of dumps, but as of this writing, the test for whether 01291 AUTO_INCREMENT columns are allowed and wether AUTO_INCREMENT=... 01292 is supported is identical, !(file->table_flags() & HA_NO_AUTO_INCREMENT)) 01293 Because of that, we do not explicitly test for the feature, 01294 but may extrapolate its existence from that of an AUTO_INCREMENT column. 01295 */ 01296 01297 if(create_info.auto_increment_value > 1) 01298 { 01299 packet->append(" AUTO_INCREMENT=", 16); 01300 end= longlong10_to_str(create_info.auto_increment_value, buff,10); 01301 packet->append(buff, (uint) (end - buff)); 01302 } 01303 01304 01305 if (share->table_charset && 01306 !(thd->variables.sql_mode & MODE_MYSQL323) && 01307 !(thd->variables.sql_mode & MODE_MYSQL40)) 01308 { 01309 /* 01310 IF check_create_info 01311 THEN add DEFAULT CHARSET only if it was used when creating the table 01312 */ 01313 if (!create_info_arg || 01314 (create_info_arg->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)) 01315 { 01316 packet->append(STRING_WITH_LEN(" DEFAULT CHARSET=")); 01317 packet->append(share->table_charset->csname); 01318 if (!(share->table_charset->state & MY_CS_PRIMARY)) 01319 { 01320 packet->append(STRING_WITH_LEN(" COLLATE=")); 01321 packet->append(table->s->table_charset->name); 01322 } 01323 } 01324 } 01325 01326 if (share->min_rows) 01327 { 01328 packet->append(STRING_WITH_LEN(" MIN_ROWS=")); 01329 end= longlong10_to_str(share->min_rows, buff, 10); 01330 packet->append(buff, (uint) (end- buff)); 01331 } 01332 01333 if (share->max_rows && !table_list->schema_table) 01334 { 01335 packet->append(STRING_WITH_LEN(" MAX_ROWS=")); 01336 end= longlong10_to_str(share->max_rows, buff, 10); 01337 packet->append(buff, (uint) (end - buff)); 01338 } 01339 01340 if (share->avg_row_length) 01341 { 01342 packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH=")); 01343 end= longlong10_to_str(share->avg_row_length, buff,10); 01344 packet->append(buff, (uint) (end - buff)); 01345 } 01346 01347 if (share->db_create_options & HA_OPTION_PACK_KEYS) 01348 packet->append(STRING_WITH_LEN(" PACK_KEYS=1")); 01349 if (share->db_create_options & HA_OPTION_NO_PACK_KEYS) 01350 packet->append(STRING_WITH_LEN(" PACK_KEYS=0")); 01351 if (share->db_create_options & HA_OPTION_CHECKSUM) 01352 packet->append(STRING_WITH_LEN(" CHECKSUM=1")); 01353 if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE) 01354 packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1")); 01355 if (share->row_type != ROW_TYPE_DEFAULT) 01356 { 01357 packet->append(STRING_WITH_LEN(" ROW_FORMAT=")); 01358 packet->append(ha_row_type[(uint) share->row_type]); 01359 } 01360 if (table->s->key_block_size) 01361 { 01362 packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE=")); 01363 end= longlong10_to_str(table->s->key_block_size, buff, 10); 01364 packet->append(buff, (uint) (end - buff)); 01365 } 01366 table->file->append_create_info(packet); 01367 if (share->comment.length) 01368 { 01369 packet->append(STRING_WITH_LEN(" COMMENT=")); 01370 append_unescaped(packet, share->comment.str, share->comment.length); 01371 } 01372 if (share->connect_string.length) 01373 { 01374 packet->append(STRING_WITH_LEN(" CONNECTION=")); 01375 append_unescaped(packet, share->connect_string.str, share->connect_string.length); 01376 } 01377 append_directory(thd, packet, "DATA", create_info.data_file_name); 01378 append_directory(thd, packet, "INDEX", create_info.index_file_name); 01379 } 01380 #ifdef WITH_PARTITION_STORAGE_ENGINE 01381 { 01382 /* 01383 Partition syntax for CREATE TABLE is at the end of the syntax. 01384 */ 01385 uint part_syntax_len; 01386 char *part_syntax; 01387 if (table->part_info && 01388 (!table->part_info->is_auto_partitioned) && 01389 ((part_syntax= generate_partition_syntax(table->part_info, 01390 &part_syntax_len, 01391 FALSE, 01392 show_table_options)))) 01393 { 01394 packet->append(STRING_WITH_LEN(" /*!50100")); 01395 packet->append(part_syntax, part_syntax_len); 01396 packet->append(STRING_WITH_LEN(" */")); 01397 my_free(part_syntax, MYF(0)); 01398 } 01399 } 01400 #endif 01401 tmp_restore_column_map(table->read_set, old_map); 01402 DBUG_RETURN(0); 01403 } 01404 01405 01406 static void store_key_options(THD *thd, String *packet, TABLE *table, 01407 KEY *key_info) 01408 { 01409 bool limited_mysql_mode= (thd->variables.sql_mode & 01410 (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 | 01411 MODE_MYSQL40)) != 0; 01412 bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL | 01413 MODE_ORACLE | 01414 MODE_MSSQL | 01415 MODE_DB2 | 01416 MODE_MAXDB | 01417 MODE_ANSI)) != 0; 01418 char *end, buff[32]; 01419 01420 if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) && 01421 !limited_mysql_mode && !foreign_db_mode) 01422 { 01423 01424 if (key_info->algorithm == HA_KEY_ALG_BTREE) 01425 packet->append(STRING_WITH_LEN(" USING BTREE")); 01426 01427 if (key_info->algorithm == HA_KEY_ALG_HASH) 01428 packet->append(STRING_WITH_LEN(" USING HASH")); 01429 01430 /* send USING only in non-default case: non-spatial rtree */ 01431 if ((key_info->algorithm == HA_KEY_ALG_RTREE) && 01432 !(key_info->flags & HA_SPATIAL)) 01433 packet->append(STRING_WITH_LEN(" USING RTREE")); 01434 01435 if ((key_info->flags & HA_USES_BLOCK_SIZE) && 01436 table->s->key_block_size != key_info->block_size) 01437 { 01438 packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE=")); 01439 end= longlong10_to_str(key_info->block_size, buff, 10); 01440 packet->append(buff, (uint) (end - buff)); 01441 } 01442 } 01443 } 01444 01445 01446 void 01447 view_store_options(THD *thd, TABLE_LIST *table, String *buff) 01448 { 01449 append_algorithm(table, buff); 01450 append_definer(thd, buff, &table->definer.user, &table->definer.host); 01451 if (table->view_suid) 01452 buff->append(STRING_WITH_LEN("SQL SECURITY DEFINER ")); 01453 else 01454 buff->append(STRING_WITH_LEN("SQL SECURITY INVOKER ")); 01455 } 01456 01457 01458 /* 01459 Append DEFINER clause to the given buffer. 01460 01461 SYNOPSIS 01462 append_definer() 01463 thd [in] thread handle 01464 buffer [inout] buffer to hold DEFINER clause 01465 definer_user [in] user name part of definer 01466 definer_host [in] host name part of definer 01467 */ 01468 01469 static void append_algorithm(TABLE_LIST *table, String *buff) 01470 { 01471 buff->append(STRING_WITH_LEN("ALGORITHM=")); 01472 switch ((int8)table->algorithm) { 01473 case VIEW_ALGORITHM_UNDEFINED: 01474 buff->append(STRING_WITH_LEN("UNDEFINED ")); 01475 break; 01476 case VIEW_ALGORITHM_TMPTABLE: 01477 buff->append(STRING_WITH_LEN("TEMPTABLE ")); 01478 break; 01479 case VIEW_ALGORITHM_MERGE: 01480 buff->append(STRING_WITH_LEN("MERGE ")); 01481 break; 01482 default: 01483 DBUG_ASSERT(0); // never should happen 01484 } 01485 } 01486 01487 /* 01488 Append DEFINER clause to the given buffer. 01489 01490 SYNOPSIS 01491 append_definer() 01492 thd [in] thread handle 01493 buffer [inout] buffer to hold DEFINER clause 01494 definer_user [in] user name part of definer 01495 definer_host [in] host name part of definer 01496 */ 01497 01498 void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user, 01499 const LEX_STRING *definer_host) 01500 { 01501 buffer->append(STRING_WITH_LEN("DEFINER=")); 01502 append_identifier(thd, buffer, definer_user->str, definer_user->length); 01503 buffer->append('@'); 01504 append_identifier(thd, buffer, definer_host->str, definer_host->length); 01505 buffer->append(' '); 01506 } 01507 01508 01509 int 01510 view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) 01511 { 01512 my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL | 01513 MODE_ORACLE | 01514 MODE_MSSQL | 01515 MODE_DB2 | 01516 MODE_MAXDB | 01517 MODE_ANSI)) != 0; 01518 /* 01519 Compact output format for view can be used 01520 - if user has db of this view as current db 01521 - if this view only references table inside it's own db 01522 */ 01523 if (!thd->db || strcmp(thd->db, table->view_db.str)) 01524 table->compact_view_format= FALSE; 01525 else 01526 { 01527 TABLE_LIST *tbl; 01528 table->compact_view_format= TRUE; 01529 for (tbl= thd->lex->query_tables; 01530 tbl; 01531 tbl= tbl->next_global) 01532 { 01533 if (strcmp(table->view_db.str, tbl->view ? tbl->view_db.str :tbl->db)!= 0) 01534 { 01535 table->compact_view_format= FALSE; 01536 break; 01537 } 01538 } 01539 } 01540 01541 buff->append(STRING_WITH_LEN("CREATE ")); 01542 if (!foreign_db_mode) 01543 { 01544 view_store_options(thd, table, buff); 01545 } 01546 buff->append(STRING_WITH_LEN("VIEW ")); 01547 if (!table->compact_view_format) 01548 { 01549 append_identifier(thd, buff, table->view_db.str, table->view_db.length); 01550 buff->append('.'); 01551 } 01552 append_identifier(thd, buff, table->view_name.str, table->view_name.length); 01553 buff->append(STRING_WITH_LEN(" AS ")); 01554 01555 /* 01556 We can't just use table->query, because our SQL_MODE may trigger 01557 a different syntax, like when ANSI_QUOTES is defined. 01558 */ 01559 table->view->unit.print(buff); 01560 01561 if (table->with_check != VIEW_CHECK_NONE) 01562 { 01563 if (table->with_check == VIEW_CHECK_LOCAL) 01564 buff->append(STRING_WITH_LEN(" WITH LOCAL CHECK OPTION")); 01565 else 01566 buff->append(STRING_WITH_LEN(" WITH CASCADED CHECK OPTION")); 01567 } 01568 return 0; 01569 } 01570 01571 01572 /**************************************************************************** 01573 Return info about all processes 01574 returns for each thread: thread id, user, host, db, command, info 01575 ****************************************************************************/ 01576 01577 class thread_info :public ilink { 01578 public: 01579 static void *operator new(size_t size) 01580 { 01581 return (void*) sql_alloc((uint) size); 01582 } 01583 static void operator delete(void *ptr __attribute__((unused)), 01584 size_t size __attribute__((unused))) 01585 { TRASH(ptr, size); } 01586 01587 ulong thread_id; 01588 time_t start_time; 01589 uint command; 01590 const char *user,*host,*db,*proc_info,*state_info; 01591 char *query; 01592 }; 01593 01594 #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION 01595 template class I_List<thread_info>; 01596 #endif 01597 01598 void mysqld_list_processes(THD *thd,const char *user, bool verbose) 01599 { 01600 Item *field; 01601 List<Item> field_list; 01602 I_List<thread_info> thread_infos; 01603 ulong max_query_length= (verbose ? thd->variables.max_allowed_packet : 01604 PROCESS_LIST_WIDTH); 01605 Protocol *protocol= thd->protocol; 01606 DBUG_ENTER("mysqld_list_processes"); 01607 01608 field_list.push_back(new Item_int("Id",0,11)); 01609 field_list.push_back(new Item_empty_string("User",16)); 01610 field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN)); 01611 field_list.push_back(field=new Item_empty_string("db",NAME_LEN)); 01612 field->maybe_null=1; 01613 field_list.push_back(new Item_empty_string("Command",16)); 01614 field_list.push_back(new Item_return_int("Time",7, FIELD_TYPE_LONG)); 01615 field_list.push_back(field=new Item_empty_string("State",30)); 01616 field->maybe_null=1; 01617 field_list.push_back(field=new Item_empty_string("Info",max_query_length)); 01618 field->maybe_null=1; 01619 if (protocol->send_fields(&field_list, 01620 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) 01621 DBUG_VOID_RETURN; 01622 01623 VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list 01624 if (!thd->killed) 01625 { 01626 I_List_iterator<THD> it(threads); 01627 THD *tmp; 01628 while ((tmp=it++)) 01629 { 01630 Security_context *tmp_sctx= tmp->security_ctx; 01631 struct st_my_thread_var *mysys_var; 01632 if ((tmp->vio_ok() || tmp->system_thread) && 01633 (!user || (tmp_sctx->user && !strcmp(tmp_sctx->user, user)))) 01634 { 01635 thread_info *thd_info= new thread_info; 01636 01637 thd_info->thread_id=tmp->thread_id; 01638 thd_info->user= thd->strdup(tmp_sctx->user ? tmp_sctx->user : 01639 (tmp->system_thread ? 01640 "system user" : "unauthenticated user")); 01641 if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) && 01642 thd->security_ctx->host_or_ip[0]) 01643 { 01644 if ((thd_info->host= thd->alloc(LIST_PROCESS_HOST_LEN+1))) 01645 my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN, 01646 "%s:%u", tmp_sctx->host_or_ip, tmp->peer_port); 01647 } 01648 else 01649 thd_info->host= thd->strdup(tmp_sctx->host_or_ip); 01650 if ((thd_info->db=tmp->db)) // Safe test 01651 thd_info->db=thd->strdup(thd_info->db); 01652 thd_info->command=(int) tmp->command; 01653 if ((mysys_var= tmp->mysys_var)) 01654 pthread_mutex_lock(&mysys_var->mutex); 01655 thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0); 01656 #ifndef EMBEDDED_LIBRARY 01657 thd_info->state_info= (char*) (tmp->locked ? "Locked" : 01658 tmp->net.reading_or_writing ? 01659 (tmp->net.reading_or_writing == 2 ? 01660 "Writing to net" : 01661 thd_info->command == COM_SLEEP ? "" : 01662 "Reading from net") : 01663 tmp->proc_info ? tmp->proc_info : 01664 tmp->mysys_var && 01665 tmp->mysys_var->current_cond ? 01666 "Waiting on cond" : NullS); 01667 #else 01668 thd_info->state_info= (char*)"Writing to net"; 01669 #endif 01670 if (mysys_var) 01671 pthread_mutex_unlock(&mysys_var->mutex); 01672 01673 #if !defined(DONT_USE_THR_ALARM) && ! defined(SCO) 01674 if (pthread_kill(tmp->real_id,0)) 01675 tmp->proc_info="*** DEAD ***"; // This shouldn't happen 01676 #endif 01677 #ifdef EXTRA_DEBUG 01678 thd_info->start_time= tmp->time_after_lock; 01679 #else 01680 thd_info->start_time= tmp->start_time; 01681 #endif 01682 thd_info->query=0; 01683 if (tmp->query) 01684 { 01685 /* 01686 query_length is always set to 0 when we set query = NULL; see 01687 the comment in sql_class.h why this prevents crashes in possible 01688 races with query_length 01689 */ 01690 uint length= min(max_query_length, tmp->query_length); 01691 thd_info->query=(char*) thd->strmake(tmp->query,length); 01692 } 01693 thread_infos.append(thd_info); 01694 } 01695 } 01696 } 01697 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 01698 01699 thread_info *thd_info; 01700 time_t now= time(0); 01701 while ((thd_info=thread_infos.get())) 01702 { 01703 protocol->prepare_for_resend(); 01704 protocol->store((ulonglong) thd_info->thread_id); 01705 protocol->store(thd_info->user, system_charset_info); 01706 protocol->store(thd_info->host, system_charset_info); 01707 protocol->store(thd_info->db, system_charset_info); 01708 if (thd_info->proc_info) 01709 protocol->store(thd_info->proc_info, system_charset_info); 01710 else 01711 protocol->store(command_name[thd_info->command].str, system_charset_info); 01712 if (thd_info->start_time) 01713 protocol->store((uint32) (now - thd_info->start_time)); 01714 else 01715 protocol->store_null(); 01716 protocol->store(thd_info->state_info, system_charset_info); 01717 protocol->store(thd_info->query, system_charset_info); 01718 if (protocol->write()) 01719 break; /* purecov: inspected */ 01720 } 01721 send_eof(thd); 01722 DBUG_VOID_RETURN; 01723 } 01724 01725 int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) 01726 { 01727 TABLE *table= tables->table; 01728 CHARSET_INFO *cs= system_charset_info; 01729 char *user; 01730 time_t now= time(0); 01731 DBUG_ENTER("fill_process_list"); 01732 01733 user= thd->security_ctx->master_access & PROCESS_ACL ? 01734 NullS : thd->security_ctx->priv_user; 01735 01736 VOID(pthread_mutex_lock(&LOCK_thread_count)); 01737 01738 if (!thd->killed) 01739 { 01740 I_List_iterator<THD> it(threads); 01741 THD* tmp; 01742 01743 while ((tmp= it++)) 01744 { 01745 Security_context *tmp_sctx= tmp->security_ctx; 01746 struct st_my_thread_var *mysys_var; 01747 const char *val; 01748 01749 if ((!tmp->vio_ok() && !tmp->system_thread) || 01750 (user && (!tmp_sctx->user || strcmp(tmp_sctx->user, user)))) 01751 continue; 01752 01753 restore_record(table, s->default_values); 01754 /* ID */ 01755 table->field[0]->store((longlong) tmp->thread_id, TRUE); 01756 /* USER */ 01757 val= tmp_sctx->user ? tmp_sctx->user : 01758 (tmp->system_thread ? "system user" : "unauthenticated user"); 01759 table->field[1]->store(val, strlen(val), cs); 01760 /* HOST */ 01761 if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) && 01762 thd->security_ctx->host_or_ip[0]) 01763 { 01764 char host[LIST_PROCESS_HOST_LEN + 1]; 01765 my_snprintf(host, LIST_PROCESS_HOST_LEN, "%s:%u", 01766 tmp_sctx->host_or_ip, tmp->peer_port); 01767 table->field[2]->store(host, strlen(host), cs); 01768 } 01769 else 01770 table->field[2]->store(tmp_sctx->host_or_ip, 01771 strlen(tmp_sctx->host_or_ip), cs); 01772 /* DB */ 01773 if (tmp->db) 01774 { 01775 table->field[3]->store(tmp->db, strlen(tmp->db), cs); 01776 table->field[3]->set_notnull(); 01777 } 01778 01779 if ((mysys_var= tmp->mysys_var)) 01780 pthread_mutex_lock(&mysys_var->mutex); 01781 /* COMMAND */ 01782 if ((val= (char *) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0))) 01783 table->field[4]->store(val, strlen(val), cs); 01784 else 01785 table->field[4]->store(command_name[tmp->command].str, 01786 command_name[tmp->command].length, cs); 01787 /* TIME */ 01788 table->field[5]->store((uint32)(tmp->start_time ? 01789 now - tmp->start_time : 0), TRUE); 01790 /* STATE */ 01791 #ifndef EMBEDDED_LIBRARY 01792 val= (char*) (tmp->locked ? "Locked" : 01793 tmp->net.reading_or_writing ? 01794 (tmp->net.reading_or_writing == 2 ? 01795 "Writing to net" : 01796 tmp->command == COM_SLEEP ? "" : 01797 "Reading from net") : 01798 tmp->proc_info ? tmp->proc_info : 01799 tmp->mysys_var && 01800 tmp->mysys_var->current_cond ? 01801 "Waiting on cond" : NullS); 01802 #else 01803 val= (char *) "Writing to net"; 01804 #endif 01805 if (val) 01806 { 01807 table->field[6]->store(val, strlen(val), cs); 01808 table->field[6]->set_notnull(); 01809 } 01810 01811 if (mysys_var) 01812 pthread_mutex_unlock(&mysys_var->mutex); 01813 01814 /* INFO */ 01815 if (tmp->query) 01816 { 01817 table->field[7]->store(tmp->query, 01818 min(PROCESS_LIST_INFO_WIDTH, 01819 tmp->query_length), cs); 01820 table->field[7]->set_notnull(); 01821 } 01822 01823 if (schema_table_store_record(thd, table)) 01824 { 01825 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 01826 DBUG_RETURN(1); 01827 } 01828 } 01829 } 01830 01831 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 01832 DBUG_RETURN(0); 01833 } 01834 01835 /***************************************************************************** 01836 Status functions 01837 *****************************************************************************/ 01838 01839 static DYNAMIC_ARRAY all_status_vars; 01840 static bool status_vars_inited= 0; 01841 static int show_var_cmp(const void *var1, const void *var2) 01842 { 01843 return strcmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name); 01844 } 01845 01846 /* 01847 deletes all the SHOW_UNDEF elements from the array and calls 01848 delete_dynamic() if it's completely empty. 01849 */ 01850 static void shrink_var_array(DYNAMIC_ARRAY *array) 01851 { 01852 uint a,b; 01853 SHOW_VAR *all= dynamic_element(array, 0, SHOW_VAR *); 01854 01855 for (a= b= 0; b < array->elements; b++) 01856 if (all[b].type != SHOW_UNDEF) 01857 all[a++]= all[b]; 01858 if (a) 01859 { 01860 bzero(all+a, sizeof(SHOW_VAR)); // writing NULL-element to the end 01861 array->elements= a; 01862 } 01863 else // array is completely empty - delete it 01864 delete_dynamic(array); 01865 } 01866 01867 /* 01868 Adds an array of SHOW_VAR entries to the output of SHOW STATUS 01869 01870 SYNOPSIS 01871 add_status_vars(SHOW_VAR *list) 01872 list - an array of SHOW_VAR entries to add to all_status_vars 01873 the last entry must be {0,0,SHOW_UNDEF} 01874 01875 NOTE 01876 The handling of all_status_vars[] is completely internal, it's allocated 01877 automatically when something is added to it, and deleted completely when 01878 the last entry is removed. 01879 01880 As a special optimization, if add_status_vars() is called before 01881 init_status_vars(), it assumes "startup mode" - neither concurrent access 01882 to the array nor SHOW STATUS are possible (thus it skips locks and qsort) 01883 01884 The last entry of the all_status_vars[] should always be {0,0,SHOW_UNDEF} 01885 */ 01886 int add_status_vars(SHOW_VAR *list) 01887 { 01888 int res= 0; 01889 if (status_vars_inited) 01890 pthread_mutex_lock(&LOCK_status); 01891 if (!all_status_vars.buffer && // array is not allocated yet - do it now 01892 my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20)) 01893 { 01894 res= 1; 01895 goto err; 01896 } 01897 while (list->name) 01898 res|= insert_dynamic(&all_status_vars, (gptr)list++); 01899 res|= insert_dynamic(&all_status_vars, (gptr)list); // appending NULL-element 01900 all_status_vars.elements--; // but next insert_dynamic should overwite it 01901 if (status_vars_inited) 01902 sort_dynamic(&all_status_vars, show_var_cmp); 01903 err: 01904 if (status_vars_inited) 01905 pthread_mutex_unlock(&LOCK_status); 01906 return res; 01907 } 01908 01909 /* 01910 Make all_status_vars[] usable for SHOW STATUS 01911 01912 NOTE 01913 See add_status_vars(). Before init_status_vars() call, add_status_vars() 01914 works in a special fast "startup" mode. Thus init_status_vars() 01915 should be called as late as possible but before enabling multi-threading. 01916 */ 01917 void init_status_vars() 01918 { 01919 status_vars_inited=1; 01920 sort_dynamic(&all_status_vars, show_var_cmp); 01921 } 01922 01923 /* 01924 catch-all cleanup function, cleans up everything no matter what 01925 01926 DESCRIPTION 01927 This function is not strictly required if all add_to_status/ 01928 remove_status_vars are properly paired, but it's a safety measure that 01929 deletes everything from the all_status_vars[] even if some 01930 remove_status_vars were forgotten 01931 */ 01932 void free_status_vars() 01933 { 01934 delete_dynamic(&all_status_vars); 01935 } 01936 01937 /* 01938 Removes an array of SHOW_VAR entries from the output of SHOW STATUS 01939 01940 SYNOPSIS 01941 remove_status_vars(SHOW_VAR *list) 01942 list - an array of SHOW_VAR entries to remove to all_status_vars 01943 the last entry must be {0,0,SHOW_UNDEF} 01944 01945 NOTE 01946 there's lots of room for optimizing this, especially in non-sorted mode, 01947 but nobody cares - it may be called only in case of failed plugin 01948 initialization in the mysqld startup. 01949 */ 01950 01951 void remove_status_vars(SHOW_VAR *list) 01952 { 01953 if (status_vars_inited) 01954 { 01955 pthread_mutex_lock(&LOCK_status); 01956 SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *); 01957 int a= 0, b= all_status_vars.elements, c= (a+b)/2; 01958 01959 for (; list->name; list++) 01960 { 01961 int res= 0; 01962 for (a= 0, b= all_status_vars.elements; b-a > 1; c= (a+b)/2) 01963 { 01964 res= show_var_cmp(list, all+c); 01965 if (res < 0) 01966 b= c; 01967 else if (res > 0) 01968 a= c; 01969 else 01970 break; 01971 } 01972 if (res == 0) 01973 all[c].type= SHOW_UNDEF; 01974 } 01975 shrink_var_array(&all_status_vars); 01976 pthread_mutex_unlock(&LOCK_status); 01977 } 01978 else 01979 { 01980 SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *); 01981 uint i; 01982 for (; list->name; list++) 01983 { 01984 for (i= 0; i < all_status_vars.elements; i++) 01985 { 01986 if (show_var_cmp(list, all+i)) 01987 continue; 01988 all[i].type= SHOW_UNDEF; 01989 break; 01990 } 01991 } 01992 shrink_var_array(&all_status_vars); 01993 } 01994 } 01995 01996 static bool show_status_array(THD *thd, const char *wild, 01997 SHOW_VAR *variables, 01998 enum enum_var_type value_type, 01999 struct system_status_var *status_var, 02000 const char *prefix, TABLE *table) 02001 { 02002 char buff[SHOW_VAR_FUNC_BUFF_SIZE], *prefix_end; 02003 /* the variable name should not be longer then 80 characters */ 02004 char name_buffer[80]; 02005 int len; 02006 LEX_STRING null_lex_str; 02007 SHOW_VAR tmp, *var; 02008 DBUG_ENTER("show_status_array"); 02009 02010 null_lex_str.str= 0; // For sys_var->value_ptr() 02011 null_lex_str.length= 0; 02012 02013 prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1); 02014 if (*prefix) 02015 *prefix_end++= '_'; 02016 len=name_buffer + sizeof(name_buffer) - prefix_end; 02017 02018 for (; variables->name; variables++) 02019 { 02020 strnmov(prefix_end, variables->name, len); 02021 name_buffer[sizeof(name_buffer)-1]=0; /* Safety */ 02022 02023 /* 02024 if var->type is SHOW_FUNC, call the function. 02025 Repeat as necessary, if new var is again SHOW_FUNC 02026 */ 02027 for (var=variables; var->type == SHOW_FUNC; var= &tmp) 02028 ((mysql_show_var_func)(var->value))(thd, &tmp, buff); 02029 02030 SHOW_TYPE show_type=var->type; 02031 if (show_type == SHOW_ARRAY) 02032 { 02033 show_status_array(thd, wild, (SHOW_VAR *) var->value, 02034 value_type, status_var, name_buffer, table); 02035 } 02036 else 02037 { 02038 if (!(wild && wild[0] && wild_case_compare(system_charset_info, 02039 name_buffer, wild))) 02040 { 02041 char *value=var->value; 02042 const char *pos, *end; // We assign a lot of const's 02043 long nr; 02044 if (show_type == SHOW_SYS) 02045 { 02046 show_type= ((sys_var*) value)->type(); 02047 value= (char*) ((sys_var*) value)->value_ptr(thd, value_type, 02048 &null_lex_str); 02049 } 02050 02051 pos= end= buff; 02052 /* 02053 note that value may be == buff. All SHOW_xxx code below 02054 should still work in this case 02055 */ 02056 switch (show_type) { 02057 case SHOW_DOUBLE_STATUS: 02058 { 02059 value= ((char *) status_var + (ulong) value); 02060 end= buff + sprintf(buff, "%f", *(double*) value); 02061 break; 02062 } 02063 case SHOW_LONG_STATUS: 02064 value= ((char *) status_var + (ulong) value); 02065 /* fall through */ 02066 case SHOW_LONG: 02067 case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status() 02068 end= int10_to_str(*(long*) value, buff, 10); 02069 break; 02070 case SHOW_LONGLONG: 02071 end= longlong10_to_str(*(longlong*) value, buff, 10); 02072 break; 02073 case SHOW_HA_ROWS: 02074 end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10); 02075 break; 02076 case SHOW_BOOL: 02077 end= strmov(buff, *(bool*) value ? "ON" : "OFF"); 02078 break; 02079 case SHOW_MY_BOOL: 02080 end= strmov(buff, *(my_bool*) value ? "ON" : "OFF"); 02081 break; 02082 case SHOW_INT: 02083 end= int10_to_str((long) *(uint32*) value, buff, 10); 02084 break; 02085 case SHOW_HAVE: 02086 { 02087 SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value; 02088 pos= show_comp_option_name[(int) tmp]; 02089 end= strend(pos); 02090 break; 02091 } 02092 case SHOW_CHAR: 02093 { 02094 if (!(pos= value)) 02095 pos= ""; 02096 end= strend(pos); 02097 break; 02098 } 02099 case SHOW_CHAR_PTR: 02100 { 02101 if (!(pos= *(char**) value)) 02102 pos= ""; 02103 end= strend(pos); 02104 break; 02105 } 02106 case SHOW_KEY_CACHE_LONG: 02107 value= (char*) dflt_key_cache + (ulong)value; 02108 end= int10_to_str(*(long*) value, buff, 10); 02109 break; 02110 case SHOW_KEY_CACHE_LONGLONG: 02111 value= (char*) dflt_key_cache + (ulong)value; 02112 end= longlong10_to_str(*(longlong*) value, buff, 10); 02113 break; 02114 case SHOW_UNDEF: 02115 break; // Return empty string 02116 case SHOW_SYS: // Cannot happen 02117 default: 02118 DBUG_ASSERT(0); 02119 break; 02120 } 02121 restore_record(table, s->default_values); 02122 table->field[0]->store(name_buffer, strlen(name_buffer), 02123 system_charset_info); 02124 table->field[1]->store(pos, (uint32) (end - pos), system_charset_info); 02125 if (schema_table_store_record(thd, table)) 02126 DBUG_RETURN(TRUE); 02127 } 02128 } 02129 } 02130 02131 DBUG_RETURN(FALSE); 02132 } 02133 02134 02135 /* collect status for all running threads */ 02136 02137 void calc_sum_of_all_status(STATUS_VAR *to) 02138 { 02139 DBUG_ENTER("calc_sum_of_all_status"); 02140 02141 /* Ensure that thread id not killed during loop */ 02142 VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list 02143 02144 I_List_iterator<THD> it(threads); 02145 THD *tmp; 02146 02147 /* Get global values as base */ 02148 *to= global_status_var; 02149 02150 /* Add to this status from existing threads */ 02151 while ((tmp= it++)) 02152 add_to_status(to, &tmp->status_var); 02153 02154 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 02155 DBUG_VOID_RETURN; 02156 } 02157 02158 02159 LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str, 02160 const char* str, uint length, 02161 bool allocate_lex_string) 02162 { 02163 MEM_ROOT *mem= thd->mem_root; 02164 if (allocate_lex_string) 02165 if (!(lex_str= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING)))) 02166 return 0; 02167 lex_str->str= strmake_root(mem, str, length); 02168 lex_str->length= length; 02169 return lex_str; 02170 } 02171 02172 02173 /* INFORMATION_SCHEMA name */ 02174 LEX_STRING information_schema_name= { C_STRING_WITH_LEN("information_schema")}; 02175 02176 /* This is only used internally, but we need it here as a forward reference */ 02177 extern ST_SCHEMA_TABLE schema_tables[]; 02178 02179 typedef struct st_index_field_values 02180 { 02181 const char *db_value, *table_value; 02182 } INDEX_FIELD_VALUES; 02183 02184 02185 /* 02186 Store record to I_S table, convert HEAP table 02187 to MyISAM if necessary 02188 02189 SYNOPSIS 02190 schema_table_store_record() 02191 thd thread handler 02192 table Information schema table to be updated 02193 02194 RETURN 02195 0 success 02196 1 error 02197 */ 02198 02199 bool schema_table_store_record(THD *thd, TABLE *table) 02200 { 02201 int error; 02202 if ((error= table->file->ha_write_row(table->record[0]))) 02203 { 02204 if (create_myisam_from_heap(thd, table, 02205 table->pos_in_table_list->schema_table_param, 02206 error, 0)) 02207 return 1; 02208 } 02209 return 0; 02210 } 02211 02212 02213 void get_index_field_values(LEX *lex, INDEX_FIELD_VALUES *index_field_values) 02214 { 02215 const char *wild= lex->wild ? lex->wild->ptr() : NullS; 02216 switch (lex->sql_command) { 02217 case SQLCOM_SHOW_DATABASES: 02218 index_field_values->db_value= wild; 02219 break; 02220 case SQLCOM_SHOW_TABLES: 02221 case SQLCOM_SHOW_TABLE_STATUS: 02222 case SQLCOM_SHOW_TRIGGERS: 02223 case SQLCOM_SHOW_EVENTS: 02224 index_field_values->db_value= lex->select_lex.db; 02225 index_field_values->table_value= wild; 02226 break; 02227 default: 02228 index_field_values->db_value= NullS; 02229 index_field_values->table_value= NullS; 02230 break; 02231 } 02232 } 02233 02234 02235 int make_table_list(THD *thd, SELECT_LEX *sel, 02236 char *db, char *table) 02237 { 02238 Table_ident *table_ident; 02239 LEX_STRING ident_db, ident_table; 02240 ident_db.str= db; 02241 ident_db.length= strlen(db); 02242 ident_table.str= table; 02243 ident_table.length= strlen(table); 02244 table_ident= new Table_ident(thd, ident_db, ident_table, 1); 02245 sel->init_query(); 02246 if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ, 02247 (List<String> *) 0, (List<String> *) 0)) 02248 return 1; 02249 return 0; 02250 } 02251 02252 02253 bool uses_only_table_name_fields(Item *item, TABLE_LIST *table) 02254 { 02255 if (item->type() == Item::FUNC_ITEM) 02256 { 02257 Item_func *item_func= (Item_func*)item; 02258 Item **child; 02259 Item **item_end= (item_func->arguments()) + item_func->argument_count(); 02260 for (child= item_func->arguments(); child != item_end; child++) 02261 { 02262 if (!uses_only_table_name_fields(*child, table)) 02263 return 0; 02264 } 02265 } 02266 else if (item->type() == Item::FIELD_ITEM) 02267 { 02268 Item_field *item_field= (Item_field*)item; 02269 CHARSET_INFO *cs= system_charset_info; 02270 ST_SCHEMA_TABLE *schema_table= table->schema_table; 02271 ST_FIELD_INFO *field_info= schema_table->fields_info; 02272 const char *field_name1= schema_table->idx_field1 >= 0 ? field_info[schema_table->idx_field1].field_name : ""; 02273 const char *field_name2= schema_table->idx_field2 >= 0 ? field_info[schema_table->idx_field2].field_name : ""; 02274 if (table->table != item_field->field->table || 02275 (cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1), 02276 (uchar *) item_field->field_name, 02277 strlen(item_field->field_name), 0) && 02278 cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2), 02279 (uchar *) item_field->field_name, 02280 strlen(item_field->field_name), 0))) 02281 return 0; 02282 } 02283 else if (item->type() == Item::REF_ITEM) 02284 return uses_only_table_name_fields(item->real_item(), table); 02285 if (item->type() == Item::SUBSELECT_ITEM && 02286 !item->const_item()) 02287 return 0; 02288 02289 return 1; 02290 } 02291 02292 02293 static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table) 02294 { 02295 if (!cond) 02296 return (COND*) 0; 02297 if (cond->type() == Item::COND_ITEM) 02298 { 02299 if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) 02300 { 02301 /* Create new top level AND item */ 02302 Item_cond_and *new_cond=new Item_cond_and; 02303 if (!new_cond) 02304 return (COND*) 0; 02305 List_iterator<Item> li(*((Item_cond*) cond)->argument_list()); 02306 Item *item; 02307 while ((item=li++)) 02308 { 02309 Item *fix= make_cond_for_info_schema(item, table); 02310 if (fix) 02311 new_cond->argument_list()->push_back(fix); 02312 } 02313 switch (new_cond->argument_list()->elements) { 02314 case 0: 02315 return (COND*) 0; 02316 case 1: 02317 return new_cond->argument_list()->head(); 02318 default: 02319 new_cond->quick_fix_field(); 02320 return new_cond; 02321 } 02322 } 02323 else 02324 { // Or list 02325 Item_cond_or *new_cond=new Item_cond_or; 02326 if (!new_cond) 02327 return (COND*) 0; 02328 List_iterator<Item> li(*((Item_cond*) cond)->argument_list()); 02329 Item *item; 02330 while ((item=li++)) 02331 { 02332 Item *fix=make_cond_for_info_schema(item, table); 02333 if (!fix) 02334 return (COND*) 0; 02335 new_cond->argument_list()->push_back(fix); 02336 } 02337 new_cond->quick_fix_field(); 02338 new_cond->top_level_item(); 02339 return new_cond; 02340 } 02341 } 02342 02343 if (!uses_only_table_name_fields(cond, table)) 02344 return (COND*) 0; 02345 return cond; 02346 } 02347 02348 02349 enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table) 02350 { 02351 return (enum enum_schema_tables) (schema_table - &schema_tables[0]); 02352 } 02353 02354 02355 /* 02356 Create db names list. Information schema name always is first in list 02357 02358 SYNOPSIS 02359 make_db_list() 02360 thd thread handler 02361 files list of db names 02362 wild wild string 02363 idx_field_vals idx_field_vals->db_name contains db name or 02364 wild string 02365 with_i_schema returns 1 if we added 'IS' name to list 02366 otherwise returns 0 02367 is_wild_value if value is 1 then idx_field_vals->db_name is 02368 wild string otherwise it's db name; 02369 02370 RETURN 02371 zero success 02372 non-zero error 02373 */ 02374 02375 int make_db_list(THD *thd, List<char> *files, 02376 INDEX_FIELD_VALUES *idx_field_vals, 02377 bool *with_i_schema, bool is_wild_value) 02378 { 02379 LEX *lex= thd->lex; 02380 *with_i_schema= 0; 02381 get_index_field_values(lex, idx_field_vals); 02382 if (is_wild_value) 02383 { 02384 /* 02385 This part of code is only for SHOW DATABASES command. 02386 idx_field_vals->db_value can be 0 when we don't use 02387 LIKE clause (see also get_index_field_values() function) 02388 */ 02389 if (!idx_field_vals->db_value || 02390 !wild_case_compare(system_charset_info, 02391 information_schema_name.str, 02392 idx_field_vals->db_value)) 02393 { 02394 *with_i_schema= 1; 02395 if (files->push_back(thd->strdup(information_schema_name.str))) 02396 return 1; 02397 } 02398 return (find_files(thd, files, NullS, mysql_data_home, 02399 idx_field_vals->db_value, 1) != FIND_FILES_OK); 02400 } 02401 02402 /* 02403 This part of code is for SHOW TABLES, SHOW TABLE STATUS commands. 02404 idx_field_vals->db_value can't be 0 (see get_index_field_values() 02405 function). 02406 */ 02407 if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) 02408 { 02409 if (!my_strcasecmp(system_charset_info, information_schema_name.str, 02410 idx_field_vals->db_value)) 02411 { 02412 *with_i_schema= 1; 02413 return files->push_back(thd->strdup(information_schema_name.str)); 02414 } 02415 return files->push_back(thd->strdup(idx_field_vals->db_value)); 02416 } 02417 02418 /* 02419 Create list of existing databases. It is used in case 02420 of select from information schema table 02421 */ 02422 if (files->push_back(thd->strdup(information_schema_name.str))) 02423 return 1; 02424 *with_i_schema= 1; 02425 return (find_files(thd, files, NullS, 02426 mysql_data_home, NullS, 1) != FIND_FILES_OK); 02427 } 02428 02429 02430 int schema_tables_add(THD *thd, List<char> *files, const char *wild) 02431 { 02432 ST_SCHEMA_TABLE *tmp_schema_table= schema_tables; 02433 for (; tmp_schema_table->table_name; tmp_schema_table++) 02434 { 02435 if (tmp_schema_table->hidden) 02436 continue; 02437 if (wild) 02438 { 02439 if (lower_case_table_names) 02440 { 02441 if (wild_case_compare(files_charset_info, 02442 tmp_schema_table->table_name, 02443 wild)) 02444 continue; 02445 } 02446 else if (wild_compare(tmp_schema_table->table_name, wild, 0)) 02447 continue; 02448 } 02449 if (files->push_back(thd->strdup(tmp_schema_table->table_name))) 02450 return 1; 02451 } 02452 return 0; 02453 } 02454 02455 02456 int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) 02457 { 02458 LEX *lex= thd->lex; 02459 TABLE *table= tables->table; 02460 SELECT_LEX *select_lex= &lex->select_lex; 02461 SELECT_LEX *old_all_select_lex= lex->all_selects_list; 02462 enum_sql_command save_sql_command= lex->sql_command; 02463 SELECT_LEX *lsel= tables->schema_select_lex; 02464 ST_SCHEMA_TABLE *schema_table= tables->schema_table; 02465 SELECT_LEX sel; 02466 INDEX_FIELD_VALUES idx_field_vals; 02467 char path[FN_REFLEN], *end, *base_name, *orig_base_name, *file_name; 02468 uint len; 02469 bool with_i_schema; 02470 enum enum_schema_tables schema_table_idx; 02471 List<char> bases; 02472 List_iterator_fast<char> it(bases); 02473 COND *partial_cond; 02474 Security_context *sctx= thd->security_ctx; 02475 uint derived_tables= lex->derived_tables; 02476 int error= 1; 02477 enum legacy_db_type not_used; 02478 Open_tables_state open_tables_state_backup; 02479 bool save_view_prepare_mode= lex->view_prepare_mode; 02480 Query_tables_list query_tables_list_backup; 02481 lex->view_prepare_mode= TRUE; 02482 DBUG_ENTER("get_all_tables"); 02483 02484 LINT_INIT(end); 02485 LINT_INIT(len); 02486 02487 lex->reset_n_backup_query_tables_list(&query_tables_list_backup); 02488 02489 /* 02490 We should not introduce deadlocks even if we already have some 02491 tables open and locked, since we won't lock tables which we will 02492 open and will ignore possible name-locks for these tables. 02493 */ 02494 thd->reset_n_backup_open_tables_state(&open_tables_state_backup); 02495 02496 if (lsel) 02497 { 02498 TABLE_LIST *show_table_list= (TABLE_LIST*) lsel->table_list.first; 02499 bool res; 02500 02501 lex->all_selects_list= lsel; 02502 /* 02503 Restore thd->temporary_tables to be able to process 02504 temporary tables(only for 'show index' & 'show columns'). 02505 This should be changed when processing of temporary tables for 02506 I_S tables will be done. 02507 */ 02508 thd->temporary_tables= open_tables_state_backup.temporary_tables; 02509 /* 02510 Let us set fake sql_command so views won't try to merge 02511 themselves into main statement. If we don't do this, 02512 SELECT * from information_schema.xxxx will cause problems. 02513 SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()' 02514 */ 02515 lex->sql_command= SQLCOM_SHOW_FIELDS; 02516 res= open_normal_and_derived_tables(thd, show_table_list, 02517 MYSQL_LOCK_IGNORE_FLUSH); 02518 lex->sql_command= save_sql_command; 02519 /* 02520 get_all_tables() returns 1 on failure and 0 on success thus 02521 return only these and not the result code of ::process_table() 02522 02523 We should use show_table_list->alias instead of 02524 show_table_list->table_name because table_name 02525 could be changed during opening of I_S tables. It's safe 02526 to use alias because alias contains original table name 02527 in this case(this part of code is used only for 02528 'show columns' & 'show statistics' commands). 02529 */ 02530 error= test(schema_table->process_table(thd, show_table_list, 02531 table, res, 02532 (show_table_list->view ? 02533 show_table_list->view_db.str : 02534 show_table_list->db), 02535 show_table_list->alias)); 02536 thd->temporary_tables= 0; 02537 close_tables_for_reopen(thd, &show_table_list); 02538 goto err; 02539 } 02540 02541 schema_table_idx= get_schema_table_idx(schema_table); 02542 02543 if (make_db_list(thd, &bases, &idx_field_vals, 02544 &with_i_schema, 0)) 02545 goto err; 02546 02547 partial_cond= make_cond_for_info_schema(cond, tables); 02548 it.rewind(); /* To get access to new elements in basis list */ 02549 02550 /* 02551 Below we generate error for non existing database. 02552 (to save old behaviour for SHOW TABLES FROM db) 02553 */ 02554 while ((orig_base_name= base_name= it++) || 02555 ((sql_command_flags[save_sql_command] & CF_SHOW_TABLE_COMMAND) && 02556 (base_name= select_lex->db) && !bases.elements)) 02557 { 02558 #ifndef NO_EMBEDDED_ACCESS_CHECKS 02559 if (!check_access(thd,SELECT_ACL, base_name, 02560 &thd->col_access, 0, 1, with_i_schema) || 02561 sctx->master_access & (DB_ACLS | SHOW_DB_ACL) || 02562 acl_get(sctx->host, sctx->ip, sctx->priv_user, base_name,0) || 02563 (grant_option && !check_grant_db(thd, base_name))) 02564 #endif 02565 { 02566 List<char> files; 02567 if (with_i_schema) // information schema table names 02568 { 02569 if (schema_tables_add(thd, &files, idx_field_vals.table_value)) 02570 goto err; 02571 } 02572 else 02573 { 02574 len= build_table_filename(path, sizeof(path), base_name, "", "", 0); 02575 end= path + len; 02576 len= FN_LEN - len; 02577 find_files_result res= find_files(thd, &files, base_name, 02578 path, idx_field_vals.table_value, 0); 02579 if (res != FIND_FILES_OK) 02580 { 02581 /* 02582 Downgrade errors about problems with database directory to 02583 warnings if this is not a 'SHOW' command. Another thread 02584 may have dropped database, and we may still have a name 02585 for that directory. 02586 */ 02587 if (res == FIND_FILES_DIR && lex->sql_command == SQLCOM_END) 02588 { 02589 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 02590 thd->net.last_errno, thd->net.last_error); 02591 thd->clear_error(); 02592 continue; 02593 } 02594 else 02595 { 02596 goto err; 02597 } 02598 } 02599 if (lower_case_table_names) 02600 orig_base_name= thd->strdup(base_name); 02601 } 02602 02603 List_iterator_fast<char> it_files(files); 02604 while ((file_name= it_files++)) 02605 { 02606 restore_record(table, s->default_values); 02607 table->field[schema_table->idx_field1]-> 02608 store(base_name, strlen(base_name), system_charset_info); 02609 table->field[schema_table->idx_field2]-> 02610 store(file_name, strlen(file_name),system_charset_info); 02611 if (!partial_cond || partial_cond->val_int()) 02612 { 02613 if (schema_table_idx == SCH_TABLE_NAMES) 02614 { 02615 if (lex->verbose || 02616 (sql_command_flags[save_sql_command] & CF_STATUS_COMMAND) == 0) 02617 { 02618 if (with_i_schema) 02619 { 02620 table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), 02621 system_charset_info); 02622 } 02623 else 02624 { 02625 my_snprintf(end, len, "/%s%s", file_name, reg_ext); 02626 switch (mysql_frm_type(thd, path, ¬_used)) { 02627 case FRMTYPE_ERROR: 02628 table->field[3]->store(STRING_WITH_LEN("ERROR"), 02629 system_charset_info); 02630 break; 02631 case FRMTYPE_TABLE: 02632 table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), 02633 system_charset_info); 02634 break; 02635 case FRMTYPE_VIEW: 02636 table->field[3]->store(STRING_WITH_LEN("VIEW"), 02637 system_charset_info); 02638 break; 02639 default: 02640 DBUG_ASSERT(0); 02641 } 02642 } 02643 } 02644 if (schema_table_store_record(thd, table)) 02645 goto err; 02646 } 02647 else 02648 { 02649 int res; 02650 /* 02651 Set the parent lex of 'sel' because it is needed by 02652 sel.init_query() which is called inside make_table_list. 02653 */ 02654 sel.parent_lex= lex; 02655 if (make_table_list(thd, &sel, base_name, file_name)) 02656 goto err; 02657 TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first; 02658 lex->all_selects_list= &sel; 02659 lex->derived_tables= 0; 02660 lex->sql_command= SQLCOM_SHOW_FIELDS; 02661 res= open_normal_and_derived_tables(thd, show_table_list, 02662 MYSQL_LOCK_IGNORE_FLUSH); 02663 lex->sql_command= save_sql_command; 02664 /* 02665 We should use show_table_list->alias instead of 02666 show_table_list->table_name because table_name 02667 could be changed during opening of I_S tables. It's safe 02668 to use alias because alias contains original table name 02669 in this case. 02670 */ 02671 res= schema_table->process_table(thd, show_table_list, table, 02672 res, orig_base_name, 02673 show_table_list->alias); 02674 close_tables_for_reopen(thd, &show_table_list); 02675 DBUG_ASSERT(!lex->query_tables_own_last); 02676 if (res) 02677 goto err; 02678 } 02679 } 02680 } 02681 /* 02682 If we have information schema its always the first table and only 02683 the first table. Reset for other tables. 02684 */ 02685 with_i_schema= 0; 02686 } 02687 } 02688 02689 error= 0; 02690 err: 02691 thd->restore_backup_open_tables_state(&open_tables_state_backup); 02692 lex->restore_backup_query_tables_list(&query_tables_list_backup); 02693 lex->derived_tables= derived_tables; 02694 lex->all_selects_list= old_all_select_lex; 02695 lex->view_prepare_mode= save_view_prepare_mode; 02696 lex->sql_command= save_sql_command; 02697 DBUG_RETURN(error); 02698 } 02699 02700 02701 bool store_schema_shemata(THD* thd, TABLE *table, const char *db_name, 02702 CHARSET_INFO *cs) 02703 { 02704 restore_record(table, s->default_values); 02705 table->field[1]->store(db_name, strlen(db_name), system_charset_info); 02706 table->field[2]->store(cs->csname, strlen(cs->csname), system_charset_info); 02707 table->field[3]->store(cs->name, strlen(cs->name), system_charset_info); 02708 return schema_table_store_record(thd, table); 02709 } 02710 02711 02712 int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond) 02713 { 02714 /* 02715 TODO: fill_schema_shemata() is called when new client is connected. 02716 Returning error status in this case leads to client hangup. 02717 */ 02718 02719 INDEX_FIELD_VALUES idx_field_vals; 02720 List<char> files; 02721 char *file_name; 02722 uint length; 02723 bool with_i_schema; 02724 HA_CREATE_INFO create; 02725 TABLE *table= tables->table; 02726 Security_context *sctx= thd->security_ctx; 02727 DBUG_ENTER("fill_schema_shemata"); 02728 02729 if (make_db_list(thd, &files, &idx_field_vals, 02730 &with_i_schema, 1)) 02731 DBUG_RETURN(1); 02732 02733 List_iterator_fast<char> it(files); 02734 while ((file_name=it++)) 02735 { 02736 if (with_i_schema) // information schema name is always first in list 02737 { 02738 if (store_schema_shemata(thd, table, file_name, 02739 system_charset_info)) 02740 DBUG_RETURN(1); 02741 with_i_schema= 0; 02742 continue; 02743 } 02744 #ifndef NO_EMBEDDED_ACCESS_CHECKS 02745 if (sctx->master_access & (DB_ACLS | SHOW_DB_ACL) || 02746 acl_get(sctx->host, sctx->ip, sctx->priv_user, file_name,0) || 02747 (grant_option && !check_grant_db(thd, file_name))) 02748 #endif 02749 { 02750 load_db_opt_by_name(thd, file_name, &create); 02751 02752 if (store_schema_shemata(thd, table, file_name, 02753 create.default_table_charset)) 02754 DBUG_RETURN(1); 02755 } 02756 } 02757 DBUG_RETURN(0); 02758 } 02759 02760 02761 static int get_schema_tables_record(THD *thd, struct st_table_list *tables, 02762 TABLE *table, bool res, 02763 const char *base_name, 02764 const char *file_name) 02765 { 02766 const char *tmp_buff; 02767 TIME time; 02768 CHARSET_INFO *cs= system_charset_info; 02769 DBUG_ENTER("get_schema_tables_record"); 02770 02771 restore_record(table, s->default_values); 02772 table->field[1]->store(base_name, strlen(base_name), cs); 02773 table->field[2]->store(file_name, strlen(file_name), cs); 02774 if (res) 02775 { 02776 /* 02777 there was errors during opening tables 02778 */ 02779 const char *error= thd->net.last_error; 02780 if (tables->view) 02781 table->field[3]->store(STRING_WITH_LEN("VIEW"), cs); 02782 else if (tables->schema_table) 02783 table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs); 02784 else 02785 table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs); 02786 table->field[20]->store(error, strlen(error), cs); 02787 thd->clear_error(); 02788 } 02789 else if (tables->view) 02790 { 02791 table->field[3]->store(STRING_WITH_LEN("VIEW"), cs); 02792 table->field[20]->store(STRING_WITH_LEN("VIEW"), cs); 02793 } 02794 else 02795 { 02796 TABLE *show_table= tables->table; 02797 TABLE_SHARE *share= show_table->s; 02798 handler *file= show_table->file; 02799 02800 file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_AUTO | 02801 HA_STATUS_NO_LOCK); 02802 if (share->tmp_table == SYSTEM_TMP_TABLE) 02803 table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs); 02804 else if (share->tmp_table) 02805 table->field[3]->store(STRING_WITH_LEN("LOCAL TEMPORARY"), cs); 02806 else 02807 table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs); 02808 02809 for (int i= 4; i < 20; i++) 02810 { 02811 if (i == 7 || (i > 12 && i < 17) || i == 18) 02812 continue; 02813 table->field[i]->set_notnull(); 02814 } 02815 tmp_buff= file->table_type(); 02816 table->field[4]->store(tmp_buff, strlen(tmp_buff), cs); 02817 table->field[5]->store((longlong) share->frm_version, TRUE); 02818 enum row_type row_type = file->get_row_type(); 02819 switch (row_type) { 02820 case ROW_TYPE_NOT_USED: 02821 case ROW_TYPE_DEFAULT: 02822 tmp_buff= ((share->db_options_in_use & 02823 HA_OPTION_COMPRESS_RECORD) ? "Compressed" : 02824 (share->db_options_in_use & HA_OPTION_PACK_RECORD) ? 02825 "Dynamic" : "Fixed"); 02826 break; 02827 case ROW_TYPE_FIXED: 02828 tmp_buff= "Fixed"; 02829 break; 02830 case ROW_TYPE_DYNAMIC: 02831 tmp_buff= "Dynamic"; 02832 break; 02833 case ROW_TYPE_COMPRESSED: 02834 tmp_buff= "Compressed"; 02835 break; 02836 case ROW_TYPE_REDUNDANT: 02837 tmp_buff= "Redundant"; 02838 break; 02839 case ROW_TYPE_COMPACT: 02840 tmp_buff= "Compact"; 02841 break; 02842 case ROW_TYPE_PAGES: 02843 tmp_buff= "Paged"; 02844 break; 02845 } 02846 table->field[6]->store(tmp_buff, strlen(tmp_buff), cs); 02847 if (!tables->schema_table) 02848 { 02849 table->field[7]->store((longlong) file->stats.records, TRUE); 02850 table->field[7]->set_notnull(); 02851 } 02852 table->field[8]->store((longlong) file->stats.mean_rec_length, TRUE); 02853 table->field[9]->store((longlong) file->stats.data_file_length, TRUE); 02854 if (file->stats.max_data_file_length) 02855 { 02856 table->field[10]->store((longlong) file->stats.max_data_file_length, 02857 TRUE); 02858 } 02859 table->field[11]->store((longlong) file->stats.index_file_length, TRUE); 02860 table->field[12]->store((longlong) file->stats.delete_length, TRUE); 02861 if (show_table->found_next_number_field) 02862 { 02863 table->field[13]->store((longlong) file->stats.auto_increment_value, 02864 TRUE); 02865 table->field[13]->set_notnull(); 02866 } 02867 if (file->stats.create_time) 02868 { 02869 thd->variables.time_zone->gmt_sec_to_TIME(&time, 02870 file->stats.create_time); 02871 table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); 02872 table->field[14]->set_notnull(); 02873 } 02874 if (file->stats.update_time) 02875 { 02876 thd->variables.time_zone->gmt_sec_to_TIME(&time, 02877 file->stats.update_time); 02878 table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); 02879 table->field[15]->set_notnull(); 02880 } 02881 if (file->stats.check_time) 02882 { 02883 thd->variables.time_zone->gmt_sec_to_TIME(&time, file->stats.check_time); 02884 table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); 02885 table->field[16]->set_notnull(); 02886 } 02887 tmp_buff= (share->table_charset ? 02888 share->table_charset->name : "default"); 02889 table->field[17]->store(tmp_buff, strlen(tmp_buff), cs); 02890 if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM) 02891 { 02892 table->field[18]->store((longlong) file->checksum(), TRUE); 02893 table->field[18]->set_notnull(); 02894 } 02895 02896 char option_buff[350],*ptr; 02897 ptr=option_buff; 02898 if (share->min_rows) 02899 { 02900 ptr=strmov(ptr," min_rows="); 02901 ptr=longlong10_to_str(share->min_rows,ptr,10); 02902 } 02903 if (share->max_rows) 02904 { 02905 ptr=strmov(ptr," max_rows="); 02906 ptr=longlong10_to_str(share->max_rows,ptr,10); 02907 } 02908 if (share->avg_row_length) 02909 { 02910 ptr=strmov(ptr," avg_row_length="); 02911 ptr=longlong10_to_str(share->avg_row_length,ptr,10); 02912 } 02913 if (share->db_create_options & HA_OPTION_PACK_KEYS) 02914 ptr=strmov(ptr," pack_keys=1"); 02915 if (share->db_create_options & HA_OPTION_NO_PACK_KEYS) 02916 ptr=strmov(ptr," pack_keys=0"); 02917 if (share->db_create_options & HA_OPTION_CHECKSUM) 02918 ptr=strmov(ptr," checksum=1"); 02919 if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE) 02920 ptr=strmov(ptr," delay_key_write=1"); 02921 if (share->row_type != ROW_TYPE_DEFAULT) 02922 ptr=strxmov(ptr, " row_format=", 02923 ha_row_type[(uint) share->row_type], 02924 NullS); 02925 #ifdef WITH_PARTITION_STORAGE_ENGINE 02926 if (show_table->s->db_type == &partition_hton && 02927 show_table->part_info != NULL && 02928 show_table->part_info->no_parts > 0) 02929 ptr= strmov(ptr, " partitioned"); 02930 #endif 02931 table->field[19]->store(option_buff+1, 02932 (ptr == option_buff ? 0 : 02933 (uint) (ptr-option_buff)-1), cs); 02934 { 02935 char *comment; 02936 comment= show_table->file->update_table_comment(share->comment.str); 02937 if (comment) 02938 { 02939 table->field[20]->store(comment, 02940 (comment == share->comment.str ? 02941 share->comment.length : 02942 strlen(comment)), cs); 02943 if (comment != share->comment.str) 02944 my_free(comment, MYF(0)); 02945 } 02946 } 02947 } 02948 DBUG_RETURN(schema_table_store_record(thd, table)); 02949 } 02950 02951 02952 static int get_schema_column_record(THD *thd, struct st_table_list *tables, 02953 TABLE *table, bool res, 02954 const char *base_name, 02955 const char *file_name) 02956 { 02957 LEX *lex= thd->lex; 02958 const char *wild= lex->wild ? lex->wild->ptr() : NullS; 02959 CHARSET_INFO *cs= system_charset_info; 02960 TABLE *show_table; 02961 handler *file; 02962 Field **ptr,*field; 02963 int count; 02964 uint base_name_length, file_name_length; 02965 DBUG_ENTER("get_schema_column_record"); 02966 02967 if (res) 02968 { 02969 if (lex->sql_command != SQLCOM_SHOW_FIELDS) 02970 { 02971 /* 02972 I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS 02973 rather than in SHOW COLUMNS 02974 */ 02975 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 02976 thd->net.last_errno, thd->net.last_error); 02977 thd->clear_error(); 02978 res= 0; 02979 } 02980 DBUG_RETURN(res); 02981 } 02982 02983 show_table= tables->table; 02984 file= show_table->file; 02985 count= 0; 02986 file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); 02987 restore_record(show_table, s->default_values); 02988 base_name_length= strlen(base_name); 02989 file_name_length= strlen(file_name); 02990 show_table->use_all_columns(); // Required for default 02991 02992 for (ptr=show_table->field; (field= *ptr) ; ptr++) 02993 { 02994 const char *tmp_buff; 02995 byte *pos; 02996 bool is_blob; 02997 uint flags=field->flags; 02998 char tmp[MAX_FIELD_WIDTH]; 02999 char tmp1[MAX_FIELD_WIDTH]; 03000 String type(tmp,sizeof(tmp), system_charset_info); 03001 char *end; 03002 int decimals, field_length; 03003 03004 if (wild && wild[0] && 03005 wild_case_compare(system_charset_info, field->field_name,wild)) 03006 continue; 03007 03008 flags= field->flags; 03009 count++; 03010 /* Get default row, with all NULL fields set to NULL */ 03011 restore_record(table, s->default_values); 03012 03013 #ifndef NO_EMBEDDED_ACCESS_CHECKS 03014 uint col_access; 03015 check_access(thd,SELECT_ACL | EXTRA_ACL, base_name, 03016 &tables->grant.privilege, 0, 0, test(tables->schema_table)); 03017 col_access= get_column_grant(thd, &tables->grant, 03018 base_name, file_name, 03019 field->field_name) & COL_ACLS; 03020 if (lex->sql_command != SQLCOM_SHOW_FIELDS && 03021 !tables->schema_table && !col_access) 03022 continue; 03023 end= tmp; 03024 for (uint bitnr=0; col_access ; col_access>>=1,bitnr++) 03025 { 03026 if (col_access & 1) 03027 { 03028 *end++=','; 03029 end=strmov(end,grant_types.type_names[bitnr]); 03030 } 03031 } 03032 table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs); 03033 03034 #endif 03035 table->field[1]->store(base_name, base_name_length, cs); 03036 table->field[2]->store(file_name, file_name_length, cs); 03037 table->field[3]->store(field->field_name, strlen(field->field_name), 03038 cs); 03039 table->field[4]->store((longlong) count, TRUE); 03040 field->sql_type(type); 03041 table->field[14]->store(type.ptr(), type.length(), cs); 03042 tmp_buff= strchr(type.ptr(), '('); 03043 table->field[7]->store(type.ptr(), 03044 (tmp_buff ? tmp_buff - type.ptr() : 03045 type.length()), cs); 03046 if (show_table->timestamp_field == field && 03047 field->unireg_check != Field::TIMESTAMP_UN_FIELD) 03048 { 03049 table->field[5]->store(STRING_WITH_LEN("CURRENT_TIMESTAMP"), cs); 03050 table->field[5]->set_notnull(); 03051 } 03052 else if (field->unireg_check != Field::NEXT_NUMBER && 03053 !field->is_null() && 03054 !(field->flags & NO_DEFAULT_VALUE_FLAG)) 03055 { 03056 String def(tmp1,sizeof(tmp1), cs); 03057 type.set(tmp, sizeof(tmp), field->charset()); 03058 field->val_str(&type); 03059 uint dummy_errors; 03060 def.copy(type.ptr(), type.length(), type.charset(), cs, &dummy_errors); 03061 table->field[5]->store(def.ptr(), def.length(), def.charset()); 03062 table->field[5]->set_notnull(); 03063 } 03064 else if (field->unireg_check == Field::NEXT_NUMBER || 03065 lex->sql_command != SQLCOM_SHOW_FIELDS || 03066 field->maybe_null()) 03067 table->field[5]->set_null(); // Null as default 03068 else 03069 { 03070 table->field[5]->store("",0, cs); 03071 table->field[5]->set_notnull(); 03072 } 03073 pos=(byte*) ((flags & NOT_NULL_FLAG) ? "NO" : "YES"); 03074 table->field[6]->store((const char*) pos, 03075 strlen((const char*) pos), cs); 03076 is_blob= (field->type() == FIELD_TYPE_BLOB); 03077 if (field->has_charset() || is_blob || 03078 field->real_type() == MYSQL_TYPE_VARCHAR || // For varbinary type 03079 field->real_type() == MYSQL_TYPE_STRING) // For binary type 03080 { 03081 uint32 octet_max_length= field->max_length(); 03082 if (is_blob && octet_max_length != (uint32) 4294967295U) 03083 octet_max_length /= field->charset()->mbmaxlen; 03084 longlong char_max_len= is_blob ? 03085 (longlong) octet_max_length / field->charset()->mbminlen : 03086 (longlong) octet_max_length / field->charset()->mbmaxlen; 03087 table->field[8]->store(char_max_len, TRUE); 03088 table->field[8]->set_notnull(); 03089 table->field[9]->store((longlong) octet_max_length, TRUE); 03090 table->field[9]->set_notnull(); 03091 } 03092 03093 /* 03094 Calculate field_length and decimals. 03095 They are set to -1 if they should not be set (we should return NULL) 03096 */ 03097 03098 decimals= field->decimals(); 03099 switch (field->type()) { 03100 case FIELD_TYPE_NEWDECIMAL: 03101 field_length= ((Field_new_decimal*) field)->precision; 03102 break; 03103 case FIELD_TYPE_DECIMAL: 03104 field_length= field->field_length - (decimals ? 2 : 1); 03105 break; 03106 case FIELD_TYPE_TINY: 03107 case FIELD_TYPE_SHORT: 03108 case FIELD_TYPE_LONG: 03109 case FIELD_TYPE_LONGLONG: 03110 case FIELD_TYPE_INT24: 03111 field_length= field->max_length() - 1; 03112 break; 03113 case FIELD_TYPE_BIT: 03114 field_length= field->max_length(); 03115 decimals= -1; // return NULL 03116 break; 03117 case FIELD_TYPE_FLOAT: 03118 case FIELD_TYPE_DOUBLE: 03119 field_length= field->field_length; 03120 if (decimals == NOT_FIXED_DEC) 03121 decimals= -1; // return NULL 03122 break; 03123 default: 03124 field_length= decimals= -1; 03125 break; 03126 } 03127 03128 if (field_length >= 0) 03129 { 03130 table->field[10]->store((longlong) field_length, TRUE); 03131 table->field[10]->set_notnull(); 03132 } 03133 if (decimals >= 0) 03134 { 03135 table->field[11]->store((longlong) decimals, TRUE); 03136 table->field[11]->set_notnull(); 03137 } 03138 03139 if (field->has_charset()) 03140 { 03141 pos=(byte*) field->charset()->csname; 03142 table->field[12]->store((const char*) pos, 03143 strlen((const char*) pos), cs); 03144 table->field[12]->set_notnull(); 03145 pos=(byte*) field->charset()->name; 03146 table->field[13]->store((const char*) pos, 03147 strlen((const char*) pos), cs); 03148 table->field[13]->set_notnull(); 03149 } 03150 pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" : 03151 (field->flags & UNIQUE_KEY_FLAG) ? "UNI" : 03152 (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":""); 03153 table->field[15]->store((const char*) pos, 03154 strlen((const char*) pos), cs); 03155 03156 end= tmp; 03157 if (field->unireg_check == Field::NEXT_NUMBER) 03158 end=strmov(tmp,"auto_increment"); 03159 table->field[16]->store(tmp, (uint) (end-tmp), cs); 03160 03161 table->field[18]->store(field->comment.str, field->comment.length, cs); 03162 if (schema_table_store_record(thd, table)) 03163 DBUG_RETURN(1); 03164 } 03165 DBUG_RETURN(0); 03166 } 03167 03168 03169 03170 int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond) 03171 { 03172 CHARSET_INFO **cs; 03173 const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; 03174 TABLE *table= tables->table; 03175 CHARSET_INFO *scs= system_charset_info; 03176 03177 for (cs= all_charsets ; cs < all_charsets+255 ; cs++) 03178 { 03179 CHARSET_INFO *tmp_cs= cs[0]; 03180 if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) && 03181 (tmp_cs->state & MY_CS_AVAILABLE) && 03182 !(tmp_cs->state & MY_CS_HIDDEN) && 03183 !(wild && wild[0] && 03184 wild_case_compare(scs, tmp_cs->csname,wild))) 03185 { 03186 const char *comment; 03187 restore_record(table, s->default_values); 03188 table->field[0]->store(tmp_cs->csname, strlen(tmp_cs->csname), scs); 03189 table->field[1]->store(tmp_cs->name, strlen(tmp_cs->name), scs); 03190 comment= tmp_cs->comment ? tmp_cs->comment : ""; 03191 table->field[2]->store(comment, strlen(comment), scs); 03192 table->field[3]->store((longlong) tmp_cs->mbmaxlen, TRUE); 03193 if (schema_table_store_record(thd, table)) 03194 return 1; 03195 } 03196 } 03197 return 0; 03198 } 03199 03200 03201 static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin, 03202 void *ptable) 03203 { 03204 TABLE *table= (TABLE *) ptable; 03205 handlerton *hton= (handlerton *)plugin->data; 03206 const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; 03207 CHARSET_INFO *scs= system_charset_info; 03208 DBUG_ENTER("iter_schema_engines"); 03209 03210 if (!(hton->flags & HTON_HIDDEN)) 03211 { 03212 if (!(wild && wild[0] && 03213 wild_case_compare(scs, plugin->name.str,wild))) 03214 { 03215 LEX_STRING state[2]= {{ C_STRING_WITH_LEN("ENABLED") }, 03216 { C_STRING_WITH_LEN("DISABLED") }}; 03217 LEX_STRING yesno[2]= {{ C_STRING_WITH_LEN("NO") }, 03218 { C_STRING_WITH_LEN("YES") }}; 03219 LEX_STRING *tmp; 03220 restore_record(table, s->default_values); 03221 03222 table->field[0]->store(plugin->name.str, plugin->name.length, scs); 03223 tmp= &state[test(hton->state)]; 03224 table->field[1]->store(tmp->str, tmp->length, scs); 03225 table->field[2]->store(plugin->plugin->descr, 03226 strlen(plugin->plugin->descr), scs); 03227 tmp= &yesno[test(hton->commit)]; 03228 table->field[3]->store(tmp->str, tmp->length, scs); 03229 tmp= &yesno[test(hton->prepare)]; 03230 table->field[4]->store(tmp->str, tmp->length, scs); 03231 tmp= &yesno[test(hton->savepoint_set)]; 03232 table->field[5]->store(tmp->str, tmp->length, scs); 03233 03234 if (schema_table_store_record(thd, table)) 03235 DBUG_RETURN(1); 03236 } 03237 } 03238 DBUG_RETURN(0); 03239 } 03240 03241 03242 int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond) 03243 { 03244 return plugin_foreach(thd, iter_schema_engines, 03245 MYSQL_STORAGE_ENGINE_PLUGIN, tables->table); 03246 } 03247 03248 03249 int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond) 03250 { 03251 CHARSET_INFO **cs; 03252 const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; 03253 TABLE *table= tables->table; 03254 CHARSET_INFO *scs= system_charset_info; 03255 for (cs= all_charsets ; cs < all_charsets+255 ; cs++ ) 03256 { 03257 CHARSET_INFO **cl; 03258 CHARSET_INFO *tmp_cs= cs[0]; 03259 if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || 03260 (tmp_cs->state & MY_CS_HIDDEN) || 03261 !(tmp_cs->state & MY_CS_PRIMARY)) 03262 continue; 03263 for (cl= all_charsets; cl < all_charsets+255 ;cl ++) 03264 { 03265 CHARSET_INFO *tmp_cl= cl[0]; 03266 if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || 03267 !my_charset_same(tmp_cs, tmp_cl)) 03268 continue; 03269 if (!(wild && wild[0] && 03270 wild_case_compare(scs, tmp_cl->name,wild))) 03271 { 03272 const char *tmp_buff; 03273 restore_record(table, s->default_values); 03274 table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs); 03275 table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs); 03276 table->field[2]->store((longlong) tmp_cl->number, TRUE); 03277 tmp_buff= (tmp_cl->state & MY_CS_PRIMARY) ? "Yes" : ""; 03278 table->field[3]->store(tmp_buff, strlen(tmp_buff), scs); 03279 tmp_buff= (tmp_cl->state & MY_CS_COMPILED)? "Yes" : ""; 03280 table->field[4]->store(tmp_buff, strlen(tmp_buff), scs); 03281 table->field[5]->store((longlong) tmp_cl->strxfrm_multiply, TRUE); 03282 if (schema_table_store_record(thd, table)) 03283 return 1; 03284 } 03285 } 03286 } 03287 return 0; 03288 } 03289 03290 03291 int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond) 03292 { 03293 CHARSET_INFO **cs; 03294 TABLE *table= tables->table; 03295 CHARSET_INFO *scs= system_charset_info; 03296 for (cs= all_charsets ; cs < all_charsets+255 ; cs++ ) 03297 { 03298 CHARSET_INFO **cl; 03299 CHARSET_INFO *tmp_cs= cs[0]; 03300 if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || 03301 !(tmp_cs->state & MY_CS_PRIMARY)) 03302 continue; 03303 for (cl= all_charsets; cl < all_charsets+255 ;cl ++) 03304 { 03305 CHARSET_INFO *tmp_cl= cl[0]; 03306 if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || 03307 !my_charset_same(tmp_cs,tmp_cl)) 03308 continue; 03309 restore_record(table, s->default_values); 03310 table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs); 03311 table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs); 03312 if (schema_table_store_record(thd, table)) 03313 return 1; 03314 } 03315 } 03316 return 0; 03317 } 03318 03319 03320 bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, 03321 const char *wild, bool full_access, const char *sp_user) 03322 { 03323 String tmp_string; 03324 String sp_db, sp_name, definer; 03325 TIME time; 03326 LEX *lex= thd->lex; 03327 CHARSET_INFO *cs= system_charset_info; 03328 get_field(thd->mem_root, proc_table->field[0], &sp_db); 03329 get_field(thd->mem_root, proc_table->field[1], &sp_name); 03330 get_field(thd->mem_root, proc_table->field[11], &definer); 03331 if (!full_access) 03332 full_access= !strcmp(sp_user, definer.ptr()); 03333 if (!full_access && check_some_routine_access(thd, sp_db.ptr(), 03334 sp_name.ptr(), 03335 proc_table->field[2]-> 03336 val_int() == 03337 TYPE_ENUM_PROCEDURE)) 03338 return 0; 03339 03340 if (lex->sql_command == SQLCOM_SHOW_STATUS_PROC && 03341 proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE || 03342 lex->sql_command == SQLCOM_SHOW_STATUS_FUNC && 03343 proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION || 03344 (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0) 03345 { 03346 restore_record(table, s->default_values); 03347 if (!wild || !wild[0] || !wild_compare(sp_name.ptr(), wild, 0)) 03348 { 03349 int enum_idx= proc_table->field[5]->val_int(); 03350 table->field[3]->store(sp_name.ptr(), sp_name.length(), cs); 03351 get_field(thd->mem_root, proc_table->field[3], &tmp_string); 03352 table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs); 03353 table->field[2]->store(sp_db.ptr(), sp_db.length(), cs); 03354 get_field(thd->mem_root, proc_table->field[2], &tmp_string); 03355 table->field[4]->store(tmp_string.ptr(), tmp_string.length(), cs); 03356 if (proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION) 03357 { 03358 get_field(thd->mem_root, proc_table->field[9], &tmp_string); 03359 table->field[5]->store(tmp_string.ptr(), tmp_string.length(), cs); 03360 table->field[5]->set_notnull(); 03361 } 03362 if (full_access) 03363 { 03364 get_field(thd->mem_root, proc_table->field[10], &tmp_string); 03365 table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs); 03366 table->field[7]->set_notnull(); 03367 } 03368 table->field[6]->store(STRING_WITH_LEN("SQL"), cs); 03369 table->field[10]->store(STRING_WITH_LEN("SQL"), cs); 03370 get_field(thd->mem_root, proc_table->field[6], &tmp_string); 03371 table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs); 03372 table->field[12]->store(sp_data_access_name[enum_idx].str, 03373 sp_data_access_name[enum_idx].length , cs); 03374 get_field(thd->mem_root, proc_table->field[7], &tmp_string); 03375 table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs); 03376 bzero((char *)&time, sizeof(time)); 03377 ((Field_timestamp *) proc_table->field[12])->get_time(&time); 03378 table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); 03379 bzero((char *)&time, sizeof(time)); 03380 ((Field_timestamp *) proc_table->field[13])->get_time(&time); 03381 table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); 03382 get_field(thd->mem_root, proc_table->field[14], &tmp_string); 03383 table->field[17]->store(tmp_string.ptr(), tmp_string.length(), cs); 03384 get_field(thd->mem_root, proc_table->field[15], &tmp_string); 03385 table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs); 03386 table->field[19]->store(definer.ptr(), definer.length(), cs); 03387 return schema_table_store_record(thd, table); 03388 } 03389 } 03390 return 0; 03391 } 03392 03393 03394 int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) 03395 { 03396 TABLE *proc_table; 03397 TABLE_LIST proc_tables; 03398 const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; 03399 int res= 0; 03400 TABLE *table= tables->table; 03401 bool full_access; 03402 char definer[USER_HOST_BUFF_SIZE]; 03403 Open_tables_state open_tables_state_backup; 03404 DBUG_ENTER("fill_schema_proc"); 03405 03406 strxmov(definer, thd->security_ctx->priv_user, "@", 03407 thd->security_ctx->priv_host, NullS); 03408 /* We use this TABLE_LIST instance only for checking of privileges. */ 03409 bzero((char*) &proc_tables,sizeof(proc_tables)); 03410 proc_tables.db= (char*) "mysql"; 03411 proc_tables.db_length= 5; 03412 proc_tables.table_name= proc_tables.alias= (char*) "proc"; 03413 proc_tables.table_name_length= 4; 03414 proc_tables.lock_type= TL_READ; 03415 full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, 1); 03416 if (!(proc_table= open_proc_table_for_read(thd, &open_tables_state_backup))) 03417 { 03418 DBUG_RETURN(1); 03419 } 03420 proc_table->file->ha_index_init(0, 1); 03421 if ((res= proc_table->file->index_first(proc_table->record[0]))) 03422 { 03423 res= (res == HA_ERR_END_OF_FILE) ? 0 : 1; 03424 goto err; 03425 } 03426 if (store_schema_proc(thd, table, proc_table, wild, full_access, definer)) 03427 { 03428 res= 1; 03429 goto err; 03430 } 03431 while (!proc_table->file->index_next(proc_table->record[0])) 03432 { 03433 if (store_schema_proc(thd, table, proc_table, wild, full_access, definer)) 03434 { 03435 res= 1; 03436 goto err; 03437 } 03438 } 03439 03440 err: 03441 proc_table->file->ha_index_end(); 03442 close_proc_table(thd, &open_tables_state_backup); 03443 DBUG_RETURN(res); 03444 } 03445 03446 03447 static int get_schema_stat_record(THD *thd, struct st_table_list *tables, 03448 TABLE *table, bool res, 03449 const char *base_name, 03450 const char *file_name) 03451 { 03452 CHARSET_INFO *cs= system_charset_info; 03453 DBUG_ENTER("get_schema_stat_record"); 03454 if (res) 03455 { 03456 if (thd->lex->sql_command != SQLCOM_SHOW_KEYS) 03457 { 03458 /* 03459 I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS 03460 rather than in SHOW KEYS 03461 */ 03462 if (!tables->view) 03463 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 03464 thd->net.last_errno, thd->net.last_error); 03465 thd->clear_error(); 03466 res= 0; 03467 } 03468 DBUG_RETURN(res); 03469 } 03470 else if (!tables->view) 03471 { 03472 TABLE *show_table= tables->table; 03473 KEY *key_info=show_table->key_info; 03474 show_table->file->info(HA_STATUS_VARIABLE | 03475 HA_STATUS_NO_LOCK | 03476 HA_STATUS_TIME); 03477 for (uint i=0 ; i < show_table->s->keys ; i++,key_info++) 03478 { 03479 KEY_PART_INFO *key_part= key_info->key_part; 03480 const char *str; 03481 for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) 03482 { 03483 restore_record(table, s->default_values); 03484 table->field[1]->store(base_name, strlen(base_name), cs); 03485 table->field[2]->store(file_name, strlen(file_name), cs); 03486 table->field[3]->store((longlong) ((key_info->flags & 03487 HA_NOSAME) ? 0 : 1), TRUE); 03488 table->field[4]->store(base_name, strlen(base_name), cs); 03489 table->field[5]->store(key_info->name, strlen(key_info->name), cs); 03490 table->field[6]->store((longlong) (j+1), TRUE); 03491 str=(key_part->field ? key_part->field->field_name : 03492 "?unknown field?"); 03493 table->field[7]->store(str, strlen(str), cs); 03494 if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER) 03495 { 03496 table->field[8]->store(((key_part->key_part_flag & 03497 HA_REVERSE_SORT) ? 03498 "D" : "A"), 1, cs); 03499 table->field[8]->set_notnull(); 03500 } 03501 KEY *key=show_table->key_info+i; 03502 if (key->rec_per_key[j]) 03503 { 03504 ha_rows records=(show_table->file->stats.records / 03505 key->rec_per_key[j]); 03506 table->field[9]->store((longlong) records, TRUE); 03507 table->field[9]->set_notnull(); 03508 } 03509 if (!(key_info->flags & HA_FULLTEXT) && 03510 (key_part->field && 03511 key_part->length != 03512 show_table->field[key_part->fieldnr-1]->key_length())) 03513 { 03514 table->field[10]->store((longlong) key_part->length / 03515 key_part->field->charset()->mbmaxlen, TRUE); 03516 table->field[10]->set_notnull(); 03517 } 03518 uint flags= key_part->field ? key_part->field->flags : 0; 03519 const char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES"); 03520 table->field[12]->store(pos, strlen(pos), cs); 03521 pos= show_table->file->index_type(i); 03522 table->field[13]->store(pos, strlen(pos), cs); 03523 if (!show_table->s->keys_in_use.is_set(i)) 03524 table->field[14]->store(STRING_WITH_LEN("disabled"), cs); 03525 else 03526 table->field[14]->store("", 0, cs); 03527 table->field[14]->set_notnull(); 03528 if (schema_table_store_record(thd, table)) 03529 DBUG_RETURN(1); 03530 } 03531 } 03532 } 03533 DBUG_RETURN(res); 03534 } 03535 03536 03537 static int get_schema_views_record(THD *thd, struct st_table_list *tables, 03538 TABLE *table, bool res, 03539 const char *base_name, 03540 const char *file_name) 03541 { 03542 CHARSET_INFO *cs= system_charset_info; 03543 DBUG_ENTER("get_schema_views_record"); 03544 char definer[USER_HOST_BUFF_SIZE]; 03545 uint definer_len; 03546 03547 if (tables->view) 03548 { 03549 Security_context *sctx= thd->security_ctx; 03550 if (!tables->allowed_show) 03551 { 03552 if (!my_strcasecmp(system_charset_info, tables->definer.user.str, 03553 sctx->priv_user) && 03554 !my_strcasecmp(system_charset_info, tables->definer.host.str, 03555 sctx->priv_host)) 03556 tables->allowed_show= TRUE; 03557 } 03558 restore_record(table, s->default_values); 03559 table->field[1]->store(tables->view_db.str, tables->view_db.length, cs); 03560 table->field[2]->store(tables->view_name.str, tables->view_name.length, cs); 03561 if (tables->allowed_show) 03562 { 03563 char buff[2048]; 03564 String qwe_str(buff, sizeof(buff), cs); 03565 qwe_str.length(0); 03566 qwe_str.append(STRING_WITH_LEN("/* ")); 03567 append_algorithm(tables, &qwe_str); 03568 qwe_str.append(STRING_WITH_LEN("*/ ")); 03569 qwe_str.append(tables->query.str, tables->query.length); 03570 table->field[3]->store(qwe_str.ptr(), qwe_str.length(), cs); 03571 } 03572 03573 if (tables->with_check != VIEW_CHECK_NONE) 03574 { 03575 if (tables->with_check == VIEW_CHECK_LOCAL) 03576 table->field[4]->store(STRING_WITH_LEN("LOCAL"), cs); 03577 else 03578 table->field[4]->store(STRING_WITH_LEN("CASCADED"), cs); 03579 } 03580 else 03581 table->field[4]->store(STRING_WITH_LEN("NONE"), cs); 03582 03583 if (tables->updatable_view) 03584 table->field[5]->store(STRING_WITH_LEN("YES"), cs); 03585 else 03586 table->field[5]->store(STRING_WITH_LEN("NO"), cs); 03587 definer_len= (strxmov(definer, tables->definer.user.str, "@", 03588 tables->definer.host.str, NullS) - definer); 03589 table->field[6]->store(definer, definer_len, cs); 03590 if (tables->view_suid) 03591 table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs); 03592 else 03593 table->field[7]->store(STRING_WITH_LEN("INVOKER"), cs); 03594 if (schema_table_store_record(thd, table)) 03595 DBUG_RETURN(1); 03596 if (res) 03597 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 03598 thd->net.last_errno, thd->net.last_error); 03599 } 03600 if (res) 03601 thd->clear_error(); 03602 DBUG_RETURN(0); 03603 } 03604 03605 03606 bool store_constraints(THD *thd, TABLE *table, const char *db, 03607 const char *tname, const char *key_name, 03608 uint key_len, const char *con_type, uint con_len) 03609 { 03610 CHARSET_INFO *cs= system_charset_info; 03611 restore_record(table, s->default_values); 03612 table->field[1]->store(db, strlen(db), cs); 03613 table->field[2]->store(key_name, key_len, cs); 03614 table->field[3]->store(db, strlen(db), cs); 03615 table->field[4]->store(tname, strlen(tname), cs); 03616 table->field[5]->store(con_type, con_len, cs); 03617 return schema_table_store_record(thd, table); 03618 } 03619 03620 03621 static int get_schema_constraints_record(THD *thd, struct st_table_list *tables, 03622 TABLE *table, bool res, 03623 const char *base_name, 03624 const char *file_name) 03625 { 03626 DBUG_ENTER("get_schema_constraints_record"); 03627 if (res) 03628 { 03629 if (!tables->view) 03630 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 03631 thd->net.last_errno, thd->net.last_error); 03632 thd->clear_error(); 03633 DBUG_RETURN(0); 03634 } 03635 else if (!tables->view) 03636 { 03637 List<FOREIGN_KEY_INFO> f_key_list; 03638 TABLE *show_table= tables->table; 03639 KEY *key_info=show_table->key_info; 03640 uint primary_key= show_table->s->primary_key; 03641 show_table->file->info(HA_STATUS_VARIABLE | 03642 HA_STATUS_NO_LOCK | 03643 HA_STATUS_TIME); 03644 for (uint i=0 ; i < show_table->s->keys ; i++, key_info++) 03645 { 03646 if (i != primary_key && !(key_info->flags & HA_NOSAME)) 03647 continue; 03648 03649 if (i == primary_key && !strcmp(key_info->name, primary_key_name)) 03650 { 03651 if (store_constraints(thd, table, base_name, file_name, key_info->name, 03652 strlen(key_info->name), 03653 STRING_WITH_LEN("PRIMARY KEY"))) 03654 DBUG_RETURN(1); 03655 } 03656 else if (key_info->flags & HA_NOSAME) 03657 { 03658 if (store_constraints(thd, table, base_name, file_name, key_info->name, 03659 strlen(key_info->name), 03660 STRING_WITH_LEN("UNIQUE"))) 03661 DBUG_RETURN(1); 03662 } 03663 } 03664 03665 show_table->file->get_foreign_key_list(thd, &f_key_list); 03666 FOREIGN_KEY_INFO *f_key_info; 03667 List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list); 03668 while ((f_key_info=it++)) 03669 { 03670 if (store_constraints(thd, table, base_name, file_name, 03671 f_key_info->forein_id->str, 03672 strlen(f_key_info->forein_id->str), 03673 "FOREIGN KEY", 11)) 03674 DBUG_RETURN(1); 03675 } 03676 } 03677 DBUG_RETURN(res); 03678 } 03679 03680 03681 static bool store_trigger(THD *thd, TABLE *table, const char *db, 03682 const char *tname, LEX_STRING *trigger_name, 03683 enum trg_event_type event, 03684 enum trg_action_time_type timing, 03685 LEX_STRING *trigger_stmt, 03686 ulong sql_mode, 03687 LEX_STRING *definer_buffer) 03688 { 03689 CHARSET_INFO *cs= system_charset_info; 03690 byte *sql_mode_str; 03691 ulong sql_mode_len; 03692 03693 restore_record(table, s->default_values); 03694 table->field[1]->store(db, strlen(db), cs); 03695 table->field[2]->store(trigger_name->str, trigger_name->length, cs); 03696 table->field[3]->store(trg_event_type_names[event].str, 03697 trg_event_type_names[event].length, cs); 03698 table->field[5]->store(db, strlen(db), cs); 03699 table->field[6]->store(tname, strlen(tname), cs); 03700 table->field[9]->store(trigger_stmt->str, trigger_stmt->length, cs); 03701 table->field[10]->store(STRING_WITH_LEN("ROW"), cs); 03702 table->field[11]->store(trg_action_time_type_names[timing].str, 03703 trg_action_time_type_names[timing].length, cs); 03704 table->field[14]->store(STRING_WITH_LEN("OLD"), cs); 03705 table->field[15]->store(STRING_WITH_LEN("NEW"), cs); 03706 03707 sql_mode_str= 03708 sys_var_thd_sql_mode::symbolic_mode_representation(thd, 03709 sql_mode, 03710 &sql_mode_len); 03711 table->field[17]->store((const char*)sql_mode_str, sql_mode_len, cs); 03712 table->field[18]->store((const char *)definer_buffer->str, definer_buffer->length, cs); 03713 return schema_table_store_record(thd, table); 03714 } 03715 03716 03717 static int get_schema_triggers_record(THD *thd, struct st_table_list *tables, 03718 TABLE *table, bool res, 03719 const char *base_name, 03720 const char *file_name) 03721 { 03722 DBUG_ENTER("get_schema_triggers_record"); 03723 /* 03724 res can be non zero value when processed table is a view or 03725 error happened during opening of processed table. 03726 */ 03727 if (res) 03728 { 03729 if (!tables->view) 03730 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 03731 thd->net.last_errno, thd->net.last_error); 03732 thd->clear_error(); 03733 DBUG_RETURN(0); 03734 } 03735 if (!tables->view && tables->table->triggers) 03736 { 03737 Table_triggers_list *triggers= tables->table->triggers; 03738 int event, timing; 03739 for (event= 0; event < (int)TRG_EVENT_MAX; event++) 03740 { 03741 for (timing= 0; timing < (int)TRG_ACTION_MAX; timing++) 03742 { 03743 LEX_STRING trigger_name; 03744 LEX_STRING trigger_stmt; 03745 ulong sql_mode; 03746 char definer_holder[USER_HOST_BUFF_SIZE]; 03747 LEX_STRING definer_buffer; 03748 definer_buffer.str= definer_holder; 03749 if (triggers->get_trigger_info(thd, (enum trg_event_type) event, 03750 (enum trg_action_time_type)timing, 03751 &trigger_name, &trigger_stmt, 03752 &sql_mode, 03753 &definer_buffer)) 03754 continue; 03755 03756 if (store_trigger(thd, table, base_name, file_name, &trigger_name, 03757 (enum trg_event_type) event, 03758 (enum trg_action_time_type) timing, &trigger_stmt, 03759 sql_mode, 03760 &definer_buffer)) 03761 DBUG_RETURN(1); 03762 } 03763 } 03764 } 03765 DBUG_RETURN(0); 03766 } 03767 03768 03769 void store_key_column_usage(TABLE *table, const char*db, const char *tname, 03770 const char *key_name, uint key_len, 03771 const char *con_type, uint con_len, longlong idx) 03772 { 03773 CHARSET_INFO *cs= system_charset_info; 03774 table->field[1]->store(db, strlen(db), cs); 03775 table->field[2]->store(key_name, key_len, cs); 03776 table->field[4]->store(db, strlen(db), cs); 03777 table->field[5]->store(tname, strlen(tname), cs); 03778 table->field[6]->store(con_type, con_len, cs); 03779 table->field[7]->store((longlong) idx, TRUE); 03780 } 03781 03782 03783 static int get_schema_key_column_usage_record(THD *thd, 03784 struct st_table_list *tables, 03785 TABLE *table, bool res, 03786 const char *base_name, 03787 const char *file_name) 03788 { 03789 DBUG_ENTER("get_schema_key_column_usage_record"); 03790 if (res) 03791 { 03792 if (!tables->view) 03793 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 03794 thd->net.last_errno, thd->net.last_error); 03795 thd->clear_error(); 03796 DBUG_RETURN(0); 03797 } 03798 else if (!tables->view) 03799 { 03800 List<FOREIGN_KEY_INFO> f_key_list; 03801 TABLE *show_table= tables->table; 03802 KEY *key_info=show_table->key_info; 03803 uint primary_key= show_table->s->primary_key; 03804 show_table->file->info(HA_STATUS_VARIABLE | 03805 HA_STATUS_NO_LOCK | 03806 HA_STATUS_TIME); 03807 for (uint i=0 ; i < show_table->s->keys ; i++, key_info++) 03808 { 03809 if (i != primary_key && !(key_info->flags & HA_NOSAME)) 03810 continue; 03811 uint f_idx= 0; 03812 KEY_PART_INFO *key_part= key_info->key_part; 03813 for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) 03814 { 03815 if (key_part->field) 03816 { 03817 f_idx++; 03818 restore_record(table, s->default_values); 03819 store_key_column_usage(table, base_name, file_name, 03820 key_info->name, 03821 strlen(key_info->name), 03822 key_part->field->field_name, 03823 strlen(key_part->field->field_name), 03824 (longlong) f_idx); 03825 if (schema_table_store_record(thd, table)) 03826 DBUG_RETURN(1); 03827 } 03828 } 03829 } 03830 03831 show_table->file->get_foreign_key_list(thd, &f_key_list); 03832 FOREIGN_KEY_INFO *f_key_info; 03833 List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list); 03834 while ((f_key_info= it++)) 03835 { 03836 LEX_STRING *f_info; 03837 LEX_STRING *r_info; 03838 List_iterator_fast<LEX_STRING> it(f_key_info->foreign_fields), 03839 it1(f_key_info->referenced_fields); 03840 uint f_idx= 0; 03841 while ((f_info= it++)) 03842 { 03843 r_info= it1++; 03844 f_idx++; 03845 restore_record(table, s->default_values); 03846 store_key_column_usage(table, base_name, file_name, 03847 f_key_info->forein_id->str, 03848 f_key_info->forein_id->length, 03849 f_info->str, f_info->length, 03850 (longlong) f_idx); 03851 table->field[8]->store((longlong) f_idx, TRUE); 03852 table->field[8]->set_notnull(); 03853 table->field[9]->store(f_key_info->referenced_db->str, 03854 f_key_info->referenced_db->length, 03855 system_charset_info); 03856 table->field[9]->set_notnull(); 03857 table->field[10]->store(f_key_info->referenced_table->str, 03858 f_key_info->referenced_table->length, 03859 system_charset_info); 03860 table->field[10]->set_notnull(); 03861 table->field[11]->store(r_info->str, r_info->length, 03862 system_charset_info); 03863 table->field[11]->set_notnull(); 03864 if (schema_table_store_record(thd, table)) 03865 DBUG_RETURN(1); 03866 } 03867 } 03868 } 03869 DBUG_RETURN(res); 03870 } 03871 03872 03873 static void collect_partition_expr(List<char> &field_list, String *str) 03874 { 03875 List_iterator<char> part_it(field_list); 03876 ulong no_fields= field_list.elements; 03877 const char *field_str; 03878 str->length(0); 03879 while ((field_str= part_it++)) 03880 { 03881 str->append(field_str); 03882 if (--no_fields != 0) 03883 str->append(","); 03884 } 03885 return; 03886 } 03887 03888 03889 static void store_schema_partitions_record(THD *thd, TABLE *table, 03890 partition_element *part_elem, 03891 handler *file, uint part_id) 03892 { 03893 CHARSET_INFO *cs= system_charset_info; 03894 PARTITION_INFO stat_info; 03895 TIME time; 03896 file->get_dynamic_partition_info(&stat_info, part_id); 03897 table->field[12]->store((longlong) stat_info.records, TRUE); 03898 table->field[13]->store((longlong) stat_info.mean_rec_length, TRUE); 03899 table->field[14]->store((longlong) stat_info.data_file_length, TRUE); 03900 if (stat_info.max_data_file_length) 03901 { 03902 table->field[15]->store((longlong) stat_info.max_data_file_length, TRUE); 03903 table->field[15]->set_notnull(); 03904 } 03905 table->field[16]->store((longlong) stat_info.index_file_length, TRUE); 03906 table->field[17]->store((longlong) stat_info.delete_length, TRUE); 03907 if (stat_info.create_time) 03908 { 03909 thd->variables.time_zone->gmt_sec_to_TIME(&time, 03910 stat_info.create_time); 03911 table->field[18]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); 03912 table->field[18]->set_notnull(); 03913 } 03914 if (stat_info.update_time) 03915 { 03916 thd->variables.time_zone->gmt_sec_to_TIME(&time, 03917 stat_info.update_time); 03918 table->field[19]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); 03919 table->field[19]->set_notnull(); 03920 } 03921 if (stat_info.check_time) 03922 { 03923 thd->variables.time_zone->gmt_sec_to_TIME(&time, stat_info.check_time); 03924 table->field[20]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); 03925 table->field[20]->set_notnull(); 03926 } 03927 if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM) 03928 { 03929 table->field[21]->store((longlong) stat_info.check_sum, TRUE); 03930 table->field[21]->set_notnull(); 03931 } 03932 if (part_elem) 03933 { 03934 if (part_elem->part_comment) 03935 table->field[22]->store(part_elem->part_comment, 03936 strlen(part_elem->part_comment), cs); 03937 else 03938 table->field[22]->store(STRING_WITH_LEN("default"), cs); 03939 if (part_elem->nodegroup_id != UNDEF_NODEGROUP) 03940 table->field[23]->store((longlong) part_elem->nodegroup_id, TRUE); 03941 else 03942 table->field[23]->store(STRING_WITH_LEN("default"), cs); 03943 if (part_elem->tablespace_name) 03944 table->field[24]->store(part_elem->tablespace_name, 03945 strlen(part_elem->tablespace_name), cs); 03946 else 03947 table->field[24]->store(STRING_WITH_LEN("default"), cs); 03948 } 03949 return; 03950 } 03951 03952 03953 static int get_schema_partitions_record(THD *thd, struct st_table_list *tables, 03954 TABLE *table, bool res, 03955 const char *base_name, 03956 const char *file_name) 03957 { 03958 CHARSET_INFO *cs= system_charset_info; 03959 char buff[61]; 03960 String tmp_res(buff, sizeof(buff), cs); 03961 String tmp_str; 03962 TIME time; 03963 TABLE *show_table= tables->table; 03964 handler *file; 03965 #ifdef WITH_PARTITION_STORAGE_ENGINE 03966 partition_info *part_info; 03967 #endif 03968 DBUG_ENTER("get_schema_partitions_record"); 03969 03970 if (res) 03971 { 03972 if (!tables->view) 03973 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 03974 thd->net.last_errno, thd->net.last_error); 03975 thd->clear_error(); 03976 DBUG_RETURN(0); 03977 } 03978 file= show_table->file; 03979 #ifdef WITH_PARTITION_STORAGE_ENGINE 03980 part_info= show_table->part_info; 03981 if (part_info) 03982 { 03983 partition_element *part_elem; 03984 List_iterator<partition_element> part_it(part_info->partitions); 03985 uint part_pos= 0, part_id= 0; 03986 uint no_parts= part_info->no_parts; 03987 handler *part_file; 03988 03989 restore_record(table, s->default_values); 03990 table->field[1]->store(base_name, strlen(base_name), cs); 03991 table->field[2]->store(file_name, strlen(file_name), cs); 03992 03993 03994 /* Partition method*/ 03995 switch (part_info->part_type) { 03996 case RANGE_PARTITION: 03997 table->field[7]->store(partition_keywords[PKW_RANGE].str, 03998 partition_keywords[PKW_RANGE].length, cs); 03999 break; 04000 case LIST_PARTITION: 04001 table->field[7]->store(partition_keywords[PKW_LIST].str, 04002 partition_keywords[PKW_LIST].length, cs); 04003 break; 04004 case HASH_PARTITION: 04005 tmp_res.length(0); 04006 if (part_info->linear_hash_ind) 04007 tmp_res.append(partition_keywords[PKW_LINEAR].str, 04008 partition_keywords[PKW_LINEAR].length); 04009 if (part_info->list_of_part_fields) 04010 tmp_res.append(partition_keywords[PKW_KEY].str, 04011 partition_keywords[PKW_KEY].length); 04012 else 04013 tmp_res.append(partition_keywords[PKW_HASH].str, 04014 partition_keywords[PKW_HASH].length); 04015 table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs); 04016 break; 04017 default: 04018 DBUG_ASSERT(0); 04019 current_thd->fatal_error(); 04020 DBUG_RETURN(1); 04021 } 04022 table->field[7]->set_notnull(); 04023 04024 /* Partition expression */ 04025 if (part_info->part_expr) 04026 { 04027 table->field[9]->store(part_info->part_func_string, 04028 part_info->part_func_len, cs); 04029 } 04030 else if (part_info->list_of_part_fields) 04031 { 04032 collect_partition_expr(part_info->part_field_list, &tmp_str); 04033 table->field[9]->store(tmp_str.ptr(), tmp_str.length(), cs); 04034 } 04035 table->field[9]->set_notnull(); 04036 04037 if (part_info->is_sub_partitioned()) 04038 { 04039 /* Subpartition method */ 04040 tmp_res.length(0); 04041 if (part_info->linear_hash_ind) 04042 tmp_res.append(partition_keywords[PKW_LINEAR].str, 04043 partition_keywords[PKW_LINEAR].length); 04044 if (part_info->list_of_subpart_fields) 04045 tmp_res.append(partition_keywords[PKW_KEY].str, 04046 partition_keywords[PKW_KEY].length); 04047 else 04048 tmp_res.append(partition_keywords[PKW_HASH].str, 04049 partition_keywords[PKW_HASH].length); 04050 table->field[8]->store(tmp_res.ptr(), tmp_res.length(), cs); 04051 table->field[8]->set_notnull(); 04052 04053 /* Subpartition expression */ 04054 if (part_info->subpart_expr) 04055 { 04056 table->field[10]->store(part_info->subpart_func_string, 04057 part_info->subpart_func_len, cs); 04058 } 04059 else if (part_info->list_of_subpart_fields) 04060 { 04061 collect_partition_expr(part_info->subpart_field_list, &tmp_str); 04062 table->field[10]->store(tmp_str.ptr(), tmp_str.length(), cs); 04063 } 04064 table->field[10]->set_notnull(); 04065 } 04066 04067 while ((part_elem= part_it++)) 04068 { 04069 04070 04071 table->field[3]->store(part_elem->partition_name, 04072 strlen(part_elem->partition_name), cs); 04073 table->field[3]->set_notnull(); 04074 /* PARTITION_ORDINAL_POSITION */ 04075 table->field[5]->store((longlong) ++part_pos, TRUE); 04076 table->field[5]->set_notnull(); 04077 04078 /* Partition description */ 04079 if (part_info->part_type == RANGE_PARTITION) 04080 { 04081 if (part_elem->range_value != LONGLONG_MAX) 04082 table->field[11]->store((longlong) part_elem->range_value, FALSE); 04083 else 04084 table->field[11]->store(partition_keywords[PKW_MAXVALUE].str, 04085 partition_keywords[PKW_MAXVALUE].length, cs); 04086 table->field[11]->set_notnull(); 04087 } 04088 else if (part_info->part_type == LIST_PARTITION) 04089 { 04090 List_iterator<part_elem_value> list_val_it(part_elem->list_val_list); 04091 part_elem_value *list_value; 04092 uint no_items= part_elem->list_val_list.elements; 04093 tmp_str.length(0); 04094 tmp_res.length(0); 04095 if (part_elem->has_null_value) 04096 { 04097 tmp_str.append("NULL"); 04098 if (no_items > 0) 04099 tmp_str.append(","); 04100 } 04101 while ((list_value= list_val_it++)) 04102 { 04103 if (!list_value->unsigned_flag) 04104 tmp_res.set(list_value->value, cs); 04105 else 04106 tmp_res.set((ulonglong)list_value->value, cs); 04107 tmp_str.append(tmp_res); 04108 if (--no_items != 0) 04109 tmp_str.append(","); 04110 }; 04111 table->field[11]->store(tmp_str.ptr(), tmp_str.length(), cs); 04112 table->field[11]->set_notnull(); 04113 } 04114 04115 if (part_elem->subpartitions.elements) 04116 { 04117 List_iterator<partition_element> sub_it(part_elem->subpartitions); 04118 partition_element *subpart_elem; 04119 uint subpart_pos= 0; 04120 04121 while ((subpart_elem= sub_it++)) 04122 { 04123 table->field[4]->store(subpart_elem->partition_name, 04124 strlen(subpart_elem->partition_name), cs); 04125 table->field[4]->set_notnull(); 04126 /* SUBPARTITION_ORDINAL_POSITION */ 04127 table->field[6]->store((longlong) ++subpart_pos, TRUE); 04128 table->field[6]->set_notnull(); 04129 04130 store_schema_partitions_record(thd, table, subpart_elem, 04131 file, part_id); 04132 part_id++; 04133 if(schema_table_store_record(thd, table)) 04134 DBUG_RETURN(1); 04135 } 04136 } 04137 else 04138 { 04139 store_schema_partitions_record(thd, table, part_elem, 04140 file, part_id); 04141 part_id++; 04142 if(schema_table_store_record(thd, table)) 04143 DBUG_RETURN(1); 04144 } 04145 } 04146 DBUG_RETURN(0); 04147 } 04148 else 04149 #endif 04150 { 04151 store_schema_partitions_record(thd, table, 0, file, 0); 04152 if(schema_table_store_record(thd, table)) 04153 DBUG_RETURN(1); 04154 } 04155 DBUG_RETURN(0); 04156 } 04157 04158 04159 static interval_type get_real_interval_type(interval_type i_type) 04160 { 04161 switch (i_type) { 04162 case INTERVAL_YEAR: 04163 return INTERVAL_YEAR; 04164 04165 case INTERVAL_QUARTER: 04166 case INTERVAL_YEAR_MONTH: 04167 case INTERVAL_MONTH: 04168 return INTERVAL_MONTH; 04169 04170 case INTERVAL_WEEK: 04171 case INTERVAL_DAY: 04172 return INTERVAL_DAY; 04173 04174 case INTERVAL_DAY_HOUR: 04175 case INTERVAL_HOUR: 04176 return INTERVAL_HOUR; 04177 04178 case INTERVAL_DAY_MINUTE: 04179 case INTERVAL_HOUR_MINUTE: 04180 case INTERVAL_MINUTE: 04181 return INTERVAL_MINUTE; 04182 04183 case INTERVAL_DAY_SECOND: 04184 case INTERVAL_HOUR_SECOND: 04185 case INTERVAL_MINUTE_SECOND: 04186 case INTERVAL_SECOND: 04187 return INTERVAL_SECOND; 04188 04189 case INTERVAL_DAY_MICROSECOND: 04190 case INTERVAL_HOUR_MICROSECOND: 04191 case INTERVAL_MINUTE_MICROSECOND: 04192 case INTERVAL_SECOND_MICROSECOND: 04193 case INTERVAL_MICROSECOND: 04194 return INTERVAL_MICROSECOND; 04195 case INTERVAL_LAST: 04196 DBUG_ASSERT(0); 04197 } 04198 DBUG_ASSERT(0); 04199 return INTERVAL_SECOND; 04200 } 04201 04202 extern LEX_STRING interval_type_to_name[]; 04203 04204 04205 /* 04206 Loads an event from mysql.event and copies it's data to a row of 04207 I_S.EVENTS 04208 04209 Synopsis 04210 copy_event_to_schema_table() 04211 thd Thread 04212 sch_table The schema table (information_schema.event) 04213 event_table The event table to use for loading (mysql.event). 04214 04215 Returns 04216 0 OK 04217 1 Error 04218 */ 04219 04220 static int 04221 copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) 04222 { 04223 const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; 04224 CHARSET_INFO *scs= system_charset_info; 04225 TIME time; 04226 Event_timed et; 04227 DBUG_ENTER("fill_events_copy_to_schema_tab"); 04228 04229 restore_record(sch_table, s->default_values); 04230 04231 if (et.load_from_row(thd->mem_root, event_table)) 04232 { 04233 my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0)); 04234 DBUG_RETURN(1); 04235 } 04236 04237 if (!(!wild || !wild[0] || !wild_compare(et.name.str, wild, 0))) 04238 DBUG_RETURN(0); 04239 04240 /* 04241 Skip events in schemas one does not have access to. The check is 04242 optimized. It's guaranteed in case of SHOW EVENTS that the user 04243 has access. 04244 */ 04245 if (thd->lex->sql_command != SQLCOM_SHOW_EVENTS && 04246 check_access(thd, EVENT_ACL, et.dbname.str, 0, 0, 1, 04247 is_schema_db(et.dbname.str))) 04248 DBUG_RETURN(0); 04249 04250 /* ->field[0] is EVENT_CATALOG and is by default NULL */ 04251 04252 sch_table->field[ISE_EVENT_SCHEMA]-> 04253 store(et.dbname.str, et.dbname.length,scs); 04254 sch_table->field[ISE_EVENT_NAME]-> 04255 store(et.name.str, et.name.length, scs); 04256 sch_table->field[ISE_DEFINER]-> 04257 store(et.definer.str, et.definer.length, scs); 04258 sch_table->field[ISE_EVENT_BODY]-> 04259 store(STRING_WITH_LEN("SQL"), scs); 04260 sch_table->field[ISE_EVENT_DEFINITION]-> 04261 store(et.body.str, et.body.length, scs); 04262 04263 /* SQL_MODE */ 04264 { 04265 byte *sql_mode_str; 04266 ulong sql_mode_len= 0; 04267 sql_mode_str= 04268 sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode, 04269 &sql_mode_len); 04270 sch_table->field[ISE_SQL_MODE]-> 04271 store((const char*)sql_mode_str, sql_mode_len, scs); 04272 } 04273 04274 if (et.expression) 04275 { 04276 String show_str; 04277 /* type */ 04278 sch_table->field[ISE_EVENT_TYPE]->store(STRING_WITH_LEN("RECURRING"), scs); 04279 04280 if (Events::reconstruct_interval_expression(&show_str, et.interval, 04281 et.expression)) 04282 DBUG_RETURN(1); 04283 04284 sch_table->field[ISE_INTERVAL_VALUE]->set_notnull(); 04285 sch_table->field[ISE_INTERVAL_VALUE]-> 04286 store(show_str.ptr(), show_str.length(), scs); 04287 04288 LEX_STRING *ival= &interval_type_to_name[et.interval]; 04289 sch_table->field[ISE_INTERVAL_FIELD]->set_notnull(); 04290 sch_table->field[ISE_INTERVAL_FIELD]->store(ival->str, ival->length, scs); 04291 04292 /* starts & ends . STARTS is always set - see sql_yacc.yy */ 04293 sch_table->field[ISE_STARTS]->set_notnull(); 04294 sch_table->field[ISE_STARTS]-> 04295 store_time(&et.starts, MYSQL_TIMESTAMP_DATETIME); 04296 04297 if (!et.ends_null) 04298 { 04299 sch_table->field[ISE_ENDS]->set_notnull(); 04300 sch_table->field[ISE_ENDS]-> 04301 store_time(&et.ends, MYSQL_TIMESTAMP_DATETIME); 04302 } 04303 } 04304 else 04305 { 04306 /* type */ 04307 sch_table->field[ISE_EVENT_TYPE]->store(STRING_WITH_LEN("ONE TIME"), scs); 04308 04309 sch_table->field[ISE_EXECUTE_AT]->set_notnull(); 04310 sch_table->field[ISE_EXECUTE_AT]-> 04311 store_time(&et.execute_at, MYSQL_TIMESTAMP_DATETIME); 04312 } 04313 04314 /* status */ 04315 if (et.status == Event_timed::ENABLED) 04316 sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("ENABLED"), scs); 04317 else 04318 sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("DISABLED"), scs); 04319 04320 /* on_completion */ 04321 if (et.on_completion == Event_timed::ON_COMPLETION_DROP) 04322 sch_table->field[ISE_ON_COMPLETION]-> 04323 store(STRING_WITH_LEN("NOT PRESERVE"), scs); 04324 else 04325 sch_table->field[ISE_ON_COMPLETION]-> 04326 store(STRING_WITH_LEN("PRESERVE"), scs); 04327 04328 int not_used=0; 04329 number_to_datetime(et.created, &time, 0, ¬_used); 04330 DBUG_ASSERT(not_used==0); 04331 sch_table->field[ISE_CREATED]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); 04332 04333 number_to_datetime(et.modified, &time, 0, ¬_used); 04334 DBUG_ASSERT(not_used==0); 04335 sch_table->field[ISE_LAST_ALTERED]-> 04336 store_time(&time, MYSQL_TIMESTAMP_DATETIME); 04337 04338 if (et.last_executed.year) 04339 { 04340 sch_table->field[ISE_LAST_EXECUTED]->set_notnull(); 04341 sch_table->field[ISE_LAST_EXECUTED]-> 04342 store_time(&et.last_executed, MYSQL_TIMESTAMP_DATETIME); 04343 } 04344 04345 sch_table->field[ISE_EVENT_COMMENT]-> 04346 store(et.comment.str, et.comment.length, scs); 04347 04348 if (schema_table_store_record(thd, sch_table)) 04349 DBUG_RETURN(1); 04350 04351 DBUG_RETURN(0); 04352 } 04353 04354 04355 /* 04356 Performs an index scan of event_table (mysql.event) and fills schema_table. 04357 04358 Synopsis 04359 events_table_index_read_for_db() 04360 thd Thread 04361 schema_table The I_S.EVENTS table 04362 event_table The event table to use for loading (mysql.event) 04363 04364 Returns 04365 0 OK 04366 1 Error 04367 */ 04368 04369 static 04370 int events_table_index_read_for_db(THD *thd, TABLE *schema_table, 04371 TABLE *event_table) 04372 { 04373 int ret=0; 04374 CHARSET_INFO *scs= system_charset_info; 04375 KEY *key_info; 04376 uint key_len; 04377 byte *key_buf= NULL; 04378 LINT_INIT(key_buf); 04379 04380 DBUG_ENTER("schema_events_do_index_scan"); 04381 04382 DBUG_PRINT("info", ("Using prefix scanning on PK")); 04383 event_table->file->ha_index_init(0, 1); 04384 event_table->field[Events::FIELD_DB]-> 04385 store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs); 04386 key_info= event_table->key_info; 04387 key_len= key_info->key_part[0].store_length; 04388 04389 if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len))) 04390 { 04391 ret= 1; 04392 /* don't send error, it would be done by sql_alloc_error_handler() */ 04393 } 04394 else 04395 { 04396 key_copy(key_buf, event_table->record[0], key_info, key_len); 04397 if (!(ret= event_table->file->index_read(event_table->record[0], key_buf, 04398 key_len, HA_READ_PREFIX))) 04399 { 04400 DBUG_PRINT("info",("Found rows. Let's retrieve them. ret=%d", ret)); 04401 do 04402 { 04403 ret= copy_event_to_schema_table(thd, schema_table, event_table); 04404 if (ret == 0) 04405 ret= event_table->file->index_next_same(event_table->record[0], 04406 key_buf, key_len); 04407 } while (ret == 0); 04408 } 04409 DBUG_PRINT("info", ("Scan finished. ret=%d", ret)); 04410 } 04411 event_table->file->ha_index_end(); 04412 /* ret is guaranteed to be != 0 */ 04413 if (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND) 04414 DBUG_RETURN(0); 04415 DBUG_RETURN(1); 04416 } 04417 04418 04419 /* 04420 Performs a table scan of event_table (mysql.event) and fills schema_table. 04421 04422 Synopsis 04423 events_table_scan_all() 04424 thd Thread 04425 schema_table The I_S.EVENTS in memory table 04426 event_table The event table to use for loading. 04427 04428 Returns 04429 0 OK 04430 1 Error 04431 */ 04432 04433 static 04434 int events_table_scan_all(THD *thd, TABLE *schema_table, 04435 TABLE *event_table) 04436 { 04437 int ret; 04438 READ_RECORD read_record_info; 04439 04440 DBUG_ENTER("schema_events_do_table_scan"); 04441 init_read_record(&read_record_info, thd, event_table, NULL, 1, 0); 04442 04443 /* 04444 rr_sequential, in read_record(), returns 137==HA_ERR_END_OF_FILE, 04445 but rr_handle_error returns -1 for that reason. Thus, read_record() 04446 returns -1 eventually. 04447 */ 04448 do 04449 { 04450 ret= read_record_info.read_record(&read_record_info); 04451 if (ret == 0) 04452 ret= copy_event_to_schema_table(thd, schema_table, event_table); 04453 } 04454 while (ret == 0); 04455 04456 DBUG_PRINT("info", ("Scan finished. ret=%d", ret)); 04457 end_read_record(&read_record_info); 04458 04459 /* ret is guaranteed to be != 0 */ 04460 DBUG_RETURN(ret == -1? 0:1); 04461 } 04462 04463 04464 /* 04465 Fills I_S.EVENTS with data loaded from mysql.event. Also used by 04466 SHOW EVENTS 04467 04468 Synopsis 04469 fill_schema_events() 04470 thd Thread 04471 tables The schema table 04472 cond Unused 04473 04474 Returns 04475 0 OK 04476 1 Error 04477 */ 04478 04479 int fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) 04480 { 04481 TABLE *schema_table= tables->table; 04482 TABLE *event_table= NULL; 04483 Open_tables_state backup; 04484 int ret= 0; 04485 04486 DBUG_ENTER("fill_schema_events"); 04487 /* 04488 If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to 04489 be NULL. Let's do an assert anyway. 04490 */ 04491 if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS) 04492 { 04493 DBUG_ASSERT(thd->lex->select_lex.db); 04494 if (check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, 04495 is_schema_db(thd->lex->select_lex.db))) 04496 DBUG_RETURN(1); 04497 } 04498 04499 DBUG_PRINT("info",("db=%s", thd->lex->select_lex.db? 04500 thd->lex->select_lex.db:"(null)")); 04501 04502 thd->reset_n_backup_open_tables_state(&backup); 04503 if (Events::open_event_table(thd, TL_READ, &event_table)) 04504 { 04505 sql_print_error("Table mysql.event is damaged."); 04506 thd->restore_backup_open_tables_state(&backup); 04507 DBUG_RETURN(1); 04508 } 04509 04510 /* 04511 1. SELECT I_S => use table scan. I_S.EVENTS does not guarantee order 04512 thus we won't order it. OTOH, SHOW EVENTS will be 04513 ordered. 04514 2. SHOW EVENTS => PRIMARY KEY with prefix scanning on (db) 04515 Reasoning: Events are per schema, therefore a scan over an index 04516 will save use from doing a table scan and comparing 04517 every single row's `db` with the schema which we show. 04518 */ 04519 if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS) 04520 ret= events_table_index_read_for_db(thd, schema_table, event_table); 04521 else 04522 ret= events_table_scan_all(thd, schema_table, event_table); 04523 04524 close_thread_tables(thd); 04525 thd->restore_backup_open_tables_state(&backup); 04526 04527 DBUG_PRINT("info", ("Return code=%d", ret)); 04528 DBUG_RETURN(ret); 04529 } 04530 04531 04532 int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond) 04533 { 04534 DBUG_ENTER("fill_open_tables"); 04535 const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; 04536 TABLE *table= tables->table; 04537 CHARSET_INFO *cs= system_charset_info; 04538 OPEN_TABLE_LIST *open_list; 04539 if (!(open_list=list_open_tables(thd,thd->lex->select_lex.db, wild)) 04540 && thd->is_fatal_error) 04541 DBUG_RETURN(1); 04542 04543 for (; open_list ; open_list=open_list->next) 04544 { 04545 restore_record(table, s->default_values); 04546 table->field[0]->store(open_list->db, strlen(open_list->db), cs); 04547 table->field[1]->store(open_list->table, strlen(open_list->table), cs); 04548 table->field[2]->store((longlong) open_list->in_use, TRUE); 04549 table->field[3]->store((longlong) open_list->locked, TRUE); 04550 if (schema_table_store_record(thd, table)) 04551 DBUG_RETURN(1); 04552 } 04553 DBUG_RETURN(0); 04554 } 04555 04556 04557 int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) 04558 { 04559 DBUG_ENTER("fill_variables"); 04560 int res= 0; 04561 LEX *lex= thd->lex; 04562 const char *wild= lex->wild ? lex->wild->ptr() : NullS; 04563 pthread_mutex_lock(&LOCK_global_system_variables); 04564 res= show_status_array(thd, wild, init_vars, 04565 lex->option_type, 0, "", tables->table); 04566 pthread_mutex_unlock(&LOCK_global_system_variables); 04567 DBUG_RETURN(res); 04568 } 04569 04570 04571 int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) 04572 { 04573 DBUG_ENTER("fill_status"); 04574 LEX *lex= thd->lex; 04575 const char *wild= lex->wild ? lex->wild->ptr() : NullS; 04576 int res= 0; 04577 STATUS_VAR tmp; 04578 pthread_mutex_lock(&LOCK_status); 04579 if (lex->option_type == OPT_GLOBAL) 04580 calc_sum_of_all_status(&tmp); 04581 res= show_status_array(thd, wild, 04582 (SHOW_VAR *)all_status_vars.buffer, 04583 OPT_GLOBAL, 04584 (lex->option_type == OPT_GLOBAL ? 04585 &tmp: thd->initial_status_var), "",tables->table); 04586 pthread_mutex_unlock(&LOCK_status); 04587 DBUG_RETURN(res); 04588 } 04589 04590 04591 /* 04592 Fill and store records into I_S.referential_constraints table 04593 04594 SYNOPSIS 04595 get_referential_constraints_record() 04596 thd thread handle 04597 tables table list struct(processed table) 04598 table I_S table 04599 res 1 means the error during opening of the processed table 04600 0 means processed table is opened without error 04601 base_name db name 04602 file_name table name 04603 04604 RETURN 04605 0 ok 04606 # error 04607 */ 04608 04609 static int 04610 get_referential_constraints_record(THD *thd, struct st_table_list *tables, 04611 TABLE *table, bool res, 04612 const char *base_name, const char *file_name) 04613 { 04614 CHARSET_INFO *cs= system_charset_info; 04615 DBUG_ENTER("get_referential_constraints_record"); 04616 04617 if (res) 04618 { 04619 if (!tables->view) 04620 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 04621 thd->net.last_errno, thd->net.last_error); 04622 thd->clear_error(); 04623 DBUG_RETURN(0); 04624 } 04625 if (!tables->view) 04626 { 04627 List<FOREIGN_KEY_INFO> f_key_list; 04628 TABLE *show_table= tables->table; 04629 show_table->file->info(HA_STATUS_VARIABLE | 04630 HA_STATUS_NO_LOCK | 04631 HA_STATUS_TIME); 04632 04633 show_table->file->get_foreign_key_list(thd, &f_key_list); 04634 FOREIGN_KEY_INFO *f_key_info; 04635 List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list); 04636 while ((f_key_info= it++)) 04637 { 04638 restore_record(table, s->default_values); 04639 table->field[1]->store(base_name, strlen(base_name), cs); 04640 table->field[9]->store(file_name, strlen(file_name), cs); 04641 table->field[2]->store(f_key_info->forein_id->str, 04642 f_key_info->forein_id->length, cs); 04643 table->field[4]->store(f_key_info->referenced_db->str, 04644 f_key_info->referenced_db->length, cs); 04645 table->field[5]->store(f_key_info->referenced_table->str, 04646 f_key_info->referenced_table->length, cs); 04647 table->field[6]->store(STRING_WITH_LEN("NONE"), cs); 04648 table->field[7]->store(f_key_info->update_method->str, 04649 f_key_info->update_method->length, cs); 04650 table->field[8]->store(f_key_info->delete_method->str, 04651 f_key_info->delete_method->length, cs); 04652 if (schema_table_store_record(thd, table)) 04653 DBUG_RETURN(1); 04654 } 04655 } 04656 DBUG_RETURN(0); 04657 } 04658 04659 04660 /* 04661 Find schema_tables elment by name 04662 04663 SYNOPSIS 04664 find_schema_table() 04665 thd thread handler 04666 table_name table name 04667 04668 RETURN 04669 0 table not found 04670 # pointer to 'shema_tables' element 04671 */ 04672 04673 ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name) 04674 { 04675 ST_SCHEMA_TABLE *schema_table= schema_tables; 04676 for (; schema_table->table_name; schema_table++) 04677 { 04678 if (!my_strcasecmp(system_charset_info, 04679 schema_table->table_name, 04680 table_name)) 04681 return schema_table; 04682 } 04683 return 0; 04684 } 04685 04686 04687 ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx) 04688 { 04689 return &schema_tables[schema_table_idx]; 04690 } 04691 04692 04693 /* 04694 Create information_schema table using schema_table data 04695 04696 SYNOPSIS 04697 create_schema_table() 04698 thd thread handler 04699 schema_table pointer to 'shema_tables' element 04700 04701 RETURN 04702 # Pointer to created table 04703 0 Can't create table 04704 */ 04705 04706 TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) 04707 { 04708 int field_count= 0; 04709 Item *item; 04710 TABLE *table; 04711 List<Item> field_list; 04712 ST_SCHEMA_TABLE *schema_table= table_list->schema_table; 04713 ST_FIELD_INFO *fields_info= schema_table->fields_info; 04714 CHARSET_INFO *cs= system_charset_info; 04715 DBUG_ENTER("create_schema_table"); 04716 04717 for (; fields_info->field_name; fields_info++) 04718 { 04719 switch (fields_info->field_type) { 04720 case MYSQL_TYPE_LONG: 04721 if (!(item= new Item_int(fields_info->field_name, 04722 fields_info->value, 04723 fields_info->field_length))) 04724 { 04725 DBUG_RETURN(0); 04726 } 04727 break; 04728 case MYSQL_TYPE_TIMESTAMP: 04729 if (!(item=new Item_datetime(fields_info->field_name))) 04730 { 04731 DBUG_RETURN(0); 04732 } 04733 break; 04734 default: 04735 /* this should be changed when Item_empty_string is fixed(in 4.1) */ 04736 if (!(item= new Item_empty_string("", 0, cs))) 04737 { 04738 DBUG_RETURN(0); 04739 } 04740 item->max_length= fields_info->field_length * cs->mbmaxlen; 04741 item->set_name(fields_info->field_name, 04742 strlen(fields_info->field_name), cs); 04743 break; 04744 } 04745 field_list.push_back(item); 04746 item->maybe_null= fields_info->maybe_null; 04747 field_count++; 04748 } 04749 TMP_TABLE_PARAM *tmp_table_param = 04750 (TMP_TABLE_PARAM*) (thd->alloc(sizeof(TMP_TABLE_PARAM))); 04751 tmp_table_param->init(); 04752 tmp_table_param->table_charset= cs; 04753 tmp_table_param->field_count= field_count; 04754 tmp_table_param->schema_table= 1; 04755 SELECT_LEX *select_lex= thd->lex->current_select; 04756 if (!(table= create_tmp_table(thd, tmp_table_param, 04757 field_list, (ORDER*) 0, 0, 0, 04758 (select_lex->options | thd->options | 04759 TMP_TABLE_ALL_COLUMNS), 04760 HA_POS_ERROR, table_list->alias))) 04761 DBUG_RETURN(0); 04762 table_list->schema_table_param= tmp_table_param; 04763 DBUG_RETURN(table); 04764 } 04765 04766 04767 /* 04768 For old SHOW compatibility. It is used when 04769 old SHOW doesn't have generated column names 04770 Make list of fields for SHOW 04771 04772 SYNOPSIS 04773 make_old_format() 04774 thd thread handler 04775 schema_table pointer to 'schema_tables' element 04776 04777 RETURN 04778 1 error 04779 0 success 04780 */ 04781 04782 int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) 04783 { 04784 ST_FIELD_INFO *field_info= schema_table->fields_info; 04785 Name_resolution_context *context= &thd->lex->select_lex.context; 04786 for (; field_info->field_name; field_info++) 04787 { 04788 if (field_info->old_name) 04789 { 04790 Item_field *field= new Item_field(context, 04791 NullS, NullS, field_info->field_name); 04792 if (field) 04793 { 04794 field->set_name(field_info->old_name, 04795 strlen(field_info->old_name), 04796 system_charset_info); 04797 if (add_item_to_list(thd, field)) 04798 return 1; 04799 } 04800 } 04801 } 04802 return 0; 04803 } 04804 04805 04806 int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) 04807 { 04808 char tmp[128]; 04809 LEX *lex= thd->lex; 04810 SELECT_LEX *sel= lex->current_select; 04811 Name_resolution_context *context= &sel->context; 04812 04813 if (!sel->item_list.elements) 04814 { 04815 ST_FIELD_INFO *field_info= &schema_table->fields_info[1]; 04816 String buffer(tmp,sizeof(tmp), system_charset_info); 04817 Item_field *field= new Item_field(context, 04818 NullS, NullS, field_info->field_name); 04819 if (!field || add_item_to_list(thd, field)) 04820 return 1; 04821 buffer.length(0); 04822 buffer.append(field_info->old_name); 04823 if (lex->wild && lex->wild->ptr()) 04824 { 04825 buffer.append(STRING_WITH_LEN(" (")); 04826 buffer.append(lex->wild->ptr()); 04827 buffer.append(')'); 04828 } 04829 field->set_name(buffer.ptr(), buffer.length(), system_charset_info); 04830 } 04831 return 0; 04832 } 04833 04834 04835 int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) 04836 { 04837 char tmp[128]; 04838 String buffer(tmp,sizeof(tmp), thd->charset()); 04839 LEX *lex= thd->lex; 04840 Name_resolution_context *context= &lex->select_lex.context; 04841 04842 ST_FIELD_INFO *field_info= &schema_table->fields_info[2]; 04843 buffer.length(0); 04844 buffer.append(field_info->old_name); 04845 buffer.append(lex->select_lex.db); 04846 if (lex->wild && lex->wild->ptr()) 04847 { 04848 buffer.append(STRING_WITH_LEN(" (")); 04849 buffer.append(lex->wild->ptr()); 04850 buffer.append(')'); 04851 } 04852 Item_field *field= new Item_field(context, 04853 NullS, NullS, field_info->field_name); 04854 if (add_item_to_list(thd, field)) 04855 return 1; 04856 field->set_name(buffer.ptr(), buffer.length(), system_charset_info); 04857 if (thd->lex->verbose) 04858 { 04859 field->set_name(buffer.ptr(), buffer.length(), system_charset_info); 04860 field_info= &schema_table->fields_info[3]; 04861 field= new Item_field(context, NullS, NullS, field_info->field_name); 04862 if (add_item_to_list(thd, field)) 04863 return 1; 04864 field->set_name(field_info->old_name, strlen(field_info->old_name), 04865 system_charset_info); 04866 } 04867 return 0; 04868 } 04869 04870 04871 int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) 04872 { 04873 int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1}; 04874 int *field_num= fields_arr; 04875 ST_FIELD_INFO *field_info; 04876 Name_resolution_context *context= &thd->lex->select_lex.context; 04877 04878 for (; *field_num >= 0; field_num++) 04879 { 04880 field_info= &schema_table->fields_info[*field_num]; 04881 if (!thd->lex->verbose && (*field_num == 13 || 04882 *field_num == 17 || 04883 *field_num == 18)) 04884 continue; 04885 Item_field *field= new Item_field(context, 04886 NullS, NullS, field_info->field_name); 04887 if (field) 04888 { 04889 field->set_name(field_info->old_name, 04890 strlen(field_info->old_name), 04891 system_charset_info); 04892 if (add_item_to_list(thd, field)) 04893 return 1; 04894 } 04895 } 04896 return 0; 04897 } 04898 04899 04900 int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) 04901 { 04902 int fields_arr[]= {0, 2, 1, 3, -1}; 04903 int *field_num= fields_arr; 04904 ST_FIELD_INFO *field_info; 04905 Name_resolution_context *context= &thd->lex->select_lex.context; 04906 04907 for (; *field_num >= 0; field_num++) 04908 { 04909 field_info= &schema_table->fields_info[*field_num]; 04910 Item_field *field= new Item_field(context, 04911 NullS, NullS, field_info->field_name); 04912 if (field) 04913 { 04914 field->set_name(field_info->old_name, 04915 strlen(field_info->old_name), 04916 system_charset_info); 04917 if (add_item_to_list(thd, field)) 04918 return 1; 04919 } 04920 } 04921 return 0; 04922 } 04923 04924 04925 int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) 04926 { 04927 int fields_arr[]= {2, 3, 4, 19, 16, 15, 14, 18, -1}; 04928 int *field_num= fields_arr; 04929 ST_FIELD_INFO *field_info; 04930 Name_resolution_context *context= &thd->lex->select_lex.context; 04931 04932 for (; *field_num >= 0; field_num++) 04933 { 04934 field_info= &schema_table->fields_info[*field_num]; 04935 Item_field *field= new Item_field(context, 04936 NullS, NullS, field_info->field_name); 04937 if (field) 04938 { 04939 field->set_name(field_info->old_name, 04940 strlen(field_info->old_name), 04941 system_charset_info); 04942 if (add_item_to_list(thd, field)) 04943 return 1; 04944 } 04945 } 04946 return 0; 04947 } 04948 04949 04950 /* 04951 Create information_schema table 04952 04953 SYNOPSIS 04954 mysql_schema_table() 04955 thd thread handler 04956 lex pointer to LEX 04957 table_list pointer to table_list 04958 04959 RETURN 04960 0 success 04961 1 error 04962 */ 04963 04964 int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) 04965 { 04966 TABLE *table; 04967 DBUG_ENTER("mysql_schema_table"); 04968 if (!(table= table_list->schema_table->create_table(thd, table_list))) 04969 { 04970 DBUG_RETURN(1); 04971 } 04972 table->s->tmp_table= SYSTEM_TMP_TABLE; 04973 table->grant.privilege= SELECT_ACL; 04974 /* 04975 This test is necessary to make 04976 case insensitive file systems + 04977 upper case table names(information schema tables) + 04978 views 04979 working correctly 04980 */ 04981 if (table_list->schema_table_name) 04982 table->alias_name_used= my_strcasecmp(table_alias_charset, 04983 table_list->schema_table_name, 04984 table_list->alias); 04985 table_list->table_name= table->s->table_name.str; 04986 table_list->table_name_length= table->s->table_name.length; 04987 table_list->table= table; 04988 table->next= thd->derived_tables; 04989 thd->derived_tables= table; 04990 table_list->select_lex->options |= OPTION_SCHEMA_TABLE; 04991 lex->safe_to_cache_query= 0; 04992 04993 if (table_list->schema_table_reformed) // show command 04994 { 04995 SELECT_LEX *sel= lex->current_select; 04996 Item *item; 04997 Field_translator *transl, *org_transl; 04998 04999 if (table_list->field_translation) 05000 { 05001 Field_translator *end= table_list->field_translation_end; 05002 for (transl= table_list->field_translation; transl < end; transl++) 05003 { 05004 if (!transl->item->fixed && 05005 transl->item->fix_fields(thd, &transl->item)) 05006 DBUG_RETURN(1); 05007 } 05008 DBUG_RETURN(0); 05009 } 05010 List_iterator_fast<Item> it(sel->item_list); 05011 if (!(transl= 05012 (Field_translator*)(thd->stmt_arena-> 05013 alloc(sel->item_list.elements * 05014 sizeof(Field_translator))))) 05015 { 05016 DBUG_RETURN(1); 05017 } 05018 for (org_transl= transl; (item= it++); transl++) 05019 { 05020 transl->item= item; 05021 transl->name= item->name; 05022 if (!item->fixed && item->fix_fields(thd, &transl->item)) 05023 { 05024 DBUG_RETURN(1); 05025 } 05026 } 05027 table_list->field_translation= org_transl; 05028 table_list->field_translation_end= transl; 05029 } 05030 05031 DBUG_RETURN(0); 05032 } 05033 05034 05035 /* 05036 Generate select from information_schema table 05037 05038 SYNOPSIS 05039 make_schema_select() 05040 thd thread handler 05041 sel pointer to SELECT_LEX 05042 schema_table_idx index of 'schema_tables' element 05043 05044 RETURN 05045 0 success 05046 1 error 05047 */ 05048 05049 int make_schema_select(THD *thd, SELECT_LEX *sel, 05050 enum enum_schema_tables schema_table_idx) 05051 { 05052 ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx); 05053 LEX_STRING db, table; 05054 DBUG_ENTER("mysql_schema_select"); 05055 DBUG_PRINT("enter", ("mysql_schema_select: %s", schema_table->table_name)); 05056 /* 05057 We have to make non const db_name & table_name 05058 because of lower_case_table_names 05059 */ 05060 make_lex_string(thd, &db, information_schema_name.str, 05061 information_schema_name.length, 0); 05062 make_lex_string(thd, &table, schema_table->table_name, 05063 strlen(schema_table->table_name), 0); 05064 if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */ 05065 !sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0), 05066 0, 0, TL_READ, (List<String> *) 0, 05067 (List<String> *) 0)) 05068 { 05069 DBUG_RETURN(1); 05070 } 05071 DBUG_RETURN(0); 05072 } 05073 05074 05075 /* 05076 Fill temporary schema tables before SELECT 05077 05078 SYNOPSIS 05079 get_schema_tables_result() 05080 join join which use schema tables 05081 05082 RETURN 05083 FALSE success 05084 TRUE error 05085 */ 05086 05087 bool get_schema_tables_result(JOIN *join) 05088 { 05089 JOIN_TAB *tmp_join_tab= join->join_tab+join->tables; 05090 THD *thd= join->thd; 05091 LEX *lex= thd->lex; 05092 bool result= 0; 05093 DBUG_ENTER("get_schema_tables_result"); 05094 05095 thd->no_warnings_for_error= 1; 05096 for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++) 05097 { 05098 if (!tab->table || !tab->table->pos_in_table_list) 05099 break; 05100 05101 TABLE_LIST *table_list= tab->table->pos_in_table_list; 05102 if (table_list->schema_table && thd->fill_information_schema_tables()) 05103 { 05104 bool is_subselect= (&lex->unit != lex->current_select->master_unit() && 05105 lex->current_select->master_unit()->item); 05106 /* 05107 The schema table is already processed and 05108 the statement is not a subselect. 05109 So we don't need to handle this table again. 05110 */ 05111 if (table_list->is_schema_table_processed && !is_subselect) 05112 continue; 05113 05114 if (is_subselect) // is subselect 05115 { 05116 table_list->table->file->extra(HA_EXTRA_RESET_STATE); 05117 table_list->table->file->delete_all_rows(); 05118 free_io_cache(table_list->table); 05119 filesort_free_buffers(table_list->table); 05120 table_list->table->null_row= 0; 05121 } 05122 else 05123 table_list->table->file->stats.records= 0; 05124 05125 if (table_list->schema_table->fill_table(thd, table_list, 05126 tab->select_cond)) 05127 { 05128 result= 1; 05129 join->error= 1; 05130 table_list->is_schema_table_processed= TRUE; 05131 break; 05132 } 05133 table_list->is_schema_table_processed= TRUE; 05134 } 05135 } 05136 thd->no_warnings_for_error= 0; 05137 DBUG_RETURN(result); 05138 } 05139 05140 struct run_hton_fill_schema_files_args 05141 { 05142 TABLE_LIST *tables; 05143 COND *cond; 05144 }; 05145 05146 static my_bool run_hton_fill_schema_files(THD *thd, st_plugin_int *plugin, 05147 void *arg) 05148 { 05149 struct run_hton_fill_schema_files_args *args= 05150 (run_hton_fill_schema_files_args *) arg; 05151 handlerton *hton= (handlerton *)plugin->data; 05152 if(hton->fill_files_table) 05153 hton->fill_files_table(thd, args->tables, args->cond); 05154 return false; 05155 } 05156 05157 int fill_schema_files(THD *thd, TABLE_LIST *tables, COND *cond) 05158 { 05159 int i; 05160 TABLE *table= tables->table; 05161 DBUG_ENTER("fill_schema_files"); 05162 05163 struct run_hton_fill_schema_files_args args; 05164 args.tables= tables; 05165 args.cond= cond; 05166 05167 plugin_foreach(thd, run_hton_fill_schema_files, 05168 MYSQL_STORAGE_ENGINE_PLUGIN, &args); 05169 05170 DBUG_RETURN(0); 05171 } 05172 05173 ST_FIELD_INFO schema_fields_info[]= 05174 { 05175 {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05176 {"SCHEMA_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database"}, 05177 {"DEFAULT_CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0}, 05178 {"DEFAULT_COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0}, 05179 {"SQL_PATH", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05180 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05181 }; 05182 05183 05184 ST_FIELD_INFO tables_fields_info[]= 05185 { 05186 {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05187 {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05188 {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"}, 05189 {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05190 {"ENGINE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine"}, 05191 {"VERSION", 21 , MYSQL_TYPE_LONG, 0, 1, "Version"}, 05192 {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format"}, 05193 {"TABLE_ROWS", 21 , MYSQL_TYPE_LONG, 0, 1, "Rows"}, 05194 {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Avg_row_length"}, 05195 {"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_length"}, 05196 {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Max_data_length"}, 05197 {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Index_length"}, 05198 {"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_free"}, 05199 {"AUTO_INCREMENT", 21 , MYSQL_TYPE_LONG, 0, 1, "Auto_increment"}, 05200 {"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Create_time"}, 05201 {"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Update_time"}, 05202 {"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Check_time"}, 05203 {"TABLE_COLLATION", 64, MYSQL_TYPE_STRING, 0, 1, "Collation"}, 05204 {"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, "Checksum"}, 05205 {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options"}, 05206 {"TABLE_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment"}, 05207 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05208 }; 05209 05210 05211 ST_FIELD_INFO columns_fields_info[]= 05212 { 05213 {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05214 {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05215 {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05216 {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Field"}, 05217 {"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, 05218 {"COLUMN_DEFAULT", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Default"}, 05219 {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"}, 05220 {"DATA_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05221 {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, 05222 {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, 05223 {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, 05224 {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, 05225 {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0}, 05226 {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, "Collation"}, 05227 {"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type"}, 05228 {"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key"}, 05229 {"EXTRA", 20, MYSQL_TYPE_STRING, 0, 0, "Extra"}, 05230 {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges"}, 05231 {"COLUMN_COMMENT", 255, MYSQL_TYPE_STRING, 0, 0, "Comment"}, 05232 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05233 }; 05234 05235 05236 ST_FIELD_INFO charsets_fields_info[]= 05237 { 05238 {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset"}, 05239 {"DEFAULT_COLLATE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Default collation"}, 05240 {"DESCRIPTION", 60, MYSQL_TYPE_STRING, 0, 0, "Description"}, 05241 {"MAXLEN", 3 ,MYSQL_TYPE_LONG, 0, 0, "Maxlen"}, 05242 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05243 }; 05244 05245 05246 ST_FIELD_INFO collation_fields_info[]= 05247 { 05248 {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Collation"}, 05249 {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset"}, 05250 {"ID", 11, MYSQL_TYPE_LONG, 0, 0, "Id"}, 05251 {"IS_DEFAULT", 3, MYSQL_TYPE_STRING, 0, 0, "Default"}, 05252 {"IS_COMPILED", 3, MYSQL_TYPE_STRING, 0, 0, "Compiled"}, 05253 {"SORTLEN", 3 ,MYSQL_TYPE_LONG, 0, 0, "Sortlen"}, 05254 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05255 }; 05256 05257 05258 ST_FIELD_INFO engines_fields_info[]= 05259 { 05260 {"ENGINE", 64, MYSQL_TYPE_STRING, 0, 0, "Engine"}, 05261 {"SUPPORT", 8, MYSQL_TYPE_STRING, 0, 0, "Support"}, 05262 {"COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment"}, 05263 {"TRANSACTIONS", 3, MYSQL_TYPE_STRING, 0, 0, "Transactions"}, 05264 {"XA", 3, MYSQL_TYPE_STRING, 0, 0, "XA"}, 05265 {"SAVEPOINTS", 3 ,MYSQL_TYPE_STRING, 0, 0, "Savepoints"}, 05266 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05267 }; 05268 05269 05270 ST_FIELD_INFO events_fields_info[]= 05271 { 05272 {"EVENT_CATALOG", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05273 {"EVENT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Db"}, 05274 {"EVENT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"}, 05275 {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer"}, 05276 {"EVENT_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0}, 05277 {"EVENT_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, 05278 {"EVENT_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"}, 05279 {"EXECUTE_AT", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Execute at"}, 05280 {"INTERVAL_VALUE", 256, MYSQL_TYPE_STRING, 0, 1, "Interval value"}, 05281 {"INTERVAL_FIELD", 18, MYSQL_TYPE_STRING, 0, 1, "Interval field"}, 05282 {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, 05283 {"STARTS", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Starts"}, 05284 {"ENDS", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Ends"}, 05285 {"STATUS", 8, MYSQL_TYPE_STRING, 0, 0, "Status"}, 05286 {"ON_COMPLETION", 12, MYSQL_TYPE_STRING, 0, 0, 0}, 05287 {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0}, 05288 {"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0}, 05289 {"LAST_EXECUTED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0}, 05290 {"EVENT_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05291 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05292 }; 05293 05294 05295 05296 ST_FIELD_INFO coll_charset_app_fields_info[]= 05297 { 05298 {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0}, 05299 {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0}, 05300 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05301 }; 05302 05303 05304 ST_FIELD_INFO proc_fields_info[]= 05305 { 05306 {"SPECIFIC_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05307 {"ROUTINE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05308 {"ROUTINE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Db"}, 05309 {"ROUTINE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"}, 05310 {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"}, 05311 {"DTD_IDENTIFIER", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05312 {"ROUTINE_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0}, 05313 {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, 05314 {"EXTERNAL_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05315 {"EXTERNAL_LANGUAGE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05316 {"PARAMETER_STYLE", 8, MYSQL_TYPE_STRING, 0, 0, 0}, 05317 {"IS_DETERMINISTIC", 3, MYSQL_TYPE_STRING, 0, 0, 0}, 05318 {"SQL_DATA_ACCESS", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05319 {"SQL_PATH", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05320 {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, "Security_type"}, 05321 {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Created"}, 05322 {"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Modified"}, 05323 {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, 05324 {"ROUTINE_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Comment"}, 05325 {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer"}, 05326 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05327 }; 05328 05329 05330 ST_FIELD_INFO stat_fields_info[]= 05331 { 05332 {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05333 {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05334 {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"}, 05335 {"NON_UNIQUE", 1, MYSQL_TYPE_LONG, 0, 0, "Non_unique"}, 05336 {"INDEX_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05337 {"INDEX_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Key_name"}, 05338 {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONG, 0, 0, "Seq_in_index"}, 05339 {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name"}, 05340 {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation"}, 05341 {"CARDINALITY", 21, MYSQL_TYPE_LONG, 0, 1, "Cardinality"}, 05342 {"SUB_PART", 3, MYSQL_TYPE_LONG, 0, 1, "Sub_part"}, 05343 {"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, "Packed"}, 05344 {"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"}, 05345 {"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, "Index_type"}, 05346 {"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, "Comment"}, 05347 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05348 }; 05349 05350 05351 ST_FIELD_INFO view_fields_info[]= 05352 { 05353 {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05354 {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05355 {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05356 {"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, 05357 {"CHECK_OPTION", 8, MYSQL_TYPE_STRING, 0, 0, 0}, 05358 {"IS_UPDATABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0}, 05359 {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, 0}, 05360 {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, 0}, 05361 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05362 }; 05363 05364 05365 ST_FIELD_INFO user_privileges_fields_info[]= 05366 { 05367 {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0}, 05368 {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05369 {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05370 {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0}, 05371 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05372 }; 05373 05374 05375 ST_FIELD_INFO schema_privileges_fields_info[]= 05376 { 05377 {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0}, 05378 {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05379 {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05380 {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05381 {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0}, 05382 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05383 }; 05384 05385 05386 ST_FIELD_INFO table_privileges_fields_info[]= 05387 { 05388 {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0}, 05389 {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05390 {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05391 {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05392 {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05393 {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0}, 05394 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05395 }; 05396 05397 05398 ST_FIELD_INFO column_privileges_fields_info[]= 05399 { 05400 {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0}, 05401 {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05402 {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05403 {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05404 {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05405 {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05406 {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0}, 05407 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05408 }; 05409 05410 05411 ST_FIELD_INFO table_constraints_fields_info[]= 05412 { 05413 {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05414 {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05415 {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05416 {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05417 {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05418 {"CONSTRAINT_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05419 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05420 }; 05421 05422 05423 ST_FIELD_INFO key_column_usage_fields_info[]= 05424 { 05425 {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05426 {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05427 {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05428 {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05429 {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05430 {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05431 {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05432 {"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONG, 0, 0, 0}, 05433 {"POSITION_IN_UNIQUE_CONSTRAINT", 10 ,MYSQL_TYPE_LONG, 0, 1, 0}, 05434 {"REFERENCED_TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05435 {"REFERENCED_TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05436 {"REFERENCED_COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05437 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05438 }; 05439 05440 05441 ST_FIELD_INFO table_names_fields_info[]= 05442 { 05443 {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05444 {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05445 {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_"}, 05446 {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type"}, 05447 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05448 }; 05449 05450 05451 ST_FIELD_INFO open_tables_fields_info[]= 05452 { 05453 {"Database", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database"}, 05454 {"Table",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"}, 05455 {"In_use", 1, MYSQL_TYPE_LONG, 0, 0, "In_use"}, 05456 {"Name_locked", 4, MYSQL_TYPE_LONG, 0, 0, "Name_locked"}, 05457 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05458 }; 05459 05460 05461 ST_FIELD_INFO triggers_fields_info[]= 05462 { 05463 {"TRIGGER_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05464 {"TRIGGER_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05465 {"TRIGGER_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Trigger"}, 05466 {"EVENT_MANIPULATION", 6, MYSQL_TYPE_STRING, 0, 0, "Event"}, 05467 {"EVENT_OBJECT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05468 {"EVENT_OBJECT_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05469 {"EVENT_OBJECT_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"}, 05470 {"ACTION_ORDER", 4, MYSQL_TYPE_LONG, 0, 0, 0}, 05471 {"ACTION_CONDITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, 05472 {"ACTION_STATEMENT", 65535, MYSQL_TYPE_STRING, 0, 0, "Statement"}, 05473 {"ACTION_ORIENTATION", 9, MYSQL_TYPE_STRING, 0, 0, 0}, 05474 {"ACTION_TIMING", 6, MYSQL_TYPE_STRING, 0, 0, "Timing"}, 05475 {"ACTION_REFERENCE_OLD_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05476 {"ACTION_REFERENCE_NEW_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05477 {"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0}, 05478 {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0}, 05479 {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Created"}, 05480 {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, "sql_mode"}, 05481 {"DEFINER", 65535, MYSQL_TYPE_STRING, 0, 0, "Definer"}, 05482 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05483 }; 05484 05485 05486 ST_FIELD_INFO partitions_fields_info[]= 05487 { 05488 {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05489 {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05490 {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05491 {"PARTITION_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05492 {"SUBPARTITION_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05493 {"PARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, 05494 {"SUBPARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, 05495 {"PARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0}, 05496 {"SUBPARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0}, 05497 {"PARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, 05498 {"SUBPARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, 05499 {"PARTITION_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, 05500 {"TABLE_ROWS", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, 05501 {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, 05502 {"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, 05503 {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, 05504 {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, 05505 {"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, 05506 {"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0}, 05507 {"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0}, 05508 {"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0}, 05509 {"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, 05510 {"PARTITION_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, 0}, 05511 {"NODEGROUP", 12 , MYSQL_TYPE_STRING, 0, 0, 0}, 05512 {"TABLESPACE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05513 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05514 }; 05515 05516 05517 ST_FIELD_INFO variables_fields_info[]= 05518 { 05519 {"Variable_name", 80, MYSQL_TYPE_STRING, 0, 0, "Variable_name"}, 05520 {"Value", 255, MYSQL_TYPE_STRING, 0, 0, "Value"}, 05521 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05522 }; 05523 05524 05525 ST_FIELD_INFO processlist_fields_info[]= 05526 { 05527 {"ID", 4, MYSQL_TYPE_LONG, 0, 0, "Id"}, 05528 {"USER", 16, MYSQL_TYPE_STRING, 0, 0, "User"}, 05529 {"HOST", LIST_PROCESS_HOST_LEN, MYSQL_TYPE_STRING, 0, 0, "Host"}, 05530 {"DB", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Db"}, 05531 {"COMMAND", 16, MYSQL_TYPE_STRING, 0, 0, "Command"}, 05532 {"TIME", 7, MYSQL_TYPE_LONG, 0, 0, "Time"}, 05533 {"STATE", 30, MYSQL_TYPE_STRING, 0, 1, "State"}, 05534 {"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info"}, 05535 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05536 }; 05537 05538 05539 ST_FIELD_INFO plugin_fields_info[]= 05540 { 05541 {"PLUGIN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"}, 05542 {"PLUGIN_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0}, 05543 {"PLUGIN_STATUS", 10, MYSQL_TYPE_STRING, 0, 0, "Status"}, 05544 {"PLUGIN_TYPE", 80, MYSQL_TYPE_STRING, 0, 0, "Type"}, 05545 {"PLUGIN_TYPE_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0}, 05546 {"PLUGIN_LIBRARY", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Library"}, 05547 {"PLUGIN_LIBRARY_VERSION", 20, MYSQL_TYPE_STRING, 0, 1, 0}, 05548 {"PLUGIN_AUTHOR", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05549 {"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, 05550 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05551 }; 05552 05553 ST_FIELD_INFO files_fields_info[]= 05554 { 05555 {"FILE_ID", 4, MYSQL_TYPE_LONG, 0, 0, 0}, 05556 {"FILE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05557 {"FILE_TYPE", 20, MYSQL_TYPE_STRING, 0, 0, 0}, 05558 {"TABLESPACE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05559 {"TABLE_CATALOG", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05560 {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05561 {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05562 {"LOGFILE_GROUP_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05563 {"LOGFILE_GROUP_NUMBER", 4, MYSQL_TYPE_LONG, 0, 0, 0}, 05564 {"ENGINE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05565 {"FULLTEXT_KEYS", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05566 {"DELETED_ROWS", 4, MYSQL_TYPE_LONG, 0, 0, 0}, 05567 {"UPDATE_COUNT", 4, MYSQL_TYPE_LONG, 0, 0, 0}, 05568 {"FREE_EXTENTS", 4, MYSQL_TYPE_LONG, 0, 0, 0}, 05569 {"TOTAL_EXTENTS", 4, MYSQL_TYPE_LONG, 0, 0, 0}, 05570 {"EXTENT_SIZE", 4, MYSQL_TYPE_LONG, 0, 0, 0}, 05571 {"INITIAL_SIZE", 21, MYSQL_TYPE_LONG, 0, 0, 0}, 05572 {"MAXIMUM_SIZE", 21, MYSQL_TYPE_LONG, 0, 0, 0}, 05573 {"AUTOEXTEND_SIZE", 21, MYSQL_TYPE_LONG, 0, 0, 0}, 05574 {"CREATION_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0}, 05575 {"LAST_UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0}, 05576 {"LAST_ACCESS_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0}, 05577 {"RECOVER_TIME", 4, MYSQL_TYPE_LONG, 0, 0, 0}, 05578 {"TRANSACTION_COUNTER", 4, MYSQL_TYPE_LONG, 0, 0, 0}, 05579 {"VERSION", 21 , MYSQL_TYPE_LONG, 0, 1, "Version"}, 05580 {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format"}, 05581 {"TABLE_ROWS", 21 , MYSQL_TYPE_LONG, 0, 1, "Rows"}, 05582 {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Avg_row_length"}, 05583 {"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_length"}, 05584 {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Max_data_length"}, 05585 {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Index_length"}, 05586 {"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_free"}, 05587 {"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Create_time"}, 05588 {"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Update_time"}, 05589 {"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Check_time"}, 05590 {"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, "Checksum"}, 05591 {"STATUS", 20, MYSQL_TYPE_STRING, 0, 0, 0}, 05592 {"EXTRA", 255, MYSQL_TYPE_STRING, 0, 0, 0}, 05593 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05594 }; 05595 05596 ST_FIELD_INFO referential_constraints_fields_info[]= 05597 { 05598 {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05599 {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05600 {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05601 {"UNIQUE_CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, 05602 {"UNIQUE_CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05603 {"UNIQUE_CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05604 {"MATCH_OPTION", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05605 {"UPDATE_RULE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05606 {"DELETE_RULE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05607 {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, 05608 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} 05609 }; 05610 05611 05612 /* 05613 Description of ST_FIELD_INFO in table.h 05614 05615 Make sure that the order of schema_tables and enum_schema_tables are the same. 05616 05617 */ 05618 05619 ST_SCHEMA_TABLE schema_tables[]= 05620 { 05621 {"CHARACTER_SETS", charsets_fields_info, create_schema_table, 05622 fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0}, 05623 {"COLLATIONS", collation_fields_info, create_schema_table, 05624 fill_schema_collation, make_old_format, 0, -1, -1, 0}, 05625 {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info, 05626 create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1, 0}, 05627 {"COLUMNS", columns_fields_info, create_schema_table, 05628 get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2, 0}, 05629 {"COLUMN_PRIVILEGES", column_privileges_fields_info, create_schema_table, 05630 fill_schema_column_privileges, 0, 0, -1, -1, 0}, 05631 {"ENGINES", engines_fields_info, create_schema_table, 05632 fill_schema_engines, make_old_format, 0, -1, -1, 0}, 05633 {"EVENTS", events_fields_info, create_schema_table, 05634 fill_schema_events, make_old_format, 0, -1, -1, 0}, 05635 {"FILES", files_fields_info, create_schema_table, 05636 fill_schema_files, 0, 0, -1, -1, 0}, 05637 {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table, 05638 get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0}, 05639 {"OPEN_TABLES", open_tables_fields_info, create_schema_table, 05640 fill_open_tables, make_old_format, 0, -1, -1, 1}, 05641 {"PARTITIONS", partitions_fields_info, create_schema_table, 05642 get_all_tables, 0, get_schema_partitions_record, 1, 2, 0}, 05643 {"PLUGINS", plugin_fields_info, create_schema_table, 05644 fill_plugins, make_old_format, 0, -1, -1, 0}, 05645 {"PROCESSLIST", processlist_fields_info, create_schema_table, 05646 fill_schema_processlist, make_old_format, 0, -1, -1, 0}, 05647 {"REFERENTIAL_CONSTRAINTS", referential_constraints_fields_info, 05648 create_schema_table, get_all_tables, 0, get_referential_constraints_record, 05649 1, 9, 0}, 05650 {"ROUTINES", proc_fields_info, create_schema_table, 05651 fill_schema_proc, make_proc_old_format, 0, -1, -1, 0}, 05652 {"SCHEMATA", schema_fields_info, create_schema_table, 05653 fill_schema_shemata, make_schemata_old_format, 0, 1, -1, 0}, 05654 {"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table, 05655 fill_schema_schema_privileges, 0, 0, -1, -1, 0}, 05656 {"STATISTICS", stat_fields_info, create_schema_table, 05657 get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0}, 05658 {"STATUS", variables_fields_info, create_schema_table, fill_status, 05659 make_old_format, 0, -1, -1, 1}, 05660 {"TABLES", tables_fields_info, create_schema_table, 05661 get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0}, 05662 {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table, 05663 get_all_tables, 0, get_schema_constraints_record, 3, 4, 0}, 05664 {"TABLE_NAMES", table_names_fields_info, create_schema_table, 05665 get_all_tables, make_table_names_old_format, 0, 1, 2, 1}, 05666 {"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table, 05667 fill_schema_table_privileges, 0, 0, -1, -1, 0}, 05668 {"TRIGGERS", triggers_fields_info, create_schema_table, 05669 get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0}, 05670 {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table, 05671 fill_schema_user_privileges, 0, 0, -1, -1, 0}, 05672 {"VARIABLES", variables_fields_info, create_schema_table, fill_variables, 05673 make_old_format, 0, -1, -1, 1}, 05674 {"VIEWS", view_fields_info, create_schema_table, 05675 get_all_tables, 0, get_schema_views_record, 1, 2, 0}, 05676 {0, 0, 0, 0, 0, 0, 0, 0, 0} 05677 }; 05678 05679 05680 #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION 05681 template class List_iterator_fast<char>; 05682 template class List<char>; 05683 #endif
1.4.7

