1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

A fix and a test case for Bug#12713 "Error in a stored function called from

a SELECT doesn't cause ROLLBACK of statem".

The idea of the fix is to ensure that we always commit the current
statement at the end of dispatch_command(). In order to not issue
redundant disc syncs, an optimization of the two-phase commit
protocol is implemented to bypass the two phase commit if
the transaction is read-only.
This commit is contained in:
kostja@dipika.(none)
2008-02-19 14:43:01 +03:00
parent 48d326612a
commit acf9b1f346
27 changed files with 2514 additions and 247 deletions

View File

@ -541,6 +541,10 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list)
/**
INSERT statement implementation
@note Like implementations of other DDL/DML in MySQL, this function
relies on the caller to close the thread tables. This is done in the
end of dispatch_command().
*/
bool mysql_insert(THD *thd,TABLE_LIST *table_list,
@ -893,12 +897,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
}
DBUG_ASSERT(transactional_table || !changed ||
thd->transaction.stmt.modified_non_trans_table);
if (transactional_table)
error=ha_autocommit_or_rollback(thd,error);
if (thd->lock)
{
mysql_unlock_tables(thd, thd->lock);
/*
Invalidate the table in the query cache if something changed
after unlocking when changes become fisible.
@ -909,7 +910,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
{
query_cache_invalidate3(thd, table_list, 1);
}
thd->lock=0;
}
}
thd_proc_info(thd, "end");
@ -2445,7 +2445,7 @@ err:
first call to ha_*_row() instead. Remove code that are used to
cover for the case outlined above.
*/
ha_rollback_stmt(thd);
ha_autocommit_or_rollback(thd, 1);
#ifndef __WIN__
end:
@ -3139,18 +3139,6 @@ bool select_insert::send_eof()
thd->query, thd->query_length,
trans_table, FALSE, killed_status);
}
/*
We will call ha_autocommit_or_rollback() also for
non-transactional tables under row-based replication: there might
be events in the binary logs transaction, and we need to write
them to the binary log.
*/
if (trans_table || thd->current_stmt_binlog_row_based)
{
int error2= ha_autocommit_or_rollback(thd, error);
if (error2 && !error)
error= error2;
}
table->file->ha_release_auto_increment();
if (error)
@ -3228,7 +3216,6 @@ void select_insert::abort() {
table->file->ha_release_auto_increment();
}
ha_rollback_stmt(thd);
DBUG_VOID_RETURN;
}
@ -3667,7 +3654,10 @@ bool select_create::send_eof()
nevertheless.
*/
if (!table->s->tmp_table)
ha_commit(thd); // Can fail, but we proceed anyway
{
ha_autocommit_or_rollback(thd, 0);
end_active_trans(thd);
}
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
@ -3691,12 +3681,9 @@ void select_create::abort()
by removing the table, even for non-transactional tables.
*/
tmp_disable_binlog(thd);
select_insert::abort();
reenable_binlog(thd);
/*
We roll back the statement, including truncating the transaction
cache of the binary log, if the statement failed.
In select_insert::abort() we roll back the statement, including
truncating the transaction cache of the binary log.
We roll back the statement prior to deleting the table and prior
to releasing the lock on the table, since there might be potential
@ -3707,8 +3694,9 @@ void select_create::abort()
of the table succeeded or not, since we need to reset the binary
log state.
*/
if (thd->current_stmt_binlog_row_based)
ha_rollback_stmt(thd);
select_insert::abort();
reenable_binlog(thd);
if (m_plock)
{