1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

5.3->5.5 merge

This commit is contained in:
Sergei Golubchik
2011-11-22 18:04:38 +01:00
394 changed files with 17631 additions and 3357 deletions

View File

@ -118,7 +118,8 @@
"FUNCTION" : "PROCEDURE")
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
static void sql_kill(THD *thd, ulong id, bool only_kill_query);
static void sql_kill(THD *thd, ulong id, killed_state state);
static void sql_kill_user(THD *thd, LEX_USER *user, killed_state state);
static bool execute_show_status(THD *, TABLE_LIST *);
static bool execute_rename_table(THD *, TABLE_LIST *, TABLE_LIST *);
@ -1362,7 +1363,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
status_var_increment(thd->status_var.com_stat[SQLCOM_KILL]);
ulong id=(ulong) uint4korr(packet);
sql_kill(thd,id,false);
sql_kill(thd,id, KILL_CONNECTION_HARD);
break;
}
case COM_SET_OPTION:
@ -1443,6 +1444,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
MYSQL_COMMAND_DONE(res);
}
/* Check that some variables are reset properly */
DBUG_ASSERT(thd->abort_on_warning == 0);
DBUG_RETURN(error);
}
@ -3653,8 +3657,6 @@ end_with_restore_list:
}
case SQLCOM_KILL:
{
Item *it= (Item *)lex->value_list.head();
if (lex->table_or_sp_used())
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "Usage of subqueries or stored "
@ -3662,13 +3664,20 @@ end_with_restore_list:
break;
}
if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1))
if (lex->kill_type == KILL_TYPE_ID)
{
my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
MYF(0));
goto error;
Item *it= (Item *)lex->value_list.head();
if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1))
{
my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
MYF(0));
goto error;
}
sql_kill(thd, (ulong) it->val_int(), lex->kill_signal);
}
sql_kill(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
else
sql_kill_user(thd, get_current_user(thd, lex->users_list.head()),
lex->kill_signal);
break;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@ -3740,7 +3749,17 @@ end_with_restore_list:
}
/* Disconnect the current client connection. */
if (tx_release)
thd->killed= THD::KILL_CONNECTION;
{
thd->killed= KILL_CONNECTION;
if (global_system_variables.log_warnings > 3)
{
Security_context *sctx= &thd->main_security_ctx;
sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
thd->thread_id,(thd->db ? thd->db : "unconnected"),
sctx->user ? sctx->user : "unauthenticated",
sctx->host_or_ip, "RELEASE");
}
}
my_ok(thd);
break;
}
@ -3770,7 +3789,7 @@ end_with_restore_list:
}
/* Disconnect the current client connection. */
if (tx_release)
thd->killed= THD::KILL_CONNECTION;
thd->killed= KILL_CONNECTION;
my_ok(thd);
break;
}
@ -4035,7 +4054,8 @@ create_sp_error:
case SQLCOM_ALTER_FUNCTION:
{
int sp_result;
int type= (lex->sql_command == SQLCOM_ALTER_PROCEDURE ?
enum stored_procedure_type type;
type= (lex->sql_command == SQLCOM_ALTER_PROCEDURE ?
TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
if (check_routine_access(thd, ALTER_PROC_ACL, lex->spname->m_db.str,
@ -4112,7 +4132,8 @@ create_sp_error:
#endif
int sp_result;
int type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ?
enum stored_procedure_type type;
type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ?
TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
char *db= lex->spname->m_db.str;
char *name= lex->spname->m_name.str;
@ -4199,7 +4220,7 @@ create_sp_error:
{
#ifndef DBUG_OFF
sp_head *sp;
int type= (lex->sql_command == SQLCOM_SHOW_PROC_CODE ?
stored_procedure_type type= (lex->sql_command == SQLCOM_SHOW_PROC_CODE ?
TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
if (sp_cache_routine(thd, type, lex->spname, FALSE, &sp))
@ -4445,9 +4466,9 @@ finish:
if (! thd->stmt_da->is_set())
thd->send_kill_message();
}
if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA)
if (thd->killed < KILL_CONNECTION)
{
thd->killed= THD::NOT_KILLED;
thd->killed= NOT_KILLED;
thd->mysys_var->abort= 0;
}
if (thd->is_error() || (thd->variables.option_bits & OPTION_MASTER_SQL_ERROR))
@ -4518,7 +4539,6 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
param->select_limit=
new Item_int((ulonglong) thd->variables.select_limit);
}
thd->thd_marker.emb_on_expr_nest= NULL;
if (!(res= open_and_lock_tables(thd, all_tables, TRUE, 0)))
{
if (lex->describe)
@ -5418,7 +5438,6 @@ void THD::reset_for_next_command(bool calculate_userstat)
thd->query_plan_flags= QPLAN_INIT;
thd->query_plan_fsort_passes= 0;
thd->thd_marker.emb_on_expr_nest= NULL;
thd->reset_current_stmt_binlog_format_row();
thd->binlog_unsafe_warning_flags= 0;
@ -5485,6 +5504,7 @@ mysql_new_select(LEX *lex, bool move_down)
DBUG_RETURN(1);
}
select_lex->nest_level= lex->nest_level;
select_lex->nest_level_base= &thd->lex->unit;
if (move_down)
{
SELECT_LEX_UNIT *unit;
@ -6508,12 +6528,13 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields,
This is written such that we have a short lock on LOCK_thread_count
*/
uint kill_one_thread(THD *thd, ulong id, bool only_kill_query)
uint kill_one_thread(THD *thd, ulong id, killed_state kill_signal)
{
THD *tmp;
uint error=ER_NO_SUCH_THREAD;
DBUG_ENTER("kill_one_thread");
DBUG_PRINT("enter", ("id=%lu only_kill=%d", id, only_kill_query));
DBUG_PRINT("enter", ("id: %lu signal: %u", id, (uint) kill_signal));
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
I_List_iterator<THD> it(threads);
while ((tmp=it++))
@ -6544,12 +6565,16 @@ uint kill_one_thread(THD *thd, ulong id, bool only_kill_query)
If user of both killer and killee are non-NULL, proceed with
slayage if both are string-equal.
It's ok to also kill DELAYED threads with KILL_CONNECTION instead of
KILL_SYSTEM_THREAD; The difference is that KILL_CONNECTION may be
faster and do a harder kill than KILL_SYSTEM_THREAD;
*/
if ((thd->security_ctx->master_access & SUPER_ACL) ||
thd->security_ctx->user_matches(tmp->security_ctx))
{
tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION);
tmp->awake(kill_signal);
error=0;
}
else
@ -6561,6 +6586,76 @@ uint kill_one_thread(THD *thd, ulong id, bool only_kill_query)
}
/**
kill all threads from one user
@param thd Thread class
@param user_name User name for threads we should kill
@param only_kill_query Should it kill the query or the connection
@note
This is written such that we have a short lock on LOCK_thread_count
If we can't kill all threads because of security issues, no threads
are killed.
*/
static uint kill_threads_for_user(THD *thd, LEX_USER *user,
killed_state kill_signal, ha_rows *rows)
{
THD *tmp;
List<THD> threads_to_kill;
DBUG_ENTER("kill_threads_for_user");
*rows= 0;
if (thd->is_fatal_error) // If we run out of memory
DBUG_RETURN(ER_OUT_OF_RESOURCES);
DBUG_PRINT("enter", ("user: %s signal: %u", user->user.str,
(uint) kill_signal));
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
if (tmp->command == COM_DAEMON)
continue;
/*
Check that hostname (if given) and user name matches.
host.str[0] == '%' means that host name was not given. See sql_yacc.yy
*/
if (((user->host.str[0] == '%' && !user->host.str[1]) ||
!strcmp(tmp->security_ctx->host, user->host.str)) &&
!strcmp(tmp->security_ctx->user, user->user.str))
{
if (!(thd->security_ctx->master_access & SUPER_ACL) &&
!thd->security_ctx->user_matches(tmp->security_ctx))
{
mysql_mutex_unlock(&LOCK_thread_count);
DBUG_RETURN(ER_KILL_DENIED_ERROR);
}
if (!threads_to_kill.push_back(tmp, tmp->mem_root))
mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
}
}
mysql_mutex_unlock(&LOCK_thread_count);
if (!threads_to_kill.is_empty())
{
List_iterator_fast<THD> it(threads_to_kill);
THD *ptr;
while ((ptr= it++))
{
ptr->awake(kill_signal);
mysql_mutex_unlock(&ptr->LOCK_thd_data);
(*rows)++;
}
}
DBUG_RETURN(0);
}
/*
kills a thread and sends response
@ -6572,10 +6667,10 @@ uint kill_one_thread(THD *thd, ulong id, bool only_kill_query)
*/
static
void sql_kill(THD *thd, ulong id, bool only_kill_query)
void sql_kill(THD *thd, ulong id, killed_state state)
{
uint error;
if (!(error= kill_one_thread(thd, id, only_kill_query)))
if (!(error= kill_one_thread(thd, id, state)))
{
if (! thd->killed)
my_ok(thd);
@ -6585,6 +6680,24 @@ void sql_kill(THD *thd, ulong id, bool only_kill_query)
}
static
void sql_kill_user(THD *thd, LEX_USER *user, killed_state state)
{
uint error;
ha_rows rows;
if (!(error= kill_threads_for_user(thd, user, state, &rows)))
my_ok(thd, rows);
else
{
/*
This is probably ER_OUT_OF_RESOURCES, but in the future we may
want to write the name of the user we tried to kill
*/
my_error(error, MYF(0), user->host.str, user->user.str);
}
}
/** If pointer is not a null pointer, append filename to it. */
bool append_file_to_dir(THD *thd, const char **filename_ptr,