00001 /* Copyright (C) 2000-2003 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 #define MYSQL_LEX 1 00018 #include "mysql_priv.h" 00019 #include "sql_repl.h" 00020 #include "rpl_filter.h" 00021 #include "repl_failsafe.h" 00022 #include <m_ctype.h> 00023 #include <myisam.h> 00024 #include <my_dir.h> 00025 00026 #include "sp_head.h" 00027 #include "sp.h" 00028 #include "sp_cache.h" 00029 #include "events.h" 00030 #include "event_timed.h" 00031 00032 #ifdef HAVE_OPENSSL 00033 /* 00034 Without SSL the handshake consists of one packet. This packet 00035 has both client capabilites and scrambled password. 00036 With SSL the handshake might consist of two packets. If the first 00037 packet (client capabilities) has CLIENT_SSL flag set, we have to 00038 switch to SSL and read the second packet. The scrambled password 00039 is in the second packet and client_capabilites field will be ignored. 00040 Maybe it is better to accept flags other than CLIENT_SSL from the 00041 second packet? 00042 */ 00043 #define SSL_HANDSHAKE_SIZE 2 00044 #define NORMAL_HANDSHAKE_SIZE 6 00045 #define MIN_HANDSHAKE_SIZE 2 00046 #else 00047 #define MIN_HANDSHAKE_SIZE 6 00048 #endif /* HAVE_OPENSSL */ 00049 00050 /* Used in error handling only */ 00051 #define SP_TYPE_STRING(LP) \ 00052 ((LP)->sphead->m_type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE") 00053 #define SP_COM_STRING(LP) \ 00054 ((LP)->sql_command == SQLCOM_CREATE_SPFUNCTION || \ 00055 (LP)->sql_command == SQLCOM_ALTER_FUNCTION || \ 00056 (LP)->sql_command == SQLCOM_SHOW_CREATE_FUNC || \ 00057 (LP)->sql_command == SQLCOM_DROP_FUNCTION ? \ 00058 "FUNCTION" : "PROCEDURE") 00059 00060 #ifdef SOLARIS 00061 extern "C" int gethostname(char *name, int namelen); 00062 #endif 00063 00064 static void time_out_user_resource_limits(THD *thd, USER_CONN *uc); 00065 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00066 static int check_for_max_user_connections(THD *thd, USER_CONN *uc); 00067 static void decrease_user_connections(USER_CONN *uc); 00068 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 00069 static bool check_multi_update_lock(THD *thd); 00070 static void remove_escape(char *name); 00071 static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables); 00072 00073 const char *any_db="*any*"; // Special symbol for check_access 00074 00075 const LEX_STRING command_name[]={ 00076 C_STRING_WITH_LEN("Sleep"), 00077 C_STRING_WITH_LEN("Quit"), 00078 C_STRING_WITH_LEN("Init DB"), 00079 C_STRING_WITH_LEN("Query"), 00080 C_STRING_WITH_LEN("Field List"), 00081 C_STRING_WITH_LEN("Create DB"), 00082 C_STRING_WITH_LEN("Drop DB"), 00083 C_STRING_WITH_LEN("Refresh"), 00084 C_STRING_WITH_LEN("Shutdown"), 00085 C_STRING_WITH_LEN("Statistics"), 00086 C_STRING_WITH_LEN("Processlist"), 00087 C_STRING_WITH_LEN("Connect"), 00088 C_STRING_WITH_LEN("Kill"), 00089 C_STRING_WITH_LEN("Debug"), 00090 C_STRING_WITH_LEN("Ping"), 00091 C_STRING_WITH_LEN("Time"), 00092 C_STRING_WITH_LEN("Delayed insert"), 00093 C_STRING_WITH_LEN("Change user"), 00094 C_STRING_WITH_LEN("Binlog Dump"), 00095 C_STRING_WITH_LEN("Table Dump"), 00096 C_STRING_WITH_LEN("Connect Out"), 00097 C_STRING_WITH_LEN("Register Slave"), 00098 C_STRING_WITH_LEN("Prepare"), 00099 C_STRING_WITH_LEN("Execute"), 00100 C_STRING_WITH_LEN("Long Data"), 00101 C_STRING_WITH_LEN("Close stmt"), 00102 C_STRING_WITH_LEN("Reset stmt"), 00103 C_STRING_WITH_LEN("Set option"), 00104 C_STRING_WITH_LEN("Fetch"), 00105 C_STRING_WITH_LEN("Daemon"), 00106 C_STRING_WITH_LEN("Error") // Last command number 00107 }; 00108 00109 const char *xa_state_names[]={ 00110 "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED" 00111 }; 00112 00113 #ifdef __WIN__ 00114 static void test_signal(int sig_ptr) 00115 { 00116 #if !defined( DBUG_OFF) 00117 MessageBox(NULL,"Test signal","DBUG",MB_OK); 00118 #endif 00119 } 00120 static void init_signals(void) 00121 { 00122 int signals[7] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGBREAK,SIGABRT } ; 00123 for (int i=0 ; i < 7 ; i++) 00124 signal( signals[i], test_signal) ; 00125 } 00126 #endif 00127 00128 static void unlock_locked_tables(THD *thd) 00129 { 00130 if (thd->locked_tables) 00131 { 00132 thd->lock=thd->locked_tables; 00133 thd->locked_tables=0; // Will be automatically closed 00134 close_thread_tables(thd); // Free tables 00135 } 00136 } 00137 00138 00139 bool end_active_trans(THD *thd) 00140 { 00141 int error=0; 00142 DBUG_ENTER("end_active_trans"); 00143 if (unlikely(thd->in_sub_stmt)) 00144 { 00145 my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); 00146 DBUG_RETURN(1); 00147 } 00148 if (thd->transaction.xid_state.xa_state != XA_NOTR) 00149 { 00150 my_error(ER_XAER_RMFAIL, MYF(0), 00151 xa_state_names[thd->transaction.xid_state.xa_state]); 00152 DBUG_RETURN(1); 00153 } 00154 if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | 00155 OPTION_TABLE_LOCK)) 00156 { 00157 DBUG_PRINT("info",("options: 0x%lx", (ulong) thd->options)); 00158 /* Safety if one did "drop table" on locked tables */ 00159 if (!thd->locked_tables) 00160 thd->options&= ~OPTION_TABLE_LOCK; 00161 thd->server_status&= ~SERVER_STATUS_IN_TRANS; 00162 if (ha_commit(thd)) 00163 error=1; 00164 } 00165 thd->options&= ~(OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE | 00166 OPTION_KEEP_LOG); 00167 DBUG_RETURN(error); 00168 } 00169 00170 bool begin_trans(THD *thd) 00171 { 00172 int error=0; 00173 if (unlikely(thd->in_sub_stmt)) 00174 { 00175 my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); 00176 return 1; 00177 } 00178 if (thd->locked_tables) 00179 { 00180 thd->lock=thd->locked_tables; 00181 thd->locked_tables=0; // Will be automatically closed 00182 close_thread_tables(thd); // Free tables 00183 } 00184 if (end_active_trans(thd)) 00185 error= -1; 00186 else 00187 { 00188 LEX *lex= thd->lex; 00189 thd->options|= OPTION_BEGIN; 00190 thd->server_status|= SERVER_STATUS_IN_TRANS; 00191 if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) 00192 error= ha_start_consistent_snapshot(thd); 00193 } 00194 return error; 00195 } 00196 00197 #ifdef HAVE_REPLICATION 00198 /* 00199 Returns true if all tables should be ignored 00200 */ 00201 inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables) 00202 { 00203 return rpl_filter->is_on() && tables && !thd->spcont && 00204 !rpl_filter->tables_ok(thd->db, tables); 00205 } 00206 #endif 00207 00208 00209 static bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables) 00210 { 00211 for (TABLE_LIST *table= tables; table; table= table->next_global) 00212 { 00213 DBUG_ASSERT(table->db && table->table_name); 00214 if (table->updating && 00215 !find_temporary_table(thd, table->db, table->table_name)) 00216 return 1; 00217 } 00218 return 0; 00219 } 00220 00221 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00222 static HASH hash_user_connections; 00223 00224 static int get_or_create_user_conn(THD *thd, const char *user, 00225 const char *host, 00226 USER_RESOURCES *mqh) 00227 { 00228 int return_val= 0; 00229 uint temp_len, user_len; 00230 char temp_user[USER_HOST_BUFF_SIZE]; 00231 struct user_conn *uc; 00232 00233 DBUG_ASSERT(user != 0); 00234 DBUG_ASSERT(host != 0); 00235 00236 user_len= strlen(user); 00237 temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1; 00238 (void) pthread_mutex_lock(&LOCK_user_conn); 00239 if (!(uc = (struct user_conn *) hash_search(&hash_user_connections, 00240 (byte*) temp_user, temp_len))) 00241 { 00242 /* First connection for user; Create a user connection object */ 00243 if (!(uc= ((struct user_conn*) 00244 my_malloc(sizeof(struct user_conn) + temp_len+1, 00245 MYF(MY_WME))))) 00246 { 00247 net_send_error(thd, 0, NullS); // Out of memory 00248 return_val= 1; 00249 goto end; 00250 } 00251 uc->user=(char*) (uc+1); 00252 memcpy(uc->user,temp_user,temp_len+1); 00253 uc->host= uc->user + user_len + 1; 00254 uc->len= temp_len; 00255 uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0; 00256 uc->user_resources= *mqh; 00257 uc->intime= thd->thr_create_time; 00258 if (my_hash_insert(&hash_user_connections, (byte*) uc)) 00259 { 00260 my_free((char*) uc,0); 00261 net_send_error(thd, 0, NullS); // Out of memory 00262 return_val= 1; 00263 goto end; 00264 } 00265 } 00266 thd->user_connect=uc; 00267 uc->connections++; 00268 end: 00269 (void) pthread_mutex_unlock(&LOCK_user_conn); 00270 return return_val; 00271 00272 } 00273 #endif /* !NO_EMBEDDED_ACCESS_CHECKS */ 00274 00275 00276 /* 00277 Check if user exist and password supplied is correct. 00278 00279 SYNOPSIS 00280 check_user() 00281 thd thread handle, thd->security_ctx->{host,user,ip} are used 00282 command originator of the check: now check_user is called 00283 during connect and change user procedures; used for 00284 logging. 00285 passwd scrambled password received from client 00286 passwd_len length of scrambled password 00287 db database name to connect to, may be NULL 00288 check_count dont know exactly 00289 00290 Note, that host, user and passwd may point to communication buffer. 00291 Current implementation does not depend on that, but future changes 00292 should be done with this in mind; 'thd' is INOUT, all other params 00293 are 'IN'. 00294 00295 RETURN VALUE 00296 0 OK; thd->security_ctx->user/master_access/priv_user/db_access and 00297 thd->db are updated; OK is sent to client; 00298 -1 access denied or handshake error; error is sent to client; 00299 >0 error, not sent to client 00300 */ 00301 00302 int check_user(THD *thd, enum enum_server_command command, 00303 const char *passwd, uint passwd_len, const char *db, 00304 bool check_count) 00305 { 00306 DBUG_ENTER("check_user"); 00307 00308 #ifdef NO_EMBEDDED_ACCESS_CHECKS 00309 thd->main_security_ctx.master_access= GLOBAL_ACLS; // Full rights 00310 /* Change database if necessary */ 00311 if (db && db[0]) 00312 { 00313 /* 00314 thd->db is saved in caller and needs to be freed by caller if this 00315 function returns 0 00316 */ 00317 thd->reset_db(NULL, 0); 00318 if (mysql_change_db(thd, db, FALSE)) 00319 { 00320 /* Send the error to the client */ 00321 net_send_error(thd); 00322 DBUG_RETURN(-1); 00323 } 00324 } 00325 send_ok(thd); 00326 DBUG_RETURN(0); 00327 #else 00328 00329 my_bool opt_secure_auth_local; 00330 pthread_mutex_lock(&LOCK_global_system_variables); 00331 opt_secure_auth_local= opt_secure_auth; 00332 pthread_mutex_unlock(&LOCK_global_system_variables); 00333 00334 /* 00335 If the server is running in secure auth mode, short scrambles are 00336 forbidden. 00337 */ 00338 if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323) 00339 { 00340 net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE); 00341 general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE)); 00342 DBUG_RETURN(-1); 00343 } 00344 if (passwd_len != 0 && 00345 passwd_len != SCRAMBLE_LENGTH && 00346 passwd_len != SCRAMBLE_LENGTH_323) 00347 DBUG_RETURN(ER_HANDSHAKE_ERROR); 00348 00349 /* 00350 Clear thd->db as it points to something, that will be freed when 00351 connection is closed. We don't want to accidentally free a wrong pointer 00352 if connect failed. Also in case of 'CHANGE USER' failure, current 00353 database will be switched to 'no database selected'. 00354 */ 00355 thd->reset_db(NULL, 0); 00356 00357 USER_RESOURCES ur; 00358 int res= acl_getroot(thd, &ur, passwd, passwd_len); 00359 #ifndef EMBEDDED_LIBRARY 00360 if (res == -1) 00361 { 00362 /* 00363 This happens when client (new) sends password scrambled with 00364 scramble(), but database holds old value (scrambled with 00365 scramble_323()). Here we please client to send scrambled_password 00366 in old format. 00367 */ 00368 NET *net= &thd->net; 00369 if (opt_secure_auth_local) 00370 { 00371 net_printf_error(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE, 00372 thd->main_security_ctx.user, 00373 thd->main_security_ctx.host_or_ip); 00374 general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE), 00375 thd->main_security_ctx.user, 00376 thd->main_security_ctx.host_or_ip); 00377 DBUG_RETURN(-1); 00378 } 00379 /* We have to read very specific packet size */ 00380 if (send_old_password_request(thd) || 00381 my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) 00382 { 00383 inc_host_errors(&thd->remote.sin_addr); 00384 DBUG_RETURN(ER_HANDSHAKE_ERROR); 00385 } 00386 /* Final attempt to check the user based on reply */ 00387 /* So as passwd is short, errcode is always >= 0 */ 00388 res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323); 00389 } 00390 #endif /*EMBEDDED_LIBRARY*/ 00391 /* here res is always >= 0 */ 00392 if (res == 0) 00393 { 00394 if (!(thd->main_security_ctx.master_access & 00395 NO_ACCESS)) // authentication is OK 00396 { 00397 DBUG_PRINT("info", 00398 ("Capabilities: %lx packet_length: %ld Host: '%s' " 00399 "Login user: '%s' Priv_user: '%s' Using password: %s " 00400 "Access: %u db: '%s'", 00401 thd->client_capabilities, 00402 thd->max_client_packet_length, 00403 thd->main_security_ctx.host_or_ip, 00404 thd->main_security_ctx.user, 00405 thd->main_security_ctx.priv_user, 00406 passwd_len ? "yes": "no", 00407 thd->main_security_ctx.master_access, 00408 (thd->db ? thd->db : "*none*"))); 00409 00410 if (check_count) 00411 { 00412 VOID(pthread_mutex_lock(&LOCK_thread_count)); 00413 bool count_ok= thread_count <= max_connections + delayed_insert_threads 00414 || (thd->main_security_ctx.master_access & SUPER_ACL); 00415 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 00416 if (!count_ok) 00417 { // too many connections 00418 net_send_error(thd, ER_CON_COUNT_ERROR); 00419 DBUG_RETURN(-1); 00420 } 00421 } 00422 00423 /* Why logging is performed before all checks've passed? */ 00424 general_log_print(thd, command, 00425 (thd->main_security_ctx.priv_user == 00426 thd->main_security_ctx.user ? 00427 (char*) "%s@%s on %s" : 00428 (char*) "%s@%s as anonymous on %s"), 00429 thd->main_security_ctx.user, 00430 thd->main_security_ctx.host_or_ip, 00431 db ? db : (char*) ""); 00432 00433 /* 00434 This is the default access rights for the current database. It's 00435 set to 0 here because we don't have an active database yet (and we 00436 may not have an active database to set. 00437 */ 00438 thd->main_security_ctx.db_access=0; 00439 00440 /* Don't allow user to connect if he has done too many queries */ 00441 if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn || 00442 max_user_connections) && 00443 get_or_create_user_conn(thd, 00444 (opt_old_style_user_limits ? thd->main_security_ctx.user : 00445 thd->main_security_ctx.priv_user), 00446 (opt_old_style_user_limits ? thd->main_security_ctx.host_or_ip : 00447 thd->main_security_ctx.priv_host), 00448 &ur)) 00449 DBUG_RETURN(-1); 00450 if (thd->user_connect && 00451 (thd->user_connect->user_resources.conn_per_hour || 00452 thd->user_connect->user_resources.user_conn || 00453 max_user_connections) && 00454 check_for_max_user_connections(thd, thd->user_connect)) 00455 DBUG_RETURN(-1); 00456 00457 /* Change database if necessary */ 00458 if (db && db[0]) 00459 { 00460 if (mysql_change_db(thd, db, FALSE)) 00461 { 00462 /* Send error to the client */ 00463 net_send_error(thd); 00464 if (thd->user_connect) 00465 decrease_user_connections(thd->user_connect); 00466 DBUG_RETURN(-1); 00467 } 00468 } 00469 send_ok(thd); 00470 thd->password= test(passwd_len); // remember for error messages 00471 /* Ready to handle queries */ 00472 DBUG_RETURN(0); 00473 } 00474 } 00475 else if (res == 2) // client gave short hash, server has long hash 00476 { 00477 net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE); 00478 general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE)); 00479 DBUG_RETURN(-1); 00480 } 00481 net_printf_error(thd, ER_ACCESS_DENIED_ERROR, 00482 thd->main_security_ctx.user, 00483 thd->main_security_ctx.host_or_ip, 00484 passwd_len ? ER(ER_YES) : ER(ER_NO)); 00485 general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR), 00486 thd->main_security_ctx.user, 00487 thd->main_security_ctx.host_or_ip, 00488 passwd_len ? ER(ER_YES) : ER(ER_NO)); 00489 DBUG_RETURN(-1); 00490 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 00491 } 00492 00493 /* 00494 Check for maximum allowable user connections, if the mysqld server is 00495 started with corresponding variable that is greater then 0. 00496 */ 00497 00498 extern "C" byte *get_key_conn(user_conn *buff, uint *length, 00499 my_bool not_used __attribute__((unused))) 00500 { 00501 *length=buff->len; 00502 return (byte*) buff->user; 00503 } 00504 00505 extern "C" void free_user(struct user_conn *uc) 00506 { 00507 my_free((char*) uc,MYF(0)); 00508 } 00509 00510 void init_max_user_conn(void) 00511 { 00512 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00513 (void) hash_init(&hash_user_connections,system_charset_info,max_connections, 00514 0,0, 00515 (hash_get_key) get_key_conn, (hash_free_key) free_user, 00516 0); 00517 #endif 00518 } 00519 00520 00521 /* 00522 check if user has already too many connections 00523 00524 SYNOPSIS 00525 check_for_max_user_connections() 00526 thd Thread handle 00527 uc User connect object 00528 00529 NOTES 00530 If check fails, we decrease user connection count, which means one 00531 shouldn't call decrease_user_connections() after this function. 00532 00533 RETURN 00534 0 ok 00535 1 error 00536 */ 00537 00538 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00539 00540 static int check_for_max_user_connections(THD *thd, USER_CONN *uc) 00541 { 00542 int error=0; 00543 DBUG_ENTER("check_for_max_user_connections"); 00544 00545 (void) pthread_mutex_lock(&LOCK_user_conn); 00546 if (max_user_connections && !uc->user_resources.user_conn && 00547 max_user_connections < (uint) uc->connections) 00548 { 00549 net_printf_error(thd, ER_TOO_MANY_USER_CONNECTIONS, uc->user); 00550 error=1; 00551 goto end; 00552 } 00553 time_out_user_resource_limits(thd, uc); 00554 if (uc->user_resources.user_conn && 00555 uc->user_resources.user_conn < uc->connections) 00556 { 00557 net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, 00558 "max_user_connections", 00559 (long) uc->user_resources.user_conn); 00560 error= 1; 00561 goto end; 00562 } 00563 if (uc->user_resources.conn_per_hour && 00564 uc->user_resources.conn_per_hour <= uc->conn_per_hour) 00565 { 00566 net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, 00567 "max_connections_per_hour", 00568 (long) uc->user_resources.conn_per_hour); 00569 error=1; 00570 goto end; 00571 } 00572 uc->conn_per_hour++; 00573 00574 end: 00575 if (error) 00576 uc->connections--; // no need for decrease_user_connections() here 00577 (void) pthread_mutex_unlock(&LOCK_user_conn); 00578 DBUG_RETURN(error); 00579 } 00580 00581 /* 00582 Decrease user connection count 00583 00584 SYNOPSIS 00585 decrease_user_connections() 00586 uc User connection object 00587 00588 NOTES 00589 If there is a n user connection object for a connection 00590 (which only happens if 'max_user_connections' is defined or 00591 if someone has created a resource grant for a user), then 00592 the connection count is always incremented on connect. 00593 00594 The user connect object is not freed if some users has 00595 'max connections per hour' defined as we need to be able to hold 00596 count over the lifetime of the connection. 00597 */ 00598 00599 static void decrease_user_connections(USER_CONN *uc) 00600 { 00601 DBUG_ENTER("decrease_user_connections"); 00602 (void) pthread_mutex_lock(&LOCK_user_conn); 00603 DBUG_ASSERT(uc->connections); 00604 if (!--uc->connections && !mqh_used) 00605 { 00606 /* Last connection for user; Delete it */ 00607 (void) hash_delete(&hash_user_connections,(byte*) uc); 00608 } 00609 (void) pthread_mutex_unlock(&LOCK_user_conn); 00610 DBUG_VOID_RETURN; 00611 } 00612 00613 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 00614 00615 00616 void free_max_user_conn(void) 00617 { 00618 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00619 hash_free(&hash_user_connections); 00620 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 00621 } 00622 00623 00624 00625 /* 00626 Mark all commands that somehow changes a table 00627 This is used to check number of updates / hour 00628 00629 sql_command is actually set to SQLCOM_END sometimes 00630 so we need the +1 to include it in the array. 00631 00632 See COMMAND_FLAG_xxx for different type of commands 00633 2 - query that returns meaningful ROW_COUNT() - 00634 a number of modified rows 00635 */ 00636 00637 uint sql_command_flags[SQLCOM_END+1]; 00638 00639 void init_update_queries(void) 00640 { 00641 bzero((gptr) &sql_command_flags, sizeof(sql_command_flags)); 00642 00643 sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA; 00644 sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA; 00645 sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA; 00646 sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA; 00647 sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA; 00648 sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA; 00649 sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA; 00650 sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA; 00651 sql_command_flags[SQLCOM_RENAME_TABLE]= CF_CHANGES_DATA; 00652 sql_command_flags[SQLCOM_BACKUP_TABLE]= CF_CHANGES_DATA; 00653 sql_command_flags[SQLCOM_RESTORE_TABLE]= CF_CHANGES_DATA; 00654 sql_command_flags[SQLCOM_DROP_INDEX]= CF_CHANGES_DATA; 00655 sql_command_flags[SQLCOM_CREATE_VIEW]= CF_CHANGES_DATA; 00656 sql_command_flags[SQLCOM_DROP_VIEW]= CF_CHANGES_DATA; 00657 sql_command_flags[SQLCOM_CREATE_EVENT]= CF_CHANGES_DATA; 00658 sql_command_flags[SQLCOM_ALTER_EVENT]= CF_CHANGES_DATA; 00659 sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA; 00660 00661 sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00662 sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00663 sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00664 sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00665 sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00666 sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00667 sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00668 sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00669 00670 sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND; 00671 sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND; 00672 sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND; 00673 sql_command_flags[SQLCOM_SHOW_DATABASES]= CF_STATUS_COMMAND; 00674 sql_command_flags[SQLCOM_SHOW_TRIGGERS]= CF_STATUS_COMMAND; 00675 sql_command_flags[SQLCOM_SHOW_EVENTS]= CF_STATUS_COMMAND; 00676 sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]= CF_STATUS_COMMAND; 00677 sql_command_flags[SQLCOM_SHOW_PLUGINS]= CF_STATUS_COMMAND; 00678 sql_command_flags[SQLCOM_SHOW_FIELDS]= CF_STATUS_COMMAND; 00679 sql_command_flags[SQLCOM_SHOW_KEYS]= CF_STATUS_COMMAND; 00680 sql_command_flags[SQLCOM_SHOW_VARIABLES]= CF_STATUS_COMMAND; 00681 sql_command_flags[SQLCOM_SHOW_CHARSETS]= CF_STATUS_COMMAND; 00682 sql_command_flags[SQLCOM_SHOW_COLLATIONS]= CF_STATUS_COMMAND; 00683 sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND; 00684 00685 sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND | 00686 CF_SHOW_TABLE_COMMAND); 00687 sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND | 00688 CF_SHOW_TABLE_COMMAND); 00689 00690 /* 00691 The following is used to preserver CF_ROW_COUNT during the 00692 a CALL or EXECUTE statement, so the value generated by the 00693 last called (or executed) statement is preserved. 00694 See mysql_execute_command() for how CF_ROW_COUNT is used. 00695 */ 00696 sql_command_flags[SQLCOM_CALL]= CF_HAS_ROW_COUNT; 00697 sql_command_flags[SQLCOM_EXECUTE]= CF_HAS_ROW_COUNT; 00698 } 00699 00700 00701 bool is_update_query(enum enum_sql_command command) 00702 { 00703 DBUG_ASSERT(command >= 0 && command <= SQLCOM_END); 00704 return (sql_command_flags[command] & CF_CHANGES_DATA) != 0; 00705 } 00706 00707 /* 00708 Reset per-hour user resource limits when it has been more than 00709 an hour since they were last checked 00710 00711 SYNOPSIS: 00712 time_out_user_resource_limits() 00713 thd Thread handler 00714 uc User connection details 00715 00716 NOTE: 00717 This assumes that the LOCK_user_conn mutex has been acquired, so it is 00718 safe to test and modify members of the USER_CONN structure. 00719 */ 00720 00721 static void time_out_user_resource_limits(THD *thd, USER_CONN *uc) 00722 { 00723 time_t check_time = thd->start_time ? thd->start_time : time(NULL); 00724 DBUG_ENTER("time_out_user_resource_limits"); 00725 00726 /* If more than a hour since last check, reset resource checking */ 00727 if (check_time - uc->intime >= 3600) 00728 { 00729 uc->questions=1; 00730 uc->updates=0; 00731 uc->conn_per_hour=0; 00732 uc->intime=check_time; 00733 } 00734 00735 DBUG_VOID_RETURN; 00736 } 00737 00738 00739 /* 00740 Check if maximum queries per hour limit has been reached 00741 returns 0 if OK. 00742 */ 00743 00744 static bool check_mqh(THD *thd, uint check_command) 00745 { 00746 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00747 bool error= 0; 00748 USER_CONN *uc=thd->user_connect; 00749 DBUG_ENTER("check_mqh"); 00750 DBUG_ASSERT(uc != 0); 00751 00752 (void) pthread_mutex_lock(&LOCK_user_conn); 00753 00754 time_out_user_resource_limits(thd, uc); 00755 00756 /* Check that we have not done too many questions / hour */ 00757 if (uc->user_resources.questions && 00758 uc->questions++ >= uc->user_resources.questions) 00759 { 00760 net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions", 00761 (long) uc->user_resources.questions); 00762 error=1; 00763 goto end; 00764 } 00765 if (check_command < (uint) SQLCOM_END) 00766 { 00767 /* Check that we have not done too many updates / hour */ 00768 if (uc->user_resources.updates && 00769 (sql_command_flags[check_command] & CF_CHANGES_DATA) && 00770 uc->updates++ >= uc->user_resources.updates) 00771 { 00772 net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates", 00773 (long) uc->user_resources.updates); 00774 error=1; 00775 goto end; 00776 } 00777 } 00778 end: 00779 (void) pthread_mutex_unlock(&LOCK_user_conn); 00780 DBUG_RETURN(error); 00781 #else 00782 return (0); 00783 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 00784 } 00785 00786 00787 static void reset_mqh(LEX_USER *lu, bool get_them= 0) 00788 { 00789 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00790 (void) pthread_mutex_lock(&LOCK_user_conn); 00791 if (lu) // for GRANT 00792 { 00793 USER_CONN *uc; 00794 uint temp_len=lu->user.length+lu->host.length+2; 00795 char temp_user[USER_HOST_BUFF_SIZE]; 00796 00797 memcpy(temp_user,lu->user.str,lu->user.length); 00798 memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length); 00799 temp_user[lu->user.length]='\0'; temp_user[temp_len-1]=0; 00800 if ((uc = (struct user_conn *) hash_search(&hash_user_connections, 00801 (byte*) temp_user, temp_len))) 00802 { 00803 uc->questions=0; 00804 get_mqh(temp_user,&temp_user[lu->user.length+1],uc); 00805 uc->updates=0; 00806 uc->conn_per_hour=0; 00807 } 00808 } 00809 else 00810 { 00811 /* for FLUSH PRIVILEGES and FLUSH USER_RESOURCES */ 00812 for (uint idx=0;idx < hash_user_connections.records; idx++) 00813 { 00814 USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections, 00815 idx); 00816 if (get_them) 00817 get_mqh(uc->user,uc->host,uc); 00818 uc->questions=0; 00819 uc->updates=0; 00820 uc->conn_per_hour=0; 00821 } 00822 } 00823 (void) pthread_mutex_unlock(&LOCK_user_conn); 00824 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 00825 } 00826 00827 void thd_init_client_charset(THD *thd, uint cs_number) 00828 { 00829 /* 00830 Use server character set and collation if 00831 - opt_character_set_client_handshake is not set 00832 - client has not specified a character set 00833 - client character set is the same as the servers 00834 - client character set doesn't exists in server 00835 */ 00836 if (!opt_character_set_client_handshake || 00837 !(thd->variables.character_set_client= get_charset(cs_number, MYF(0))) || 00838 !my_strcasecmp(&my_charset_latin1, 00839 global_system_variables.character_set_client->name, 00840 thd->variables.character_set_client->name)) 00841 { 00842 thd->variables.character_set_client= 00843 global_system_variables.character_set_client; 00844 thd->variables.collation_connection= 00845 global_system_variables.collation_connection; 00846 thd->variables.character_set_results= 00847 global_system_variables.character_set_results; 00848 } 00849 else 00850 { 00851 thd->variables.character_set_results= 00852 thd->variables.collation_connection= 00853 thd->variables.character_set_client; 00854 } 00855 } 00856 00857 00858 /* 00859 Perform handshake, authorize client and update thd ACL variables. 00860 SYNOPSIS 00861 check_connection() 00862 thd thread handle 00863 00864 RETURN 00865 0 success, OK is sent to user, thd is updated. 00866 -1 error, which is sent to user 00867 > 0 error code (not sent to user) 00868 */ 00869 00870 #ifndef EMBEDDED_LIBRARY 00871 static int check_connection(THD *thd) 00872 { 00873 uint connect_errors= 0; 00874 NET *net= &thd->net; 00875 ulong pkt_len= 0; 00876 char *end; 00877 00878 DBUG_PRINT("info", 00879 ("New connection received on %s", vio_description(net->vio))); 00880 #ifdef SIGNAL_WITH_VIO_CLOSE 00881 thd->set_active_vio(net->vio); 00882 #endif 00883 00884 if (!thd->main_security_ctx.host) // If TCP/IP connection 00885 { 00886 char ip[30]; 00887 00888 if (vio_peer_addr(net->vio, ip, &thd->peer_port)) 00889 return (ER_BAD_HOST_ERROR); 00890 if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(0)))) 00891 return (ER_OUT_OF_RESOURCES); 00892 thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip; 00893 vio_in_addr(net->vio,&thd->remote.sin_addr); 00894 if (!(specialflag & SPECIAL_NO_RESOLVE)) 00895 { 00896 vio_in_addr(net->vio,&thd->remote.sin_addr); 00897 thd->main_security_ctx.host= 00898 ip_to_hostname(&thd->remote.sin_addr, &connect_errors); 00899 /* Cut very long hostnames to avoid possible overflows */ 00900 if (thd->main_security_ctx.host) 00901 { 00902 if (thd->main_security_ctx.host != my_localhost) 00903 thd->main_security_ctx.host[min(strlen(thd->main_security_ctx.host), 00904 HOSTNAME_LENGTH)]= 0; 00905 thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host; 00906 } 00907 if (connect_errors > max_connect_errors) 00908 return(ER_HOST_IS_BLOCKED); 00909 } 00910 DBUG_PRINT("info",("Host: %s ip: %s", 00911 (thd->main_security_ctx.host ? 00912 thd->main_security_ctx.host : "unknown host"), 00913 (thd->main_security_ctx.ip ? 00914 thd->main_security_ctx.ip : "unknown ip"))); 00915 if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip)) 00916 return(ER_HOST_NOT_PRIVILEGED); 00917 } 00918 else /* Hostname given means that the connection was on a socket */ 00919 { 00920 DBUG_PRINT("info",("Host: %s", thd->main_security_ctx.host)); 00921 thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host; 00922 thd->main_security_ctx.ip= 0; 00923 /* Reset sin_addr */ 00924 bzero((char*) &thd->remote, sizeof(thd->remote)); 00925 } 00926 vio_keepalive(net->vio, TRUE); 00927 { 00928 /* buff[] needs to big enough to hold the server_version variable */ 00929 char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64]; 00930 ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB | 00931 CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION); 00932 00933 if (opt_using_transactions) 00934 client_flags|=CLIENT_TRANSACTIONS; 00935 #ifdef HAVE_COMPRESS 00936 client_flags |= CLIENT_COMPRESS; 00937 #endif /* HAVE_COMPRESS */ 00938 #ifdef HAVE_OPENSSL 00939 if (ssl_acceptor_fd) 00940 client_flags |= CLIENT_SSL; /* Wow, SSL is available! */ 00941 #endif /* HAVE_OPENSSL */ 00942 00943 end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1; 00944 int4store((uchar*) end, thd->thread_id); 00945 end+= 4; 00946 /* 00947 So as check_connection is the only entry point to authorization 00948 procedure, scramble is set here. This gives us new scramble for 00949 each handshake. 00950 */ 00951 create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand); 00952 /* 00953 Old clients does not understand long scrambles, but can ignore packet 00954 tail: that's why first part of the scramble is placed here, and second 00955 part at the end of packet. 00956 */ 00957 end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1; 00958 00959 int2store(end, client_flags); 00960 /* write server characteristics: up to 16 bytes allowed */ 00961 end[2]=(char) default_charset_info->number; 00962 int2store(end+3, thd->server_status); 00963 bzero(end+5, 13); 00964 end+= 18; 00965 /* write scramble tail */ 00966 end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323, 00967 SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1; 00968 00969 /* At this point we write connection message and read reply */ 00970 if (net_write_command(net, (uchar) protocol_version, "", 0, buff, 00971 (uint) (end-buff)) || 00972 (pkt_len= my_net_read(net)) == packet_error || 00973 pkt_len < MIN_HANDSHAKE_SIZE) 00974 { 00975 inc_host_errors(&thd->remote.sin_addr); 00976 return(ER_HANDSHAKE_ERROR); 00977 } 00978 } 00979 #ifdef _CUSTOMCONFIG_ 00980 #include "_cust_sql_parse.h" 00981 #endif 00982 if (connect_errors) 00983 reset_host_errors(&thd->remote.sin_addr); 00984 if (thd->packet.alloc(thd->variables.net_buffer_length)) 00985 return(ER_OUT_OF_RESOURCES); 00986 00987 thd->client_capabilities=uint2korr(net->read_pos); 00988 if (thd->client_capabilities & CLIENT_PROTOCOL_41) 00989 { 00990 thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16; 00991 thd->max_client_packet_length= uint4korr(net->read_pos+4); 00992 DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8])); 00993 thd_init_client_charset(thd, (uint) net->read_pos[8]); 00994 thd->update_charset(); 00995 end= (char*) net->read_pos+32; 00996 } 00997 else 00998 { 00999 thd->max_client_packet_length= uint3korr(net->read_pos+2); 01000 end= (char*) net->read_pos+5; 01001 } 01002 01003 if (thd->client_capabilities & CLIENT_IGNORE_SPACE) 01004 thd->variables.sql_mode|= MODE_IGNORE_SPACE; 01005 #ifdef HAVE_OPENSSL 01006 DBUG_PRINT("info", ("client capabilities: %d", thd->client_capabilities)); 01007 if (thd->client_capabilities & CLIENT_SSL) 01008 { 01009 /* Do the SSL layering. */ 01010 if (!ssl_acceptor_fd) 01011 { 01012 inc_host_errors(&thd->remote.sin_addr); 01013 return(ER_HANDSHAKE_ERROR); 01014 } 01015 DBUG_PRINT("info", ("IO layer change in progress...")); 01016 if (sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout)) 01017 { 01018 DBUG_PRINT("error", ("Failed to accept new SSL connection")); 01019 inc_host_errors(&thd->remote.sin_addr); 01020 return(ER_HANDSHAKE_ERROR); 01021 } 01022 DBUG_PRINT("info", ("Reading user information over SSL layer")); 01023 if ((pkt_len= my_net_read(net)) == packet_error || 01024 pkt_len < NORMAL_HANDSHAKE_SIZE) 01025 { 01026 DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)", 01027 pkt_len)); 01028 inc_host_errors(&thd->remote.sin_addr); 01029 return(ER_HANDSHAKE_ERROR); 01030 } 01031 } 01032 #endif 01033 01034 if (end >= (char*) net->read_pos+ pkt_len +2) 01035 { 01036 inc_host_errors(&thd->remote.sin_addr); 01037 return(ER_HANDSHAKE_ERROR); 01038 } 01039 01040 if (thd->client_capabilities & CLIENT_INTERACTIVE) 01041 thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout; 01042 if ((thd->client_capabilities & CLIENT_TRANSACTIONS) && 01043 opt_using_transactions) 01044 net->return_status= &thd->server_status; 01045 net->read_timeout=(uint) thd->variables.net_read_timeout; 01046 01047 char *user= end; 01048 char *passwd= strend(user)+1; 01049 uint user_len= passwd - user - 1; 01050 char *db= passwd; 01051 char db_buff[NAME_LEN+1]; // buffer to store db in utf8 01052 char user_buff[USERNAME_LENGTH+1]; // buffer to store user in utf8 01053 uint dummy_errors; 01054 01055 /* 01056 Old clients send null-terminated string as password; new clients send 01057 the size (1 byte) + string (not null-terminated). Hence in case of empty 01058 password both send '\0'. 01059 */ 01060 uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? 01061 *passwd++ : strlen(passwd); 01062 db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ? 01063 db + passwd_len + 1 : 0; 01064 uint db_len= db ? strlen(db) : 0; 01065 01066 if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len) 01067 { 01068 inc_host_errors(&thd->remote.sin_addr); 01069 return ER_HANDSHAKE_ERROR; 01070 } 01071 01072 /* Since 4.1 all database names are stored in utf8 */ 01073 if (db) 01074 { 01075 db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, 01076 system_charset_info, 01077 db, db_len, 01078 thd->charset(), &dummy_errors)]= 0; 01079 db= db_buff; 01080 } 01081 01082 user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1, 01083 system_charset_info, user, user_len, 01084 thd->charset(), &dummy_errors)]= '\0'; 01085 user= user_buff; 01086 01087 /* If username starts and ends in "'", chop them off */ 01088 if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'') 01089 { 01090 user[user_len-1]= 0; 01091 user++; 01092 user_len-= 2; 01093 } 01094 01095 if (thd->main_security_ctx.user) 01096 x_free(thd->main_security_ctx.user); 01097 if (!(thd->main_security_ctx.user= my_strdup(user, MYF(0)))) 01098 return (ER_OUT_OF_RESOURCES); 01099 return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE); 01100 } 01101 01102 01103 void execute_init_command(THD *thd, sys_var_str *init_command_var, 01104 rw_lock_t *var_mutex) 01105 { 01106 Vio* save_vio; 01107 ulong save_client_capabilities; 01108 01109 thd->proc_info= "Execution of init_command"; 01110 /* 01111 We need to lock init_command_var because 01112 during execution of init_command_var query 01113 values of init_command_var can't be changed 01114 */ 01115 rw_rdlock(var_mutex); 01116 thd->query= init_command_var->value; 01117 thd->query_length= init_command_var->value_length; 01118 save_client_capabilities= thd->client_capabilities; 01119 thd->client_capabilities|= CLIENT_MULTI_QUERIES; 01120 /* 01121 We don't need return result of execution to client side. 01122 To forbid this we should set thd->net.vio to 0. 01123 */ 01124 save_vio= thd->net.vio; 01125 thd->net.vio= 0; 01126 thd->net.no_send_error= 0; 01127 dispatch_command(COM_QUERY, thd, thd->query, thd->query_length+1); 01128 rw_unlock(var_mutex); 01129 thd->client_capabilities= save_client_capabilities; 01130 thd->net.vio= save_vio; 01131 } 01132 01133 01134 pthread_handler_t handle_one_connection(void *arg) 01135 { 01136 THD *thd=(THD*) arg; 01137 uint launch_time = 01138 (uint) ((thd->thr_create_time = time(NULL)) - thd->connect_time); 01139 if (launch_time >= slow_launch_time) 01140 statistic_increment(slow_launch_threads,&LOCK_status ); 01141 01142 pthread_detach_this_thread(); 01143 01144 #if !defined( __WIN__) // Win32 calls this in pthread_create 01145 /* The following calls needs to be done before we call DBUG_ macros */ 01146 if (!(test_flags & TEST_NO_THREADS) & my_thread_init()) 01147 { 01148 close_connection(thd, ER_OUT_OF_RESOURCES, 1); 01149 statistic_increment(aborted_connects,&LOCK_status); 01150 end_thread(thd,0); 01151 return 0; 01152 } 01153 #endif 01154 01155 /* 01156 handle_one_connection() is the only way a thread would start 01157 and would always be on top of the stack, therefore, the thread 01158 stack always starts at the address of the first local variable 01159 of handle_one_connection, which is thd. We need to know the 01160 start of the stack so that we could check for stack overruns. 01161 */ 01162 DBUG_PRINT("info", ("handle_one_connection called by thread %d\n", 01163 thd->thread_id)); 01164 /* now that we've called my_thread_init(), it is safe to call DBUG_* */ 01165 01166 #if defined(__WIN__) 01167 init_signals(); 01168 #elif !defined(__NETWARE__) 01169 sigset_t set; 01170 VOID(sigemptyset(&set)); // Get mask in use 01171 VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals)); 01172 #endif 01173 thd->thread_stack= (char*) &thd; 01174 if (thd->store_globals()) 01175 { 01176 close_connection(thd, ER_OUT_OF_RESOURCES, 1); 01177 statistic_increment(aborted_connects,&LOCK_status); 01178 end_thread(thd,0); 01179 return 0; 01180 } 01181 01182 do 01183 { 01184 int error; 01185 NET *net= &thd->net; 01186 Security_context *sctx= thd->security_ctx; 01187 net->no_send_error= 0; 01188 01189 if ((error=check_connection(thd))) 01190 { // Wrong permissions 01191 if (error > 0) 01192 net_printf_error(thd, error, sctx->host_or_ip); 01193 #ifdef __NT__ 01194 if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE) 01195 my_sleep(1000); /* must wait after eof() */ 01196 #endif 01197 statistic_increment(aborted_connects,&LOCK_status); 01198 goto end_thread; 01199 } 01200 #ifdef __NETWARE__ 01201 netware_reg_user(sctx->ip, sctx->user, "MySQL"); 01202 #endif 01203 if (thd->variables.max_join_size == HA_POS_ERROR) 01204 thd->options |= OPTION_BIG_SELECTS; 01205 if (thd->client_capabilities & CLIENT_COMPRESS) 01206 net->compress=1; // Use compression 01207 01208 thd->version= refresh_version; 01209 thd->proc_info= 0; 01210 thd->command= COM_SLEEP; 01211 thd->set_time(); 01212 thd->init_for_queries(); 01213 01214 if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL)) 01215 { 01216 execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect); 01217 if (thd->query_error) 01218 thd->killed= THD::KILL_CONNECTION; 01219 thd->proc_info=0; 01220 thd->set_time(); 01221 thd->init_for_queries(); 01222 } 01223 01224 while (!net->error && net->vio != 0 && 01225 !(thd->killed == THD::KILL_CONNECTION)) 01226 { 01227 net->no_send_error= 0; 01228 if (do_command(thd)) 01229 break; 01230 } 01231 if (thd->user_connect) 01232 decrease_user_connections(thd->user_connect); 01233 if (net->error && net->vio != 0 && net->report_error) 01234 { 01235 if (!thd->killed && thd->variables.log_warnings > 1) 01236 sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION), 01237 thd->thread_id,(thd->db ? thd->db : "unconnected"), 01238 sctx->user ? sctx->user : "unauthenticated", 01239 sctx->host_or_ip, 01240 (net->last_errno ? ER(net->last_errno) : 01241 ER(ER_UNKNOWN_ERROR))); 01242 net_send_error(thd, net->last_errno, NullS); 01243 statistic_increment(aborted_threads,&LOCK_status); 01244 } 01245 else if (thd->killed) 01246 { 01247 statistic_increment(aborted_threads,&LOCK_status); 01248 } 01249 01250 end_thread: 01251 close_connection(thd, 0, 1); 01252 end_thread(thd,1); 01253 /* 01254 If end_thread returns, we are either running with --one-thread 01255 or this thread has been schedule to handle the next query 01256 */ 01257 thd= current_thd; 01258 thd->thread_stack= (char*) &thd; 01259 } while (!(test_flags & TEST_NO_THREADS)); 01260 /* The following is only executed if we are not using --one-thread */ 01261 return(0); /* purecov: deadcode */ 01262 } 01263 01264 #endif /* EMBEDDED_LIBRARY */ 01265 01266 /* 01267 Execute commands from bootstrap_file. 01268 Used when creating the initial grant tables 01269 */ 01270 01271 pthread_handler_t handle_bootstrap(void *arg) 01272 { 01273 THD *thd=(THD*) arg; 01274 FILE *file=bootstrap_file; 01275 char *buff; 01276 01277 /* The following must be called before DBUG_ENTER */ 01278 thd->thread_stack= (char*) &thd; 01279 if (my_thread_init() || thd->store_globals()) 01280 { 01281 #ifndef EMBEDDED_LIBRARY 01282 close_connection(thd, ER_OUT_OF_RESOURCES, 1); 01283 #endif 01284 thd->fatal_error(); 01285 goto end; 01286 } 01287 DBUG_ENTER("handle_bootstrap"); 01288 01289 #ifndef EMBEDDED_LIBRARY 01290 pthread_detach_this_thread(); 01291 thd->thread_stack= (char*) &thd; 01292 #if !defined(__WIN__) && !defined(__NETWARE__) 01293 sigset_t set; 01294 VOID(sigemptyset(&set)); // Get mask in use 01295 VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals)); 01296 #endif 01297 #endif /* EMBEDDED_LIBRARY */ 01298 01299 if (thd->variables.max_join_size == HA_POS_ERROR) 01300 thd->options |= OPTION_BIG_SELECTS; 01301 01302 thd->proc_info=0; 01303 thd->version=refresh_version; 01304 thd->security_ctx->priv_user= 01305 thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME)); 01306 thd->security_ctx->priv_host[0]=0; 01307 /* 01308 Make the "client" handle multiple results. This is necessary 01309 to enable stored procedures with SELECTs and Dynamic SQL 01310 in init-file. 01311 */ 01312 thd->client_capabilities|= CLIENT_MULTI_RESULTS; 01313 01314 buff= (char*) thd->net.buff; 01315 thd->init_for_queries(); 01316 while (fgets(buff, thd->net.max_packet, file)) 01317 { 01318 ulong length= (ulong) strlen(buff); 01319 while (buff[length-1] != '\n' && !feof(file)) 01320 { 01321 /* 01322 We got only a part of the current string. Will try to increase 01323 net buffer then read the rest of the current string. 01324 */ 01325 if (net_realloc(&(thd->net), 2 * thd->net.max_packet)) 01326 { 01327 net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS); 01328 thd->fatal_error(); 01329 break; 01330 } 01331 buff= (char*) thd->net.buff; 01332 fgets(buff + length, thd->net.max_packet - length, file); 01333 length+= (ulong) strlen(buff + length); 01334 } 01335 if (thd->is_fatal_error) 01336 break; 01337 01338 while (length && (my_isspace(thd->charset(), buff[length-1]) || 01339 buff[length-1] == ';')) 01340 length--; 01341 buff[length]=0; 01342 thd->query_length=length; 01343 thd->query= thd->memdup_w_gap(buff, length+1, 01344 thd->db_length+1+QUERY_CACHE_FLAGS_SIZE); 01345 thd->query[length] = '\0'; 01346 /* 01347 We don't need to obtain LOCK_thread_count here because in bootstrap 01348 mode we have only one thread. 01349 */ 01350 thd->query_id=next_query_id(); 01351 mysql_parse(thd,thd->query,length); 01352 close_thread_tables(thd); // Free tables 01353 if (thd->is_fatal_error) 01354 break; 01355 free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); 01356 #ifdef USING_TRANSACTIONS 01357 free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC)); 01358 #endif 01359 } 01360 01361 /* thd->fatal_error should be set in case something went wrong */ 01362 end: 01363 bootstrap_error= thd->is_fatal_error; 01364 01365 net_end(&thd->net); 01366 thd->cleanup(); 01367 delete thd; 01368 01369 #ifndef EMBEDDED_LIBRARY 01370 (void) pthread_mutex_lock(&LOCK_thread_count); 01371 thread_count--; 01372 (void) pthread_mutex_unlock(&LOCK_thread_count); 01373 (void) pthread_cond_broadcast(&COND_thread_count); 01374 my_thread_end(); 01375 pthread_exit(0); 01376 #endif 01377 DBUG_RETURN(0); 01378 } 01379 01380 01381 /* This works because items are allocated with sql_alloc() */ 01382 01383 void free_items(Item *item) 01384 { 01385 Item *next; 01386 DBUG_ENTER("free_items"); 01387 for (; item ; item=next) 01388 { 01389 next=item->next; 01390 item->delete_self(); 01391 } 01392 DBUG_VOID_RETURN; 01393 } 01394 01395 /* This works because items are allocated with sql_alloc() */ 01396 01397 void cleanup_items(Item *item) 01398 { 01399 DBUG_ENTER("cleanup_items"); 01400 for (; item ; item=item->next) 01401 item->cleanup(); 01402 DBUG_VOID_RETURN; 01403 } 01404 01405 /* 01406 Handle COM_TABLE_DUMP command 01407 01408 SYNOPSIS 01409 mysql_table_dump 01410 thd thread handle 01411 db database name or an empty string. If empty, 01412 the current database of the connection is used 01413 tbl_name name of the table to dump 01414 01415 NOTES 01416 This function is written to handle one specific command only. 01417 01418 RETURN VALUE 01419 0 success 01420 1 error, the error message is set in THD 01421 */ 01422 01423 static 01424 int mysql_table_dump(THD* thd, char* db, char* tbl_name) 01425 { 01426 TABLE* table; 01427 TABLE_LIST* table_list; 01428 int error = 0; 01429 DBUG_ENTER("mysql_table_dump"); 01430 db = (db && db[0]) ? db : thd->db; 01431 if (!(table_list = (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST)))) 01432 DBUG_RETURN(1); // out of memory 01433 table_list->db= db; 01434 table_list->table_name= table_list->alias= tbl_name; 01435 table_list->lock_type= TL_READ_NO_INSERT; 01436 table_list->prev_global= &table_list; // can be removed after merge with 4.1 01437 01438 if (!db || check_db_name(db)) 01439 { 01440 my_error(ER_WRONG_DB_NAME ,MYF(0), db ? db : "NULL"); 01441 goto err; 01442 } 01443 if (lower_case_table_names) 01444 my_casedn_str(files_charset_info, tbl_name); 01445 remove_escape(table_list->table_name); 01446 01447 if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT))) 01448 DBUG_RETURN(1); 01449 01450 if (check_one_table_access(thd, SELECT_ACL, table_list)) 01451 goto err; 01452 thd->free_list = 0; 01453 thd->query_length=(uint) strlen(tbl_name); 01454 thd->query = tbl_name; 01455 if ((error = mysqld_dump_create_info(thd, table_list, -1))) 01456 { 01457 my_error(ER_GET_ERRNO, MYF(0), my_errno); 01458 goto err; 01459 } 01460 net_flush(&thd->net); 01461 if ((error= table->file->dump(thd,-1))) 01462 my_error(ER_GET_ERRNO, MYF(0), error); 01463 01464 err: 01465 DBUG_RETURN(error); 01466 } 01467 01468 /* 01469 Ends the current transaction and (maybe) begin the next 01470 01471 SYNOPSIS 01472 end_trans() 01473 thd Current thread 01474 completion Completion type 01475 01476 RETURN 01477 0 - OK 01478 */ 01479 01480 int end_trans(THD *thd, enum enum_mysql_completiontype completion) 01481 { 01482 bool do_release= 0; 01483 int res= 0; 01484 DBUG_ENTER("end_trans"); 01485 01486 if (unlikely(thd->in_sub_stmt)) 01487 { 01488 my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); 01489 DBUG_RETURN(1); 01490 } 01491 if (thd->transaction.xid_state.xa_state != XA_NOTR) 01492 { 01493 my_error(ER_XAER_RMFAIL, MYF(0), 01494 xa_state_names[thd->transaction.xid_state.xa_state]); 01495 DBUG_RETURN(1); 01496 } 01497 switch (completion) { 01498 case COMMIT: 01499 /* 01500 We don't use end_active_trans() here to ensure that this works 01501 even if there is a problem with the OPTION_AUTO_COMMIT flag 01502 (Which of course should never happen...) 01503 */ 01504 thd->server_status&= ~SERVER_STATUS_IN_TRANS; 01505 res= ha_commit(thd); 01506 thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE | 01507 OPTION_KEEP_LOG); 01508 break; 01509 case COMMIT_RELEASE: 01510 do_release= 1; /* fall through */ 01511 case COMMIT_AND_CHAIN: 01512 res= end_active_trans(thd); 01513 if (!res && completion == COMMIT_AND_CHAIN) 01514 res= begin_trans(thd); 01515 break; 01516 case ROLLBACK_RELEASE: 01517 do_release= 1; /* fall through */ 01518 case ROLLBACK: 01519 case ROLLBACK_AND_CHAIN: 01520 { 01521 thd->server_status&= ~SERVER_STATUS_IN_TRANS; 01522 if (ha_rollback(thd)) 01523 res= -1; 01524 thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE | 01525 OPTION_KEEP_LOG); 01526 if (!res && (completion == ROLLBACK_AND_CHAIN)) 01527 res= begin_trans(thd); 01528 break; 01529 } 01530 default: 01531 res= -1; 01532 my_error(ER_UNKNOWN_COM_ERROR, MYF(0)); 01533 DBUG_RETURN(-1); 01534 } 01535 01536 if (res < 0) 01537 my_error(thd->killed_errno(), MYF(0)); 01538 else if ((res == 0) && do_release) 01539 thd->killed= THD::KILL_CONNECTION; 01540 01541 DBUG_RETURN(res); 01542 } 01543 01544 #ifndef EMBEDDED_LIBRARY 01545 01546 /* 01547 Read one command from socket and execute it (query or simple command). 01548 This function is called in loop from thread function. 01549 SYNOPSIS 01550 do_command() 01551 RETURN VALUE 01552 0 success 01553 1 request of thread shutdown (see dispatch_command() description) 01554 */ 01555 01556 bool do_command(THD *thd) 01557 { 01558 char *packet; 01559 uint old_timeout; 01560 ulong packet_length; 01561 NET *net; 01562 enum enum_server_command command; 01563 DBUG_ENTER("do_command"); 01564 01565 net= &thd->net; 01566 /* 01567 indicator of uninitialized lex => normal flow of errors handling 01568 (see my_message_sql) 01569 */ 01570 thd->lex->current_select= 0; 01571 01572 packet=0; 01573 old_timeout=net->read_timeout; 01574 /* Wait max for 8 hours */ 01575 net->read_timeout=(uint) thd->variables.net_wait_timeout; 01576 thd->clear_error(); // Clear error message 01577 01578 net_new_transaction(net); 01579 if ((packet_length=my_net_read(net)) == packet_error) 01580 { 01581 DBUG_PRINT("info",("Got error %d reading command from socket %s", 01582 net->error, 01583 vio_description(net->vio))); 01584 /* Check if we can continue without closing the connection */ 01585 if (net->error != 3) 01586 { 01587 statistic_increment(aborted_threads,&LOCK_status); 01588 DBUG_RETURN(TRUE); // We have to close it. 01589 } 01590 net_send_error(thd, net->last_errno, NullS); 01591 net->error= 0; 01592 DBUG_RETURN(FALSE); 01593 } 01594 else 01595 { 01596 packet=(char*) net->read_pos; 01597 command = (enum enum_server_command) (uchar) packet[0]; 01598 if (command >= COM_END) 01599 command= COM_END; // Wrong command 01600 DBUG_PRINT("info",("Command on %s = %d (%s)", 01601 vio_description(net->vio), command, 01602 command_name[command])); 01603 } 01604 net->read_timeout=old_timeout; // restore it 01605 /* 01606 packet_length contains length of data, as it was stored in packet 01607 header. In case of malformed header, packet_length can be zero. 01608 If packet_length is not zero, my_net_read ensures that this number 01609 of bytes was actually read from network. Additionally my_net_read 01610 sets packet[packet_length]= 0 (thus if packet_length == 0, 01611 command == packet[0] == COM_SLEEP). 01612 In dispatch_command packet[packet_length] points beyond the end of packet. 01613 */ 01614 DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length)); 01615 } 01616 #endif /* EMBEDDED_LIBRARY */ 01617 01618 01619 /* 01620 Perform one connection-level (COM_XXXX) command. 01621 01622 SYNOPSIS 01623 dispatch_command() 01624 thd connection handle 01625 command type of command to perform 01626 packet data for the command, packet is always null-terminated 01627 packet_length length of packet + 1 (to show that data is 01628 null-terminated) except for COM_SLEEP, where it 01629 can be zero. 01630 RETURN VALUE 01631 0 ok 01632 1 request of thread shutdown, i. e. if command is 01633 COM_QUIT/COM_SHUTDOWN 01634 */ 01635 01636 bool dispatch_command(enum enum_server_command command, THD *thd, 01637 char* packet, uint packet_length) 01638 { 01639 NET *net= &thd->net; 01640 bool error= 0; 01641 DBUG_ENTER("dispatch_command"); 01642 01643 if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA) 01644 thd->killed= THD::NOT_KILLED; 01645 01646 thd->command=command; 01647 /* 01648 Commands which always take a long time are logged into 01649 the slow log only if opt_log_slow_admin_statements is set. 01650 */ 01651 thd->enable_slow_log= TRUE; 01652 thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */ 01653 thd->set_time(); 01654 VOID(pthread_mutex_lock(&LOCK_thread_count)); 01655 thd->query_id=query_id; 01656 if (command != COM_STATISTICS && command != COM_PING) 01657 next_query_id(); 01658 thread_running++; 01659 /* TODO: set thd->lex->sql_command to SQLCOM_END here */ 01660 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 01661 01662 thd->server_status&= 01663 ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED); 01664 switch (command) { 01665 case COM_INIT_DB: 01666 { 01667 LEX_STRING tmp; 01668 statistic_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB], 01669 &LOCK_status); 01670 thd->convert_string(&tmp, system_charset_info, 01671 packet, strlen(packet), thd->charset()); 01672 if (!mysql_change_db(thd, tmp.str, FALSE)) 01673 { 01674 general_log_print(thd, command, "%s",thd->db); 01675 send_ok(thd); 01676 } 01677 break; 01678 } 01679 #ifdef HAVE_REPLICATION 01680 case COM_REGISTER_SLAVE: 01681 { 01682 if (!register_slave(thd, (uchar*)packet, packet_length)) 01683 send_ok(thd); 01684 break; 01685 } 01686 #endif 01687 case COM_TABLE_DUMP: 01688 { 01689 char *db, *tbl_name; 01690 uint db_len= *(uchar*) packet; 01691 if (db_len >= packet_length || db_len > NAME_LEN) 01692 { 01693 my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); 01694 break; 01695 } 01696 uint tbl_len= *(uchar*) (packet + db_len + 1); 01697 if (db_len+tbl_len+2 > packet_length || tbl_len > NAME_LEN) 01698 { 01699 my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); 01700 break; 01701 } 01702 01703 statistic_increment(thd->status_var.com_other, &LOCK_status); 01704 thd->enable_slow_log= opt_log_slow_admin_statements; 01705 db= thd->alloc(db_len + tbl_len + 2); 01706 if (!db) 01707 { 01708 my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); 01709 break; 01710 } 01711 tbl_name= strmake(db, packet + 1, db_len)+1; 01712 strmake(tbl_name, packet + db_len + 2, tbl_len); 01713 mysql_table_dump(thd, db, tbl_name); 01714 break; 01715 } 01716 case COM_CHANGE_USER: 01717 { 01718 thd->change_user(); 01719 thd->clear_error(); // if errors from rollback 01720 01721 statistic_increment(thd->status_var.com_other, &LOCK_status); 01722 char *user= (char*) packet; 01723 char *passwd= strend(user)+1; 01724 /* 01725 Old clients send null-terminated string ('\0' for empty string) for 01726 password. New clients send the size (1 byte) + string (not null 01727 terminated, so also '\0' for empty string). 01728 */ 01729 char db_buff[NAME_LEN+1]; // buffer to store db in utf8 01730 char *db= passwd; 01731 uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? 01732 *passwd++ : strlen(passwd); 01733 db+= passwd_len + 1; 01734 #ifndef EMBEDDED_LIBRARY 01735 /* Small check for incoming packet */ 01736 if ((uint) ((uchar*) db - net->read_pos) > packet_length) 01737 { 01738 my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); 01739 break; 01740 } 01741 #endif 01742 /* Convert database name to utf8 */ 01743 uint dummy_errors; 01744 db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, 01745 system_charset_info, db, strlen(db), 01746 thd->charset(), &dummy_errors)]= 0; 01747 db= db_buff; 01748 01749 /* Save user and privileges */ 01750 uint save_db_length= thd->db_length; 01751 char *save_db= thd->db; 01752 Security_context save_security_ctx= *thd->security_ctx; 01753 USER_CONN *save_user_connect= thd->user_connect; 01754 01755 if (!(thd->security_ctx->user= my_strdup(user, MYF(0)))) 01756 { 01757 thd->security_ctx->user= save_security_ctx.user; 01758 my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); 01759 break; 01760 } 01761 01762 /* Clear variables that are allocated */ 01763 thd->user_connect= 0; 01764 int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE); 01765 01766 if (res) 01767 { 01768 /* authentication failure, we shall restore old user */ 01769 if (res > 0) 01770 my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); 01771 x_free(thd->security_ctx->user); 01772 *thd->security_ctx= save_security_ctx; 01773 thd->user_connect= save_user_connect; 01774 thd->db= save_db; 01775 thd->db_length= save_db_length; 01776 } 01777 else 01778 { 01779 #ifndef NO_EMBEDDED_ACCESS_CHECKS 01780 /* we've authenticated new user */ 01781 if (save_user_connect) 01782 decrease_user_connections(save_user_connect); 01783 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 01784 x_free((gptr) save_db); 01785 x_free((gptr) save_security_ctx.user); 01786 } 01787 break; 01788 } 01789 case COM_STMT_EXECUTE: 01790 { 01791 mysql_stmt_execute(thd, packet, packet_length); 01792 break; 01793 } 01794 case COM_STMT_FETCH: 01795 { 01796 mysql_stmt_fetch(thd, packet, packet_length); 01797 break; 01798 } 01799 case COM_STMT_SEND_LONG_DATA: 01800 { 01801 mysql_stmt_get_longdata(thd, packet, packet_length); 01802 break; 01803 } 01804 case COM_STMT_PREPARE: 01805 { 01806 mysql_stmt_prepare(thd, packet, packet_length); 01807 break; 01808 } 01809 case COM_STMT_CLOSE: 01810 { 01811 mysql_stmt_close(thd, packet); 01812 break; 01813 } 01814 case COM_STMT_RESET: 01815 { 01816 mysql_stmt_reset(thd, packet); 01817 break; 01818 } 01819 case COM_QUERY: 01820 { 01821 if (alloc_query(thd, packet, packet_length)) 01822 break; // fatal error is set 01823 char *packet_end= thd->query + thd->query_length; 01824 general_log_print(thd, command, "%.*b", thd->query_length, thd->query); 01825 DBUG_PRINT("query",("%-.4096s",thd->query)); 01826 01827 if (!(specialflag & SPECIAL_NO_PRIOR)) 01828 my_pthread_setprio(pthread_self(),QUERY_PRIOR); 01829 01830 mysql_parse(thd,thd->query, thd->query_length); 01831 01832 while (!thd->killed && thd->lex->found_semicolon && !thd->net.report_error) 01833 { 01834 char *packet= thd->lex->found_semicolon; 01835 net->no_send_error= 0; 01836 /* 01837 Multiple queries exits, execute them individually 01838 */ 01839 if (thd->lock || thd->open_tables || thd->derived_tables || 01840 thd->prelocked_mode) 01841 close_thread_tables(thd); 01842 ulong length= (ulong)(packet_end-packet); 01843 01844 log_slow_statement(thd); 01845 01846 /* Remove garbage at start of query */ 01847 while (my_isspace(thd->charset(), *packet) && length > 0) 01848 { 01849 packet++; 01850 length--; 01851 } 01852 VOID(pthread_mutex_lock(&LOCK_thread_count)); 01853 thd->query_length= length; 01854 thd->query= packet; 01855 thd->query_id= next_query_id(); 01856 thd->set_time(); /* Reset the query start time. */ 01857 /* TODO: set thd->lex->sql_command to SQLCOM_END here */ 01858 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 01859 mysql_parse(thd, packet, length); 01860 } 01861 01862 if (!(specialflag & SPECIAL_NO_PRIOR)) 01863 my_pthread_setprio(pthread_self(),WAIT_PRIOR); 01864 DBUG_PRINT("info",("query ready")); 01865 break; 01866 } 01867 case COM_FIELD_LIST: // This isn't actually needed 01868 #ifdef DONT_ALLOW_SHOW_COMMANDS 01869 my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), 01870 MYF(0)); /* purecov: inspected */ 01871 break; 01872 #else 01873 { 01874 char *fields, *pend; 01875 /* Locked closure of all tables */ 01876 TABLE_LIST *locked_tables= NULL; 01877 TABLE_LIST table_list; 01878 LEX_STRING conv_name; 01879 /* Saved variable value */ 01880 my_bool old_innodb_table_locks= thd->variables.innodb_table_locks; 01881 01882 01883 /* used as fields initializator */ 01884 lex_start(thd, 0, 0); 01885 01886 01887 statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS], 01888 &LOCK_status); 01889 bzero((char*) &table_list,sizeof(table_list)); 01890 if (thd->copy_db_to(&table_list.db, 0)) 01891 break; 01892 pend= strend(packet); 01893 thd->convert_string(&conv_name, system_charset_info, 01894 packet, (uint) (pend-packet), thd->charset()); 01895 table_list.alias= table_list.table_name= conv_name.str; 01896 packet= pend+1; 01897 01898 if (!my_strcasecmp(system_charset_info, table_list.db, 01899 information_schema_name.str)) 01900 { 01901 ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, table_list.alias); 01902 if (schema_table) 01903 table_list.schema_table= schema_table; 01904 } 01905 01906 thd->query_length= strlen(packet); // for simplicity: don't optimize 01907 if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1))) 01908 break; 01909 general_log_print(thd, command, "%s %s", table_list.table_name, fields); 01910 if (lower_case_table_names) 01911 my_casedn_str(files_charset_info, table_list.table_name); 01912 remove_escape(table_list.table_name); // This can't have wildcards 01913 01914 if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege, 01915 0, 0, test(table_list.schema_table))) 01916 break; 01917 if (grant_option && 01918 check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0)) 01919 break; 01920 /* init structures for VIEW processing */ 01921 table_list.select_lex= &(thd->lex->select_lex); 01922 mysql_init_query(thd, (uchar*)"", 0); 01923 thd->lex-> 01924 select_lex.table_list.link_in_list((byte*) &table_list, 01925 (byte**) &table_list.next_local); 01926 thd->lex->add_to_query_tables(&table_list); 01927 01928 /* switch on VIEW optimisation: do not fill temporary tables */ 01929 thd->lex->sql_command= SQLCOM_SHOW_FIELDS; 01930 mysqld_list_fields(thd,&table_list,fields); 01931 thd->lex->unit.cleanup(); 01932 thd->cleanup_after_query(); 01933 break; 01934 } 01935 #endif 01936 case COM_QUIT: 01937 /* We don't calculate statistics for this command */ 01938 general_log_print(thd, command, NullS); 01939 net->error=0; // Don't give 'abort' message 01940 error=TRUE; // End server 01941 break; 01942 01943 case COM_CREATE_DB: // QQ: To be removed 01944 { 01945 char *db=thd->strdup(packet), *alias; 01946 HA_CREATE_INFO create_info; 01947 01948 statistic_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB], 01949 &LOCK_status); 01950 // null test to handle EOM 01951 if (!db || !(alias= thd->strdup(db)) || check_db_name(db)) 01952 { 01953 my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL"); 01954 break; 01955 } 01956 if (check_access(thd,CREATE_ACL,db,0,1,0,is_schema_db(db))) 01957 break; 01958 general_log_print(thd, command, packet); 01959 bzero(&create_info, sizeof(create_info)); 01960 mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db), 01961 &create_info, 0); 01962 break; 01963 } 01964 case COM_DROP_DB: // QQ: To be removed 01965 { 01966 statistic_increment(thd->status_var.com_stat[SQLCOM_DROP_DB], 01967 &LOCK_status); 01968 char *db=thd->strdup(packet); 01969 /* null test to handle EOM */ 01970 if (!db || check_db_name(db)) 01971 { 01972 my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL"); 01973 break; 01974 } 01975 if (check_access(thd,DROP_ACL,db,0,1,0,is_schema_db(db))) 01976 break; 01977 if (thd->locked_tables || thd->active_transaction()) 01978 { 01979 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, 01980 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); 01981 break; 01982 } 01983 general_log_print(thd, command, db); 01984 mysql_rm_db(thd, db, 0, 0); 01985 break; 01986 } 01987 #ifndef EMBEDDED_LIBRARY 01988 case COM_BINLOG_DUMP: 01989 { 01990 ulong pos; 01991 ushort flags; 01992 uint32 slave_server_id; 01993 01994 statistic_increment(thd->status_var.com_other,&LOCK_status); 01995 thd->enable_slow_log= opt_log_slow_admin_statements; 01996 if (check_global_access(thd, REPL_SLAVE_ACL)) 01997 break; 01998 01999 /* TODO: The following has to be changed to an 8 byte integer */ 02000 pos = uint4korr(packet); 02001 flags = uint2korr(packet + 4); 02002 thd->server_id=0; /* avoid suicide */ 02003 if ((slave_server_id= uint4korr(packet+6))) // mysqlbinlog.server_id==0 02004 kill_zombie_dump_threads(slave_server_id); 02005 thd->server_id = slave_server_id; 02006 02007 general_log_print(thd, command, "Log: '%s' Pos: %ld", packet+10, 02008 (long) pos); 02009 mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags); 02010 unregister_slave(thd,1,1); 02011 /* fake COM_QUIT -- if we get here, the thread needs to terminate */ 02012 error = TRUE; 02013 net->error = 0; 02014 break; 02015 } 02016 #endif 02017 case COM_REFRESH: 02018 { 02019 bool not_used; 02020 statistic_increment(thd->status_var.com_stat[SQLCOM_FLUSH], 02021 &LOCK_status); 02022 ulong options= (ulong) (uchar) packet[0]; 02023 if (check_global_access(thd,RELOAD_ACL)) 02024 break; 02025 general_log_print(thd, command, NullS); 02026 if (!reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, ¬_used)) 02027 send_ok(thd); 02028 break; 02029 } 02030 #ifndef EMBEDDED_LIBRARY 02031 case COM_SHUTDOWN: 02032 { 02033 statistic_increment(thd->status_var.com_other, &LOCK_status); 02034 if (check_global_access(thd,SHUTDOWN_ACL)) 02035 break; /* purecov: inspected */ 02036 /* 02037 If the client is < 4.1.3, it is going to send us no argument; then 02038 packet_length is 1, packet[0] is the end 0 of the packet. Note that 02039 SHUTDOWN_DEFAULT is 0. If client is >= 4.1.3, the shutdown level is in 02040 packet[0]. 02041 */ 02042 enum mysql_enum_shutdown_level level= 02043 (enum mysql_enum_shutdown_level) (uchar) packet[0]; 02044 DBUG_PRINT("quit",("Got shutdown command for level %u", level)); 02045 if (level == SHUTDOWN_DEFAULT) 02046 level= SHUTDOWN_WAIT_ALL_BUFFERS; // soon default will be configurable 02047 else if (level != SHUTDOWN_WAIT_ALL_BUFFERS) 02048 { 02049 my_error(ER_NOT_SUPPORTED_YET, MYF(0), "this shutdown level"); 02050 break; 02051 } 02052 DBUG_PRINT("quit",("Got shutdown command for level %u", level)); 02053 general_log_print(thd, command, NullS); 02054 send_eof(thd); 02055 #ifdef __WIN__ 02056 sleep(1); // must wait after eof() 02057 #endif 02058 send_eof(thd); // This is for 'quit request' 02059 close_connection(thd, 0, 1); 02060 close_thread_tables(thd); // Free before kill 02061 kill_mysql(); 02062 error=TRUE; 02063 break; 02064 } 02065 #endif 02066 case COM_STATISTICS: 02067 { 02068 general_log_print(thd, command, NullS); 02069 statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS], 02070 &LOCK_status); 02071 #ifndef EMBEDDED_LIBRARY 02072 char buff[200]; 02073 #else 02074 char *buff= thd->net.last_error; 02075 #endif 02076 02077 STATUS_VAR current_global_status_var; 02078 calc_sum_of_all_status(¤t_global_status_var); 02079 02080 ulong uptime = (ulong) (thd->start_time - start_time); 02081 sprintf((char*) buff, 02082 "Uptime: %lu Threads: %d Questions: %lu Slow queries: %lu Opens: %lu Flush tables: %lu Open tables: %u Queries per second avg: %.3f", 02083 uptime, 02084 (int) thread_count, (ulong) thd->query_id, 02085 current_global_status_var.long_query_count, 02086 current_global_status_var.opened_tables, refresh_version, 02087 cached_open_tables(), 02088 (uptime ? (ulonglong2double(thd->query_id) / (double) uptime) : 02089 (double) 0)); 02090 #ifdef SAFEMALLOC 02091 if (sf_malloc_cur_memory) // Using SAFEMALLOC 02092 sprintf(strend(buff), " Memory in use: %ldK Max memory used: %ldK", 02093 (sf_malloc_cur_memory+1023L)/1024L, 02094 (sf_malloc_max_memory+1023L)/1024L); 02095 #endif 02096 #ifndef EMBEDDED_LIBRARY 02097 VOID(my_net_write(net, buff,(uint) strlen(buff))); 02098 VOID(net_flush(net)); 02099 #endif 02100 break; 02101 } 02102 case COM_PING: 02103 statistic_increment(thd->status_var.com_other, &LOCK_status); 02104 send_ok(thd); // Tell client we are alive 02105 break; 02106 case COM_PROCESS_INFO: 02107 statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST], 02108 &LOCK_status); 02109 if (!thd->security_ctx->priv_user[0] && 02110 check_global_access(thd, PROCESS_ACL)) 02111 break; 02112 general_log_print(thd, command, NullS); 02113 mysqld_list_processes(thd, 02114 thd->security_ctx->master_access & PROCESS_ACL ? 02115 NullS : thd->security_ctx->priv_user, 0); 02116 break; 02117 case COM_PROCESS_KILL: 02118 { 02119 statistic_increment(thd->status_var.com_stat[SQLCOM_KILL], &LOCK_status); 02120 ulong id=(ulong) uint4korr(packet); 02121 sql_kill(thd,id,false); 02122 break; 02123 } 02124 case COM_SET_OPTION: 02125 { 02126 statistic_increment(thd->status_var.com_stat[SQLCOM_SET_OPTION], 02127 &LOCK_status); 02128 enum_mysql_set_option command= (enum_mysql_set_option) uint2korr(packet); 02129 switch (command) { 02130 case MYSQL_OPTION_MULTI_STATEMENTS_ON: 02131 thd->client_capabilities|= CLIENT_MULTI_STATEMENTS; 02132 send_eof(thd); 02133 break; 02134 case MYSQL_OPTION_MULTI_STATEMENTS_OFF: 02135 thd->client_capabilities&= ~CLIENT_MULTI_STATEMENTS; 02136 send_eof(thd); 02137 break; 02138 default: 02139 my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); 02140 break; 02141 } 02142 break; 02143 } 02144 case COM_DEBUG: 02145 statistic_increment(thd->status_var.com_other, &LOCK_status); 02146 if (check_global_access(thd, SUPER_ACL)) 02147 break; /* purecov: inspected */ 02148 mysql_print_status(); 02149 general_log_print(thd, command, NullS); 02150 send_eof(thd); 02151 break; 02152 case COM_SLEEP: 02153 case COM_CONNECT: // Impossible here 02154 case COM_TIME: // Impossible from client 02155 case COM_DELAYED_INSERT: 02156 case COM_END: 02157 default: 02158 my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); 02159 break; 02160 } 02161 if (thd->lock || thd->open_tables || thd->derived_tables || 02162 thd->prelocked_mode) 02163 { 02164 thd->proc_info="closing tables"; 02165 close_thread_tables(thd); /* Free tables */ 02166 } 02167 /* 02168 assume handlers auto-commit (if some doesn't - transaction handling 02169 in MySQL should be redesigned to support it; it's a big change, 02170 and it's not worth it - better to commit explicitly only writing 02171 transactions, read-only ones should better take care of themselves. 02172 saves some work in 2pc too) 02173 see also sql_base.cc - close_thread_tables() 02174 */ 02175 bzero(&thd->transaction.stmt, sizeof(thd->transaction.stmt)); 02176 if (!thd->active_transaction()) 02177 thd->transaction.xid_state.xid.null(); 02178 02179 /* report error issued during command execution */ 02180 if (thd->killed_errno() && !thd->net.report_error) 02181 thd->send_kill_message(); 02182 if (thd->net.report_error) 02183 net_send_error(thd); 02184 02185 log_slow_statement(thd); 02186 02187 thd->proc_info="cleaning up"; 02188 VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list 02189 thd->proc_info=0; 02190 thd->command=COM_SLEEP; 02191 thd->query=0; 02192 thd->query_length=0; 02193 thread_running--; 02194 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 02195 thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory 02196 free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); 02197 DBUG_RETURN(error); 02198 } 02199 02200 02201 void log_slow_statement(THD *thd) 02202 { 02203 time_t start_of_query; 02204 DBUG_ENTER("log_slow_statement"); 02205 02206 /* 02207 The following should never be true with our current code base, 02208 but better to keep this here so we don't accidently try to log a 02209 statement in a trigger or stored function 02210 */ 02211 if (unlikely(thd->in_sub_stmt)) 02212 DBUG_VOID_RETURN; // Don't set time for sub stmt 02213 02214 start_of_query= thd->start_time; 02215 thd->end_time(); // Set start time 02216 02217 /* 02218 Do not log administrative statements unless the appropriate option is 02219 set; do not log into slow log if reading from backup. 02220 */ 02221 if (thd->enable_slow_log && !thd->user_time) 02222 { 02223 thd->proc_info="logging slow query"; 02224 02225 if ((ulong) (thd->start_time - thd->time_after_lock) > 02226 thd->variables.long_query_time || 02227 ((thd->server_status & 02228 (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) && 02229 (specialflag & SPECIAL_LOG_QUERIES_NOT_USING_INDEXES))) 02230 { 02231 thd->status_var.long_query_count++; 02232 slow_log_print(thd, thd->query, thd->query_length, start_of_query); 02233 } 02234 } 02235 DBUG_VOID_RETURN; 02236 } 02237 02238 02239 /* 02240 Create a TABLE_LIST object for an INFORMATION_SCHEMA table. 02241 02242 SYNOPSIS 02243 prepare_schema_table() 02244 thd thread handle 02245 lex current lex 02246 table_ident table alias if it's used 02247 schema_table_idx the type of the INFORMATION_SCHEMA table to be 02248 created 02249 02250 DESCRIPTION 02251 This function is used in the parser to convert a SHOW or DESCRIBE 02252 table_name command to a SELECT from INFORMATION_SCHEMA. 02253 It prepares a SELECT_LEX and a TABLE_LIST object to represent the 02254 given command as a SELECT parse tree. 02255 02256 NOTES 02257 Due to the way this function works with memory and LEX it cannot 02258 be used outside the parser (parse tree transformations outside 02259 the parser break PS and SP). 02260 02261 RETURN VALUE 02262 0 success 02263 1 out of memory or SHOW commands are not allowed 02264 in this version of the server. 02265 */ 02266 02267 int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, 02268 enum enum_schema_tables schema_table_idx) 02269 { 02270 DBUG_ENTER("prepare_schema_table"); 02271 SELECT_LEX *sel= 0; 02272 switch (schema_table_idx) { 02273 case SCH_SCHEMATA: 02274 #if defined(DONT_ALLOW_SHOW_COMMANDS) 02275 my_message(ER_NOT_ALLOWED_COMMAND, 02276 ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */ 02277 DBUG_RETURN(1); 02278 #else 02279 if ((specialflag & SPECIAL_SKIP_SHOW_DB) && 02280 check_global_access(thd, SHOW_DB_ACL)) 02281 DBUG_RETURN(1); 02282 break; 02283 #endif 02284 case SCH_TABLE_NAMES: 02285 case SCH_TABLES: 02286 case SCH_VIEWS: 02287 case SCH_TRIGGERS: 02288 case SCH_EVENTS: 02289 #ifdef DONT_ALLOW_SHOW_COMMANDS 02290 my_message(ER_NOT_ALLOWED_COMMAND, 02291 ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */ 02292 DBUG_RETURN(1); 02293 #else 02294 { 02295 char *db; 02296 if (lex->select_lex.db == NULL && 02297 thd->copy_db_to(&lex->select_lex.db, 0)) 02298 { 02299 DBUG_RETURN(1); 02300 } 02301 db= lex->select_lex.db; 02302 remove_escape(db); // Fix escaped '_' 02303 if (check_db_name(db)) 02304 { 02305 my_error(ER_WRONG_DB_NAME, MYF(0), db); 02306 DBUG_RETURN(1); 02307 } 02308 if (check_access(thd, SELECT_ACL, db, &thd->col_access, 0, 0, 02309 is_schema_db(db))) 02310 DBUG_RETURN(1); /* purecov: inspected */ 02311 if (!thd->col_access && check_grant_db(thd,db)) 02312 { 02313 my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), 02314 thd->security_ctx->priv_user, thd->security_ctx->priv_host, 02315 db); 02316 DBUG_RETURN(1); 02317 } 02318 break; 02319 } 02320 #endif 02321 case SCH_COLUMNS: 02322 case SCH_STATISTICS: 02323 #ifdef DONT_ALLOW_SHOW_COMMANDS 02324 my_message(ER_NOT_ALLOWED_COMMAND, 02325 ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */ 02326 DBUG_RETURN(1); 02327 #else 02328 if (table_ident) 02329 { 02330 TABLE_LIST **query_tables_last= lex->query_tables_last; 02331 sel= new SELECT_LEX(); 02332 /* 'parent_lex' is used in init_query() so it must be before it. */ 02333 sel->parent_lex= lex; 02334 sel->init_query(); 02335 if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ, 02336 (List<String> *) 0, (List<String> *) 0)) 02337 DBUG_RETURN(1); 02338 lex->query_tables_last= query_tables_last; 02339 TABLE_LIST *table_list= (TABLE_LIST*) sel->table_list.first; 02340 char *db= table_list->db; 02341 remove_escape(db); // Fix escaped '_' 02342 remove_escape(table_list->table_name); 02343 if (check_access(thd,SELECT_ACL | EXTRA_ACL,db, 02344 &table_list->grant.privilege, 0, 0, 02345 test(table_list->schema_table))) 02346 DBUG_RETURN(1); /* purecov: inspected */ 02347 if (grant_option && check_grant(thd, SELECT_ACL, table_list, 2, 02348 UINT_MAX, 0)) 02349 DBUG_RETURN(1); 02350 break; 02351 } 02352 #endif 02353 case SCH_OPEN_TABLES: 02354 case SCH_VARIABLES: 02355 case SCH_STATUS: 02356 case SCH_PROCEDURES: 02357 case SCH_CHARSETS: 02358 case SCH_ENGINES: 02359 case SCH_COLLATIONS: 02360 case SCH_COLLATION_CHARACTER_SET_APPLICABILITY: 02361 case SCH_USER_PRIVILEGES: 02362 case SCH_SCHEMA_PRIVILEGES: 02363 case SCH_TABLE_PRIVILEGES: 02364 case SCH_COLUMN_PRIVILEGES: 02365 case SCH_TABLE_CONSTRAINTS: 02366 case SCH_KEY_COLUMN_USAGE: 02367 default: 02368 break; 02369 } 02370 02371 SELECT_LEX *select_lex= lex->current_select; 02372 if (make_schema_select(thd, select_lex, schema_table_idx)) 02373 { 02374 DBUG_RETURN(1); 02375 } 02376 TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first; 02377 table_list->schema_select_lex= sel; 02378 table_list->schema_table_reformed= 1; 02379 DBUG_RETURN(0); 02380 } 02381 02382 02383 /* 02384 Read query from packet and store in thd->query 02385 Used in COM_QUERY and COM_STMT_PREPARE 02386 02387 DESCRIPTION 02388 Sets the following THD variables: 02389 query 02390 query_length 02391 02392 RETURN VALUES 02393 FALSE ok 02394 TRUE error; In this case thd->fatal_error is set 02395 */ 02396 02397 bool alloc_query(THD *thd, const char *packet, uint packet_length) 02398 { 02399 packet_length--; // Remove end null 02400 /* Remove garbage at start and end of query */ 02401 while (my_isspace(thd->charset(),packet[0]) && packet_length > 0) 02402 { 02403 packet++; 02404 packet_length--; 02405 } 02406 const char *pos= packet + packet_length; // Point at end null 02407 while (packet_length > 0 && 02408 (pos[-1] == ';' || my_isspace(thd->charset() ,pos[-1]))) 02409 { 02410 pos--; 02411 packet_length--; 02412 } 02413 /* We must allocate some extra memory for query cache */ 02414 thd->query_length= 0; // Extra safety: Avoid races 02415 if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet), 02416 packet_length, 02417 thd->db_length+ 1 + 02418 QUERY_CACHE_FLAGS_SIZE))) 02419 return TRUE; 02420 thd->query[packet_length]=0; 02421 thd->query_length= packet_length; 02422 02423 /* Reclaim some memory */ 02424 thd->packet.shrink(thd->variables.net_buffer_length); 02425 thd->convert_buffer.shrink(thd->variables.net_buffer_length); 02426 02427 return FALSE; 02428 } 02429 02430 static void reset_one_shot_variables(THD *thd) 02431 { 02432 thd->variables.character_set_client= 02433 global_system_variables.character_set_client; 02434 thd->variables.collation_connection= 02435 global_system_variables.collation_connection; 02436 thd->variables.collation_database= 02437 global_system_variables.collation_database; 02438 thd->variables.collation_server= 02439 global_system_variables.collation_server; 02440 thd->update_charset(); 02441 thd->variables.time_zone= 02442 global_system_variables.time_zone; 02443 thd->one_shot_set= 0; 02444 } 02445 02446 02447 /* 02448 Execute command saved in thd and lex->sql_command 02449 02450 SYNOPSIS 02451 mysql_execute_command() 02452 thd Thread handle 02453 02454 IMPLEMENTATION 02455 02456 Before every operation that can request a write lock for a table 02457 wait if a global read lock exists. However do not wait if this 02458 thread has locked tables already. No new locks can be requested 02459 until the other locks are released. The thread that requests the 02460 global read lock waits for write locked tables to become unlocked. 02461 02462 Note that wait_if_global_read_lock() sets a protection against a new 02463 global read lock when it succeeds. This needs to be released by 02464 start_waiting_global_read_lock() after the operation. 02465 02466 RETURN 02467 FALSE OK 02468 TRUE Error 02469 */ 02470 02471 bool 02472 mysql_execute_command(THD *thd) 02473 { 02474 bool res= FALSE; 02475 bool need_start_waiting= FALSE; // have protection against global read lock 02476 int result= 0; 02477 LEX *lex= thd->lex; 02478 /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */ 02479 SELECT_LEX *select_lex= &lex->select_lex; 02480 /* first table of first SELECT_LEX */ 02481 TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first; 02482 /* list of all tables in query */ 02483 TABLE_LIST *all_tables; 02484 /* most outer SELECT_LEX_UNIT of query */ 02485 SELECT_LEX_UNIT *unit= &lex->unit; 02486 /* Saved variable value */ 02487 DBUG_ENTER("mysql_execute_command"); 02488 thd->net.no_send_error= 0; 02489 #ifdef WITH_PARTITION_STORAGE_ENGINE 02490 thd->work_part_info= 0; 02491 #endif 02492 02493 /* 02494 In many cases first table of main SELECT_LEX have special meaning => 02495 check that it is first table in global list and relink it first in 02496 queries_tables list if it is necessary (we need such relinking only 02497 for queries with subqueries in select list, in this case tables of 02498 subqueries will go to global list first) 02499 02500 all_tables will differ from first_table only if most upper SELECT_LEX 02501 do not contain tables. 02502 02503 Because of above in place where should be at least one table in most 02504 outer SELECT_LEX we have following check: 02505 DBUG_ASSERT(first_table == all_tables); 02506 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02507 */ 02508 lex->first_lists_tables_same(); 02509 /* should be assigned after making first tables same */ 02510 all_tables= lex->query_tables; 02511 /* set context for commands which do not use setup_tables */ 02512 select_lex-> 02513 context.resolve_in_table_list_only((TABLE_LIST*)select_lex-> 02514 table_list.first); 02515 02516 /* 02517 Reset warning count for each query that uses tables 02518 A better approach would be to reset this for any commands 02519 that is not a SHOW command or a select that only access local 02520 variables, but for now this is probably good enough. 02521 Don't reset warnings when executing a stored routine. 02522 */ 02523 if ((all_tables || &lex->select_lex != lex->all_selects_list || 02524 lex->sroutines.records) && !thd->spcont || 02525 lex->time_zone_tables_used) 02526 mysql_reset_errors(thd, 0); 02527 02528 #ifdef HAVE_REPLICATION 02529 if (unlikely(thd->slave_thread)) 02530 { 02531 /* 02532 Check if statment should be skipped because of slave filtering 02533 rules 02534 02535 Exceptions are: 02536 - UPDATE MULTI: For this statement, we want to check the filtering 02537 rules later in the code 02538 - SET: we always execute it (Not that many SET commands exists in 02539 the binary log anyway -- only 4.1 masters write SET statements, 02540 in 5.0 there are no SET statements in the binary log) 02541 - DROP TEMPORARY TABLE IF EXISTS: we always execute it (otherwise we 02542 have stale files on slave caused by exclusion of one tmp table). 02543 */ 02544 if (!(lex->sql_command == SQLCOM_UPDATE_MULTI) && 02545 !(lex->sql_command == SQLCOM_SET_OPTION) && 02546 !(lex->sql_command == SQLCOM_DROP_TABLE && 02547 lex->drop_temporary && lex->drop_if_exists) && 02548 all_tables_not_ok(thd, all_tables)) 02549 { 02550 /* we warn the slave SQL thread */ 02551 my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); 02552 reset_one_shot_variables(thd); 02553 DBUG_RETURN(0); 02554 } 02555 } 02556 else 02557 { 02558 #endif /* HAVE_REPLICATION */ 02559 /* 02560 When option readonly is set deny operations which change non-temporary 02561 tables. Except for the replication thread and the 'super' users. 02562 */ 02563 if (opt_readonly && 02564 !(thd->security_ctx->master_access & SUPER_ACL) && 02565 (sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) && 02566 !((lex->sql_command == SQLCOM_CREATE_TABLE) && 02567 (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) && 02568 ((lex->sql_command != SQLCOM_UPDATE_MULTI) && 02569 some_non_temp_table_to_be_updated(thd, all_tables))) 02570 { 02571 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); 02572 DBUG_RETURN(-1); 02573 } 02574 #ifdef HAVE_REPLICATION 02575 } /* endif unlikely slave */ 02576 #endif 02577 statistic_increment(thd->status_var.com_stat[lex->sql_command], 02578 &LOCK_status); 02579 02580 switch (lex->sql_command) { 02581 case SQLCOM_SHOW_EVENTS: 02582 if ((res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, 02583 is_schema_db(thd->lex->select_lex.db)))) 02584 break; 02585 /* fall through */ 02586 case SQLCOM_SHOW_STATUS_PROC: 02587 case SQLCOM_SHOW_STATUS_FUNC: 02588 res= execute_sqlcom_select(thd, all_tables); 02589 break; 02590 case SQLCOM_SHOW_STATUS: 02591 { 02592 system_status_var old_status_var= thd->status_var; 02593 thd->initial_status_var= &old_status_var; 02594 res= execute_sqlcom_select(thd, all_tables); 02595 /* Don't log SHOW STATUS commands to slow query log */ 02596 thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED | 02597 SERVER_QUERY_NO_GOOD_INDEX_USED); 02598 /* 02599 restore status variables, as we don't want 'show status' to cause 02600 changes 02601 */ 02602 pthread_mutex_lock(&LOCK_status); 02603 add_diff_to_status(&global_status_var, &thd->status_var, 02604 &old_status_var); 02605 thd->status_var= old_status_var; 02606 pthread_mutex_unlock(&LOCK_status); 02607 break; 02608 } 02609 case SQLCOM_SHOW_DATABASES: 02610 case SQLCOM_SHOW_TABLES: 02611 case SQLCOM_SHOW_TRIGGERS: 02612 case SQLCOM_SHOW_TABLE_STATUS: 02613 case SQLCOM_SHOW_OPEN_TABLES: 02614 case SQLCOM_SHOW_PLUGINS: 02615 case SQLCOM_SHOW_FIELDS: 02616 case SQLCOM_SHOW_KEYS: 02617 case SQLCOM_SHOW_VARIABLES: 02618 case SQLCOM_SHOW_CHARSETS: 02619 case SQLCOM_SHOW_COLLATIONS: 02620 case SQLCOM_SELECT: 02621 thd->status_var.last_query_cost= 0.0; 02622 if (all_tables) 02623 { 02624 res= check_table_access(thd, 02625 lex->exchange ? SELECT_ACL | FILE_ACL : 02626 SELECT_ACL, 02627 all_tables, 0); 02628 } 02629 else 02630 res= check_access(thd, 02631 lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL, 02632 any_db, 0, 0, 0, 0); 02633 if (!res) 02634 res= execute_sqlcom_select(thd, all_tables); 02635 break; 02636 case SQLCOM_PREPARE: 02637 { 02638 mysql_sql_stmt_prepare(thd); 02639 break; 02640 } 02641 case SQLCOM_EXECUTE: 02642 { 02643 mysql_sql_stmt_execute(thd); 02644 break; 02645 } 02646 case SQLCOM_DEALLOCATE_PREPARE: 02647 { 02648 mysql_sql_stmt_close(thd); 02649 break; 02650 } 02651 case SQLCOM_DO: 02652 if (check_table_access(thd, SELECT_ACL, all_tables, 0) || 02653 open_and_lock_tables(thd, all_tables)) 02654 goto error; 02655 02656 res= mysql_do(thd, *lex->insert_list); 02657 break; 02658 02659 case SQLCOM_EMPTY_QUERY: 02660 send_ok(thd); 02661 break; 02662 02663 case SQLCOM_HELP: 02664 res= mysqld_help(thd,lex->help_arg); 02665 break; 02666 02667 #ifndef EMBEDDED_LIBRARY 02668 case SQLCOM_PURGE: 02669 { 02670 if (check_global_access(thd, SUPER_ACL)) 02671 goto error; 02672 /* PURGE MASTER LOGS TO 'file' */ 02673 res = purge_master_logs(thd, lex->to_log); 02674 break; 02675 } 02676 case SQLCOM_PURGE_BEFORE: 02677 { 02678 Item *it; 02679 02680 if (check_global_access(thd, SUPER_ACL)) 02681 goto error; 02682 /* PURGE MASTER LOGS BEFORE 'data' */ 02683 it= (Item *)lex->value_list.head(); 02684 if ((!it->fixed && it->fix_fields(lex->thd, &it)) || 02685 it->check_cols(1)) 02686 { 02687 my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE"); 02688 goto error; 02689 } 02690 it= new Item_func_unix_timestamp(it); 02691 /* 02692 it is OK only emulate fix_fieds, because we need only 02693 value of constant 02694 */ 02695 it->quick_fix_field(); 02696 res = purge_master_logs_before_date(thd, (ulong)it->val_int()); 02697 break; 02698 } 02699 #endif 02700 case SQLCOM_SHOW_WARNS: 02701 { 02702 res= mysqld_show_warnings(thd, (ulong) 02703 ((1L << (uint) MYSQL_ERROR::WARN_LEVEL_NOTE) | 02704 (1L << (uint) MYSQL_ERROR::WARN_LEVEL_WARN) | 02705 (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR) 02706 )); 02707 break; 02708 } 02709 case SQLCOM_SHOW_ERRORS: 02710 { 02711 res= mysqld_show_warnings(thd, (ulong) 02712 (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR)); 02713 break; 02714 } 02715 case SQLCOM_SHOW_NEW_MASTER: 02716 { 02717 if (check_global_access(thd, REPL_SLAVE_ACL)) 02718 goto error; 02719 /* This query don't work now. See comment in repl_failsafe.cc */ 02720 #ifndef WORKING_NEW_MASTER 02721 my_error(ER_NOT_SUPPORTED_YET, MYF(0), "SHOW NEW MASTER"); 02722 goto error; 02723 #else 02724 res = show_new_master(thd); 02725 break; 02726 #endif 02727 } 02728 02729 #ifdef HAVE_REPLICATION 02730 case SQLCOM_SHOW_SLAVE_HOSTS: 02731 { 02732 if (check_global_access(thd, REPL_SLAVE_ACL)) 02733 goto error; 02734 res = show_slave_hosts(thd); 02735 break; 02736 } 02737 case SQLCOM_SHOW_BINLOG_EVENTS: 02738 { 02739 if (check_global_access(thd, REPL_SLAVE_ACL)) 02740 goto error; 02741 res = mysql_show_binlog_events(thd); 02742 break; 02743 } 02744 #endif 02745 02746 case SQLCOM_BACKUP_TABLE: 02747 { 02748 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02749 if (check_table_access(thd, SELECT_ACL, all_tables, 0) || 02750 check_global_access(thd, FILE_ACL)) 02751 goto error; /* purecov: inspected */ 02752 thd->enable_slow_log= opt_log_slow_admin_statements; 02753 res = mysql_backup_table(thd, first_table); 02754 select_lex->table_list.first= (byte*) first_table; 02755 lex->query_tables=all_tables; 02756 break; 02757 } 02758 case SQLCOM_RESTORE_TABLE: 02759 { 02760 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02761 if (check_table_access(thd, INSERT_ACL, all_tables, 0) || 02762 check_global_access(thd, FILE_ACL)) 02763 goto error; /* purecov: inspected */ 02764 thd->enable_slow_log= opt_log_slow_admin_statements; 02765 res = mysql_restore_table(thd, first_table); 02766 select_lex->table_list.first= (byte*) first_table; 02767 lex->query_tables=all_tables; 02768 break; 02769 } 02770 case SQLCOM_ASSIGN_TO_KEYCACHE: 02771 { 02772 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02773 if (check_access(thd, INDEX_ACL, first_table->db, 02774 &first_table->grant.privilege, 0, 0, 02775 test(first_table->schema_table))) 02776 goto error; 02777 res= mysql_assign_to_keycache(thd, first_table, &lex->ident); 02778 break; 02779 } 02780 case SQLCOM_PRELOAD_KEYS: 02781 { 02782 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02783 if (check_access(thd, INDEX_ACL, first_table->db, 02784 &first_table->grant.privilege, 0, 0, 02785 test(first_table->schema_table))) 02786 goto error; 02787 res = mysql_preload_keys(thd, first_table); 02788 break; 02789 } 02790 #ifdef HAVE_REPLICATION 02791 case SQLCOM_CHANGE_MASTER: 02792 { 02793 if (check_global_access(thd, SUPER_ACL)) 02794 goto error; 02795 pthread_mutex_lock(&LOCK_active_mi); 02796 res = change_master(thd,active_mi); 02797 pthread_mutex_unlock(&LOCK_active_mi); 02798 break; 02799 } 02800 case SQLCOM_SHOW_SLAVE_STAT: 02801 { 02802 /* Accept one of two privileges */ 02803 if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) 02804 goto error; 02805 pthread_mutex_lock(&LOCK_active_mi); 02806 res = show_master_info(thd,active_mi); 02807 pthread_mutex_unlock(&LOCK_active_mi); 02808 break; 02809 } 02810 case SQLCOM_SHOW_MASTER_STAT: 02811 { 02812 /* Accept one of two privileges */ 02813 if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) 02814 goto error; 02815 res = show_binlog_info(thd); 02816 break; 02817 } 02818 02819 case SQLCOM_LOAD_MASTER_DATA: // sync with master 02820 if (check_global_access(thd, SUPER_ACL)) 02821 goto error; 02822 if (end_active_trans(thd)) 02823 goto error; 02824 res = load_master_data(thd); 02825 break; 02826 #endif /* HAVE_REPLICATION */ 02827 case SQLCOM_SHOW_ENGINE_STATUS: 02828 { 02829 if (check_global_access(thd, SUPER_ACL)) 02830 goto error; 02831 res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_STATUS); 02832 break; 02833 } 02834 case SQLCOM_SHOW_ENGINE_MUTEX: 02835 { 02836 if (check_global_access(thd, SUPER_ACL)) 02837 goto error; 02838 res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_MUTEX); 02839 break; 02840 } 02841 #ifdef HAVE_REPLICATION 02842 case SQLCOM_LOAD_MASTER_TABLE: 02843 { 02844 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02845 DBUG_ASSERT(first_table->db); /* Must be set in the parser */ 02846 02847 if (check_access(thd, CREATE_ACL, first_table->db, 02848 &first_table->grant.privilege, 0, 0, 02849 test(first_table->schema_table))) 02850 goto error; /* purecov: inspected */ 02851 if (grant_option) 02852 { 02853 /* Check that the first table has CREATE privilege */ 02854 if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0)) 02855 goto error; 02856 } 02857 if (strlen(first_table->table_name) > NAME_LEN) 02858 { 02859 my_error(ER_WRONG_TABLE_NAME, MYF(0), first_table->table_name); 02860 break; 02861 } 02862 pthread_mutex_lock(&LOCK_active_mi); 02863 /* 02864 fetch_master_table will send the error to the client on failure. 02865 Give error if the table already exists. 02866 */ 02867 if (!fetch_master_table(thd, first_table->db, first_table->table_name, 02868 active_mi, 0, 0)) 02869 { 02870 send_ok(thd); 02871 } 02872 pthread_mutex_unlock(&LOCK_active_mi); 02873 break; 02874 } 02875 #endif /* HAVE_REPLICATION */ 02876 02877 case SQLCOM_CREATE_TABLE: 02878 { 02879 /* If CREATE TABLE of non-temporary table, do implicit commit */ 02880 if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) 02881 { 02882 if (end_active_trans(thd)) 02883 { 02884 res= -1; 02885 break; 02886 } 02887 } 02888 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02889 bool link_to_local; 02890 // Skip first table, which is the table we are creating 02891 TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local); 02892 TABLE_LIST *select_tables= lex->query_tables; 02893 02894 if ((res= create_table_precheck(thd, select_tables, create_table))) 02895 goto end_with_restore_list; 02896 02897 #ifndef HAVE_READLINK 02898 lex->create_info.data_file_name=lex->create_info.index_file_name=0; 02899 #else 02900 /* Fix names if symlinked tables */ 02901 if (append_file_to_dir(thd, &lex->create_info.data_file_name, 02902 create_table->table_name) || 02903 append_file_to_dir(thd, &lex->create_info.index_file_name, 02904 create_table->table_name)) 02905 goto end_with_restore_list; 02906 #endif 02907 /* 02908 If we are using SET CHARSET without DEFAULT, add an implicit 02909 DEFAULT to not confuse old users. (This may change). 02910 */ 02911 if ((lex->create_info.used_fields & 02912 (HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) == 02913 HA_CREATE_USED_CHARSET) 02914 { 02915 lex->create_info.used_fields&= ~HA_CREATE_USED_CHARSET; 02916 lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET; 02917 lex->create_info.default_table_charset= lex->create_info.table_charset; 02918 lex->create_info.table_charset= 0; 02919 } 02920 /* 02921 The create-select command will open and read-lock the select table 02922 and then create, open and write-lock the new table. If a global 02923 read lock steps in, we get a deadlock. The write lock waits for 02924 the global read lock, while the global read lock waits for the 02925 select table to be closed. So we wait until the global readlock is 02926 gone before starting both steps. Note that 02927 wait_if_global_read_lock() sets a protection against a new global 02928 read lock when it succeeds. This needs to be released by 02929 start_waiting_global_read_lock(). We protect the normal CREATE 02930 TABLE in the same way. That way we avoid that a new table is 02931 created during a gobal read lock. 02932 */ 02933 if (!thd->locked_tables && 02934 !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) 02935 { 02936 res= 1; 02937 goto end_with_restore_list; 02938 } 02939 #ifdef WITH_PARTITION_STORAGE_ENGINE 02940 { 02941 partition_info *part_info= thd->lex->part_info; 02942 if (part_info && !(part_info= thd->lex->part_info->get_clone())) 02943 { 02944 res= -1; 02945 goto end_with_restore_list; 02946 } 02947 thd->work_part_info= part_info; 02948 } 02949 #endif 02950 if (select_lex->item_list.elements) // With select 02951 { 02952 select_result *result; 02953 02954 select_lex->options|= SELECT_NO_UNLOCK; 02955 unit->set_limit(select_lex); 02956 02957 if (!(res= open_and_lock_tables(thd, select_tables))) 02958 { 02959 /* 02960 Is table which we are changing used somewhere in other parts 02961 of query 02962 */ 02963 if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) 02964 { 02965 TABLE_LIST *duplicate; 02966 if ((duplicate= unique_table(thd, create_table, select_tables))) 02967 { 02968 update_non_unique_table_error(create_table, "CREATE", duplicate); 02969 res= 1; 02970 goto end_with_restore_list; 02971 } 02972 } 02973 /* If we create merge table, we have to test tables in merge, too */ 02974 if (lex->create_info.used_fields & HA_CREATE_USED_UNION) 02975 { 02976 TABLE_LIST *tab; 02977 for (tab= (TABLE_LIST*) lex->create_info.merge_list.first; 02978 tab; 02979 tab= tab->next_local) 02980 { 02981 TABLE_LIST *duplicate; 02982 if ((duplicate= unique_table(thd, tab, select_tables))) 02983 { 02984 update_non_unique_table_error(tab, "CREATE", duplicate); 02985 res= 1; 02986 goto end_with_restore_list; 02987 } 02988 } 02989 } 02990 02991 if ((result= new select_create(create_table, 02992 &lex->create_info, 02993 lex->create_list, 02994 lex->key_list, 02995 select_lex->item_list, 02996 lex->duplicates, 02997 lex->ignore))) 02998 { 02999 /* 03000 CREATE from SELECT give its SELECT_LEX for SELECT, 03001 and item_list belong to SELECT 03002 */ 03003 res= handle_select(thd, lex, result, 0); 03004 delete result; 03005 } 03006 /* reset for PS */ 03007 lex->create_list.empty(); 03008 lex->key_list.empty(); 03009 } 03010 } 03011 else 03012 { 03013 /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */ 03014 if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) 03015 thd->options|= OPTION_KEEP_LOG; 03016 /* regular create */ 03017 if (lex->like_name) 03018 res= mysql_create_like_table(thd, create_table, &lex->create_info, 03019 lex->like_name); 03020 else 03021 { 03022 res= mysql_create_table(thd, create_table->db, 03023 create_table->table_name, &lex->create_info, 03024 lex->create_list, 03025 lex->key_list, 0, 0, 1); 03026 } 03027 if (!res) 03028 send_ok(thd); 03029 } 03030 03031 /* put tables back for PS rexecuting */ 03032 end_with_restore_list: 03033 lex->link_first_table_back(create_table, link_to_local); 03034 break; 03035 } 03036 case SQLCOM_CREATE_INDEX: 03037 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03038 if (check_one_table_access(thd, INDEX_ACL, all_tables)) 03039 goto error; /* purecov: inspected */ 03040 thd->enable_slow_log= opt_log_slow_admin_statements; 03041 if (end_active_trans(thd)) 03042 goto error; 03043 res= mysql_create_index(thd, first_table, lex->key_list); 03044 break; 03045 03046 #ifdef HAVE_REPLICATION 03047 case SQLCOM_SLAVE_START: 03048 { 03049 pthread_mutex_lock(&LOCK_active_mi); 03050 start_slave(thd,active_mi,1 /* net report*/); 03051 pthread_mutex_unlock(&LOCK_active_mi); 03052 break; 03053 } 03054 case SQLCOM_SLAVE_STOP: 03055 /* 03056 If the client thread has locked tables, a deadlock is possible. 03057 Assume that 03058 - the client thread does LOCK TABLE t READ. 03059 - then the master updates t. 03060 - then the SQL slave thread wants to update t, 03061 so it waits for the client thread because t is locked by it. 03062 - then the client thread does SLAVE STOP. 03063 SLAVE STOP waits for the SQL slave thread to terminate its 03064 update t, which waits for the client thread because t is locked by it. 03065 To prevent that, refuse SLAVE STOP if the 03066 client thread has locked tables 03067 */ 03068 if (thd->locked_tables || thd->active_transaction() || thd->global_read_lock) 03069 { 03070 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, 03071 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); 03072 goto error; 03073 } 03074 { 03075 pthread_mutex_lock(&LOCK_active_mi); 03076 stop_slave(thd,active_mi,1/* net report*/); 03077 pthread_mutex_unlock(&LOCK_active_mi); 03078 break; 03079 } 03080 #endif /* HAVE_REPLICATION */ 03081 03082 case SQLCOM_ALTER_TABLE: 03083 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03084 #if defined(DONT_ALLOW_SHOW_COMMANDS) 03085 my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), 03086 MYF(0)); /* purecov: inspected */ 03087 goto error; 03088 #else 03089 { 03090 ulong priv=0; 03091 ulong priv_needed= ALTER_ACL; 03092 /* We also require DROP priv for ALTER TABLE ... DROP PARTITION */ 03093 if (lex->alter_info.flags & ALTER_DROP_PARTITION) 03094 priv_needed|= DROP_ACL; 03095 03096 if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN)) 03097 { 03098 my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name); 03099 goto error; 03100 } 03101 /* Must be set in the parser */ 03102 DBUG_ASSERT(select_lex->db); 03103 if (check_access(thd, priv_needed, first_table->db, 03104 &first_table->grant.privilege, 0, 0, 03105 test(first_table->schema_table)) || 03106 check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0, 03107 is_schema_db(select_lex->db))|| 03108 check_merge_table_access(thd, first_table->db, 03109 (TABLE_LIST *) 03110 lex->create_info.merge_list.first)) 03111 goto error; /* purecov: inspected */ 03112 if (grant_option) 03113 { 03114 if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0)) 03115 goto error; 03116 if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL)) 03117 { // Rename of table 03118 TABLE_LIST tmp_table; 03119 bzero((char*) &tmp_table,sizeof(tmp_table)); 03120 tmp_table.table_name=lex->name; 03121 tmp_table.db=select_lex->db; 03122 tmp_table.grant.privilege=priv; 03123 if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0, 03124 UINT_MAX, 0)) 03125 goto error; 03126 } 03127 } 03128 /* Don't yet allow changing of symlinks with ALTER TABLE */ 03129 if (lex->create_info.data_file_name) 03130 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, 03131 "DATA DIRECTORY option ignored"); 03132 if (lex->create_info.index_file_name) 03133 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, 03134 "INDEX DIRECTORY option ignored"); 03135 lex->create_info.data_file_name=lex->create_info.index_file_name=0; 03136 /* ALTER TABLE ends previous transaction */ 03137 if (end_active_trans(thd)) 03138 goto error; 03139 03140 if (!thd->locked_tables && 03141 !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) 03142 { 03143 res= 1; 03144 break; 03145 } 03146 03147 thd->enable_slow_log= opt_log_slow_admin_statements; 03148 res= mysql_alter_table(thd, select_lex->db, lex->name, 03149 &lex->create_info, 03150 first_table, lex->create_list, 03151 lex->key_list, 03152 select_lex->order_list.elements, 03153 (ORDER *) select_lex->order_list.first, 03154 lex->ignore, &lex->alter_info, 1); 03155 break; 03156 } 03157 #endif /*DONT_ALLOW_SHOW_COMMANDS*/ 03158 case SQLCOM_RENAME_TABLE: 03159 { 03160 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03161 TABLE_LIST *table; 03162 for (table= first_table; table; table= table->next_local->next_local) 03163 { 03164 if (check_access(thd, ALTER_ACL | DROP_ACL, table->db, 03165 &table->grant.privilege,0,0, test(table->schema_table)) || 03166 check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db, 03167 &table->next_local->grant.privilege, 0, 0, 03168 test(table->next_local->schema_table))) 03169 goto error; 03170 if (grant_option) 03171 { 03172 TABLE_LIST old_list, new_list; 03173 /* 03174 we do not need initialize old_list and new_list because we will 03175 come table[0] and table->next[0] there 03176 */ 03177 old_list= table[0]; 03178 new_list= table->next_local[0]; 03179 if (check_grant(thd, ALTER_ACL, &old_list, 0, 1, 0) || 03180 (!test_all_bits(table->next_local->grant.privilege, 03181 INSERT_ACL | CREATE_ACL) && 03182 check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0))) 03183 goto error; 03184 } 03185 } 03186 query_cache_invalidate3(thd, first_table, 0); 03187 if (end_active_trans(thd) || mysql_rename_tables(thd, first_table, 0)) 03188 goto error; 03189 break; 03190 } 03191 #ifndef EMBEDDED_LIBRARY 03192 case SQLCOM_SHOW_BINLOGS: 03193 #ifdef DONT_ALLOW_SHOW_COMMANDS 03194 my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), 03195 MYF(0)); /* purecov: inspected */ 03196 goto error; 03197 #else 03198 { 03199 if (check_global_access(thd, SUPER_ACL)) 03200 goto error; 03201 res = show_binlogs(thd); 03202 break; 03203 } 03204 #endif 03205 #endif /* EMBEDDED_LIBRARY */ 03206 case SQLCOM_SHOW_CREATE: 03207 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03208 #ifdef DONT_ALLOW_SHOW_COMMANDS 03209 my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), 03210 MYF(0)); /* purecov: inspected */ 03211 goto error; 03212 #else 03213 { 03214 /* Ignore temporary tables if this is "SHOW CREATE VIEW" */ 03215 if (lex->only_view) 03216 first_table->skip_temporary= 1; 03217 03218 if (check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db, 03219 &first_table->grant.privilege, 0, 0, 03220 test(first_table->schema_table))) 03221 goto error; 03222 if (grant_option && check_grant(thd, SELECT_ACL, all_tables, 2, UINT_MAX, 0)) 03223 goto error; 03224 res= mysqld_show_create(thd, first_table); 03225 break; 03226 } 03227 #endif 03228 case SQLCOM_CHECKSUM: 03229 { 03230 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03231 if (check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables, 0)) 03232 goto error; /* purecov: inspected */ 03233 res = mysql_checksum_table(thd, first_table, &lex->check_opt); 03234 break; 03235 } 03236 case SQLCOM_REPAIR: 03237 { 03238 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03239 if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) 03240 goto error; /* purecov: inspected */ 03241 thd->enable_slow_log= opt_log_slow_admin_statements; 03242 res= mysql_repair_table(thd, first_table, &lex->check_opt); 03243 /* ! we write after unlocking the table */ 03244 if (!res && !lex->no_write_to_binlog) 03245 { 03246 if (mysql_bin_log.is_open()) 03247 { 03248 thd->clear_error(); // No binlog error generated 03249 thd->binlog_query(THD::STMT_QUERY_TYPE, 03250 thd->query, thd->query_length, 0, FALSE); 03251 } 03252 } 03253 select_lex->table_list.first= (byte*) first_table; 03254 lex->query_tables=all_tables; 03255 break; 03256 } 03257 case SQLCOM_CHECK: 03258 { 03259 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03260 if (check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables, 0)) 03261 goto error; /* purecov: inspected */ 03262 thd->enable_slow_log= opt_log_slow_admin_statements; 03263 res = mysql_check_table(thd, first_table, &lex->check_opt); 03264 select_lex->table_list.first= (byte*) first_table; 03265 lex->query_tables=all_tables; 03266 break; 03267 } 03268 case SQLCOM_ANALYZE: 03269 { 03270 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03271 if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) 03272 goto error; /* purecov: inspected */ 03273 thd->enable_slow_log= opt_log_slow_admin_statements; 03274 res= mysql_analyze_table(thd, first_table, &lex->check_opt); 03275 /* ! we write after unlocking the table */ 03276 if (!res && !lex->no_write_to_binlog) 03277 { 03278 if (mysql_bin_log.is_open()) 03279 { 03280 thd->clear_error(); // No binlog error generated 03281 thd->binlog_query(THD::STMT_QUERY_TYPE, 03282 thd->query, thd->query_length, 0, FALSE); 03283 } 03284 } 03285 select_lex->table_list.first= (byte*) first_table; 03286 lex->query_tables=all_tables; 03287 break; 03288 } 03289 03290 case SQLCOM_OPTIMIZE: 03291 { 03292 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03293 if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) 03294 goto error; /* purecov: inspected */ 03295 thd->enable_slow_log= opt_log_slow_admin_statements; 03296 res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ? 03297 mysql_recreate_table(thd, first_table, 1) : 03298 mysql_optimize_table(thd, first_table, &lex->check_opt); 03299 /* ! we write after unlocking the table */ 03300 if (!res && !lex->no_write_to_binlog) 03301 { 03302 if (mysql_bin_log.is_open()) 03303 { 03304 thd->clear_error(); // No binlog error generated 03305 thd->binlog_query(THD::STMT_QUERY_TYPE, 03306 thd->query, thd->query_length, 0, FALSE); 03307 } 03308 } 03309 select_lex->table_list.first= (byte*) first_table; 03310 lex->query_tables=all_tables; 03311 break; 03312 } 03313 case SQLCOM_UPDATE: 03314 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03315 if (update_precheck(thd, all_tables)) 03316 break; 03317 DBUG_ASSERT(select_lex->offset_limit == 0); 03318 unit->set_limit(select_lex); 03319 res= (result= mysql_update(thd, all_tables, 03320 select_lex->item_list, 03321 lex->value_list, 03322 select_lex->where, 03323 select_lex->order_list.elements, 03324 (ORDER *) select_lex->order_list.first, 03325 unit->select_limit_cnt, 03326 lex->duplicates, lex->ignore)); 03327 /* mysql_update return 2 if we need to switch to multi-update */ 03328 if (result != 2) 03329 break; 03330 case SQLCOM_UPDATE_MULTI: 03331 { 03332 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03333 /* if we switched from normal update, rights are checked */ 03334 if (result != 2) 03335 { 03336 if ((res= multi_update_precheck(thd, all_tables))) 03337 break; 03338 } 03339 else 03340 res= 0; 03341 03342 res= mysql_multi_update_prepare(thd); 03343 03344 #ifdef HAVE_REPLICATION 03345 /* Check slave filtering rules */ 03346 if (unlikely(thd->slave_thread)) 03347 { 03348 if (all_tables_not_ok(thd, all_tables)) 03349 { 03350 if (res!= 0) 03351 { 03352 res= 0; /* don't care of prev failure */ 03353 thd->clear_error(); /* filters are of highest prior */ 03354 } 03355 /* we warn the slave SQL thread */ 03356 my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); 03357 break; 03358 } 03359 if (res) 03360 break; 03361 } 03362 else 03363 { 03364 #endif /* HAVE_REPLICATION */ 03365 if (res) 03366 break; 03367 if (opt_readonly && 03368 !(thd->security_ctx->master_access & SUPER_ACL) && 03369 some_non_temp_table_to_be_updated(thd, all_tables)) 03370 { 03371 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); 03372 break; 03373 } 03374 #ifdef HAVE_REPLICATION 03375 } /* unlikely */ 03376 #endif 03377 03378 res= mysql_multi_update(thd, all_tables, 03379 &select_lex->item_list, 03380 &lex->value_list, 03381 select_lex->where, 03382 select_lex->options, 03383 lex->duplicates, lex->ignore, unit, select_lex); 03384 break; 03385 } 03386 case SQLCOM_REPLACE: 03387 case SQLCOM_INSERT: 03388 { 03389 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03390 if ((res= insert_precheck(thd, all_tables))) 03391 break; 03392 /* Skip first table, which is the table we are inserting in */ 03393 select_lex->context.table_list= first_table->next_local; 03394 03395 if (!thd->locked_tables && 03396 !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) 03397 { 03398 res= 1; 03399 break; 03400 } 03401 03402 res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values, 03403 lex->update_list, lex->value_list, 03404 lex->duplicates, lex->ignore); 03405 /* do not show last insert ID if VIEW does not have auto_inc */ 03406 if (first_table->view && !first_table->contain_auto_increment) 03407 thd->first_successful_insert_id_in_cur_stmt= 0; 03408 break; 03409 } 03410 case SQLCOM_REPLACE_SELECT: 03411 case SQLCOM_INSERT_SELECT: 03412 { 03413 select_result *result; 03414 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03415 if ((res= insert_precheck(thd, all_tables))) 03416 break; 03417 03418 /* Fix lock for first table */ 03419 if (first_table->lock_type == TL_WRITE_DELAYED) 03420 first_table->lock_type= TL_WRITE; 03421 03422 /* Don't unlock tables until command is written to binary log */ 03423 select_lex->options|= SELECT_NO_UNLOCK; 03424 03425 unit->set_limit(select_lex); 03426 03427 if (! thd->locked_tables && 03428 ! (need_start_waiting= ! wait_if_global_read_lock(thd, 0, 1))) 03429 { 03430 res= 1; 03431 break; 03432 } 03433 03434 if (!(res= open_and_lock_tables(thd, all_tables))) 03435 { 03436 /* Skip first table, which is the table we are inserting in */ 03437 TABLE_LIST *second_table= first_table->next_local; 03438 select_lex->table_list.first= (byte*) second_table; 03439 select_lex->context.table_list= 03440 select_lex->context.first_name_resolution_table= second_table; 03441 res= mysql_insert_select_prepare(thd); 03442 if (!res && (result= new select_insert(first_table, first_table->table, 03443 &lex->field_list, 03444 &lex->update_list, 03445 &lex->value_list, 03446 lex->duplicates, lex->ignore))) 03447 { 03448 res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE); 03449 /* 03450 Invalidate the table in the query cache if something changed 03451 after unlocking when changes become visible. 03452 TODO: this is workaround. right way will be move invalidating in 03453 the unlock procedure. 03454 */ 03455 if (first_table->lock_type == TL_WRITE_CONCURRENT_INSERT && 03456 thd->lock) 03457 { 03458 mysql_unlock_tables(thd, thd->lock); 03459 query_cache_invalidate3(thd, first_table, 1); 03460 thd->lock=0; 03461 } 03462 delete result; 03463 } 03464 /* revert changes for SP */ 03465 select_lex->table_list.first= (byte*) first_table; 03466 } 03467 /* do not show last insert ID if VIEW does not have auto_inc */ 03468 if (first_table->view && !first_table->contain_auto_increment) 03469 thd->first_successful_insert_id_in_cur_stmt= 0; 03470 break; 03471 } 03472 case SQLCOM_TRUNCATE: 03473 if (end_active_trans(thd)) 03474 { 03475 res= -1; 03476 break; 03477 } 03478 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03479 if (check_one_table_access(thd, DELETE_ACL, all_tables)) 03480 goto error; 03481 /* 03482 Don't allow this within a transaction because we want to use 03483 re-generate table 03484 */ 03485 if (thd->locked_tables || thd->active_transaction()) 03486 { 03487 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, 03488 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); 03489 goto error; 03490 } 03491 03492 res= mysql_truncate(thd, first_table, 0); 03493 break; 03494 case SQLCOM_DELETE: 03495 { 03496 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03497 if ((res= delete_precheck(thd, all_tables))) 03498 break; 03499 DBUG_ASSERT(select_lex->offset_limit == 0); 03500 unit->set_limit(select_lex); 03501 03502 if (!thd->locked_tables && 03503 !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) 03504 { 03505 res= 1; 03506 break; 03507 } 03508 03509 res = mysql_delete(thd, all_tables, select_lex->where, 03510 &select_lex->order_list, 03511 unit->select_limit_cnt, select_lex->options, 03512 FALSE); 03513 break; 03514 } 03515 case SQLCOM_DELETE_MULTI: 03516 { 03517 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03518 TABLE_LIST *aux_tables= 03519 (TABLE_LIST *)thd->lex->auxiliary_table_list.first; 03520 multi_delete *result; 03521 03522 if (!thd->locked_tables && 03523 !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) 03524 { 03525 res= 1; 03526 break; 03527 } 03528 03529 if ((res= multi_delete_precheck(thd, all_tables))) 03530 break; 03531 03532 /* condition will be TRUE on SP re-excuting */ 03533 if (select_lex->item_list.elements != 0) 03534 select_lex->item_list.empty(); 03535 if (add_item_to_list(thd, new Item_null())) 03536 goto error; 03537 03538 thd->proc_info="init"; 03539 if ((res= open_and_lock_tables(thd, all_tables))) 03540 break; 03541 03542 if ((res= mysql_multi_delete_prepare(thd))) 03543 goto error; 03544 03545 if (!thd->is_fatal_error && (result= new multi_delete(aux_tables, 03546 lex->table_count))) 03547 { 03548 res= mysql_select(thd, &select_lex->ref_pointer_array, 03549 select_lex->get_table_list(), 03550 select_lex->with_wild, 03551 select_lex->item_list, 03552 select_lex->where, 03553 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL, 03554 (ORDER *)NULL, 03555 select_lex->options | thd->options | 03556 SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | 03557 OPTION_SETUP_TABLES_DONE, 03558 result, unit, select_lex); 03559 delete result; 03560 } 03561 else 03562 res= TRUE; // Error 03563 break; 03564 } 03565 case SQLCOM_DROP_TABLE: 03566 { 03567 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03568 if (!lex->drop_temporary) 03569 { 03570 if (check_table_access(thd, DROP_ACL, all_tables, 0)) 03571 goto error; /* purecov: inspected */ 03572 if (end_active_trans(thd)) 03573 goto error; 03574 } 03575 else 03576 { 03577 /* 03578 If this is a slave thread, we may sometimes execute some 03579 DROP / * 40005 TEMPORARY * / TABLE 03580 that come from parts of binlogs (likely if we use RESET SLAVE or CHANGE 03581 MASTER TO), while the temporary table has already been dropped. 03582 To not generate such irrelevant "table does not exist errors", 03583 we silently add IF EXISTS if TEMPORARY was used. 03584 */ 03585 if (thd->slave_thread) 03586 lex->drop_if_exists= 1; 03587 03588 /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */ 03589 thd->options|= OPTION_KEEP_LOG; 03590 } 03591 res= mysql_rm_table(thd, first_table, lex->drop_if_exists, 03592 lex->drop_temporary); 03593 } 03594 break; 03595 case SQLCOM_DROP_INDEX: 03596 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03597 if (check_one_table_access(thd, INDEX_ACL, all_tables)) 03598 goto error; /* purecov: inspected */ 03599 if (end_active_trans(thd)) 03600 goto error; 03601 res= mysql_drop_index(thd, first_table, &lex->alter_info); 03602 break; 03603 case SQLCOM_SHOW_PROCESSLIST: 03604 if (!thd->security_ctx->priv_user[0] && 03605 check_global_access(thd,PROCESS_ACL)) 03606 break; 03607 mysqld_list_processes(thd, 03608 (thd->security_ctx->master_access & PROCESS_ACL ? 03609 NullS : 03610 thd->security_ctx->priv_user), 03611 lex->verbose); 03612 break; 03613 case SQLCOM_SHOW_STORAGE_ENGINES: 03614 res= mysqld_show_storage_engines(thd); 03615 break; 03616 case SQLCOM_SHOW_AUTHORS: 03617 res= mysqld_show_authors(thd); 03618 break; 03619 case SQLCOM_SHOW_CONTRIBUTORS: 03620 res= mysqld_show_contributors(thd); 03621 break; 03622 case SQLCOM_SHOW_PRIVILEGES: 03623 res= mysqld_show_privileges(thd); 03624 break; 03625 case SQLCOM_SHOW_COLUMN_TYPES: 03626 res= mysqld_show_column_types(thd); 03627 break; 03628 case SQLCOM_SHOW_ENGINE_LOGS: 03629 #ifdef DONT_ALLOW_SHOW_COMMANDS 03630 my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), 03631 MYF(0)); /* purecov: inspected */ 03632 goto error; 03633 #else 03634 { 03635 if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0,0)) 03636 goto error; 03637 res= ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_LOGS); 03638 break; 03639 } 03640 #endif 03641 case SQLCOM_CHANGE_DB: 03642 if (!mysql_change_db(thd,select_lex->db,FALSE)) 03643 send_ok(thd); 03644 break; 03645 03646 case SQLCOM_LOAD: 03647 { 03648 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03649 uint privilege= (lex->duplicates == DUP_REPLACE ? 03650 INSERT_ACL | DELETE_ACL : INSERT_ACL) | 03651 (lex->local_file ? 0 : FILE_ACL); 03652 03653 if (lex->local_file) 03654 { 03655 if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) || 03656 !opt_local_infile) 03657 { 03658 my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); 03659 goto error; 03660 } 03661 } 03662 03663 if (check_one_table_access(thd, privilege, all_tables)) 03664 goto error; 03665 03666 res= mysql_load(thd, lex->exchange, first_table, lex->field_list, 03667 lex->update_list, lex->value_list, lex->duplicates, 03668 lex->ignore, (bool) lex->local_file); 03669 break; 03670 } 03671 03672 case SQLCOM_SET_OPTION: 03673 { 03674 List<set_var_base> *lex_var_list= &lex->var_list; 03675 if ((check_table_access(thd, SELECT_ACL, all_tables, 0) || 03676 open_and_lock_tables(thd, all_tables))) 03677 goto error; 03678 if (lex->one_shot_set && not_all_support_one_shot(lex_var_list)) 03679 { 03680 my_error(ER_RESERVED_SYNTAX, MYF(0), "SET ONE_SHOT"); 03681 goto error; 03682 } 03683 if (!(res= sql_set_variables(thd, lex_var_list))) 03684 { 03685 /* 03686 If the previous command was a SET ONE_SHOT, we don't want to forget 03687 about the ONE_SHOT property of that SET. So we use a |= instead of = . 03688 */ 03689 thd->one_shot_set|= lex->one_shot_set; 03690 send_ok(thd); 03691 } 03692 break; 03693 } 03694 03695 case SQLCOM_UNLOCK_TABLES: 03696 /* 03697 It is critical for mysqldump --single-transaction --master-data that 03698 UNLOCK TABLES does not implicitely commit a connection which has only 03699 done FLUSH TABLES WITH READ LOCK + BEGIN. If this assumption becomes 03700 false, mysqldump will not work. 03701 */ 03702 unlock_locked_tables(thd); 03703 if (thd->options & OPTION_TABLE_LOCK) 03704 { 03705 end_active_trans(thd); 03706 thd->options&= ~(ulong) (OPTION_TABLE_LOCK); 03707 } 03708 if (thd->global_read_lock) 03709 unlock_global_read_lock(thd); 03710 send_ok(thd); 03711 break; 03712 case SQLCOM_LOCK_TABLES: 03713 unlock_locked_tables(thd); 03714 if (end_active_trans(thd)) 03715 goto error; 03716 if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, 0)) 03717 goto error; 03718 thd->in_lock_tables=1; 03719 thd->options|= OPTION_TABLE_LOCK; 03720 03721 if (!(res= simple_open_n_lock_tables(thd, all_tables))) 03722 { 03723 #ifdef HAVE_QUERY_CACHE 03724 if (thd->variables.query_cache_wlock_invalidate) 03725 query_cache.invalidate_locked_for_write(first_table); 03726 #endif /*HAVE_QUERY_CACHE*/ 03727 thd->locked_tables=thd->lock; 03728 thd->lock=0; 03729 send_ok(thd); 03730 } 03731 else 03732 thd->options&= ~(ulong) (OPTION_TABLE_LOCK); 03733 thd->in_lock_tables=0; 03734 break; 03735 case SQLCOM_CREATE_DB: 03736 { 03737 if (end_active_trans(thd)) 03738 { 03739 res= -1; 03740 break; 03741 } 03742 char *alias; 03743 if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name)) 03744 { 03745 my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); 03746 break; 03747 } 03748 /* 03749 If in a slave thread : 03750 CREATE DATABASE DB was certainly not preceded by USE DB. 03751 For that reason, db_ok() in sql/slave.cc did not check the 03752 do_db/ignore_db. And as this query involves no tables, tables_ok() 03753 above was not called. So we have to check rules again here. 03754 */ 03755 #ifdef HAVE_REPLICATION 03756 if (thd->slave_thread && 03757 (!rpl_filter->db_ok(lex->name) || 03758 !rpl_filter->db_ok_with_wild_table(lex->name))) 03759 { 03760 my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); 03761 break; 03762 } 03763 #endif 03764 if (check_access(thd,CREATE_ACL,lex->name,0,1,0,is_schema_db(lex->name))) 03765 break; 03766 res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name), 03767 &lex->create_info, 0); 03768 break; 03769 } 03770 case SQLCOM_DROP_DB: 03771 { 03772 if (end_active_trans(thd)) 03773 { 03774 res= -1; 03775 break; 03776 } 03777 if (check_db_name(lex->name)) 03778 { 03779 my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); 03780 break; 03781 } 03782 /* 03783 If in a slave thread : 03784 DROP DATABASE DB may not be preceded by USE DB. 03785 For that reason, maybe db_ok() in sql/slave.cc did not check the 03786 do_db/ignore_db. And as this query involves no tables, tables_ok() 03787 above was not called. So we have to check rules again here. 03788 */ 03789 #ifdef HAVE_REPLICATION 03790 if (thd->slave_thread && 03791 (!rpl_filter->db_ok(lex->name) || 03792 !rpl_filter->db_ok_with_wild_table(lex->name))) 03793 { 03794 my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); 03795 break; 03796 } 03797 #endif 03798 if (check_access(thd,DROP_ACL,lex->name,0,1,0,is_schema_db(lex->name))) 03799 break; 03800 if (thd->locked_tables || thd->active_transaction()) 03801 { 03802 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, 03803 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); 03804 goto error; 03805 } 03806 res= mysql_rm_db(thd, lex->name, lex->drop_if_exists, 0); 03807 break; 03808 } 03809 case SQLCOM_RENAME_DB: 03810 { 03811 LEX_STRING *olddb, *newdb; 03812 List_iterator <LEX_STRING> db_list(lex->db_list); 03813 olddb= db_list++; 03814 newdb= db_list++; 03815 if (end_active_trans(thd)) 03816 { 03817 res= 1; 03818 break; 03819 } 03820 #ifdef HAVE_REPLICATION 03821 if (thd->slave_thread && 03822 (!rpl_filter->db_ok(olddb->str) || 03823 !rpl_filter->db_ok(newdb->str) || 03824 !rpl_filter->db_ok_with_wild_table(olddb->str) || 03825 !rpl_filter->db_ok_with_wild_table(newdb->str))) 03826 { 03827 res= 1; 03828 my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); 03829 break; 03830 } 03831 #endif 03832 if (check_access(thd,ALTER_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) || 03833 check_access(thd,DROP_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) || 03834 check_access(thd,CREATE_ACL,newdb->str,0,1,0,is_schema_db(newdb->str))) 03835 { 03836 res= 1; 03837 break; 03838 } 03839 if (thd->locked_tables || thd->active_transaction()) 03840 { 03841 res= 1; 03842 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, 03843 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); 03844 goto error; 03845 } 03846 res= mysql_rename_db(thd, olddb, newdb); 03847 if (!res) 03848 send_ok(thd); 03849 break; 03850 } 03851 case SQLCOM_ALTER_DB: 03852 { 03853 char *db= lex->name; 03854 DBUG_ASSERT(db); /* Must be set in the parser */ 03855 if (!strip_sp(db) || check_db_name(db)) 03856 { 03857 my_error(ER_WRONG_DB_NAME, MYF(0), db); 03858 break; 03859 } 03860 /* 03861 If in a slave thread : 03862 ALTER DATABASE DB may not be preceded by USE DB. 03863 For that reason, maybe db_ok() in sql/slave.cc did not check the 03864 do_db/ignore_db. And as this query involves no tables, tables_ok() 03865 above was not called. So we have to check rules again here. 03866 */ 03867 #ifdef HAVE_REPLICATION 03868 if (thd->slave_thread && 03869 (!rpl_filter->db_ok(db) || 03870 !rpl_filter->db_ok_with_wild_table(db))) 03871 { 03872 my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); 03873 break; 03874 } 03875 #endif 03876 if (check_access(thd, ALTER_ACL, db, 0, 1, 0, is_schema_db(db))) 03877 break; 03878 if (thd->locked_tables || thd->active_transaction()) 03879 { 03880 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, 03881 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); 03882 goto error; 03883 } 03884 res= mysql_alter_db(thd, db, &lex->create_info); 03885 break; 03886 } 03887 case SQLCOM_SHOW_CREATE_DB: 03888 { 03889 if (!strip_sp(lex->name) || check_db_name(lex->name)) 03890 { 03891 my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); 03892 break; 03893 } 03894 res=mysqld_show_create_db(thd,lex->name,&lex->create_info); 03895 break; 03896 } 03897 case SQLCOM_CREATE_EVENT: 03898 case SQLCOM_ALTER_EVENT: 03899 case SQLCOM_DROP_EVENT: 03900 { 03901 uint rows_affected= 1; 03902 DBUG_ASSERT(lex->et); 03903 do { 03904 if (! lex->et->dbname.str || 03905 (lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname && 03906 !lex->spname->m_db.str)) 03907 { 03908 my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); 03909 res= true; 03910 break; 03911 } 03912 03913 if (check_access(thd, EVENT_ACL, lex->et->dbname.str, 0, 0, 0, 03914 is_schema_db(lex->et->dbname.str)) || 03915 (lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname && 03916 (check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0, 03917 is_schema_db(lex->spname->m_db.str))))) 03918 break; 03919 03920 if (end_active_trans(thd)) 03921 { 03922 res= -1; 03923 break; 03924 } 03925 03926 switch (lex->sql_command) { 03927 case SQLCOM_CREATE_EVENT: 03928 res= Events::create_event(thd, lex->et, 03929 (uint) lex->create_info.options, 03930 &rows_affected); 03931 break; 03932 case SQLCOM_ALTER_EVENT: 03933 res= Events::update_event(thd, lex->et, lex->spname, 03934 &rows_affected); 03935 break; 03936 case SQLCOM_DROP_EVENT: 03937 res= Events::drop_event(thd, lex->et, lex->drop_if_exists, 03938 &rows_affected); 03939 default:; 03940 } 03941 DBUG_PRINT("info", ("CREATE/ALTER/DROP returned error code=%d af_rows=%d", 03942 res, rows_affected)); 03943 if (!res) 03944 send_ok(thd, rows_affected); 03945 03946 /* lex->unit.cleanup() is called outside, no need to call it here */ 03947 } while (0); 03948 if (!thd->spcont) 03949 { 03950 lex->et->free_sphead_on_delete= true; 03951 lex->et->free_sp(); 03952 lex->et->deinit_mutexes(); 03953 } 03954 03955 break; 03956 } 03957 case SQLCOM_SHOW_CREATE_EVENT: 03958 { 03959 DBUG_ASSERT(lex->spname); 03960 DBUG_ASSERT(lex->et); 03961 if (! lex->spname->m_db.str) 03962 { 03963 my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); 03964 res= true; 03965 break; 03966 } 03967 if (check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0, 03968 is_schema_db(lex->spname->m_db.str))) 03969 break; 03970 03971 if (lex->spname->m_name.length > NAME_LEN) 03972 { 03973 my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str); 03974 goto error; 03975 } 03976 res= Events::show_create_event(thd, lex->spname); 03977 break; 03978 } 03979 #ifndef DBUG_OFF 03980 case SQLCOM_SHOW_SCHEDULER_STATUS: 03981 { 03982 res= Events::dump_internal_status(thd); 03983 break; 03984 } 03985 #endif 03986 case SQLCOM_CREATE_FUNCTION: // UDF function 03987 { 03988 if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0)) 03989 break; 03990 #ifdef HAVE_DLOPEN 03991 if (sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, 03992 &thd->sp_func_cache, FALSE)) 03993 { 03994 my_error(ER_UDF_EXISTS, MYF(0), lex->spname->m_name.str); 03995 goto error; 03996 } 03997 if (!(res = mysql_create_function(thd, &lex->udf))) 03998 send_ok(thd); 03999 #else 04000 my_error(ER_CANT_OPEN_LIBRARY, MYF(0), lex->udf.dl, 0, "feature disabled"); 04001 res= TRUE; 04002 #endif 04003 break; 04004 } 04005 #ifndef NO_EMBEDDED_ACCESS_CHECKS 04006 case SQLCOM_CREATE_USER: 04007 { 04008 if (check_access(thd, INSERT_ACL, "mysql", 0, 1, 1, 0) && 04009 check_global_access(thd,CREATE_USER_ACL)) 04010 break; 04011 if (end_active_trans(thd)) 04012 goto error; 04013 if (!(res= mysql_create_user(thd, lex->users_list))) 04014 { 04015 if (mysql_bin_log.is_open()) 04016 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04017 thd->query, thd->query_length, FALSE, FALSE); 04018 send_ok(thd); 04019 } 04020 break; 04021 } 04022 case SQLCOM_DROP_USER: 04023 { 04024 if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 1, 0) && 04025 check_global_access(thd,CREATE_USER_ACL)) 04026 break; 04027 if (end_active_trans(thd)) 04028 goto error; 04029 if (!(res= mysql_drop_user(thd, lex->users_list))) 04030 { 04031 if (mysql_bin_log.is_open()) 04032 { 04033 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04034 thd->query, thd->query_length, FALSE, FALSE); 04035 } 04036 send_ok(thd); 04037 } 04038 break; 04039 } 04040 case SQLCOM_RENAME_USER: 04041 { 04042 if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) && 04043 check_global_access(thd,CREATE_USER_ACL)) 04044 break; 04045 if (end_active_trans(thd)) 04046 goto error; 04047 if (!(res= mysql_rename_user(thd, lex->users_list))) 04048 { 04049 if (mysql_bin_log.is_open()) 04050 { 04051 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04052 thd->query, thd->query_length, FALSE, FALSE); 04053 } 04054 send_ok(thd); 04055 } 04056 break; 04057 } 04058 case SQLCOM_REVOKE_ALL: 04059 { 04060 if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) && 04061 check_global_access(thd,CREATE_USER_ACL)) 04062 break; 04063 if (!(res = mysql_revoke_all(thd, lex->users_list))) 04064 { 04065 if (mysql_bin_log.is_open()) 04066 { 04067 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04068 thd->query, thd->query_length, FALSE, FALSE); 04069 } 04070 send_ok(thd); 04071 } 04072 break; 04073 } 04074 case SQLCOM_REVOKE: 04075 case SQLCOM_GRANT: 04076 { 04077 if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL, 04078 first_table ? first_table->db : select_lex->db, 04079 first_table ? &first_table->grant.privilege : 0, 04080 first_table ? 0 : 1, 0, 04081 first_table ? (bool) first_table->schema_table : 04082 select_lex->db ? is_schema_db(select_lex->db) : 0)) 04083 goto error; 04084 04085 if (thd->security_ctx->user) // If not replication 04086 { 04087 LEX_USER *user, *tmp_user; 04088 04089 List_iterator <LEX_USER> user_list(lex->users_list); 04090 while ((tmp_user= user_list++)) 04091 { 04092 if (!(user= get_current_user(thd, tmp_user))) 04093 goto error; 04094 if (specialflag & SPECIAL_NO_RESOLVE && 04095 hostname_requires_resolving(user->host.str)) 04096 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 04097 ER_WARN_HOSTNAME_WONT_WORK, 04098 ER(ER_WARN_HOSTNAME_WONT_WORK), 04099 user->host.str); 04100 // Are we trying to change a password of another user 04101 DBUG_ASSERT(user->host.str != 0); 04102 if (strcmp(thd->security_ctx->user, user->user.str) || 04103 my_strcasecmp(system_charset_info, 04104 user->host.str, thd->security_ctx->host_or_ip)) 04105 { 04106 // TODO: use check_change_password() 04107 if (is_acl_user(user->host.str, user->user.str) && 04108 user->password.str && 04109 check_access(thd, UPDATE_ACL,"mysql",0,1,1,0)) 04110 { 04111 my_message(ER_PASSWORD_NOT_ALLOWED, 04112 ER(ER_PASSWORD_NOT_ALLOWED), MYF(0)); 04113 goto error; 04114 } 04115 } 04116 } 04117 } 04118 if (first_table) 04119 { 04120 if (lex->type == TYPE_ENUM_PROCEDURE || 04121 lex->type == TYPE_ENUM_FUNCTION) 04122 { 04123 uint grants= lex->all_privileges 04124 ? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL) 04125 : lex->grant; 04126 if (grant_option && 04127 check_grant_routine(thd, grants | GRANT_ACL, all_tables, 04128 lex->type == TYPE_ENUM_PROCEDURE, 0)) 04129 goto error; 04130 res= mysql_routine_grant(thd, all_tables, 04131 lex->type == TYPE_ENUM_PROCEDURE, 04132 lex->users_list, grants, 04133 lex->sql_command == SQLCOM_REVOKE, 0); 04134 } 04135 else 04136 { 04137 if (grant_option && check_grant(thd, 04138 (lex->grant | lex->grant_tot_col | 04139 GRANT_ACL), 04140 all_tables, 0, UINT_MAX, 0)) 04141 goto error; 04142 res= mysql_table_grant(thd, all_tables, lex->users_list, 04143 lex->columns, lex->grant, 04144 lex->sql_command == SQLCOM_REVOKE); 04145 } 04146 if (!res && mysql_bin_log.is_open()) 04147 { 04148 thd->clear_error(); 04149 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04150 thd->query, thd->query_length, FALSE, FALSE); 04151 } 04152 } 04153 else 04154 { 04155 if (lex->columns.elements || lex->type) 04156 { 04157 my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE), 04158 MYF(0)); 04159 goto error; 04160 } 04161 else 04162 res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant, 04163 lex->sql_command == SQLCOM_REVOKE); 04164 if (!res) 04165 { 04166 if (mysql_bin_log.is_open()) 04167 { 04168 thd->clear_error(); 04169 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04170 thd->query, thd->query_length, FALSE, FALSE); 04171 } 04172 if (lex->sql_command == SQLCOM_GRANT) 04173 { 04174 List_iterator <LEX_USER> str_list(lex->users_list); 04175 LEX_USER *user, *tmp_user; 04176 while ((tmp_user=str_list++)) 04177 { 04178 if (!(user= get_current_user(thd, tmp_user))) 04179 goto error; 04180 reset_mqh(user); 04181 } 04182 } 04183 } 04184 } 04185 break; 04186 } 04187 #endif 04188 case SQLCOM_RESET: 04189 /* 04190 RESET commands are never written to the binary log, so we have to 04191 initialize this variable because RESET shares the same code as FLUSH 04192 */ 04193 lex->no_write_to_binlog= 1; 04194 case SQLCOM_FLUSH: 04195 { 04196 bool write_to_binlog; 04197 if (check_global_access(thd,RELOAD_ACL)) 04198 goto error; 04199 /* 04200 reload_acl_and_cache() will tell us if we are allowed to write to the 04201 binlog or not. 04202 */ 04203 if (!reload_acl_and_cache(thd, lex->type, first_table, &write_to_binlog)) 04204 { 04205 /* 04206 We WANT to write and we CAN write. 04207 ! we write after unlocking the table. 04208 */ 04209 if (!lex->no_write_to_binlog && write_to_binlog) 04210 { 04211 if (mysql_bin_log.is_open()) 04212 { 04213 thd->binlog_query(THD::STMT_QUERY_TYPE, 04214 thd->query, thd->query_length, 0, FALSE); 04215 } 04216 } 04217 send_ok(thd); 04218 } 04219 break; 04220 } 04221 case SQLCOM_KILL: 04222 { 04223 Item *it= (Item *)lex->value_list.head(); 04224 04225 if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1)) 04226 { 04227 my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), 04228 MYF(0)); 04229 goto error; 04230 } 04231 sql_kill(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY); 04232 break; 04233 } 04234 #ifndef NO_EMBEDDED_ACCESS_CHECKS 04235 case SQLCOM_SHOW_GRANTS: 04236 { 04237 LEX_USER *grant_user= get_current_user(thd, lex->grant_user); 04238 if (!grant_user) 04239 goto error; 04240 if ((thd->security_ctx->priv_user && 04241 !strcmp(thd->security_ctx->priv_user, grant_user->user.str)) || 04242 !check_access(thd, SELECT_ACL, "mysql",0,1,0,0)) 04243 { 04244 res = mysql_show_grants(thd, grant_user); 04245 } 04246 break; 04247 } 04248 #endif 04249 case SQLCOM_HA_OPEN: 04250 DBUG_ASSERT(first_table == all_tables && first_table != 0); 04251 if (check_table_access(thd, SELECT_ACL, all_tables, 0)) 04252 goto error; 04253 res= mysql_ha_open(thd, first_table, 0); 04254 break; 04255 case SQLCOM_HA_CLOSE: 04256 DBUG_ASSERT(first_table == all_tables && first_table != 0); 04257 res= mysql_ha_close(thd, first_table); 04258 break; 04259 case SQLCOM_HA_READ: 04260 DBUG_ASSERT(first_table == all_tables && first_table != 0); 04261 /* 04262 There is no need to check for table permissions here, because 04263 if a user has no permissions to read a table, he won't be 04264 able to open it (with SQLCOM_HA_OPEN) in the first place. 04265 */ 04266 unit->set_limit(select_lex); 04267 res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str, 04268 lex->insert_list, lex->ha_rkey_mode, select_lex->where, 04269 unit->select_limit_cnt, unit->offset_limit_cnt); 04270 break; 04271 04272 case SQLCOM_BEGIN: 04273 if (thd->transaction.xid_state.xa_state != XA_NOTR) 04274 { 04275 my_error(ER_XAER_RMFAIL, MYF(0), 04276 xa_state_names[thd->transaction.xid_state.xa_state]); 04277 break; 04278 } 04279 if (begin_trans(thd)) 04280 goto error; 04281 send_ok(thd); 04282 break; 04283 case SQLCOM_COMMIT: 04284 if (end_trans(thd, lex->tx_release ? COMMIT_RELEASE : 04285 lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT)) 04286 goto error; 04287 send_ok(thd); 04288 break; 04289 case SQLCOM_ROLLBACK: 04290 if (end_trans(thd, lex->tx_release ? ROLLBACK_RELEASE : 04291 lex->tx_chain ? ROLLBACK_AND_CHAIN : ROLLBACK)) 04292 goto error; 04293 send_ok(thd); 04294 break; 04295 case SQLCOM_RELEASE_SAVEPOINT: 04296 { 04297 SAVEPOINT *sv; 04298 for (sv=thd->transaction.savepoints; sv; sv=sv->prev) 04299 { 04300 if (my_strnncoll(system_charset_info, 04301 (uchar *)lex->ident.str, lex->ident.length, 04302 (uchar *)sv->name, sv->length) == 0) 04303 break; 04304 } 04305 if (sv) 04306 { 04307 if (ha_release_savepoint(thd, sv)) 04308 res= TRUE; // cannot happen 04309 else 04310 send_ok(thd); 04311 thd->transaction.savepoints=sv->prev; 04312 } 04313 else 04314 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str); 04315 break; 04316 } 04317 case SQLCOM_ROLLBACK_TO_SAVEPOINT: 04318 { 04319 SAVEPOINT *sv; 04320 for (sv=thd->transaction.savepoints; sv; sv=sv->prev) 04321 { 04322 if (my_strnncoll(system_charset_info, 04323 (uchar *)lex->ident.str, lex->ident.length, 04324 (uchar *)sv->name, sv->length) == 0) 04325 break; 04326 } 04327 if (sv) 04328 { 04329 if (ha_rollback_to_savepoint(thd, sv)) 04330 res= TRUE; // cannot happen 04331 else 04332 { 04333 if ((thd->options & 04334 (OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG)) && 04335 !thd->slave_thread) 04336 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 04337 ER_WARNING_NOT_COMPLETE_ROLLBACK, 04338 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)); 04339 send_ok(thd); 04340 } 04341 thd->transaction.savepoints=sv; 04342 } 04343 else 04344 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str); 04345 break; 04346 } 04347 case SQLCOM_SAVEPOINT: 04348 if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) || 04349 thd->in_sub_stmt) || !opt_using_transactions) 04350 send_ok(thd); 04351 else 04352 { 04353 SAVEPOINT **sv, *newsv; 04354 for (sv=&thd->transaction.savepoints; *sv; sv=&(*sv)->prev) 04355 { 04356 if (my_strnncoll(system_charset_info, 04357 (uchar *)lex->ident.str, lex->ident.length, 04358 (uchar *)(*sv)->name, (*sv)->length) == 0) 04359 break; 04360 } 04361 if (*sv) /* old savepoint of the same name exists */ 04362 { 04363 newsv=*sv; 04364 ha_release_savepoint(thd, *sv); // it cannot fail 04365 *sv=(*sv)->prev; 04366 } 04367 else if ((newsv=(SAVEPOINT *) alloc_root(&thd->transaction.mem_root, 04368 savepoint_alloc_size)) == 0) 04369 { 04370 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 04371 break; 04372 } 04373 newsv->name=strmake_root(&thd->transaction.mem_root, 04374 lex->ident.str, lex->ident.length); 04375 newsv->length=lex->ident.length; 04376 /* 04377 if we'll get an error here, don't add new savepoint to the list. 04378 we'll lose a little bit of memory in transaction mem_root, but it'll 04379 be free'd when transaction ends anyway 04380 */ 04381 if (ha_savepoint(thd, newsv)) 04382 res= TRUE; 04383 else 04384 { 04385 newsv->prev=thd->transaction.savepoints; 04386 thd->transaction.savepoints=newsv; 04387 send_ok(thd); 04388 } 04389 } 04390 break; 04391 case SQLCOM_CREATE_PROCEDURE: 04392 case SQLCOM_CREATE_SPFUNCTION: 04393 { 04394 uint namelen; 04395 char *name; 04396 int result; 04397 04398 DBUG_ASSERT(lex->sphead != 0); 04399 DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */ 04400 04401 if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0, 04402 is_schema_db(lex->sphead->m_db.str))) 04403 { 04404 delete lex->sphead; 04405 lex->sphead= 0; 04406 goto error; 04407 } 04408 04409 if (end_active_trans(thd)) 04410 { 04411 delete lex->sphead; 04412 lex->sphead= 0; 04413 goto error; 04414 } 04415 04416 name= lex->sphead->name(&namelen); 04417 #ifdef HAVE_DLOPEN 04418 if (lex->sphead->m_type == TYPE_ENUM_FUNCTION) 04419 { 04420 udf_func *udf = find_udf(name, namelen); 04421 04422 if (udf) 04423 { 04424 my_error(ER_UDF_EXISTS, MYF(0), name); 04425 delete lex->sphead; 04426 lex->sphead= 0; 04427 goto error; 04428 } 04429 } 04430 #endif 04431 04432 /* 04433 If the definer is not specified, this means that CREATE-statement missed 04434 DEFINER-clause. DEFINER-clause can be missed in two cases: 04435 04436 - The user submitted a statement w/o the clause. This is a normal 04437 case, we should assign CURRENT_USER as definer. 04438 04439 - Our slave received an updated from the master, that does not 04440 replicate definer for stored rountines. We should also assign 04441 CURRENT_USER as definer here, but also we should mark this routine 04442 as NON-SUID. This is essential for the sake of backward 04443 compatibility. 04444 04445 The problem is the slave thread is running under "special" user (@), 04446 that actually does not exist. In the older versions we do not fail 04447 execution of a stored routine if its definer does not exist and 04448 continue the execution under the authorization of the invoker 04449 (BUG#13198). And now if we try to switch to slave-current-user (@), 04450 we will fail. 04451 04452 Actually, this leads to the inconsistent state of master and 04453 slave (different definers, different SUID behaviour), but it seems, 04454 this is the best we can do. 04455 */ 04456 04457 if (!lex->definer) 04458 { 04459 bool res= FALSE; 04460 Query_arena original_arena; 04461 Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena); 04462 04463 if (!(lex->definer= create_default_definer(thd))) 04464 res= TRUE; 04465 04466 if (ps_arena) 04467 thd->restore_active_arena(ps_arena, &original_arena); 04468 04469 if (res) 04470 { 04471 /* Error has been already reported. */ 04472 delete lex->sphead; 04473 lex->sphead= 0; 04474 goto error; 04475 } 04476 04477 if (thd->slave_thread) 04478 lex->sphead->m_chistics->suid= SP_IS_NOT_SUID; 04479 } 04480 04481 /* 04482 If the specified definer differs from the current user, we should check 04483 that the current user has SUPER privilege (in order to create a stored 04484 routine under another user one must have SUPER privilege). 04485 */ 04486 04487 else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) || 04488 my_strcasecmp(system_charset_info, 04489 lex->definer->host.str, 04490 thd->security_ctx->priv_host)) 04491 { 04492 if (check_global_access(thd, SUPER_ACL)) 04493 { 04494 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); 04495 delete lex->sphead; 04496 lex->sphead= 0; 04497 goto error; 04498 } 04499 } 04500 04501 /* Check that the specified definer exists. Emit a warning if not. */ 04502 04503 #ifndef NO_EMBEDDED_ACCESS_CHECKS 04504 if (!is_acl_user(lex->definer->host.str, 04505 lex->definer->user.str)) 04506 { 04507 push_warning_printf(thd, 04508 MYSQL_ERROR::WARN_LEVEL_NOTE, 04509 ER_NO_SUCH_USER, 04510 ER(ER_NO_SUCH_USER), 04511 lex->definer->user.str, 04512 lex->definer->host.str); 04513 } 04514 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 04515 04516 res= (result= lex->sphead->create(thd)); 04517 if (result == SP_OK) 04518 { 04519 #ifndef NO_EMBEDDED_ACCESS_CHECKS 04520 /* only add privileges if really neccessary */ 04521 if (sp_automatic_privileges && !opt_noacl && 04522 check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS, 04523 lex->sphead->m_db.str, name, 04524 lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1)) 04525 { 04526 if (sp_grant_privileges(thd, lex->sphead->m_db.str, name, 04527 lex->sql_command == SQLCOM_CREATE_PROCEDURE)) 04528 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 04529 ER_PROC_AUTO_GRANT_FAIL, 04530 ER(ER_PROC_AUTO_GRANT_FAIL)); 04531 close_thread_tables(thd); 04532 } 04533 #endif 04534 lex->unit.cleanup(); 04535 delete lex->sphead; 04536 lex->sphead= 0; 04537 send_ok(thd); 04538 } 04539 else 04540 { 04541 switch (result) { 04542 case SP_WRITE_ROW_FAILED: 04543 my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name); 04544 break; 04545 case SP_NO_DB_ERROR: 04546 my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str); 04547 break; 04548 case SP_BAD_IDENTIFIER: 04549 my_error(ER_TOO_LONG_IDENT, MYF(0), name); 04550 break; 04551 case SP_BODY_TOO_LONG: 04552 my_error(ER_TOO_LONG_BODY, MYF(0), name); 04553 break; 04554 default: 04555 my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name); 04556 break; 04557 } 04558 lex->unit.cleanup(); 04559 delete lex->sphead; 04560 lex->sphead= 0; 04561 goto error; 04562 } 04563 break; 04564 } 04565 case SQLCOM_CALL: 04566 { 04567 sp_head *sp; 04568 04569 /* 04570 This will cache all SP and SF and open and lock all tables 04571 required for execution. 04572 */ 04573 if (check_table_access(thd, SELECT_ACL, all_tables, 0) || 04574 open_and_lock_tables(thd, all_tables)) 04575 goto error; 04576 04577 /* 04578 By this moment all needed SPs should be in cache so no need to look 04579 into DB. 04580 */ 04581 if (!(sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname, 04582 &thd->sp_proc_cache, TRUE))) 04583 { 04584 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE", 04585 lex->spname->m_qname.str); 04586 goto error; 04587 } 04588 else 04589 { 04590 ha_rows select_limit; 04591 /* bits that should be cleared in thd->server_status */ 04592 uint bits_to_be_cleared= 0; 04593 /* 04594 Check that the stored procedure doesn't contain Dynamic SQL 04595 and doesn't return result sets: such stored procedures can't 04596 be called from a function or trigger. 04597 */ 04598 if (thd->in_sub_stmt) 04599 { 04600 const char *where= (thd->in_sub_stmt & SUB_STMT_TRIGGER ? 04601 "trigger" : "function"); 04602 if (sp->is_not_allowed_in_function(where)) 04603 goto error; 04604 } 04605 04606 my_bool nsok= thd->net.no_send_ok; 04607 thd->net.no_send_ok= TRUE; 04608 if (sp->m_flags & sp_head::MULTI_RESULTS) 04609 { 04610 if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS)) 04611 { 04612 /* 04613 The client does not support multiple result sets being sent 04614 back 04615 */ 04616 my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str); 04617 thd->net.no_send_ok= nsok; 04618 goto error; 04619 } 04620 /* 04621 If SERVER_MORE_RESULTS_EXISTS is not set, 04622 then remember that it should be cleared 04623 */ 04624 bits_to_be_cleared= (~thd->server_status & 04625 SERVER_MORE_RESULTS_EXISTS); 04626 thd->server_status|= SERVER_MORE_RESULTS_EXISTS; 04627 } 04628 04629 #ifndef NO_EMBEDDED_ACCESS_CHECKS 04630 if (check_routine_access(thd, EXECUTE_ACL, 04631 sp->m_db.str, sp->m_name.str, TRUE, FALSE)) 04632 { 04633 thd->net.no_send_ok= nsok; 04634 goto error; 04635 } 04636 #endif 04637 select_limit= thd->variables.select_limit; 04638 thd->variables.select_limit= HA_POS_ERROR; 04639 04640 thd->row_count_func= 0; 04641 04642 /* 04643 We never write CALL statements into binlog: 04644 - If the mode is non-prelocked, each statement will be logged 04645 separately. 04646 - If the mode is prelocked, the invoking statement will care 04647 about writing into binlog. 04648 So just execute the statement. 04649 */ 04650 res= sp->execute_procedure(thd, &lex->value_list); 04651 /* 04652 If warnings have been cleared, we have to clear total_warn_count 04653 too, otherwise the clients get confused. 04654 */ 04655 if (thd->warn_list.is_empty()) 04656 thd->total_warn_count= 0; 04657 04658 thd->variables.select_limit= select_limit; 04659 04660 thd->net.no_send_ok= nsok; 04661 thd->server_status&= ~bits_to_be_cleared; 04662 04663 if (!res) 04664 send_ok(thd, (ulong) (thd->row_count_func < 0 ? 0 : 04665 thd->row_count_func)); 04666 else 04667 goto error; // Substatement should already have sent error 04668 } 04669 break; 04670 } 04671 case SQLCOM_ALTER_PROCEDURE: 04672 case SQLCOM_ALTER_FUNCTION: 04673 { 04674 int result; 04675 sp_head *sp; 04676 st_sp_chistics chistics; 04677 04678 memcpy(&chistics, &lex->sp_chistics, sizeof(chistics)); 04679 if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) 04680 sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname, 04681 &thd->sp_proc_cache, FALSE); 04682 else 04683 sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, 04684 &thd->sp_func_cache, FALSE); 04685 mysql_reset_errors(thd, 0); 04686 if (! sp) 04687 { 04688 if (lex->spname->m_db.str) 04689 result= SP_KEY_NOT_FOUND; 04690 else 04691 { 04692 my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); 04693 goto error; 04694 } 04695 } 04696 else 04697 { 04698 if (check_routine_access(thd, ALTER_PROC_ACL, sp->m_db.str, 04699 sp->m_name.str, 04700 lex->sql_command == SQLCOM_ALTER_PROCEDURE, 0)) 04701 goto error; 04702 04703 if (end_active_trans(thd)) 04704 goto error; 04705 memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics)); 04706 if ((sp->m_type == TYPE_ENUM_FUNCTION) && 04707 !trust_function_creators && mysql_bin_log.is_open() && 04708 !sp->m_chistics->detistic && 04709 (chistics.daccess == SP_CONTAINS_SQL || 04710 chistics.daccess == SP_MODIFIES_SQL_DATA)) 04711 { 04712 my_message(ER_BINLOG_UNSAFE_ROUTINE, 04713 ER(ER_BINLOG_UNSAFE_ROUTINE), MYF(0)); 04714 result= SP_INTERNAL_ERROR; 04715 } 04716 else 04717 { 04718 /* 04719 Note that if you implement the capability of ALTER FUNCTION to 04720 alter the body of the function, this command should be made to 04721 follow the restrictions that log-bin-trust-function-creators=0 04722 already puts on CREATE FUNCTION. 04723 */ 04724 if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) 04725 result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics); 04726 else 04727 result= sp_update_function(thd, lex->spname, &lex->sp_chistics); 04728 } 04729 } 04730 switch (result) 04731 { 04732 case SP_OK: 04733 if (mysql_bin_log.is_open()) 04734 { 04735 thd->clear_error(); 04736 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04737 thd->query, thd->query_length, FALSE, FALSE); 04738 } 04739 send_ok(thd); 04740 break; 04741 case SP_KEY_NOT_FOUND: 04742 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), 04743 SP_COM_STRING(lex), lex->spname->m_qname.str); 04744 goto error; 04745 default: 04746 my_error(ER_SP_CANT_ALTER, MYF(0), 04747 SP_COM_STRING(lex), lex->spname->m_qname.str); 04748 goto error; 04749 } 04750 break; 04751 } 04752 case SQLCOM_DROP_PROCEDURE: 04753 case SQLCOM_DROP_FUNCTION: 04754 { 04755 int result; 04756 int type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ? 04757 TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION); 04758 04759 result= sp_routine_exists_in_table(thd, type, lex->spname); 04760 mysql_reset_errors(thd, 0); 04761 if (result == SP_OK) 04762 { 04763 char *db= lex->spname->m_db.str; 04764 char *name= lex->spname->m_name.str; 04765 04766 if (check_routine_access(thd, ALTER_PROC_ACL, db, name, 04767 lex->sql_command == SQLCOM_DROP_PROCEDURE, 0)) 04768 goto error; 04769 04770 if (end_active_trans(thd)) 04771 goto error; 04772 #ifndef NO_EMBEDDED_ACCESS_CHECKS 04773 if (sp_automatic_privileges && !opt_noacl && 04774 sp_revoke_privileges(thd, db, name, 04775 lex->sql_command == SQLCOM_DROP_PROCEDURE)) 04776 { 04777 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 04778 ER_PROC_AUTO_REVOKE_FAIL, 04779 ER(ER_PROC_AUTO_REVOKE_FAIL)); 04780 } 04781 #endif 04782 if (lex->sql_command == SQLCOM_DROP_PROCEDURE) 04783 result= sp_drop_procedure(thd, lex->spname); 04784 else 04785 result= sp_drop_function(thd, lex->spname); 04786 } 04787 else 04788 { 04789 #ifdef HAVE_DLOPEN 04790 if (lex->sql_command == SQLCOM_DROP_FUNCTION) 04791 { 04792 udf_func *udf = find_udf(lex->spname->m_name.str, 04793 lex->spname->m_name.length); 04794 if (udf) 04795 { 04796 if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0)) 04797 goto error; 04798 if (!(res = mysql_drop_function(thd, &lex->spname->m_name))) 04799 { 04800 send_ok(thd); 04801 break; 04802 } 04803 } 04804 } 04805 #endif 04806 if (lex->spname->m_db.str) 04807 result= SP_KEY_NOT_FOUND; 04808 else 04809 { 04810 my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); 04811 goto error; 04812 } 04813 } 04814 res= result; 04815 switch (result) 04816 { 04817 case SP_OK: 04818 if (mysql_bin_log.is_open()) 04819 { 04820 thd->clear_error(); 04821 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04822 thd->query, thd->query_length, FALSE, FALSE); 04823 } 04824 send_ok(thd); 04825 break; 04826 case SP_KEY_NOT_FOUND: 04827 if (lex->drop_if_exists) 04828 { 04829 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 04830 ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), 04831 SP_COM_STRING(lex), lex->spname->m_name.str); 04832 res= FALSE; 04833 send_ok(thd); 04834 break; 04835 } 04836 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), 04837 SP_COM_STRING(lex), lex->spname->m_qname.str); 04838 goto error; 04839 default: 04840 my_error(ER_SP_DROP_FAILED, MYF(0), 04841 SP_COM_STRING(lex), lex->spname->m_qname.str); 04842 goto error; 04843 } 04844 break; 04845 } 04846 case SQLCOM_SHOW_CREATE_PROC: 04847 { 04848 if (lex->spname->m_name.length > NAME_LEN) 04849 { 04850 my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str); 04851 goto error; 04852 } 04853 if (sp_show_create_procedure(thd, lex->spname) != SP_OK) 04854 { /* We don't distinguish between errors for now */ 04855 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), 04856 SP_COM_STRING(lex), lex->spname->m_name.str); 04857 goto error; 04858 } 04859 break; 04860 } 04861 case SQLCOM_SHOW_CREATE_FUNC: 04862 { 04863 if (lex->spname->m_name.length > NAME_LEN) 04864 { 04865 my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str); 04866 goto error; 04867 } 04868 if (sp_show_create_function(thd, lex->spname) != SP_OK) 04869 { /* We don't distinguish between errors for now */ 04870 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), 04871 SP_COM_STRING(lex), lex->spname->m_name.str); 04872 goto error; 04873 } 04874 break; 04875 } 04876 #ifdef NOT_USED 04877 case SQLCOM_SHOW_STATUS_PROC: 04878 { 04879 res= sp_show_status_procedure(thd, (lex->wild ? 04880 lex->wild->ptr() : NullS)); 04881 break; 04882 } 04883 case SQLCOM_SHOW_STATUS_FUNC: 04884 { 04885 res= sp_show_status_function(thd, (lex->wild ? 04886 lex->wild->ptr() : NullS)); 04887 break; 04888 } 04889 #endif 04890 #ifndef DBUG_OFF 04891 case SQLCOM_SHOW_PROC_CODE: 04892 case SQLCOM_SHOW_FUNC_CODE: 04893 { 04894 sp_head *sp; 04895 04896 if (lex->spname->m_name.length > NAME_LEN) 04897 { 04898 my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str); 04899 goto error; 04900 } 04901 if (lex->sql_command == SQLCOM_SHOW_PROC_CODE) 04902 sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname, 04903 &thd->sp_proc_cache, FALSE); 04904 else 04905 sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, 04906 &thd->sp_func_cache, FALSE); 04907 if (!sp || sp->show_routine_code(thd)) 04908 { 04909 /* We don't distinguish between errors for now */ 04910 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), 04911 SP_COM_STRING(lex), lex->spname->m_name.str); 04912 goto error; 04913 } 04914 break; 04915 } 04916 #endif // ifndef DBUG_OFF 04917 case SQLCOM_CREATE_VIEW: 04918 { 04919 if (end_active_trans(thd)) 04920 goto error; 04921 04922 if (!(res= mysql_create_view(thd, thd->lex->create_view_mode)) && 04923 mysql_bin_log.is_open()) 04924 { 04925 String buff; 04926 const LEX_STRING command[3]= 04927 {{ C_STRING_WITH_LEN("CREATE ") }, 04928 { C_STRING_WITH_LEN("ALTER ") }, 04929 { C_STRING_WITH_LEN("CREATE OR REPLACE ") }}; 04930 thd->clear_error(); 04931 04932 buff.append(command[thd->lex->create_view_mode].str, 04933 command[thd->lex->create_view_mode].length); 04934 view_store_options(thd, first_table, &buff); 04935 buff.append(STRING_WITH_LEN("VIEW ")); 04936 /* Test if user supplied a db (ie: we did not use thd->db) */ 04937 if (first_table->db && first_table->db[0] && 04938 (thd->db == NULL || strcmp(first_table->db, thd->db))) 04939 { 04940 append_identifier(thd, &buff, first_table->db, 04941 first_table->db_length); 04942 buff.append('.'); 04943 } 04944 append_identifier(thd, &buff, first_table->table_name, 04945 first_table->table_name_length); 04946 buff.append(STRING_WITH_LEN(" AS ")); 04947 buff.append(first_table->source.str, first_table->source.length); 04948 04949 thd->binlog_query(THD::STMT_QUERY_TYPE, 04950 buff.ptr(), buff.length(), FALSE, FALSE); 04951 } 04952 break; 04953 } 04954 case SQLCOM_DROP_VIEW: 04955 { 04956 if (check_table_access(thd, DROP_ACL, all_tables, 0) || 04957 end_active_trans(thd)) 04958 goto error; 04959 if (!(res= mysql_drop_view(thd, first_table, thd->lex->drop_mode)) && 04960 mysql_bin_log.is_open()) 04961 { 04962 thd->clear_error(); 04963 thd->binlog_query(THD::STMT_QUERY_TYPE, 04964 thd->query, thd->query_length, FALSE, FALSE); 04965 } 04966 break; 04967 } 04968 case SQLCOM_CREATE_TRIGGER: 04969 { 04970 if (end_active_trans(thd)) 04971 goto error; 04972 04973 res= mysql_create_or_drop_trigger(thd, all_tables, 1); 04974 04975 /* We don't care about trigger body after this point */ 04976 delete lex->sphead; 04977 lex->sphead= 0; 04978 break; 04979 } 04980 case SQLCOM_DROP_TRIGGER: 04981 { 04982 if (end_active_trans(thd)) 04983 goto error; 04984 04985 res= mysql_create_or_drop_trigger(thd, all_tables, 0); 04986 break; 04987 } 04988 case SQLCOM_XA_START: 04989 if (thd->transaction.xid_state.xa_state == XA_IDLE && 04990 thd->lex->xa_opt == XA_RESUME) 04991 { 04992 if (! thd->transaction.xid_state.xid.eq(thd->lex->xid)) 04993 { 04994 my_error(ER_XAER_NOTA, MYF(0)); 04995 break; 04996 } 04997 thd->transaction.xid_state.xa_state=XA_ACTIVE; 04998 send_ok(thd); 04999 break; 05000 } 05001 if (thd->lex->xa_opt != XA_NONE) 05002 { // JOIN is not supported yet. TODO 05003 my_error(ER_XAER_INVAL, MYF(0)); 05004 break; 05005 } 05006 if (thd->transaction.xid_state.xa_state != XA_NOTR) 05007 { 05008 my_error(ER_XAER_RMFAIL, MYF(0), 05009 xa_state_names[thd->transaction.xid_state.xa_state]); 05010 break; 05011 } 05012 if (thd->active_transaction() || thd->locked_tables) 05013 { 05014 my_error(ER_XAER_OUTSIDE, MYF(0)); 05015 break; 05016 } 05017 if (xid_cache_search(thd->lex->xid)) 05018 { 05019 my_error(ER_XAER_DUPID, MYF(0)); 05020 break; 05021 } 05022 DBUG_ASSERT(thd->transaction.xid_state.xid.is_null()); 05023 thd->transaction.xid_state.xa_state=XA_ACTIVE; 05024 thd->transaction.xid_state.xid.set(thd->lex->xid); 05025 xid_cache_insert(&thd->transaction.xid_state); 05026 thd->options= ((thd->options & ~(OPTION_STATUS_NO_TRANS_UPDATE | 05027 OPTION_KEEP_LOG)) | 05028 OPTION_BEGIN); 05029 thd->server_status|= SERVER_STATUS_IN_TRANS; 05030 send_ok(thd); 05031 break; 05032 case SQLCOM_XA_END: 05033 /* fake it */ 05034 if (thd->lex->xa_opt != XA_NONE) 05035 { // SUSPEND and FOR MIGRATE are not supported yet. TODO 05036 my_error(ER_XAER_INVAL, MYF(0)); 05037 break; 05038 } 05039 if (thd->transaction.xid_state.xa_state != XA_ACTIVE) 05040 { 05041 my_error(ER_XAER_RMFAIL, MYF(0), 05042 xa_state_names[thd->transaction.xid_state.xa_state]); 05043 break; 05044 } 05045 if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) 05046 { 05047 my_error(ER_XAER_NOTA, MYF(0)); 05048 break; 05049 } 05050 thd->transaction.xid_state.xa_state=XA_IDLE; 05051 send_ok(thd); 05052 break; 05053 case SQLCOM_XA_PREPARE: 05054 if (thd->transaction.xid_state.xa_state != XA_IDLE) 05055 { 05056 my_error(ER_XAER_RMFAIL, MYF(0), 05057 xa_state_names[thd->transaction.xid_state.xa_state]); 05058 break; 05059 } 05060 if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) 05061 { 05062 my_error(ER_XAER_NOTA, MYF(0)); 05063 break; 05064 } 05065 if (ha_prepare(thd)) 05066 { 05067 my_error(ER_XA_RBROLLBACK, MYF(0)); 05068 xid_cache_delete(&thd->transaction.xid_state); 05069 thd->transaction.xid_state.xa_state=XA_NOTR; 05070 break; 05071 } 05072 thd->transaction.xid_state.xa_state=XA_PREPARED; 05073 send_ok(thd); 05074 break; 05075 case SQLCOM_XA_COMMIT: 05076 if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) 05077 { 05078 XID_STATE *xs=xid_cache_search(thd->lex->xid); 05079 if (!xs || xs->in_thd) 05080 my_error(ER_XAER_NOTA, MYF(0)); 05081 else 05082 { 05083 ha_commit_or_rollback_by_xid(thd->lex->xid, 1); 05084 xid_cache_delete(xs); 05085 send_ok(thd); 05086 } 05087 break; 05088 } 05089 if (thd->transaction.xid_state.xa_state == XA_IDLE && 05090 thd->lex->xa_opt == XA_ONE_PHASE) 05091 { 05092 int r; 05093 if ((r= ha_commit(thd))) 05094 my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0)); 05095 else 05096 send_ok(thd); 05097 } 05098 else if (thd->transaction.xid_state.xa_state == XA_PREPARED && 05099 thd->lex->xa_opt == XA_NONE) 05100 { 05101 if (wait_if_global_read_lock(thd, 0, 0)) 05102 { 05103 ha_rollback(thd); 05104 my_error(ER_XAER_RMERR, MYF(0)); 05105 } 05106 else 05107 { 05108 if (ha_commit_one_phase(thd, 1)) 05109 my_error(ER_XAER_RMERR, MYF(0)); 05110 else 05111 send_ok(thd); 05112 start_waiting_global_read_lock(thd); 05113 } 05114 } 05115 else 05116 { 05117 my_error(ER_XAER_RMFAIL, MYF(0), 05118 xa_state_names[thd->transaction.xid_state.xa_state]); 05119 break; 05120 } 05121 thd->options&= ~(OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE | 05122 OPTION_KEEP_LOG); 05123 thd->server_status&= ~SERVER_STATUS_IN_TRANS; 05124 xid_cache_delete(&thd->transaction.xid_state); 05125 thd->transaction.xid_state.xa_state=XA_NOTR; 05126 break; 05127 case SQLCOM_XA_ROLLBACK: 05128 if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) 05129 { 05130 XID_STATE *xs=xid_cache_search(thd->lex->xid); 05131 if (!xs || xs->in_thd) 05132 my_error(ER_XAER_NOTA, MYF(0)); 05133 else 05134 { 05135 ha_commit_or_rollback_by_xid(thd->lex->xid, 0); 05136 xid_cache_delete(xs); 05137 send_ok(thd); 05138 } 05139 break; 05140 } 05141 if (thd->transaction.xid_state.xa_state != XA_IDLE && 05142 thd->transaction.xid_state.xa_state != XA_PREPARED) 05143 { 05144 my_error(ER_XAER_RMFAIL, MYF(0), 05145 xa_state_names[thd->transaction.xid_state.xa_state]); 05146 break; 05147 } 05148 if (ha_rollback(thd)) 05149 my_error(ER_XAER_RMERR, MYF(0)); 05150 else 05151 send_ok(thd); 05152 thd->options&= ~(OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE | 05153 OPTION_KEEP_LOG); 05154 thd->server_status&= ~SERVER_STATUS_IN_TRANS; 05155 xid_cache_delete(&thd->transaction.xid_state); 05156 thd->transaction.xid_state.xa_state=XA_NOTR; 05157 break; 05158 case SQLCOM_XA_RECOVER: 05159 res= mysql_xa_recover(thd); 05160 break; 05161 case SQLCOM_ALTER_TABLESPACE: 05162 if (check_access(thd, ALTER_ACL, thd->db, 0, 1, 0, thd->db ? is_schema_db(thd->db) : 0)) 05163 break; 05164 if (!(res= mysql_alter_tablespace(thd, lex->alter_tablespace_info))) 05165 send_ok(thd); 05166 break; 05167 case SQLCOM_INSTALL_PLUGIN: 05168 if (! (res= mysql_install_plugin(thd, &thd->lex->comment, 05169 &thd->lex->ident))) 05170 send_ok(thd); 05171 break; 05172 case SQLCOM_UNINSTALL_PLUGIN: 05173 if (! (res= mysql_uninstall_plugin(thd, &thd->lex->comment))) 05174 send_ok(thd); 05175 break; 05176 case SQLCOM_BINLOG_BASE64_EVENT: 05177 { 05178 #ifndef EMBEDDED_LIBRARY 05179 mysql_client_binlog_statement(thd); 05180 #else /* EMBEDDED_LIBRARY */ 05181 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "embedded"); 05182 #endif /* EMBEDDED_LIBRARY */ 05183 break; 05184 } 05185 default: 05186 #ifndef EMBEDDED_LIBRARY 05187 DBUG_ASSERT(0); /* Impossible */ 05188 #endif 05189 send_ok(thd); 05190 break; 05191 } 05192 05193 end: 05194 thd->proc_info="query end"; 05195 05196 /* 05197 Binlog-related cleanup: 05198 Reset system variables temporarily modified by SET ONE SHOT. 05199 05200 Exception: If this is a SET, do nothing. This is to allow 05201 mysqlbinlog to print many SET commands (in this case we want the 05202 charset temp setting to live until the real query). This is also 05203 needed so that SET CHARACTER_SET_CLIENT... does not cancel itself 05204 immediately. 05205 */ 05206 if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION) 05207 reset_one_shot_variables(thd); 05208 05209 /* 05210 The return value for ROW_COUNT() is "implementation dependent" if the 05211 statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC 05212 wants. We also keep the last value in case of SQLCOM_CALL or 05213 SQLCOM_EXECUTE. 05214 */ 05215 if (!(sql_command_flags[lex->sql_command] & CF_HAS_ROW_COUNT)) 05216 thd->row_count_func= -1; 05217 05218 goto finish; 05219 05220 error: 05221 res= TRUE; 05222 05223 finish: 05224 if (need_start_waiting) 05225 { 05226 /* 05227 Release the protection against the global read lock and wake 05228 everyone, who might want to set a global read lock. 05229 */ 05230 start_waiting_global_read_lock(thd); 05231 } 05232 DBUG_RETURN(res || thd->net.report_error); 05233 } 05234 05235 05236 static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) 05237 { 05238 LEX *lex= thd->lex; 05239 select_result *result=lex->result; 05240 bool res; 05241 /* assign global limit variable if limit is not given */ 05242 { 05243 SELECT_LEX *param= lex->unit.global_parameters; 05244 if (!param->explicit_limit) 05245 param->select_limit= 05246 new Item_int((ulonglong) thd->variables.select_limit); 05247 } 05248 if (!(res= open_and_lock_tables(thd, all_tables))) 05249 { 05250 if (lex->describe) 05251 { 05252 /* 05253 We always use select_send for EXPLAIN, even if it's an EXPLAIN 05254 for SELECT ... INTO OUTFILE: a user application should be able 05255 to prepend EXPLAIN to any query and receive output for it, 05256 even if the query itself redirects the output. 05257 */ 05258 if (!(result= new select_send())) 05259 return 1; /* purecov: inspected */ 05260 thd->send_explain_fields(result); 05261 res= mysql_explain_union(thd, &thd->lex->unit, result); 05262 if (lex->describe & DESCRIBE_EXTENDED) 05263 { 05264 char buff[1024]; 05265 String str(buff,(uint32) sizeof(buff), system_charset_info); 05266 str.length(0); 05267 thd->lex->unit.print(&str); 05268 str.append('\0'); 05269 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 05270 ER_YES, str.ptr()); 05271 } 05272 result->send_eof(); 05273 delete result; 05274 } 05275 else 05276 { 05277 if (!result && !(result= new select_send())) 05278 return 1; /* purecov: inspected */ 05279 query_cache_store_query(thd, all_tables); 05280 res= handle_select(thd, lex, result, 0); 05281 if (result != lex->result) 05282 delete result; 05283 } 05284 } 05285 return res; 05286 } 05287 05288 05289 /* 05290 Check grants for commands which work only with one table. 05291 05292 SYNOPSIS 05293 check_single_table_access() 05294 thd Thread handler 05295 privilege requested privilege 05296 all_tables global table list of query 05297 05298 RETURN 05299 0 - OK 05300 1 - access denied, error is sent to client 05301 */ 05302 05303 bool check_single_table_access(THD *thd, ulong privilege, 05304 TABLE_LIST *all_tables) 05305 { 05306 Security_context * backup_ctx= thd->security_ctx; 05307 05308 /* we need to switch to the saved context (if any) */ 05309 if (all_tables->security_ctx) 05310 thd->security_ctx= all_tables->security_ctx; 05311 05312 const char *db_name; 05313 if ((all_tables->view || all_tables->field_translation) && 05314 !all_tables->schema_table) 05315 db_name= all_tables->view_db.str; 05316 else 05317 db_name= all_tables->db; 05318 05319 if (check_access(thd, privilege, db_name, 05320 &all_tables->grant.privilege, 0, 0, 05321 test(all_tables->schema_table))) 05322 goto deny; 05323 05324 /* Show only 1 table for check_grant */ 05325 if (grant_option && check_grant(thd, privilege, all_tables, 0, 1, 0)) 05326 goto deny; 05327 05328 thd->security_ctx= backup_ctx; 05329 return 0; 05330 05331 deny: 05332 thd->security_ctx= backup_ctx; 05333 return 1; 05334 } 05335 05336 /* 05337 Check grants for commands which work only with one table and all other 05338 tables belonging to subselects or implicitly opened tables. 05339 05340 SYNOPSIS 05341 check_one_table_access() 05342 thd Thread handler 05343 privilege requested privilege 05344 all_tables global table list of query 05345 05346 RETURN 05347 0 - OK 05348 1 - access denied, error is sent to client 05349 */ 05350 05351 bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) 05352 { 05353 if (check_single_table_access (thd,privilege,all_tables)) 05354 return 1; 05355 05356 /* Check rights on tables of subselects and implictly opened tables */ 05357 TABLE_LIST *subselects_tables; 05358 if ((subselects_tables= all_tables->next_global)) 05359 { 05360 if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0))) 05361 return 1; 05362 } 05363 return 0; 05364 } 05365 05366 05367 /**************************************************************************** 05368 Get the user (global) and database privileges for all used tables 05369 05370 NOTES 05371 The idea of EXTRA_ACL is that one will be granted access to the table if 05372 one has the asked privilege on any column combination of the table; For 05373 example to be able to check a table one needs to have SELECT privilege on 05374 any column of the table. 05375 05376 RETURN 05377 0 ok 05378 1 If we can't get the privileges and we don't use table/column grants. 05379 05380 save_priv In this we store global and db level grants for the table 05381 Note that we don't store db level grants if the global grants 05382 is enough to satisfy the request and the global grants contains 05383 a SELECT grant. 05384 ****************************************************************************/ 05385 05386 bool 05387 check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, 05388 bool dont_check_global_grants, bool no_errors, bool schema_db) 05389 { 05390 Security_context *sctx= thd->security_ctx; 05391 #ifndef NO_EMBEDDED_ACCESS_CHECKS 05392 ulong db_access; 05393 bool db_is_pattern= test(want_access & GRANT_ACL); 05394 #endif 05395 ulong dummy; 05396 DBUG_ENTER("check_access"); 05397 DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu", 05398 db ? db : "", want_access, sctx->master_access)); 05399 if (save_priv) 05400 *save_priv=0; 05401 else 05402 save_priv= &dummy; 05403 05404 if ((!db || !db[0]) && !thd->db && !dont_check_global_grants) 05405 { 05406 DBUG_PRINT("error",("No database")); 05407 if (!no_errors) 05408 my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), 05409 MYF(0)); /* purecov: tested */ 05410 DBUG_RETURN(TRUE); /* purecov: tested */ 05411 } 05412 05413 if (schema_db) 05414 { 05415 if (want_access & ~(SELECT_ACL | EXTRA_ACL)) 05416 { 05417 if (!no_errors) 05418 { 05419 const char *db_name= db ? db : thd->db; 05420 my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), 05421 sctx->priv_user, sctx->priv_host, db_name); 05422 } 05423 DBUG_RETURN(TRUE); 05424 } 05425 else 05426 { 05427 *save_priv= SELECT_ACL; 05428 DBUG_RETURN(FALSE); 05429 } 05430 } 05431 05432 #ifdef NO_EMBEDDED_ACCESS_CHECKS 05433 DBUG_RETURN(0); 05434 #else 05435 if ((sctx->master_access & want_access) == want_access) 05436 { 05437 /* 05438 If we don't have a global SELECT privilege, we have to get the database 05439 specific access rights to be able to handle queries of type 05440 UPDATE t1 SET a=1 WHERE b > 0 05441 */ 05442 db_access= sctx->db_access; 05443 if (!(sctx->master_access & SELECT_ACL) && 05444 (db && (!thd->db || db_is_pattern || strcmp(db,thd->db)))) 05445 db_access=acl_get(sctx->host, sctx->ip, sctx->priv_user, db, 05446 db_is_pattern); 05447 *save_priv=sctx->master_access | db_access; 05448 DBUG_RETURN(FALSE); 05449 } 05450 if (((want_access & ~sctx->master_access) & ~(DB_ACLS | EXTRA_ACL)) || 05451 ! db && dont_check_global_grants) 05452 { // We can never grant this 05453 DBUG_PRINT("error",("No possible access")); 05454 if (!no_errors) 05455 my_error(ER_ACCESS_DENIED_ERROR, MYF(0), 05456 sctx->priv_user, 05457 sctx->priv_host, 05458 (thd->password ? 05459 ER(ER_YES) : 05460 ER(ER_NO))); /* purecov: tested */ 05461 DBUG_RETURN(TRUE); /* purecov: tested */ 05462 } 05463 05464 if (db == any_db) 05465 DBUG_RETURN(FALSE); // Allow select on anything 05466 05467 if (db && (!thd->db || db_is_pattern || strcmp(db,thd->db))) 05468 db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db, 05469 db_is_pattern); 05470 else 05471 db_access= sctx->db_access; 05472 DBUG_PRINT("info",("db_access: %lu", db_access)); 05473 /* Remove SHOW attribute and access rights we already have */ 05474 want_access &= ~(sctx->master_access | EXTRA_ACL); 05475 DBUG_PRINT("info",("db_access: %lu want_access: %lu", 05476 db_access, want_access)); 05477 db_access= ((*save_priv=(db_access | sctx->master_access)) & want_access); 05478 05479 /* grant_option is set if there exists a single table or column grant */ 05480 if (db_access == want_access || 05481 (grant_option && !dont_check_global_grants && 05482 !(want_access & ~(db_access | TABLE_ACLS | PROC_ACLS)))) 05483 DBUG_RETURN(FALSE); /* Ok */ 05484 05485 DBUG_PRINT("error",("Access denied")); 05486 if (!no_errors) 05487 my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), 05488 sctx->priv_user, sctx->priv_host, 05489 (db ? db : (thd->db ? 05490 thd->db : 05491 "unknown"))); /* purecov: tested */ 05492 DBUG_RETURN(TRUE); /* purecov: tested */ 05493 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 05494 } 05495 05496 05497 /* 05498 check for global access and give descriptive error message if it fails 05499 05500 SYNOPSIS 05501 check_global_access() 05502 thd Thread handler 05503 want_access Use should have any of these global rights 05504 05505 WARNING 05506 One gets access right if one has ANY of the rights in want_access 05507 This is useful as one in most cases only need one global right, 05508 but in some case we want to check if the user has SUPER or 05509 REPL_CLIENT_ACL rights. 05510 05511 RETURN 05512 0 ok 05513 1 Access denied. In this case an error is sent to the client 05514 */ 05515 05516 bool check_global_access(THD *thd, ulong want_access) 05517 { 05518 #ifdef NO_EMBEDDED_ACCESS_CHECKS 05519 return 0; 05520 #else 05521 char command[128]; 05522 if ((thd->security_ctx->master_access & want_access)) 05523 return 0; 05524 get_privilege_desc(command, sizeof(command), want_access); 05525 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command); 05526 return 1; 05527 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 05528 } 05529 05530 05531 /* 05532 Check the privilege for all used tables. 05533 05534 SYNOPSYS 05535 check_table_access() 05536 thd Thread context 05537 want_access Privileges requested 05538 tables List of tables to be checked 05539 no_errors FALSE/TRUE - report/don't report error to 05540 the client (using my_error() call). 05541 05542 NOTES 05543 Table privileges are cached in the table list for GRANT checking. 05544 This functions assumes that table list used and 05545 thd->lex->query_tables_own_last value correspond to each other 05546 (the latter should be either 0 or point to next_global member 05547 of one of elements of this table list). 05548 05549 RETURN VALUE 05550 FALSE - OK 05551 TRUE - Access denied 05552 */ 05553 05554 bool 05555 check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, 05556 bool no_errors) 05557 { 05558 uint found=0; 05559 ulong found_access=0; 05560 TABLE_LIST *org_tables= tables; 05561 TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table(); 05562 Security_context *sctx= thd->security_ctx, *backup_ctx= thd->security_ctx; 05563 /* 05564 The check that first_not_own_table is not reached is for the case when 05565 the given table list refers to the list for prelocking (contains tables 05566 of other queries). For simple queries first_not_own_table is 0. 05567 */ 05568 for (; tables != first_not_own_table; tables= tables->next_global) 05569 { 05570 if (tables->security_ctx) 05571 sctx= tables->security_ctx; 05572 else 05573 sctx= backup_ctx; 05574 05575 if (tables->schema_table && 05576 (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL))) 05577 { 05578 if (!no_errors) 05579 my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), 05580 sctx->priv_user, sctx->priv_host, 05581 information_schema_name.str); 05582 return TRUE; 05583 } 05584 /* 05585 Register access for view underlying table. 05586 Remove SHOW_VIEW_ACL, because it will be checked during making view 05587 */ 05588 tables->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL); 05589 if (tables->derived || tables->schema_table || 05590 (tables->table && (int)tables->table->s->tmp_table) || 05591 my_tz_check_n_skip_implicit_tables(&tables, 05592 thd->lex->time_zone_tables_used)) 05593 continue; 05594 thd->security_ctx= sctx; 05595 if ((sctx->master_access & want_access) == 05596 (want_access & ~EXTRA_ACL) && 05597 thd->db) 05598 tables->grant.privilege= want_access; 05599 else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0) 05600 { 05601 if (found && !grant_option) // db already checked 05602 tables->grant.privilege=found_access; 05603 else 05604 { 05605 if (check_access(thd,want_access,tables->db,&tables->grant.privilege, 05606 0, no_errors, test(tables->schema_table))) 05607 goto deny; // Access denied 05608 found_access=tables->grant.privilege; 05609 found=1; 05610 } 05611 } 05612 else if (check_access(thd,want_access,tables->db,&tables->grant.privilege, 05613 0, no_errors, test(tables->schema_table))) 05614 goto deny; 05615 } 05616 thd->security_ctx= backup_ctx; 05617 if (grant_option) 05618 return check_grant(thd,want_access & ~EXTRA_ACL,org_tables, 05619 test(want_access & EXTRA_ACL), UINT_MAX, no_errors); 05620 return FALSE; 05621 deny: 05622 thd->security_ctx= backup_ctx; 05623 return TRUE; 05624 } 05625 05626 05627 bool 05628 check_routine_access(THD *thd, ulong want_access,char *db, char *name, 05629 bool is_proc, bool no_errors) 05630 { 05631 TABLE_LIST tables[1]; 05632 05633 bzero((char *)tables, sizeof(TABLE_LIST)); 05634 tables->db= db; 05635 tables->table_name= tables->alias= name; 05636 05637 /* 05638 The following test is just a shortcut for check_access() (to avoid 05639 calculating db_access) under the assumption that it's common to 05640 give persons global right to execute all stored SP (but not 05641 necessary to create them). 05642 */ 05643 if ((thd->security_ctx->master_access & want_access) == want_access) 05644 tables->grant.privilege= want_access; 05645 else if (check_access(thd,want_access,db,&tables->grant.privilege, 05646 0, no_errors, 0)) 05647 return TRUE; 05648 05649 #ifndef NO_EMBEDDED_ACCESS_CHECKS 05650 if (grant_option) 05651 return check_grant_routine(thd, want_access, tables, is_proc, no_errors); 05652 #endif 05653 05654 return FALSE; 05655 } 05656 05657 05658 /* 05659 Check if the routine has any of the routine privileges 05660 05661 SYNOPSIS 05662 check_some_routine_access() 05663 thd Thread handler 05664 db Database name 05665 name Routine name 05666 05667 RETURN 05668 0 ok 05669 1 error 05670 */ 05671 05672 bool check_some_routine_access(THD *thd, const char *db, const char *name, 05673 bool is_proc) 05674 { 05675 ulong save_priv; 05676 if (thd->security_ctx->master_access & SHOW_PROC_ACLS) 05677 return FALSE; 05678 /* 05679 There are no routines in information_schema db. So we can safely 05680 pass zero to last paramter of check_access function 05681 */ 05682 if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, 0, 1, 0) || 05683 (save_priv & SHOW_PROC_ACLS)) 05684 return FALSE; 05685 return check_routine_level_acl(thd, db, name, is_proc); 05686 } 05687 05688 05689 /* 05690 Check if the given table has any of the asked privileges 05691 05692 SYNOPSIS 05693 check_some_access() 05694 thd Thread handler 05695 want_access Bitmap of possible privileges to check for 05696 05697 RETURN 05698 0 ok 05699 1 error 05700 */ 05701 05702 05703 bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table) 05704 { 05705 ulong access; 05706 DBUG_ENTER("check_some_access"); 05707 05708 /* This loop will work as long as we have less than 32 privileges */ 05709 for (access= 1; access < want_access ; access<<= 1) 05710 { 05711 if (access & want_access) 05712 { 05713 if (!check_access(thd, access, table->db, 05714 &table->grant.privilege, 0, 1, 05715 test(table->schema_table)) && 05716 !grant_option || !check_grant(thd, access, table, 0, 1, 1)) 05717 DBUG_RETURN(0); 05718 } 05719 } 05720 DBUG_PRINT("exit",("no matching access rights")); 05721 DBUG_RETURN(1); 05722 } 05723 05724 05725 bool check_merge_table_access(THD *thd, char *db, 05726 TABLE_LIST *table_list) 05727 { 05728 int error=0; 05729 if (table_list) 05730 { 05731 /* Check that all tables use the current database */ 05732 TABLE_LIST *tmp; 05733 for (tmp= table_list; tmp; tmp= tmp->next_local) 05734 { 05735 if (!tmp->db || !tmp->db[0]) 05736 tmp->db=db; 05737 } 05738 error=check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL, 05739 table_list,0); 05740 } 05741 return error; 05742 } 05743 05744 05745 /**************************************************************************** 05746 Check stack size; Send error if there isn't enough stack to continue 05747 ****************************************************************************/ 05748 05749 #if STACK_DIRECTION < 0 05750 #define used_stack(A,B) (long) (A - B) 05751 #else 05752 #define used_stack(A,B) (long) (B - A) 05753 #endif 05754 05755 #ifndef DBUG_OFF 05756 long max_stack_used; 05757 #endif 05758 05759 #ifndef EMBEDDED_LIBRARY 05760 /* 05761 Note: The 'buf' parameter is necessary, even if it is unused here. 05762 - fix_fields functions has a "dummy" buffer large enough for the 05763 corresponding exec. (Thus we only have to check in fix_fields.) 05764 - Passing to check_stack_overrun() prevents the compiler from removing it. 05765 */ 05766 bool check_stack_overrun(THD *thd, long margin, 05767 char *buf __attribute__((unused))) 05768 { 05769 long stack_used; 05770 DBUG_ASSERT(thd == current_thd); 05771 if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >= 05772 (long) (thread_stack - margin)) 05773 { 05774 sprintf(errbuff[0],ER(ER_STACK_OVERRUN_NEED_MORE), 05775 stack_used,thread_stack,margin); 05776 my_message(ER_STACK_OVERRUN_NEED_MORE,errbuff[0],MYF(0)); 05777 thd->fatal_error(); 05778 return 1; 05779 } 05780 #ifndef DBUG_OFF 05781 max_stack_used= max(max_stack_used, stack_used); 05782 #endif 05783 return 0; 05784 } 05785 #endif /* EMBEDDED_LIBRARY */ 05786 05787 #define MY_YACC_INIT 1000 // Start with big alloc 05788 #define MY_YACC_MAX 32000 // Because of 'short' 05789 05790 bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) 05791 { 05792 LEX *lex= current_thd->lex; 05793 ulong old_info=0; 05794 if ((uint) *yystacksize >= MY_YACC_MAX) 05795 return 1; 05796 if (!lex->yacc_yyvs) 05797 old_info= *yystacksize; 05798 *yystacksize= set_zone((*yystacksize)*2,MY_YACC_INIT,MY_YACC_MAX); 05799 if (!(lex->yacc_yyvs= (char*) 05800 my_realloc((gptr) lex->yacc_yyvs, 05801 *yystacksize*sizeof(**yyvs), 05802 MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) || 05803 !(lex->yacc_yyss= (char*) 05804 my_realloc((gptr) lex->yacc_yyss, 05805 *yystacksize*sizeof(**yyss), 05806 MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR)))) 05807 return 1; 05808 if (old_info) 05809 { // Copy old info from stack 05810 memcpy(lex->yacc_yyss, (gptr) *yyss, old_info*sizeof(**yyss)); 05811 memcpy(lex->yacc_yyvs, (gptr) *yyvs, old_info*sizeof(**yyvs)); 05812 } 05813 *yyss=(short*) lex->yacc_yyss; 05814 *yyvs=(YYSTYPE*) lex->yacc_yyvs; 05815 return 0; 05816 } 05817 05818 05819 /**************************************************************************** 05820 Initialize global thd variables needed for query 05821 ****************************************************************************/ 05822 05823 void 05824 mysql_init_query(THD *thd, uchar *buf, uint length) 05825 { 05826 DBUG_ENTER("mysql_init_query"); 05827 lex_start(thd, buf, length); 05828 mysql_reset_thd_for_next_command(thd); 05829 DBUG_VOID_RETURN; 05830 } 05831 05832 05833 /* 05834 Reset THD part responsible for command processing state. 05835 05836 DESCRIPTION 05837 This needs to be called before execution of every statement 05838 (prepared or conventional). 05839 It is not called by substatements of routines. 05840 05841 TODO 05842 Make it a method of THD and align its name with the rest of 05843 reset/end/start/init methods. 05844 Call it after we use THD for queries, not before. 05845 */ 05846 05847 void mysql_reset_thd_for_next_command(THD *thd) 05848 { 05849 DBUG_ENTER("mysql_reset_thd_for_next_command"); 05850 DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */ 05851 thd->free_list= 0; 05852 thd->select_number= 1; 05853 thd->auto_inc_intervals_in_cur_stmt_for_binlog.empty(); 05854 thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 05855 thd->query_start_used= 0; 05856 thd->is_fatal_error= thd->time_zone_used= 0; 05857 thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS | 05858 SERVER_QUERY_NO_INDEX_USED | 05859 SERVER_QUERY_NO_GOOD_INDEX_USED); 05860 /* 05861 If in autocommit mode and not in a transaction, reset 05862 OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings 05863 in ha_rollback_trans() about some tables couldn't be rolled back. 05864 */ 05865 if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) 05866 thd->options&= ~(OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG); 05867 05868 DBUG_ASSERT(thd->security_ctx== &thd->main_security_ctx); 05869 thd->tmp_table_used= 0; 05870 if (!thd->in_sub_stmt) 05871 { 05872 if (opt_bin_log) 05873 { 05874 reset_dynamic(&thd->user_var_events); 05875 thd->user_var_events_alloc= thd->mem_root; 05876 } 05877 thd->clear_error(); 05878 thd->total_warn_count=0; // Warnings for this query 05879 thd->rand_used= 0; 05880 thd->sent_row_count= thd->examined_row_count= 0; 05881 } 05882 /* 05883 Because we come here only for start of top-statements, binlog format is 05884 constant inside a complex statement (using stored functions) etc. 05885 */ 05886 thd->reset_current_stmt_binlog_row_based(); 05887 05888 DBUG_VOID_RETURN; 05889 } 05890 05891 05892 void 05893 mysql_init_select(LEX *lex) 05894 { 05895 SELECT_LEX *select_lex= lex->current_select; 05896 select_lex->init_select(); 05897 lex->wild= 0; 05898 if (select_lex == &lex->select_lex) 05899 { 05900 DBUG_ASSERT(lex->result == 0); 05901 lex->exchange= 0; 05902 } 05903 } 05904 05905 05906 bool 05907 mysql_new_select(LEX *lex, bool move_down) 05908 { 05909 SELECT_LEX *select_lex; 05910 THD *thd= lex->thd; 05911 DBUG_ENTER("mysql_new_select"); 05912 05913 if (!(select_lex= new (thd->mem_root) SELECT_LEX())) 05914 DBUG_RETURN(1); 05915 select_lex->select_number= ++thd->select_number; 05916 select_lex->parent_lex= lex; /* Used in init_query. */ 05917 select_lex->init_query(); 05918 select_lex->init_select(); 05919 lex->nest_level++; 05920 select_lex->nest_level= lex->nest_level; 05921 /* 05922 Don't evaluate this subquery during statement prepare even if 05923 it's a constant one. The flag is switched off in the end of 05924 mysql_stmt_prepare. 05925 */ 05926 if (thd->stmt_arena->is_stmt_prepare()) 05927 select_lex->uncacheable|= UNCACHEABLE_PREPARE; 05928 if (move_down) 05929 { 05930 SELECT_LEX_UNIT *unit; 05931 lex->subqueries= TRUE; 05932 /* first select_lex of subselect or derived table */ 05933 if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT())) 05934 DBUG_RETURN(1); 05935 05936 unit->init_query(); 05937 unit->init_select(); 05938 unit->thd= thd; 05939 unit->include_down(lex->current_select); 05940 unit->link_next= 0; 05941 unit->link_prev= 0; 05942 unit->return_to= lex->current_select; 05943 select_lex->include_down(unit); 05944 /* 05945 By default we assume that it is usual subselect and we have outer name 05946 resolution context, if no we will assign it to 0 later 05947 */ 05948 select_lex->context.outer_context= &select_lex->outer_select()->context; 05949 } 05950 else 05951 { 05952 if (lex->current_select->order_list.first && !lex->current_select->braces) 05953 { 05954 my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY"); 05955 DBUG_RETURN(1); 05956 } 05957 select_lex->include_neighbour(lex->current_select); 05958 SELECT_LEX_UNIT *unit= select_lex->master_unit(); 05959 if (!unit->fake_select_lex && unit->add_fake_select_lex(lex->thd)) 05960 DBUG_RETURN(1); 05961 select_lex->context.outer_context= 05962 unit->first_select()->context.outer_context; 05963 } 05964 05965 select_lex->master_unit()->global_parameters= select_lex; 05966 select_lex->include_global((st_select_lex_node**)&lex->all_selects_list); 05967 lex->current_select= select_lex; 05968 /* 05969 in subquery is SELECT query and we allow resolution of names in SELECT 05970 list 05971 */ 05972 select_lex->context.resolve_in_select_list= TRUE; 05973 DBUG_RETURN(0); 05974 } 05975 05976 /* 05977 Create a select to return the same output as 'SELECT @@var_name'. 05978 05979 SYNOPSIS 05980 create_select_for_variable() 05981 var_name Variable name 05982 05983 DESCRIPTION 05984 Used for SHOW COUNT(*) [ WARNINGS | ERROR] 05985 05986 This will crash with a core dump if the variable doesn't exists 05987 */ 05988 05989 void create_select_for_variable(const char *var_name) 05990 { 05991 THD *thd; 05992 LEX *lex; 05993 LEX_STRING tmp, null_lex_string; 05994 Item *var; 05995 char buff[MAX_SYS_VAR_LENGTH*2+4+8], *end; 05996 DBUG_ENTER("create_select_for_variable"); 05997 05998 thd= current_thd; 05999 lex= thd->lex; 06000 mysql_init_select(lex); 06001 lex->sql_command= SQLCOM_SELECT; 06002 tmp.str= (char*) var_name; 06003 tmp.length=strlen(var_name); 06004 bzero((char*) &null_lex_string.str, sizeof(null_lex_string)); 06005 /* 06006 We set the name of Item to @@session.var_name because that then is used 06007 as the column name in the output. 06008 */ 06009 if ((var= get_system_var(thd, OPT_SESSION, tmp, null_lex_string))) 06010 { 06011 end= strxmov(buff, "@@session.", var_name, NullS); 06012 var->set_name(buff, end-buff, system_charset_info); 06013 add_item_to_list(thd, var); 06014 } 06015 DBUG_VOID_RETURN; 06016 } 06017 06018 06019 void mysql_init_multi_delete(LEX *lex) 06020 { 06021 lex->sql_command= SQLCOM_DELETE_MULTI; 06022 mysql_init_select(lex); 06023 lex->select_lex.select_limit= 0; 06024 lex->unit.select_limit_cnt= HA_POS_ERROR; 06025 lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list); 06026 lex->lock_option= using_update_log ? TL_READ_NO_INSERT : TL_READ; 06027 lex->query_tables= 0; 06028 lex->query_tables_last= &lex->query_tables; 06029 } 06030 06031 /* 06032 When you modify mysql_parse(), you may need to mofify 06033 mysql_test_parse_for_slave() in this same file. 06034 */ 06035 06036 void mysql_parse(THD *thd, char *inBuf, uint length) 06037 { 06038 DBUG_ENTER("mysql_parse"); 06039 mysql_init_query(thd, (uchar*) inBuf, length); 06040 if (query_cache_send_result_to_client(thd, inBuf, length) <= 0) 06041 { 06042 LEX *lex= thd->lex; 06043 06044 sp_cache_flush_obsolete(&thd->sp_proc_cache); 06045 sp_cache_flush_obsolete(&thd->sp_func_cache); 06046 06047 if (!MYSQLparse((void *)thd) && ! thd->is_fatal_error) 06048 { 06049 #ifndef NO_EMBEDDED_ACCESS_CHECKS 06050 if (mqh_used && thd->user_connect && 06051 check_mqh(thd, lex->sql_command)) 06052 { 06053 thd->net.error = 0; 06054 } 06055 else 06056 #endif 06057 { 06058 if (thd->net.report_error) 06059 { 06060 delete lex->sphead; 06061 lex->sphead= NULL; 06062 if (lex->et) 06063 { 06064 lex->et->free_sphead_on_delete= true; 06065 /* alloced on thd->mem_root so no real memory free but dtor call */ 06066 lex->et->free_sp(); 06067 lex->et->deinit_mutexes(); 06068 lex->et= NULL; 06069 } 06070 } 06071 else 06072 { 06073 /* 06074 Binlog logs a string starting from thd->query and having length 06075 thd->query_length; so we set thd->query_length correctly (to not 06076 log several statements in one event, when we executed only first). 06077 We set it to not see the ';' (otherwise it would get into binlog 06078 and Query_log_event::print() would give ';;' output). 06079 This also helps display only the current query in SHOW 06080 PROCESSLIST. 06081 Note that we don't need LOCK_thread_count to modify query_length. 06082 */ 06083 if (lex->found_semicolon && 06084 (thd->query_length= (ulong)(lex->found_semicolon - thd->query))) 06085 thd->query_length--; 06086 /* Actually execute the query */ 06087 mysql_execute_command(thd); 06088 query_cache_end_of_result(thd); 06089 } 06090 } 06091 lex->unit.cleanup(); 06092 } 06093 else 06094 { 06095 DBUG_ASSERT(thd->net.report_error); 06096 DBUG_PRINT("info",("Command aborted. Fatal_error: %d", 06097 thd->is_fatal_error)); 06098 query_cache_abort(&thd->net); 06099 lex->unit.cleanup(); 06100 if (lex->sphead) 06101 { 06102 /* Clean up after failed stored procedure/function */ 06103 delete lex->sphead; 06104 lex->sphead= NULL; 06105 } 06106 if (lex->et) 06107 { 06108 lex->et->free_sphead_on_delete= true; 06109 lex->et->free_sp(); 06110 lex->et->deinit_mutexes(); 06111 lex->et= NULL; 06112 } 06113 } 06114 thd->proc_info="freeing items"; 06115 thd->end_statement(); 06116 thd->cleanup_after_query(); 06117 DBUG_ASSERT(thd->change_list.is_empty()); 06118 } 06119 DBUG_VOID_RETURN; 06120 } 06121 06122 06123 #ifdef HAVE_REPLICATION 06124 /* 06125 Usable by the replication SQL thread only: just parse a query to know if it 06126 can be ignored because of replicate-*-table rules. 06127 06128 RETURN VALUES 06129 0 cannot be ignored 06130 1 can be ignored 06131 */ 06132 06133 bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) 06134 { 06135 LEX *lex= thd->lex; 06136 bool error= 0; 06137 DBUG_ENTER("mysql_test_parse_for_slave"); 06138 06139 mysql_init_query(thd, (uchar*) inBuf, length); 06140 if (!MYSQLparse((void*) thd) && ! thd->is_fatal_error && 06141 all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first)) 06142 error= 1; /* Ignore question */ 06143 thd->end_statement(); 06144 thd->cleanup_after_query(); 06145 DBUG_RETURN(error); 06146 } 06147 #endif 06148 06149 06150 06151 /***************************************************************************** 06152 ** Store field definition for create 06153 ** Return 0 if ok 06154 ******************************************************************************/ 06155 06156 bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, 06157 char *length, char *decimals, 06158 uint type_modifier, 06159 Item *default_value, Item *on_update_value, 06160 LEX_STRING *comment, 06161 char *change, 06162 List<String> *interval_list, CHARSET_INFO *cs, 06163 uint uint_geom_type) 06164 { 06165 register create_field *new_field; 06166 LEX *lex= thd->lex; 06167 DBUG_ENTER("add_field_to_list"); 06168 06169 if (strlen(field_name) > NAME_LEN) 06170 { 06171 my_error(ER_TOO_LONG_IDENT, MYF(0), field_name); /* purecov: inspected */ 06172 DBUG_RETURN(1); /* purecov: inspected */ 06173 } 06174 if (type_modifier & PRI_KEY_FLAG) 06175 { 06176 lex->col_list.push_back(new key_part_spec(field_name,0)); 06177 lex->key_list.push_back(new Key(Key::PRIMARY, NullS, 06178 &default_key_create_info, 06179 0, lex->col_list)); 06180 lex->col_list.empty(); 06181 } 06182 if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG)) 06183 { 06184 lex->col_list.push_back(new key_part_spec(field_name,0)); 06185 lex->key_list.push_back(new Key(Key::UNIQUE, NullS, 06186 &default_key_create_info, 0, 06187 lex->col_list)); 06188 lex->col_list.empty(); 06189 } 06190 06191 if (default_value) 06192 { 06193 /* 06194 Default value should be literal => basic constants => 06195 no need fix_fields() 06196 06197 We allow only one function as part of default value - 06198 NOW() as default for TIMESTAMP type. 06199 */ 06200 if (default_value->type() == Item::FUNC_ITEM && 06201 !(((Item_func*)default_value)->functype() == Item_func::NOW_FUNC && 06202 type == FIELD_TYPE_TIMESTAMP)) 06203 { 06204 my_error(ER_INVALID_DEFAULT, MYF(0), field_name); 06205 DBUG_RETURN(1); 06206 } 06207 else if (default_value->type() == Item::NULL_ITEM) 06208 { 06209 default_value= 0; 06210 if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == 06211 NOT_NULL_FLAG) 06212 { 06213 my_error(ER_INVALID_DEFAULT, MYF(0), field_name); 06214 DBUG_RETURN(1); 06215 } 06216 } 06217 else if (type_modifier & AUTO_INCREMENT_FLAG) 06218 { 06219 my_error(ER_INVALID_DEFAULT, MYF(0), field_name); 06220 DBUG_RETURN(1); 06221 } 06222 } 06223 06224 if (on_update_value && type != FIELD_TYPE_TIMESTAMP) 06225 { 06226 my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name); 06227 DBUG_RETURN(1); 06228 } 06229 06230 if (type == FIELD_TYPE_TIMESTAMP && length) 06231 { 06232 /* Display widths are no longer supported for TIMSTAMP as of MySQL 4.1. 06233 In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4), 06234 and so on, the display width is ignored. 06235 */ 06236 char buf[32]; 06237 my_snprintf(buf, sizeof(buf), "TIMESTAMP(%s)", length); 06238 WARN_DEPRECATED(thd, "5.2", buf, "'TIMESTAMP'"); 06239 } 06240 06241 if (!(new_field= new create_field()) || 06242 new_field->init(thd, field_name, type, length, decimals, type_modifier, 06243 default_value, on_update_value, comment, change, 06244 interval_list, cs, uint_geom_type)) 06245 DBUG_RETURN(1); 06246 06247 lex->create_list.push_back(new_field); 06248 lex->last_field=new_field; 06249 DBUG_RETURN(0); 06250 } 06251 06252 06253 /* Store position for column in ALTER TABLE .. ADD column */ 06254 06255 void store_position_for_column(const char *name) 06256 { 06257 current_thd->lex->last_field->after=my_const_cast(char*) (name); 06258 } 06259 06260 bool 06261 add_proc_to_list(THD* thd, Item *item) 06262 { 06263 ORDER *order; 06264 Item **item_ptr; 06265 06266 if (!(order = (ORDER *) thd->alloc(sizeof(ORDER)+sizeof(Item*)))) 06267 return 1; 06268 item_ptr = (Item**) (order+1); 06269 *item_ptr= item; 06270 order->item=item_ptr; 06271 order->free_me=0; 06272 thd->lex->proc_list.link_in_list((byte*) order,(byte**) &order->next); 06273 return 0; 06274 } 06275 06276 06277 /* Fix escaping of _, % and \ in database and table names (for ODBC) */ 06278 06279 static void remove_escape(char *name) 06280 { 06281 if (!*name) // For empty DB names 06282 return; 06283 char *to; 06284 #ifdef USE_MB 06285 char *strend=name+(uint) strlen(name); 06286 #endif 06287 for (to=name; *name ; name++) 06288 { 06289 #ifdef USE_MB 06290 int l; 06291 if (use_mb(system_charset_info) && 06292 (l = my_ismbchar(system_charset_info, name, strend))) 06293 { 06294 while (l--) 06295 *to++ = *name++; 06296 name--; 06297 continue; 06298 } 06299 #endif 06300 if (*name == '\\' && name[1]) 06301 name++; // Skip '\\' 06302 *to++= *name; 06303 } 06304 *to=0; 06305 } 06306 06307 /**************************************************************************** 06308 ** save order by and tables in own lists 06309 ****************************************************************************/ 06310 06311 06312 bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc) 06313 { 06314 ORDER *order; 06315 DBUG_ENTER("add_to_list"); 06316 if (!(order = (ORDER *) thd->alloc(sizeof(ORDER)))) 06317 DBUG_RETURN(1); 06318 order->item_ptr= item; 06319 order->item= &order->item_ptr; 06320 order->asc = asc; 06321 order->free_me=0; 06322 order->used=0; 06323 order->counter_used= 0; 06324 list.link_in_list((byte*) order,(byte**) &order->next); 06325 DBUG_RETURN(0); 06326 } 06327 06328 06329 /* 06330 Add a table to list of used tables 06331 06332 SYNOPSIS 06333 add_table_to_list() 06334 table Table to add 06335 alias alias for table (or null if no alias) 06336 table_options A set of the following bits: 06337 TL_OPTION_UPDATING Table will be updated 06338 TL_OPTION_FORCE_INDEX Force usage of index 06339 lock_type How table should be locked 06340 use_index List of indexed used in USE INDEX 06341 ignore_index List of indexed used in IGNORE INDEX 06342 06343 RETURN 06344 0 Error 06345 # Pointer to TABLE_LIST element added to the total table list 06346 */ 06347 06348 TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, 06349 Table_ident *table, 06350 LEX_STRING *alias, 06351 ulong table_options, 06352 thr_lock_type lock_type, 06353 List<String> *use_index_arg, 06354 List<String> *ignore_index_arg, 06355 LEX_STRING *option) 06356 { 06357 register TABLE_LIST *ptr; 06358 TABLE_LIST *previous_table_ref; /* The table preceding the current one. */ 06359 char *alias_str; 06360 LEX *lex= thd->lex; 06361 DBUG_ENTER("add_table_to_list"); 06362 LINT_INIT(previous_table_ref); 06363 06364 if (!table) 06365 DBUG_RETURN(0); // End of memory 06366 alias_str= alias ? alias->str : table->table.str; 06367 if (check_table_name(table->table.str, table->table.length)) 06368 { 06369 my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str); 06370 DBUG_RETURN(0); 06371 } 06372 06373 if (table->is_derived_table() == FALSE && table->db.str && 06374 check_db_name(table->db.str)) 06375 { 06376 my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str); 06377 DBUG_RETURN(0); 06378 } 06379 06380 if (!alias) /* Alias is case sensitive */ 06381 { 06382 if (table->sel) 06383 { 06384 my_message(ER_DERIVED_MUST_HAVE_ALIAS, 06385 ER(ER_DERIVED_MUST_HAVE_ALIAS), MYF(0)); 06386 DBUG_RETURN(0); 06387 } 06388 if (!(alias_str=thd->memdup(alias_str,table->table.length+1))) 06389 DBUG_RETURN(0); 06390 } 06391 if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))) 06392 DBUG_RETURN(0); /* purecov: inspected */ 06393 if (table->db.str) 06394 { 06395 ptr->db= table->db.str; 06396 ptr->db_length= table->db.length; 06397 } 06398 else if (thd->copy_db_to(&ptr->db, &ptr->db_length)) 06399 DBUG_RETURN(0); 06400 06401 ptr->alias= alias_str; 06402 if (lower_case_table_names && table->table.length) 06403 my_casedn_str(files_charset_info, table->table.str); 06404 ptr->table_name=table->table.str; 06405 ptr->table_name_length=table->table.length; 06406 ptr->lock_type= lock_type; 06407 ptr->updating= test(table_options & TL_OPTION_UPDATING); 06408 ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX); 06409 ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES); 06410 ptr->derived= table->sel; 06411 if (!ptr->derived && !my_strcasecmp(system_charset_info, ptr->db, 06412 information_schema_name.str)) 06413 { 06414 ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, ptr->table_name); 06415 if (!schema_table || 06416 (schema_table->hidden && 06417 (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0)) 06418 { 06419 my_error(ER_UNKNOWN_TABLE, MYF(0), 06420 ptr->table_name, information_schema_name.str); 06421 DBUG_RETURN(0); 06422 } 06423 ptr->schema_table_name= ptr->table_name; 06424 ptr->schema_table= schema_table; 06425 } 06426 ptr->select_lex= lex->current_select; 06427 ptr->cacheable_table= 1; 06428 if (use_index_arg) 06429 ptr->use_index=(List<String> *) thd->memdup((gptr) use_index_arg, 06430 sizeof(*use_index_arg)); 06431 if (ignore_index_arg) 06432 ptr->ignore_index=(List<String> *) thd->memdup((gptr) ignore_index_arg, 06433 sizeof(*ignore_index_arg)); 06434 ptr->option= option ? option->str : 0; 06435 /* check that used name is unique */ 06436 if (lock_type != TL_IGNORE) 06437 { 06438 TABLE_LIST *first_table= (TABLE_LIST*) table_list.first; 06439 if (lex->sql_command == SQLCOM_CREATE_VIEW) 06440 first_table= first_table ? first_table->next_local : NULL; 06441 for (TABLE_LIST *tables= first_table ; 06442 tables ; 06443 tables=tables->next_local) 06444 { 06445 if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) && 06446 !strcmp(ptr->db, tables->db)) 06447 { 06448 my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str); /* purecov: tested */ 06449 DBUG_RETURN(0); /* purecov: tested */ 06450 } 06451 } 06452 } 06453 /* Store the table reference preceding the current one. */ 06454 if (table_list.elements > 0) 06455 { 06456 /* 06457 table_list.next points to the last inserted TABLE_LIST->next_local' 06458 element 06459 We don't use the offsetof() macro here to avoid warnings from gcc 06460 */ 06461 previous_table_ref= (TABLE_LIST*) ((char*) table_list.next - 06462 ((char*) &(ptr->next_local) - 06463 (char*) ptr)); 06464 /* 06465 Set next_name_resolution_table of the previous table reference to point 06466 to the current table reference. In effect the list 06467 TABLE_LIST::next_name_resolution_table coincides with 06468 TABLE_LIST::next_local. Later this may be changed in 06469 store_top_level_join_columns() for NATURAL/USING joins. 06470 */ 06471 previous_table_ref->next_name_resolution_table= ptr; 06472 } 06473 06474 /* 06475 Link the current table reference in a local list (list for current select). 06476 Notice that as a side effect here we set the next_local field of the 06477 previous table reference to 'ptr'. Here we also add one element to the 06478 list 'table_list'. 06479 */ 06480 table_list.link_in_list((byte*) ptr, (byte**) &ptr->next_local); 06481 ptr->next_name_resolution_table= NULL; 06482 /* Link table in global list (all used tables) */ 06483 lex->add_to_query_tables(ptr); 06484 DBUG_RETURN(ptr); 06485 } 06486 06487 06488 /* 06489 Initialize a new table list for a nested join 06490 06491 SYNOPSIS 06492 init_nested_join() 06493 thd current thread 06494 06495 DESCRIPTION 06496 The function initializes a structure of the TABLE_LIST type 06497 for a nested join. It sets up its nested join list as empty. 06498 The created structure is added to the front of the current 06499 join list in the st_select_lex object. Then the function 06500 changes the current nest level for joins to refer to the newly 06501 created empty list after having saved the info on the old level 06502 in the initialized structure. 06503 06504 RETURN VALUE 06505 0, if success 06506 1, otherwise 06507 */ 06508 06509 bool st_select_lex::init_nested_join(THD *thd) 06510 { 06511 TABLE_LIST *ptr; 06512 NESTED_JOIN *nested_join; 06513 DBUG_ENTER("init_nested_join"); 06514 06515 if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+ 06516 sizeof(NESTED_JOIN)))) 06517 DBUG_RETURN(1); 06518 nested_join= ptr->nested_join= 06519 ((NESTED_JOIN*) ((byte*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST)))); 06520 06521 join_list->push_front(ptr); 06522 ptr->embedding= embedding; 06523 ptr->join_list= join_list; 06524 embedding= ptr; 06525 join_list= &nested_join->join_list; 06526 join_list->empty(); 06527 DBUG_RETURN(0); 06528 } 06529 06530 06531 /* 06532 End a nested join table list 06533 06534 SYNOPSIS 06535 end_nested_join() 06536 thd current thread 06537 06538 DESCRIPTION 06539 The function returns to the previous join nest level. 06540 If the current level contains only one member, the function 06541 moves it one level up, eliminating the nest. 06542 06543 RETURN VALUE 06544 Pointer to TABLE_LIST element added to the total table list, if success 06545 0, otherwise 06546 */ 06547 06548 TABLE_LIST *st_select_lex::end_nested_join(THD *thd) 06549 { 06550 TABLE_LIST *ptr; 06551 NESTED_JOIN *nested_join; 06552 DBUG_ENTER("end_nested_join"); 06553 06554 DBUG_ASSERT(embedding); 06555 ptr= embedding; 06556 join_list= ptr->join_list; 06557 embedding= ptr->embedding; 06558 nested_join= ptr->nested_join; 06559 if (nested_join->join_list.elements == 1) 06560 { 06561 TABLE_LIST *embedded= nested_join->join_list.head(); 06562 join_list->pop(); 06563 embedded->join_list= join_list; 06564 embedded->embedding= embedding; 06565 join_list->push_front(embedded); 06566 ptr= embedded; 06567 } 06568 else if (nested_join->join_list.elements == 0) 06569 { 06570 join_list->pop(); 06571 ptr= 0; // return value 06572 } 06573 DBUG_RETURN(ptr); 06574 } 06575 06576 06577 /* 06578 Nest last join operation 06579 06580 SYNOPSIS 06581 nest_last_join() 06582 thd current thread 06583 06584 DESCRIPTION 06585 The function nest last join operation as if it was enclosed in braces. 06586 06587 RETURN VALUE 06588 0 Error 06589 # Pointer to TABLE_LIST element created for the new nested join 06590 06591 */ 06592 06593 TABLE_LIST *st_select_lex::nest_last_join(THD *thd) 06594 { 06595 TABLE_LIST *ptr; 06596 NESTED_JOIN *nested_join; 06597 List<TABLE_LIST> *embedded_list; 06598 DBUG_ENTER("nest_last_join"); 06599 06600 if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+ 06601 sizeof(NESTED_JOIN)))) 06602 DBUG_RETURN(0); 06603 nested_join= ptr->nested_join= 06604 ((NESTED_JOIN*) ((byte*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST)))); 06605 06606 ptr->embedding= embedding; 06607 ptr->join_list= join_list; 06608 embedded_list= &nested_join->join_list; 06609 embedded_list->empty(); 06610 06611 for (uint i=0; i < 2; i++) 06612 { 06613 TABLE_LIST *table= join_list->pop(); 06614 table->join_list= embedded_list; 06615 table->embedding= ptr; 06616 embedded_list->push_back(table); 06617 if (table->natural_join) 06618 { 06619 ptr->is_natural_join= TRUE; 06620 /* 06621 If this is a JOIN ... USING, move the list of joined fields to the 06622 table reference that describes the join. 06623 */ 06624 if (table->join_using_fields) 06625 { 06626 ptr->join_using_fields= table->join_using_fields; 06627 table->join_using_fields= NULL; 06628 } 06629 } 06630 } 06631 join_list->push_front(ptr); 06632 nested_join->used_tables= nested_join->not_null_tables= (table_map) 0; 06633 DBUG_RETURN(ptr); 06634 } 06635 06636 06637 /* 06638 Add a table to the current join list 06639 06640 SYNOPSIS 06641 add_joined_table() 06642 table the table to add 06643 06644 DESCRIPTION 06645 The function puts a table in front of the current join list 06646 of st_select_lex object. 06647 Thus, joined tables are put into this list in the reverse order 06648 (the most outer join operation follows first). 06649 06650 RETURN VALUE 06651 None 06652 */ 06653 06654 void st_select_lex::add_joined_table(TABLE_LIST *table) 06655 { 06656 DBUG_ENTER("add_joined_table"); 06657 join_list->push_front(table); 06658 table->join_list= join_list; 06659 table->embedding= embedding; 06660 DBUG_VOID_RETURN; 06661 } 06662 06663 06664 /* 06665 Convert a right join into equivalent left join 06666 06667 SYNOPSIS 06668 convert_right_join() 06669 thd current thread 06670 06671 DESCRIPTION 06672 The function takes the current join list t[0],t[1] ... and 06673 effectively converts it into the list t[1],t[0] ... 06674 Although the outer_join flag for the new nested table contains 06675 JOIN_TYPE_RIGHT, it will be handled as the inner table of a left join 06676 operation. 06677 06678 EXAMPLES 06679 SELECT * FROM t1 RIGHT JOIN t2 ON on_expr => 06680 SELECT * FROM t2 LEFT JOIN t1 ON on_expr 06681 06682 SELECT * FROM t1,t2 RIGHT JOIN t3 ON on_expr => 06683 SELECT * FROM t1,t3 LEFT JOIN t2 ON on_expr 06684 06685 SELECT * FROM t1,t2 RIGHT JOIN (t3,t4) ON on_expr => 06686 SELECT * FROM t1,(t3,t4) LEFT JOIN t2 ON on_expr 06687 06688 SELECT * FROM t1 LEFT JOIN t2 ON on_expr1 RIGHT JOIN t3 ON on_expr2 => 06689 SELECT * FROM t3 LEFT JOIN (t1 LEFT JOIN t2 ON on_expr2) ON on_expr1 06690 06691 RETURN 06692 Pointer to the table representing the inner table, if success 06693 0, otherwise 06694 */ 06695 06696 TABLE_LIST *st_select_lex::convert_right_join() 06697 { 06698 TABLE_LIST *tab2= join_list->pop(); 06699 TABLE_LIST *tab1= join_list->pop(); 06700 DBUG_ENTER("convert_right_join"); 06701 06702 join_list->push_front(tab2); 06703 join_list->push_front(tab1); 06704 tab1->outer_join|= JOIN_TYPE_RIGHT; 06705 06706 DBUG_RETURN(tab1); 06707 } 06708 06709 /* 06710 Set lock for all tables in current select level 06711 06712 SYNOPSIS: 06713 set_lock_for_tables() 06714 lock_type Lock to set for tables 06715 06716 NOTE: 06717 If lock is a write lock, then tables->updating is set 1 06718 This is to get tables_ok to know that the table is updated by the 06719 query 06720 */ 06721 06722 void st_select_lex::set_lock_for_tables(thr_lock_type lock_type) 06723 { 06724 bool for_update= lock_type >= TL_READ_NO_INSERT; 06725 DBUG_ENTER("set_lock_for_tables"); 06726 DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type, 06727 for_update)); 06728 06729 for (TABLE_LIST *tables= (TABLE_LIST*) table_list.first; 06730 tables; 06731 tables= tables->next_local) 06732 { 06733 tables->lock_type= lock_type; 06734 tables->updating= for_update; 06735 } 06736 DBUG_VOID_RETURN; 06737 } 06738 06739 06740 /* 06741 Create a fake SELECT_LEX for a unit 06742 06743 SYNOPSIS: 06744 add_fake_select_lex() 06745 thd thread handle 06746 06747 DESCRIPTION 06748 The method create a fake SELECT_LEX object for a unit. 06749 This object is created for any union construct containing a union 06750 operation and also for any single select union construct of the form 06751 (SELECT ... ORDER BY order_list [LIMIT n]) ORDER BY ... 06752 or of the form 06753 (SELECT ... ORDER BY LIMIT n) ORDER BY ... 06754 06755 NOTES 06756 The object is used to retrieve rows from the temporary table 06757 where the result on the union is obtained. 06758 06759 RETURN VALUES 06760 1 on failure to create the object 06761 0 on success 06762 */ 06763 06764 bool st_select_lex_unit::add_fake_select_lex(THD *thd) 06765 { 06766 SELECT_LEX *first_sl= first_select(); 06767 DBUG_ENTER("add_fake_select_lex"); 06768 DBUG_ASSERT(!fake_select_lex); 06769 06770 if (!(fake_select_lex= new (thd->mem_root) SELECT_LEX())) 06771 DBUG_RETURN(1); 06772 fake_select_lex->include_standalone(this, 06773 (SELECT_LEX_NODE**)&fake_select_lex); 06774 fake_select_lex->select_number= INT_MAX; 06775 fake_select_lex->parent_lex= thd->lex; /* Used in init_query. */ 06776 fake_select_lex->make_empty_select(); 06777 fake_select_lex->linkage= GLOBAL_OPTIONS_TYPE; 06778 fake_select_lex->select_limit= 0; 06779 06780 fake_select_lex->context.outer_context=first_sl->context.outer_context; 06781 /* allow item list resolving in fake select for ORDER BY */ 06782 fake_select_lex->context.resolve_in_select_list= TRUE; 06783 fake_select_lex->context.select_lex= fake_select_lex; 06784 06785 if (!first_sl->next_select()) 06786 { 06787 /* 06788 This works only for 06789 (SELECT ... ORDER BY list [LIMIT n]) ORDER BY order_list [LIMIT m], 06790 (SELECT ... LIMIT n) ORDER BY order_list [LIMIT m] 06791 just before the parser starts processing order_list 06792 */ 06793 global_parameters= fake_select_lex; 06794 fake_select_lex->no_table_names_allowed= 1; 06795 thd->lex->current_select= fake_select_lex; 06796 } 06797 thd->lex->pop_context(); 06798 DBUG_RETURN(0); 06799 } 06800 06801 06802 /* 06803 Push a new name resolution context for a JOIN ... ON clause to the 06804 context stack of a query block. 06805 06806 SYNOPSIS 06807 push_new_name_resolution_context() 06808 thd pointer to current thread 06809 left_op left operand of the JOIN 06810 right_op rigth operand of the JOIN 06811 06812 DESCRIPTION 06813 Create a new name resolution context for a JOIN ... ON clause, 06814 set the first and last leaves of the list of table references 06815 to be used for name resolution, and push the newly created 06816 context to the stack of contexts of the query. 06817 06818 RETURN 06819 FALSE if all is OK 06820 TRUE if a memory allocation error occured 06821 */ 06822 06823 bool 06824 push_new_name_resolution_context(THD *thd, 06825 TABLE_LIST *left_op, TABLE_LIST *right_op) 06826 { 06827 Name_resolution_context *on_context; 06828 if (!(on_context= new (thd->mem_root) Name_resolution_context)) 06829 return TRUE; 06830 on_context->init(); 06831 on_context->first_name_resolution_table= 06832 left_op->first_leaf_for_name_resolution(); 06833 on_context->last_name_resolution_table= 06834 right_op->last_leaf_for_name_resolution(); 06835 return thd->lex->push_context(on_context); 06836 } 06837 06838 06839 /* 06840 Add an ON condition to the second operand of a JOIN ... ON. 06841 06842 SYNOPSIS 06843 add_join_on 06844 b the second operand of a JOIN ... ON 06845 expr the condition to be added to the ON clause 06846 06847 DESCRIPTION 06848 Add an ON condition to the right operand of a JOIN ... ON clause. 06849 06850 RETURN 06851 FALSE if there was some error 06852 TRUE if all is OK 06853 */ 06854 06855 void add_join_on(TABLE_LIST *b, Item *expr) 06856 { 06857 if (expr) 06858 { 06859 if (!b->on_expr) 06860 b->on_expr= expr; 06861 else 06862 { 06863 /* 06864 If called from the parser, this happens if you have both a 06865 right and left join. If called later, it happens if we add more 06866 than one condition to the ON clause. 06867 */ 06868 b->on_expr= new Item_cond_and(b->on_expr,expr); 06869 } 06870 b->on_expr->top_level_item(); 06871 } 06872 } 06873 06874 06875 /* 06876 Mark that there is a NATURAL JOIN or JOIN ... USING between two 06877 tables. 06878 06879 SYNOPSIS 06880 add_join_natural() 06881 a Left join argument 06882 b Right join argument 06883 using_fields Field names from USING clause 06884 06885 IMPLEMENTATION 06886 This function marks that table b should be joined with a either via 06887 a NATURAL JOIN or via JOIN ... USING. Both join types are special 06888 cases of each other, so we treat them together. The function 06889 setup_conds() creates a list of equal condition between all fields 06890 of the same name for NATURAL JOIN or the fields in 'using_fields' 06891 for JOIN ... USING. The list of equality conditions is stored 06892 either in b->on_expr, or in JOIN::conds, depending on whether there 06893 was an outer join. 06894 06895 EXAMPLE 06896 SELECT * FROM t1 NATURAL LEFT JOIN t2 06897 <=> 06898 SELECT * FROM t1 LEFT JOIN t2 ON (t1.i=t2.i and t1.j=t2.j ... ) 06899 06900 SELECT * FROM t1 NATURAL JOIN t2 WHERE <some_cond> 06901 <=> 06902 SELECT * FROM t1, t2 WHERE (t1.i=t2.i and t1.j=t2.j and <some_cond>) 06903 06904 SELECT * FROM t1 JOIN t2 USING(j) WHERE <some_cond> 06905 <=> 06906 SELECT * FROM t1, t2 WHERE (t1.j=t2.j and <some_cond>) 06907 06908 RETURN 06909 None 06910 */ 06911 06912 void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields) 06913 { 06914 b->natural_join= a; 06915 b->join_using_fields= using_fields; 06916 } 06917 06918 06919 /* 06920 Reload/resets privileges and the different caches. 06921 06922 SYNOPSIS 06923 reload_acl_and_cache() 06924 thd Thread handler (can be NULL!) 06925 options What should be reset/reloaded (tables, privileges, 06926 slave...) 06927 tables Tables to flush (if any) 06928 write_to_binlog Depending on 'options', it may be very bad to write the 06929 query to the binlog (e.g. FLUSH SLAVE); this is a 06930 pointer where reload_acl_and_cache() will put 0 if 06931 it thinks we really should not write to the binlog. 06932 Otherwise it will put 1. 06933 06934 RETURN 06935 0 ok 06936 !=0 error. thd->killed or thd->net.report_error is set 06937 */ 06938 06939 bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, 06940 bool *write_to_binlog) 06941 { 06942 bool result=0; 06943 select_errors=0; /* Write if more errors */ 06944 bool tmp_write_to_binlog= 1; 06945 06946 if (thd && thd->in_sub_stmt) 06947 { 06948 my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "FLUSH"); 06949 return 1; 06950 } 06951 06952 #ifndef NO_EMBEDDED_ACCESS_CHECKS 06953 if (options & REFRESH_GRANT) 06954 { 06955 THD *tmp_thd= 0; 06956 /* 06957 If reload_acl_and_cache() is called from SIGHUP handler we have to 06958 allocate temporary THD for execution of acl_reload()/grant_reload(). 06959 */ 06960 if (!thd && (thd= (tmp_thd= new THD))) 06961 { 06962 thd->thread_stack= (char*) &tmp_thd; 06963 thd->store_globals(); 06964 } 06965 if (thd) 06966 { 06967 (void)acl_reload(thd); 06968 (void)grant_reload(thd); 06969 } 06970 if (tmp_thd) 06971 { 06972 delete tmp_thd; 06973 /* Remember that we don't have a THD */ 06974 my_pthread_setspecific_ptr(THR_THD, 0); 06975 thd= 0; 06976 } 06977 reset_mqh((LEX_USER *)NULL, TRUE); 06978 } 06979 #endif 06980 if (options & REFRESH_LOG) 06981 { 06982 /* 06983 Flush the normal query log, the update log, the binary log, 06984 the slow query log, the relay log (if it exists) and the log 06985 tables. 06986 */ 06987 06988 /* 06989 Writing this command to the binlog may result in infinite loops 06990 when doing mysqlbinlog|mysql, and anyway it does not really make 06991 sense to log it automatically (would cause more trouble to users 06992 than it would help them) 06993 */ 06994 tmp_write_to_binlog= 0; 06995 mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE); 06996 #ifdef HAVE_REPLICATION 06997 pthread_mutex_lock(&LOCK_active_mi); 06998 rotate_relay_log(active_mi); 06999 pthread_mutex_unlock(&LOCK_active_mi); 07000 #endif 07001 07002 /* flush slow and general logs */ 07003 logger.flush_logs(thd); 07004 07005 if (ha_flush_logs(NULL)) 07006 result=1; 07007 if (flush_error_log()) 07008 result=1; 07009 } 07010 #ifdef HAVE_QUERY_CACHE 07011 if (options & REFRESH_QUERY_CACHE_FREE) 07012 { 07013 query_cache.pack(); // FLUSH QUERY CACHE 07014 options &= ~REFRESH_QUERY_CACHE; // Don't flush cache, just free memory 07015 } 07016 if (options & (REFRESH_TABLES | REFRESH_QUERY_CACHE)) 07017 { 07018 query_cache.flush(); // RESET QUERY CACHE 07019 } 07020 #endif /*HAVE_QUERY_CACHE*/ 07021 /* 07022 Note that if REFRESH_READ_LOCK bit is set then REFRESH_TABLES is set too 07023 (see sql_yacc.yy) 07024 */ 07025 if (options & (REFRESH_TABLES | REFRESH_READ_LOCK)) 07026 { 07027 if ((options & REFRESH_READ_LOCK) && thd) 07028 { 07029 /* 07030 We must not try to aspire a global read lock if we have a write 07031 locked table. This would lead to a deadlock when trying to 07032 reopen (and re-lock) the table after the flush. 07033 */ 07034 if (thd->locked_tables) 07035 { 07036 THR_LOCK_DATA **lock_p= thd->locked_tables->locks; 07037 THR_LOCK_DATA **end_p= lock_p + thd->locked_tables->lock_count; 07038 07039 for (; lock_p < end_p; lock_p++) 07040 { 07041 if ((*lock_p)->type == TL_WRITE) 07042 { 07043 my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); 07044 return 1; 07045 } 07046 } 07047 } 07048 /* 07049 Writing to the binlog could cause deadlocks, as we don't log 07050 UNLOCK TABLES 07051 */ 07052 tmp_write_to_binlog= 0; 07053 if (lock_global_read_lock(thd)) 07054 return 1; // Killed 07055 result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, 07056 tables); 07057 if (make_global_read_lock_block_commit(thd)) // Killed 07058 { 07059 /* Don't leave things in a half-locked state */ 07060 unlock_global_read_lock(thd); 07061 return 1; 07062 } 07063 } 07064 else 07065 result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables); 07066 my_dbopt_cleanup(); 07067 } 07068 if (options & REFRESH_HOSTS) 07069 hostname_cache_refresh(); 07070 if (thd && (options & REFRESH_STATUS)) 07071 refresh_status(thd); 07072 if (options & REFRESH_THREADS) 07073 flush_thread_cache(); 07074 #ifdef HAVE_REPLICATION 07075 if (options & REFRESH_MASTER) 07076 { 07077 DBUG_ASSERT(thd); 07078 tmp_write_to_binlog= 0; 07079 if (reset_master(thd)) 07080 { 07081 result=1; 07082 thd->fatal_error(); // Ensure client get error 07083 } 07084 } 07085 #endif 07086 #ifdef OPENSSL 07087 if (options & REFRESH_DES_KEY_FILE) 07088 { 07089 if (des_key_file) 07090 result=load_des_key_file(des_key_file); 07091 } 07092 #endif 07093 #ifdef HAVE_REPLICATION 07094 if (options & REFRESH_SLAVE) 07095 { 07096 tmp_write_to_binlog= 0; 07097 pthread_mutex_lock(&LOCK_active_mi); 07098 if (reset_slave(thd, active_mi)) 07099 result=1; 07100 pthread_mutex_unlock(&LOCK_active_mi); 07101 } 07102 #endif 07103 if (options & REFRESH_USER_RESOURCES) 07104 reset_mqh((LEX_USER *) NULL); 07105 *write_to_binlog= tmp_write_to_binlog; 07106 return result; 07107 } 07108 07109 07110 /* 07111 kills a thread 07112 07113 SYNOPSIS 07114 kill_one_thread() 07115 thd Thread class 07116 id Thread id 07117 only_kill_query Should it kill the query or the connection 07118 07119 NOTES 07120 This is written such that we have a short lock on LOCK_thread_count 07121 */ 07122 07123 uint kill_one_thread(THD *thd, ulong id, bool only_kill_query) 07124 { 07125 THD *tmp; 07126 uint error=ER_NO_SUCH_THREAD; 07127 DBUG_ENTER("kill_one_thread"); 07128 DBUG_PRINT("enter", ("id=%lu only_kill=%d", id, only_kill_query)); 07129 VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list 07130 I_List_iterator<THD> it(threads); 07131 while ((tmp=it++)) 07132 { 07133 if (tmp->command == COM_DAEMON) 07134 continue; 07135 if (tmp->thread_id == id) 07136 { 07137 pthread_mutex_lock(&tmp->LOCK_delete); // Lock from delete 07138 break; 07139 } 07140 } 07141 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 07142 if (tmp) 07143 { 07144 if ((thd->security_ctx->master_access & SUPER_ACL) || 07145 !strcmp(thd->security_ctx->user, tmp->security_ctx->user)) 07146 { 07147 tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION); 07148 error=0; 07149 } 07150 else 07151 error=ER_KILL_DENIED_ERROR; 07152 pthread_mutex_unlock(&tmp->LOCK_delete); 07153 } 07154 DBUG_PRINT("exit", ("%d", error)); 07155 DBUG_RETURN(error); 07156 } 07157 07158 07159 /* 07160 kills a thread and sends response 07161 07162 SYNOPSIS 07163 sql_kill() 07164 thd Thread class 07165 id Thread id 07166 only_kill_query Should it kill the query or the connection 07167 */ 07168 07169 void sql_kill(THD *thd, ulong id, bool only_kill_query) 07170 { 07171 uint error; 07172 if (!(error= kill_one_thread(thd, id, only_kill_query))) 07173 send_ok(thd); 07174 else 07175 my_error(error, MYF(0), id); 07176 } 07177 07178 07179 /* If pointer is not a null pointer, append filename to it */ 07180 07181 bool append_file_to_dir(THD *thd, const char **filename_ptr, 07182 const char *table_name) 07183 { 07184 char buff[FN_REFLEN],*ptr, *end; 07185 if (!*filename_ptr) 07186 return 0; // nothing to do 07187 07188 /* Check that the filename is not too long and it's a hard path */ 07189 if (strlen(*filename_ptr)+strlen(table_name) >= FN_REFLEN-1 || 07190 !test_if_hard_path(*filename_ptr)) 07191 { 07192 my_error(ER_WRONG_TABLE_NAME, MYF(0), *filename_ptr); 07193 return 1; 07194 } 07195 /* Fix is using unix filename format on dos */ 07196 strmov(buff,*filename_ptr); 07197 end=convert_dirname(buff, *filename_ptr, NullS); 07198 if (!(ptr=thd->alloc((uint) (end-buff)+(uint) strlen(table_name)+1))) 07199 return 1; // End of memory 07200 *filename_ptr=ptr; 07201 strxmov(ptr,buff,table_name,NullS); 07202 return 0; 07203 } 07204 07205 07206 /* 07207 Check if the select is a simple select (not an union) 07208 07209 SYNOPSIS 07210 check_simple_select() 07211 07212 RETURN VALUES 07213 0 ok 07214 1 error ; In this case the error messege is sent to the client 07215 */ 07216 07217 bool check_simple_select() 07218 { 07219 THD *thd= current_thd; 07220 LEX *lex= thd->lex; 07221 if (lex->current_select != &lex->select_lex) 07222 { 07223 char command[80]; 07224 strmake(command, lex->yylval->symbol.str, 07225 min(lex->yylval->symbol.length, sizeof(command)-1)); 07226 my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command); 07227 return 1; 07228 } 07229 return 0; 07230 } 07231 07232 07233 Comp_creator *comp_eq_creator(bool invert) 07234 { 07235 return invert?(Comp_creator *)&ne_creator:(Comp_creator *)&eq_creator; 07236 } 07237 07238 07239 Comp_creator *comp_ge_creator(bool invert) 07240 { 07241 return invert?(Comp_creator *)<_creator:(Comp_creator *)&ge_creator; 07242 } 07243 07244 07245 Comp_creator *comp_gt_creator(bool invert) 07246 { 07247 return invert?(Comp_creator *)&le_creator:(Comp_creator *)>_creator; 07248 } 07249 07250 07251 Comp_creator *comp_le_creator(bool invert) 07252 { 07253 return invert?(Comp_creator *)>_creator:(Comp_creator *)&le_creator; 07254 } 07255 07256 07257 Comp_creator *comp_lt_creator(bool invert) 07258 { 07259 return invert?(Comp_creator *)&ge_creator:(Comp_creator *)<_creator; 07260 } 07261 07262 07263 Comp_creator *comp_ne_creator(bool invert) 07264 { 07265 return invert?(Comp_creator *)&eq_creator:(Comp_creator *)&ne_creator; 07266 } 07267 07268 07269 /* 07270 Construct ALL/ANY/SOME subquery Item 07271 07272 SYNOPSIS 07273 all_any_subquery_creator() 07274 left_expr - pointer to left expression 07275 cmp - compare function creator 07276 all - true if we create ALL subquery 07277 select_lex - pointer on parsed subquery structure 07278 07279 RETURN VALUE 07280 constructed Item (or 0 if out of memory) 07281 */ 07282 Item * all_any_subquery_creator(Item *left_expr, 07283 chooser_compare_func_creator cmp, 07284 bool all, 07285 SELECT_LEX *select_lex) 07286 { 07287 if ((cmp == &comp_eq_creator) && !all) // = ANY <=> IN 07288 return new Item_in_subselect(left_expr, select_lex); 07289 07290 if ((cmp == &comp_ne_creator) && all) // <> ALL <=> NOT IN 07291 return new Item_func_not(new Item_in_subselect(left_expr, select_lex)); 07292 07293 Item_allany_subselect *it= 07294 new Item_allany_subselect(left_expr, cmp, select_lex, all); 07295 if (all) 07296 return it->upper_item= new Item_func_not_all(it); /* ALL */ 07297 07298 return it->upper_item= new Item_func_nop_all(it); /* ANY/SOME */ 07299 } 07300 07301 07302 /* 07303 CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with 07304 the proper arguments. This isn't very fast but it should work for most 07305 cases. 07306 07307 In the future ALTER TABLE will notice that only added indexes 07308 and create these one by one for the existing table without having to do 07309 a full rebuild. 07310 07311 One should normally create all indexes with CREATE TABLE or ALTER TABLE. 07312 */ 07313 07314 bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) 07315 { 07316 List<create_field> fields; 07317 ALTER_INFO alter_info; 07318 alter_info.flags= ALTER_ADD_INDEX; 07319 HA_CREATE_INFO create_info; 07320 DBUG_ENTER("mysql_create_index"); 07321 bzero((char*) &create_info,sizeof(create_info)); 07322 create_info.db_type= 0; 07323 create_info.default_table_charset= thd->variables.collation_database; 07324 DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, 07325 &create_info, table_list, 07326 fields, keys, 0, (ORDER*)0, 07327 0, &alter_info, 1)); 07328 } 07329 07330 07331 bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) 07332 { 07333 List<create_field> fields; 07334 List<Key> keys; 07335 HA_CREATE_INFO create_info; 07336 DBUG_ENTER("mysql_drop_index"); 07337 bzero((char*) &create_info,sizeof(create_info)); 07338 create_info.db_type= 0; 07339 create_info.default_table_charset= thd->variables.collation_database; 07340 alter_info->clear(); 07341 alter_info->flags= ALTER_DROP_INDEX; 07342 DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, 07343 &create_info, table_list, 07344 fields, keys, 0, (ORDER*)0, 07345 0, alter_info, 1)); 07346 } 07347 07348 07349 /* 07350 Multi update query pre-check 07351 07352 SYNOPSIS 07353 multi_update_precheck() 07354 thd Thread handler 07355 tables Global/local table list (have to be the same) 07356 07357 RETURN VALUE 07358 FALSE OK 07359 TRUE Error 07360 */ 07361 07362 bool multi_update_precheck(THD *thd, TABLE_LIST *tables) 07363 { 07364 const char *msg= 0; 07365 TABLE_LIST *table; 07366 LEX *lex= thd->lex; 07367 SELECT_LEX *select_lex= &lex->select_lex; 07368 DBUG_ENTER("multi_update_precheck"); 07369 07370 if (select_lex->item_list.elements != lex->value_list.elements) 07371 { 07372 my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0)); 07373 DBUG_RETURN(TRUE); 07374 } 07375 /* 07376 Ensure that we have UPDATE or SELECT privilege for each table 07377 The exact privilege is checked in mysql_multi_update() 07378 */ 07379 for (table= tables; table; table= table->next_local) 07380 { 07381 if (table->derived) 07382 table->grant.privilege= SELECT_ACL; 07383 else if ((check_access(thd, UPDATE_ACL, table->db, 07384 &table->grant.privilege, 0, 1, 07385 test(table->schema_table)) || 07386 grant_option && 07387 check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) && 07388 (check_access(thd, SELECT_ACL, table->db, 07389 &table->grant.privilege, 0, 0, 07390 test(table->schema_table)) || 07391 grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0))) 07392 DBUG_RETURN(TRUE); 07393 07394 table->table_in_first_from_clause= 1; 07395 } 07396 /* 07397 Is there tables of subqueries? 07398 */ 07399 if (&lex->select_lex != lex->all_selects_list || lex->time_zone_tables_used) 07400 { 07401 DBUG_PRINT("info",("Checking sub query list")); 07402 for (table= tables; table; table= table->next_global) 07403 { 07404 if (!my_tz_check_n_skip_implicit_tables(&table, 07405 lex->time_zone_tables_used) && 07406 !table->table_in_first_from_clause) 07407 { 07408 if (check_access(thd, SELECT_ACL, table->db, 07409 &table->grant.privilege, 0, 0, 07410 test(table->schema_table)) || 07411 grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0)) 07412 DBUG_RETURN(TRUE); 07413 } 07414 } 07415 } 07416 07417 if (select_lex->order_list.elements) 07418 msg= "ORDER BY"; 07419 else if (select_lex->select_limit) 07420 msg= "LIMIT"; 07421 if (msg) 07422 { 07423 my_error(ER_WRONG_USAGE, MYF(0), "UPDATE", msg); 07424 DBUG_RETURN(TRUE); 07425 } 07426 DBUG_RETURN(FALSE); 07427 } 07428 07429 /* 07430 Multi delete query pre-check 07431 07432 SYNOPSIS 07433 multi_delete_precheck() 07434 thd Thread handler 07435 tables Global/local table list 07436 07437 RETURN VALUE 07438 FALSE OK 07439 TRUE error 07440 */ 07441 07442 bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) 07443 { 07444 SELECT_LEX *select_lex= &thd->lex->select_lex; 07445 TABLE_LIST *aux_tables= 07446 (TABLE_LIST *)thd->lex->auxiliary_table_list.first; 07447 TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; 07448 DBUG_ENTER("multi_delete_precheck"); 07449 07450 /* sql_yacc guarantees that tables and aux_tables are not zero */ 07451 DBUG_ASSERT(aux_tables != 0); 07452 if (check_table_access(thd, SELECT_ACL, tables, 0)) 07453 DBUG_RETURN(TRUE); 07454 07455 /* 07456 Since aux_tables list is not part of LEX::query_tables list we 07457 have to juggle with LEX::query_tables_own_last value to be able 07458 call check_table_access() safely. 07459 */ 07460 thd->lex->query_tables_own_last= 0; 07461 if (check_table_access(thd, DELETE_ACL, aux_tables, 0)) 07462 { 07463 thd->lex->query_tables_own_last= save_query_tables_own_last; 07464 DBUG_RETURN(TRUE); 07465 } 07466 thd->lex->query_tables_own_last= save_query_tables_own_last; 07467 07468 if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where) 07469 { 07470 my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, 07471 ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0)); 07472 DBUG_RETURN(TRUE); 07473 } 07474 DBUG_RETURN(FALSE); 07475 } 07476 07477 07478 /* 07479 Link tables in auxilary table list of multi-delete with corresponding 07480 elements in main table list, and set proper locks for them. 07481 07482 SYNOPSIS 07483 multi_delete_set_locks_and_link_aux_tables() 07484 lex - pointer to LEX representing multi-delete 07485 07486 RETURN VALUE 07487 FALSE - success 07488 TRUE - error 07489 */ 07490 07491 bool multi_delete_set_locks_and_link_aux_tables(LEX *lex) 07492 { 07493 TABLE_LIST *tables= (TABLE_LIST*)lex->select_lex.table_list.first; 07494 TABLE_LIST *target_tbl; 07495 DBUG_ENTER("multi_delete_set_locks_and_link_aux_tables"); 07496 07497 lex->table_count= 0; 07498 07499 for (target_tbl= (TABLE_LIST *)lex->auxiliary_table_list.first; 07500 target_tbl; target_tbl= target_tbl->next_local) 07501 { 07502 lex->table_count++; 07503 /* All tables in aux_tables must be found in FROM PART */ 07504 TABLE_LIST *walk; 07505 for (walk= tables; walk; walk= walk->next_local) 07506 { 07507 if (!my_strcasecmp(table_alias_charset, 07508 target_tbl->alias, walk->alias) && 07509 !strcmp(walk->db, target_tbl->db)) 07510 break; 07511 } 07512 if (!walk) 07513 { 07514 my_error(ER_UNKNOWN_TABLE, MYF(0), 07515 target_tbl->table_name, "MULTI DELETE"); 07516 DBUG_RETURN(TRUE); 07517 } 07518 if (!walk->derived) 07519 { 07520 target_tbl->table_name= walk->table_name; 07521 target_tbl->table_name_length= walk->table_name_length; 07522 } 07523 walk->updating= target_tbl->updating; 07524 walk->lock_type= target_tbl->lock_type; 07525 target_tbl->correspondent_table= walk; // Remember corresponding table 07526 } 07527 DBUG_RETURN(FALSE); 07528 } 07529 07530 07531 /* 07532 simple UPDATE query pre-check 07533 07534 SYNOPSIS 07535 update_precheck() 07536 thd Thread handler 07537 tables Global table list 07538 07539 RETURN VALUE 07540 FALSE OK 07541 TRUE Error 07542 */ 07543 07544 bool update_precheck(THD *thd, TABLE_LIST *tables) 07545 { 07546 DBUG_ENTER("update_precheck"); 07547 if (thd->lex->select_lex.item_list.elements != thd->lex->value_list.elements) 07548 { 07549 my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0)); 07550 DBUG_RETURN(TRUE); 07551 } 07552 DBUG_RETURN(check_one_table_access(thd, UPDATE_ACL, tables)); 07553 } 07554 07555 07556 /* 07557 simple DELETE query pre-check 07558 07559 SYNOPSIS 07560 delete_precheck() 07561 thd Thread handler 07562 tables Global table list 07563 07564 RETURN VALUE 07565 FALSE OK 07566 TRUE error 07567 */ 07568 07569 bool delete_precheck(THD *thd, TABLE_LIST *tables) 07570 { 07571 DBUG_ENTER("delete_precheck"); 07572 if (check_one_table_access(thd, DELETE_ACL, tables)) 07573 DBUG_RETURN(TRUE); 07574 /* Set privilege for the WHERE clause */ 07575 tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); 07576 DBUG_RETURN(FALSE); 07577 } 07578 07579 07580 /* 07581 simple INSERT query pre-check 07582 07583 SYNOPSIS 07584 insert_precheck() 07585 thd Thread handler 07586 tables Global table list 07587 07588 RETURN VALUE 07589 FALSE OK 07590 TRUE error 07591 */ 07592 07593 bool insert_precheck(THD *thd, TABLE_LIST *tables) 07594 { 07595 LEX *lex= thd->lex; 07596 DBUG_ENTER("insert_precheck"); 07597 07598 /* 07599 Check that we have modify privileges for the first table and 07600 select privileges for the rest 07601 */ 07602 ulong privilege= (INSERT_ACL | 07603 (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) | 07604 (lex->value_list.elements ? UPDATE_ACL : 0)); 07605 07606 if (check_one_table_access(thd, privilege, tables)) 07607 DBUG_RETURN(TRUE); 07608 07609 if (lex->update_list.elements != lex->value_list.elements) 07610 { 07611 my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0)); 07612 DBUG_RETURN(TRUE); 07613 } 07614 DBUG_RETURN(FALSE); 07615 } 07616 07617 07618 /* 07619 CREATE TABLE query pre-check 07620 07621 SYNOPSIS 07622 create_table_precheck() 07623 thd Thread handler 07624 tables Global table list 07625 create_table Table which will be created 07626 07627 RETURN VALUE 07628 FALSE OK 07629 TRUE Error 07630 */ 07631 07632 bool create_table_precheck(THD *thd, TABLE_LIST *tables, 07633 TABLE_LIST *create_table) 07634 { 07635 LEX *lex= thd->lex; 07636 SELECT_LEX *select_lex= &lex->select_lex; 07637 ulong want_priv; 07638 bool error= TRUE; // Error message is given 07639 DBUG_ENTER("create_table_precheck"); 07640 07641 want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? 07642 CREATE_TMP_ACL : CREATE_ACL); 07643 lex->create_info.alias= create_table->alias; 07644 if (check_access(thd, want_priv, create_table->db, 07645 &create_table->grant.privilege, 0, 0, 07646 test(create_table->schema_table)) || 07647 check_merge_table_access(thd, create_table->db, 07648 (TABLE_LIST *) 07649 lex->create_info.merge_list.first)) 07650 goto err; 07651 if (grant_option && want_priv != CREATE_TMP_ACL && 07652 check_grant(thd, want_priv, create_table, 0, 1, 0)) 07653 goto err; 07654 07655 if (select_lex->item_list.elements) 07656 { 07657 /* Check permissions for used tables in CREATE TABLE ... SELECT */ 07658 07659 #ifdef NOT_NECESSARY_TO_CHECK_CREATE_TABLE_EXIST_WHEN_PREPARING_STATEMENT 07660 /* This code throws an ill error for CREATE TABLE t1 SELECT * FROM t1 */ 07661 /* 07662 Only do the check for PS, becasue we on execute we have to check that 07663 against the opened tables to ensure we don't use a table that is part 07664 of the view (which can only be done after the table has been opened). 07665 */ 07666 if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) 07667 { 07668 /* 07669 For temporary tables we don't have to check if the created table exists 07670 */ 07671 if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && 07672 find_table_in_global_list(tables, create_table->db, 07673 create_table->table_name)) 07674 { 07675 error= FALSE; 07676 goto err; 07677 } 07678 } 07679 #endif 07680 if (tables && check_table_access(thd, SELECT_ACL, tables,0)) 07681 goto err; 07682 } 07683 error= FALSE; 07684 07685 err: 07686 DBUG_RETURN(error); 07687 } 07688 07689 07690 /* 07691 negate given expression 07692 07693 SYNOPSIS 07694 negate_expression() 07695 thd thread handler 07696 expr expression for negation 07697 07698 RETURN 07699 negated expression 07700 */ 07701 07702 Item *negate_expression(THD *thd, Item *expr) 07703 { 07704 Item *negated; 07705 if (expr->type() == Item::FUNC_ITEM && 07706 ((Item_func *) expr)->functype() == Item_func::NOT_FUNC) 07707 { 07708 /* it is NOT(NOT( ... )) */ 07709 Item *arg= ((Item_func *) expr)->arguments()[0]; 07710 enum_parsing_place place= thd->lex->current_select->parsing_place; 07711 if (arg->is_bool_func() || place == IN_WHERE || place == IN_HAVING) 07712 return arg; 07713 /* 07714 if it is not boolean function then we have to emulate value of 07715 not(not(a)), it will be a != 0 07716 */ 07717 return new Item_func_ne(arg, new Item_int((char*) "0", 0, 1)); 07718 } 07719 07720 if ((negated= expr->neg_transformer(thd)) != 0) 07721 return negated; 07722 return new Item_func_not(expr); 07723 } 07724 07725 /* 07726 Set the specified definer to the default value, which is the current user in 07727 the thread. 07728 07729 SYNOPSIS 07730 get_default_definer() 07731 thd [in] thread handler 07732 definer [out] definer 07733 */ 07734 07735 void get_default_definer(THD *thd, LEX_USER *definer) 07736 { 07737 const Security_context *sctx= thd->security_ctx; 07738 07739 definer->user.str= (char *) sctx->priv_user; 07740 definer->user.length= strlen(definer->user.str); 07741 07742 definer->host.str= (char *) sctx->priv_host; 07743 definer->host.length= strlen(definer->host.str); 07744 } 07745 07746 07747 /* 07748 Create default definer for the specified THD. 07749 07750 SYNOPSIS 07751 create_default_definer() 07752 thd [in] thread handler 07753 07754 RETURN 07755 On success, return a valid pointer to the created and initialized 07756 LEX_USER, which contains definer information. 07757 On error, return 0. 07758 */ 07759 07760 LEX_USER *create_default_definer(THD *thd) 07761 { 07762 LEX_USER *definer; 07763 07764 if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) 07765 return 0; 07766 07767 get_default_definer(thd, definer); 07768 07769 return definer; 07770 } 07771 07772 07773 /* 07774 Create definer with the given user and host names. 07775 07776 SYNOPSIS 07777 create_definer() 07778 thd [in] thread handler 07779 user_name [in] user name 07780 host_name [in] host name 07781 07782 RETURN 07783 On success, return a valid pointer to the created and initialized 07784 LEX_USER, which contains definer information. 07785 On error, return 0. 07786 */ 07787 07788 LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) 07789 { 07790 LEX_USER *definer; 07791 07792 /* Create and initialize. */ 07793 07794 if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) 07795 return 0; 07796 07797 definer->user= *user_name; 07798 definer->host= *host_name; 07799 07800 return definer; 07801 } 07802 07803 07804 /* 07805 Retuns information about user or current user. 07806 07807 SYNOPSIS 07808 get_current_user() 07809 thd [in] thread handler 07810 user [in] user 07811 07812 RETURN 07813 On success, return a valid pointer to initialized 07814 LEX_USER, which contains user information. 07815 On error, return 0. 07816 */ 07817 07818 LEX_USER *get_current_user(THD *thd, LEX_USER *user) 07819 { 07820 LEX_USER *curr_user; 07821 if (!user->user.str) // current_user 07822 { 07823 if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) 07824 { 07825 my_error(ER_OUTOFMEMORY, MYF(0), sizeof(LEX_USER)); 07826 return 0; 07827 } 07828 get_default_definer(thd, curr_user); 07829 return curr_user; 07830 } 07831 return user; 07832 }
1.4.7

