1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Merge mysql-5.5-bugfixing -> mysql-5.5-innodb

This commit is contained in:
Vasil Dimov
2010-08-18 10:14:06 +03:00
424 changed files with 19834 additions and 7791 deletions

View File

@ -29,7 +29,6 @@
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
#include "sql_class.h"
#include "lock.h" // unlock_global_read_lock, mysql_unlock_tables
#include "sql_cache.h" // query_cache_abort
#include "sql_base.h" // close_thread_tables
#include "sql_time.h" // date_time_format_copy
@ -496,10 +495,8 @@ THD::THD()
:Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION,
/* statement id */ 0),
rli_fake(0),
lock_id(&main_lock_id),
user_time(0), in_sub_stmt(0),
binlog_unsafe_warning_flags(0),
stmt_accessed_table_flag(0),
binlog_table_maps(0),
table_map_for_update(0),
arg_of_last_insert_id_function(FALSE),
@ -630,7 +627,6 @@ THD::THD()
randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
substitute_null_with_insert_id = FALSE;
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
thr_lock_owner_init(&main_lock_id, &lock_info);
m_internal_handler= NULL;
current_user_used= FALSE;
@ -853,35 +849,6 @@ MYSQL_ERROR* THD::raise_condition(uint sql_errno,
}
}
/*
If a continue handler is found, the error message will be cleared
by the stored procedures code.
*/
if (!is_fatal_error && spcont &&
spcont->handle_condition(this, sql_errno, sqlstate, level, msg, &cond))
{
/*
Do not push any warnings, a handled error must be completely
silenced.
*/
DBUG_RETURN(cond);
}
/* Un-handled conditions */
cond= raise_condition_no_handler(sql_errno, sqlstate, level, msg);
DBUG_RETURN(cond);
}
MYSQL_ERROR*
THD::raise_condition_no_handler(uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg)
{
MYSQL_ERROR *cond= NULL;
DBUG_ENTER("THD::raise_condition_no_handler");
query_cache_abort(&query_cache_tls);
/* FIXME: broken special case */
@ -894,6 +861,7 @@ THD::raise_condition_no_handler(uint sql_errno,
cond= warning_info->push_warning(this, sql_errno, sqlstate, level, msg);
DBUG_RETURN(cond);
}
extern "C"
void *thd_alloc(MYSQL_THD thd, unsigned int size)
{
@ -1119,7 +1087,6 @@ THD::~THD()
}
#endif
stmt_map.reset(); /* close all prepared statements */
DBUG_ASSERT(lock_info.n_cursors == 0);
if (!cleanup_done)
cleanup();
@ -1746,9 +1713,9 @@ bool select_send::send_result_set_metadata(List<Item> &list, uint flags)
return res;
}
void select_send::abort()
void select_send::abort_result_set()
{
DBUG_ENTER("select_send::abort");
DBUG_ENTER("select_send::abort_result_set");
if (is_result_set_started && thd->spcont)
{
@ -1822,12 +1789,6 @@ bool select_send::send_eof()
*/
ha_release_temporary_latches(thd);
/* Unlock tables before sending packet to gain some speed */
if (thd->lock && ! thd->locked_tables_mode)
{
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
/*
Don't send EOF if we're in error condition (which implies we've already
sent or are sending an error)
@ -2601,7 +2562,6 @@ Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg,
id(id_arg),
mark_used_columns(MARK_COLUMNS_READ),
lex(lex_arg),
cursor(0),
db(NULL),
db_length(0)
{
@ -2623,7 +2583,6 @@ void Statement::set_statement(Statement *stmt)
mark_used_columns= stmt->mark_used_columns;
lex= stmt->lex;
query_string= stmt->query_string;
cursor= stmt->cursor;
}
@ -3720,8 +3679,17 @@ int THD::decide_logging_format(TABLE_LIST *tables)
Innodb and Falcon; Innodb and MyIsam.
*/
my_bool multi_access_engine= FALSE;
/*
Identifies if a table is changed.
*/
my_bool is_write= FALSE;
/*
A pointer to a previous table that was changed.
*/
TABLE* prev_write_table= NULL;
/*
A pointer to a previous table that was accessed.
*/
TABLE* prev_access_table= NULL;
#ifndef DBUG_OFF
@ -3745,7 +3713,8 @@ int THD::decide_logging_format(TABLE_LIST *tables)
if (table->placeholder())
continue;
if (table->table->s->table_category == TABLE_CATEGORY_PERFORMANCE)
if (table->table->s->table_category == TABLE_CATEGORY_PERFORMANCE ||
table->table->s->table_category == TABLE_CATEGORY_LOG)
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_TABLE);
handler::Table_flags const flags= table->table->file->ha_table_flags();
@ -3761,16 +3730,18 @@ int THD::decide_logging_format(TABLE_LIST *tables)
my_bool trans= table->table->file->has_transactions();
if (table->table->s->tmp_table)
set_stmt_accessed_table(trans ? STMT_WRITES_TEMP_TRANS_TABLE :
STMT_WRITES_TEMP_NON_TRANS_TABLE);
lex->set_stmt_accessed_table(trans ? LEX::STMT_WRITES_TEMP_TRANS_TABLE :
LEX::STMT_WRITES_TEMP_NON_TRANS_TABLE);
else
set_stmt_accessed_table(trans ? STMT_WRITES_TRANS_TABLE :
STMT_WRITES_NON_TRANS_TABLE);
lex->set_stmt_accessed_table(trans ? LEX::STMT_WRITES_TRANS_TABLE :
LEX::STMT_WRITES_NON_TRANS_TABLE);
flags_write_all_set &= flags;
flags_write_some_set |= flags;
is_write= TRUE;
prev_write_table= table->table;
}
flags_access_some_set |= flags;
@ -3781,11 +3752,11 @@ int THD::decide_logging_format(TABLE_LIST *tables)
my_bool trans= table->table->file->has_transactions();
if (table->table->s->tmp_table)
set_stmt_accessed_table(trans ? STMT_READS_TEMP_TRANS_TABLE :
STMT_READS_TEMP_NON_TRANS_TABLE);
lex->set_stmt_accessed_table(trans ? LEX::STMT_READS_TEMP_TRANS_TABLE :
LEX::STMT_READS_TEMP_NON_TRANS_TABLE);
else
set_stmt_accessed_table(trans ? STMT_READS_TRANS_TABLE :
STMT_READS_NON_TRANS_TABLE);
lex->set_stmt_accessed_table(trans ? LEX::STMT_READS_TRANS_TABLE :
LEX::STMT_READS_NON_TRANS_TABLE);
}
if (prev_access_table && prev_access_table->file->ht !=
@ -3857,24 +3828,24 @@ int THD::decide_logging_format(TABLE_LIST *tables)
my_bool non_trans_unsafe= FALSE;
/* Case 1. */
if (stmt_accessed_table(STMT_WRITES_TRANS_TABLE) &&
stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE))
if (lex->stmt_accessed_table(LEX::STMT_WRITES_TRANS_TABLE) &&
lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
mixed_unsafe= TRUE;
/* Case 2. */
else if (stmt_accessed_table(STMT_WRITES_TEMP_TRANS_TABLE) &&
stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE))
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TEMP_TRANS_TABLE) &&
lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
mixed_unsafe= TRUE;
/* Case 3. */
else if (stmt_accessed_table(STMT_WRITES_TRANS_TABLE) &&
stmt_accessed_table(STMT_READS_NON_TRANS_TABLE))
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TRANS_TABLE) &&
lex->stmt_accessed_table(LEX::STMT_READS_NON_TRANS_TABLE))
mixed_unsafe= TRUE;
/* Case 4. */
else if (stmt_accessed_table(STMT_WRITES_TEMP_TRANS_TABLE) &&
stmt_accessed_table(STMT_READS_NON_TRANS_TABLE))
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TEMP_TRANS_TABLE) &&
lex->stmt_accessed_table(LEX::STMT_READS_NON_TRANS_TABLE))
mixed_unsafe= TRUE;
/* Case 5. */
else if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) &&
stmt_accessed_table(STMT_READS_TRANS_TABLE) &&
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
lex->stmt_accessed_table(LEX::STMT_READS_TRANS_TABLE) &&
tx_isolation < ISO_REPEATABLE_READ)
/*
By default, InnoDB operates in REPEATABLE READ and with the option
@ -3892,28 +3863,28 @@ int THD::decide_logging_format(TABLE_LIST *tables)
if (trans_has_updated_trans_table(this))
{
/* Case 6. */
if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) &&
stmt_accessed_table(STMT_READS_TRANS_TABLE))
if (lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
lex->stmt_accessed_table(LEX::STMT_READS_TRANS_TABLE))
mixed_unsafe= TRUE;
/* Case 7. */
else if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) &&
stmt_accessed_table(STMT_READS_TEMP_TRANS_TABLE))
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
lex->stmt_accessed_table(LEX::STMT_READS_TEMP_TRANS_TABLE))
mixed_unsafe= TRUE;
/* Case 8. */
else if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) &&
stmt_accessed_table(STMT_READS_TEMP_NON_TRANS_TABLE))
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
lex->stmt_accessed_table(LEX::STMT_READS_TEMP_NON_TRANS_TABLE))
mixed_unsafe= TRUE;
/* Case 9. */
else if (stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE))
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
mixed_unsafe= TRUE;
/* Case 10. */
else if (stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
stmt_accessed_table(STMT_READS_NON_TRANS_TABLE))
else if (lex->stmt_accessed_table(LEX::STMT_WRITES_TEMP_NON_TRANS_TABLE) &&
lex->stmt_accessed_table(LEX::STMT_READS_NON_TRANS_TABLE))
mixed_unsafe= TRUE;
/* Case 11. */
else if (!variables.binlog_direct_non_trans_update &&
stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE))
lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE))
non_trans_unsafe= TRUE;
}
@ -4004,13 +3975,14 @@ int THD::decide_logging_format(TABLE_LIST *tables)
*/
my_error((error= ER_BINLOG_STMT_MODE_AND_ROW_ENGINE), MYF(0), "");
}
else if ((unsafe_flags= lex->get_stmt_unsafe_flags()) != 0)
else if (is_write && (unsafe_flags= lex->get_stmt_unsafe_flags()) != 0)
{
/*
7. Warning: Unsafe statement logged as statement due to
binlog_format = STATEMENT
*/
binlog_unsafe_warning_flags|= unsafe_flags;
DBUG_PRINT("info", ("Scheduling warning to be issued by "
"binlog_query: '%s'",
ER(ER_BINLOG_UNSAFE_STATEMENT)));
@ -4486,23 +4458,10 @@ void THD::issue_unsafe_warnings()
Ensure that binlog_unsafe_warning_flags is big enough to hold all
bits. This is actually a constant expression.
*/
DBUG_ASSERT(2 * LEX::BINLOG_STMT_UNSAFE_COUNT <=
DBUG_ASSERT(LEX::BINLOG_STMT_UNSAFE_COUNT <=
sizeof(binlog_unsafe_warning_flags) * CHAR_BIT);
uint32 unsafe_type_flags= binlog_unsafe_warning_flags;
/*
Clear: (1) bits above BINLOG_STMT_UNSAFE_COUNT; (2) bits for
warnings that have been printed already.
*/
unsafe_type_flags &= (LEX::BINLOG_STMT_UNSAFE_ALL_FLAGS ^
(unsafe_type_flags >> LEX::BINLOG_STMT_UNSAFE_COUNT));
/* If all warnings have been printed already, return. */
if (unsafe_type_flags == 0)
DBUG_VOID_RETURN;
DBUG_PRINT("info", ("unsafe_type_flags: 0x%x", unsafe_type_flags));
/*
For each unsafe_type, check if the statement is unsafe in this way
and issue a warning.
@ -4526,12 +4485,6 @@ void THD::issue_unsafe_warnings()
}
}
}
/*
Mark these unsafe types as already printed, to avoid printing
warnings for them again.
*/
binlog_unsafe_warning_flags|=
unsafe_type_flags << LEX::BINLOG_STMT_UNSAFE_COUNT;
DBUG_VOID_RETURN;
}
@ -4585,19 +4538,32 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
/*
Warnings for unsafe statements logged in statement format are
printed here instead of in decide_logging_format(). This is
because the warnings should be printed only if the statement is
actually logged. When executing decide_logging_format(), we cannot
know for sure if the statement will be logged.
printed in three places instead of in decide_logging_format().
This is because the warnings should be printed only if the statement
is actually logged. When executing decide_logging_format(), we cannot
know for sure if the statement will be logged:
1 - sp_head::execute_procedure which prints out warnings for calls to
stored procedures.
2 - sp_head::execute_function which prints out warnings for calls
involving functions.
3 - THD::binlog_query (here) which prints warning for top level
statements not covered by the two cases above: i.e., if not insided a
procedure and a function.
Besides, we should not try to print these warnings if it is not
possible to write statements to the binary log as it happens when
the execution is inside a function, or generaly speaking, when
the variables.option_bits & OPTION_BIN_LOG is false.
*/
if (variables.option_bits & OPTION_BIN_LOG)
if ((variables.option_bits & OPTION_BIN_LOG) &&
spcont == NULL && !binlog_evt_union.do_union)
issue_unsafe_warnings();
switch (qtype) {
/*
ROW_QUERY_TYPE means that the statement may be logged either in