diff options
author | Chad MILLER <chad@mysql.com> | 2009-04-14 13:20:13 -0400 |
---|---|---|
committer | Chad MILLER <chad@mysql.com> | 2009-04-14 13:20:13 -0400 |
commit | 3639528967739ace6ca187fd09584289b6ee2216 (patch) | |
tree | 55596b47965261462217616f8271d0c2b9d79ab0 /sql/sql_parse.cc | |
parent | 4e72d07e3de71a2d46f1a4d3becea00421e9b026 (diff) | |
parent | abe7def76437a37c050214a547d255a64ff11b88 (diff) | |
download | mariadb-git-3639528967739ace6ca187fd09584289b6ee2216.tar.gz |
Merge 5.0.80 release and 5.0 community. Version left at 5.0.80.clone-5.0.81-build
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r-- | sql/sql_parse.cc | 147 |
1 files changed, 124 insertions, 23 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cb55be42339..a872585e704 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -250,7 +250,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, USER_RESOURCES *mqh) { int return_val= 0; - uint temp_len, user_len; + size_t temp_len, user_len; char temp_user[USER_HOST_BUFF_SIZE]; struct user_conn *uc; @@ -261,7 +261,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1; (void) pthread_mutex_lock(&LOCK_user_conn); if (!(uc = (struct user_conn *) hash_search(&hash_user_connections, - (byte*) temp_user, temp_len))) + (byte*) temp_user, (uint) temp_len))) { /* First connection for user; Create a user connection object */ if (!(uc= ((struct user_conn*) @@ -275,7 +275,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, uc->user=(char*) (uc+1); memcpy(uc->user,temp_user,temp_len+1); uc->host= uc->user + user_len + 1; - uc->len= temp_len; + uc->len= (uint) temp_len; uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0; uc->user_resources= *mqh; uc->intime= thd->thr_create_time; @@ -328,7 +328,7 @@ int check_user(THD *thd, enum enum_server_command command, bool check_count) { DBUG_ENTER("check_user"); - LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 }; + LEX_STRING db_str= { (char *) db, db ? (uint) strlen(db) : 0 }; #ifdef NO_EMBEDDED_ACCESS_CHECKS thd->main_security_ctx.master_access= GLOBAL_ACLS; // Full rights @@ -1036,7 +1036,7 @@ static int check_connection(THD *thd) char *user= end; char *passwd= strend(user)+1; - uint user_len= passwd - user - 1; + size_t user_len= passwd - user - 1; char *db= passwd; char db_buff[NAME_LEN + 1]; // buffer to store db in utf8 char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8 @@ -1051,10 +1051,10 @@ static int check_connection(THD *thd) *passwd > 127 and become 2**32-127 after casting to uint. */ uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? - (uchar)(*passwd++) : strlen(passwd); + (uchar)(*passwd++) : (uint) strlen(passwd); db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ? db + passwd_len + 1 : 0; - uint db_len= db ? strlen(db) : 0; + size_t db_len= db ? strlen(db) : 0; if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len) { @@ -1067,13 +1067,13 @@ static int check_connection(THD *thd) { db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info, - db, db_len, + db, (uint) db_len, thd->charset(), &dummy_errors)]= 0; db= db_buff; } user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1, - system_charset_info, user, user_len, + system_charset_info, user, (uint) user_len, thd->charset(), &dummy_errors)]= '\0'; user= user_buff; @@ -1789,7 +1789,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, statistic_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB], &LOCK_status); thd->convert_string(&tmp, system_charset_info, - packet, strlen(packet), thd->charset()); + packet, (uint) strlen(packet), thd->charset()); if (!mysql_change_db(thd, &tmp, FALSE)) { mysql_log.write(thd,command,"%s",thd->db); @@ -1852,7 +1852,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, */ char db_buff[NAME_LEN+1]; // buffer to store db in utf8 char *db= passwd; - uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? + size_t passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? (uchar)(*passwd++) : strlen(passwd); db+= passwd_len + 1; #ifndef EMBEDDED_LIBRARY @@ -1866,7 +1866,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Convert database name to utf8 */ uint dummy_errors; db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, - system_charset_info, db, strlen(db), + system_charset_info, db, (uint) strlen(db), thd->charset(), &dummy_errors)]= 0; db= db_buff; @@ -1885,7 +1885,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Clear variables that are allocated */ thd->user_connect= 0; - int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE); + int res= check_user(thd, COM_CHANGE_USER, passwd, (uint) passwd_len, db, FALSE); if (res) { @@ -2041,7 +2041,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, table_list.schema_table= schema_table; } - thd->query_length= strlen(packet); // for simplicity: don't optimize + thd->query_length= (uint) strlen(packet); // for simplicity: don't optimize if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1))) break; mysql_log.write(thd,command,"%s %s",table_list.table_name, fields); @@ -2363,8 +2363,9 @@ void log_slow_statement(THD *thd) { thd_proc_info(thd, "logging slow query"); - if ((ulong) (thd->start_time - thd->time_after_lock) > - thd->variables.long_query_time || + if ((thd->start_time > thd->time_after_lock && + (ulong) (thd->start_time - thd->time_after_lock) > + thd->variables.long_query_time) || (thd->server_status & (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) && opt_log_queries_not_using_indexes && @@ -2623,6 +2624,10 @@ mysql_execute_command(THD *thd) TABLE_LIST *all_tables; /* most outer SELECT_LEX_UNIT of query */ SELECT_LEX_UNIT *unit= &lex->unit; +#ifdef HAVE_REPLICATION + /* have table map for update for multi-update statement (BUG#37051) */ + bool have_table_map_for_update= FALSE; +#endif /* Saved variable value */ DBUG_ENTER("mysql_execute_command"); thd->net.no_send_error= 0; @@ -2702,6 +2707,48 @@ mysql_execute_command(THD *thd) // force searching in slave.cc:tables_ok() all_tables->updating= 1; } + + /* + For fix of BUG#37051, the master stores the table map for update + in the Query_log_event, and the value is assigned to + thd->variables.table_map_for_update before executing the update + query. + + If thd->variables.table_map_for_update is set, then we are + replicating from a new master, we can use this value to apply + filter rules without opening all the tables. However If + thd->variables.table_map_for_update is not set, then we are + replicating from an old master, so we just skip this and + continue with the old method. And of course, the bug would still + exist for old masters. + */ + if (lex->sql_command == SQLCOM_UPDATE_MULTI && + thd->table_map_for_update) + { + have_table_map_for_update= TRUE; + table_map table_map_for_update= thd->table_map_for_update; + uint nr= 0; + TABLE_LIST *table; + for (table=all_tables; table; table=table->next_global, nr++) + { + if (table_map_for_update & ((table_map)1 << nr)) + table->updating= TRUE; + else + table->updating= FALSE; + } + + if (all_tables_not_ok(thd, all_tables)) + { + /* we warn the slave SQL thread */ + my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); + if (thd->one_shot_set) + reset_one_shot_variables(thd); + DBUG_RETURN(0); + } + + for (table=all_tables; table; table=table->next_global) + table->updating= TRUE; + } /* Check if statment should be skipped because of slave filtering @@ -3217,6 +3264,42 @@ mysql_execute_command(THD *thd) } if (select_lex->item_list.elements) // With select { + /* + If: + a) we inside an SP and there was NAME_CONST substitution, + b) binlogging is on, + c) we log the SP as separate statements + raise a warning, as it may cause problems + (see 'NAME_CONST issues' in 'Binary Logging of Stored Programs') + */ + if (thd->query_name_consts && + mysql_bin_log.is_open() && + !mysql_bin_log.is_query_in_union(thd, thd->query_id)) + { + List_iterator_fast<Item> it(select_lex->item_list); + Item *item; + uint splocal_refs= 0; + /* Count SP local vars in the top-level SELECT list */ + while ((item= it++)) + { + if (item->is_splocal()) + splocal_refs++; + } + /* + If it differs from number of NAME_CONST substitution applied, + we may have a SOME_FUNC(NAME_CONST()) in the SELECT list, + that may cause a problem with binary log (see BUG#35383), + raise a warning. + */ + if (splocal_refs != thd->query_name_consts) + push_warning(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, +"Invoked routine ran a statement that may cause problems with " +"binary log, see 'NAME_CONST issues' in 'Binary Logging of Stored Programs' " +"section of the manual."); + } + select_result *sel_result; select_lex->options|= SELECT_NO_UNLOCK; @@ -3660,7 +3743,7 @@ end_with_restore_list: #ifdef HAVE_REPLICATION /* Check slave filtering rules */ - if (unlikely(thd->slave_thread)) + if (unlikely(thd->slave_thread && !have_table_map_for_update)) { if (all_tables_not_ok(thd, all_tables)) { @@ -3969,7 +4052,7 @@ end_with_restore_list: #endif case SQLCOM_CHANGE_DB: { - LEX_STRING db_str= { (char *) select_lex->db, strlen(select_lex->db) }; + LEX_STRING db_str= { (char *) select_lex->db, (uint) strlen(select_lex->db) }; if (!mysql_change_db(thd, &db_str, FALSE)) send_ok(thd); @@ -6202,7 +6285,7 @@ void create_select_for_variable(const char *var_name) mysql_init_select(lex); lex->sql_command= SQLCOM_SELECT; tmp.str= (char*) var_name; - tmp.length=strlen(var_name); + tmp.length=(uint) strlen(var_name); bzero((char*) &null_lex_string.str, sizeof(null_lex_string)); /* We set the name of Item to @@session.var_name because that then is used @@ -6211,7 +6294,7 @@ void create_select_for_variable(const char *var_name) if ((var= get_system_var(thd, OPT_SESSION, tmp, null_lex_string))) { end= strxmov(buff, "@@session.", var_name, NullS); - var->set_name(buff, end-buff, system_charset_info); + var->set_name(buff, (uint) (end - buff), system_charset_info); add_item_to_list(thd, var); } DBUG_VOID_RETURN; @@ -7394,8 +7477,26 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query) VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (tmp) { + + /* + If we're SUPER, we can KILL anything, including system-threads. + No further checks. + + KILLer: thd->security_ctx->user could in theory be NULL while + we're still in "unauthenticated" state. This is a theoretical + case (the code suggests this could happen, so we play it safe). + + KILLee: tmp->security_ctx->user will be NULL for system threads. + We need to check so Jane Random User doesn't crash the server + when trying to kill a) system threads or b) unauthenticated users' + threads (Bug#43748). + + If user of both killer and killee are non-NULL, proceed with + slayage if both are string-equal. + */ + if ((thd->security_ctx->master_access & SUPER_ACL) || - !strcmp(thd->security_ctx->user, tmp->security_ctx->user)) + thd->security_ctx->user_matches(tmp->security_ctx)) { tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION); error=0; @@ -7954,10 +8055,10 @@ void get_default_definer(THD *thd, LEX_USER *definer) const Security_context *sctx= thd->security_ctx; definer->user.str= (char *) sctx->priv_user; - definer->user.length= strlen(definer->user.str); + definer->user.length= (uint) strlen(definer->user.str); definer->host.str= (char *) sctx->priv_host; - definer->host.length= strlen(definer->host.str); + definer->host.length= (uint) strlen(definer->host.str); } |