mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
(pushing for Andrei)
Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack Once had been set the flag might later got reset inside of a stored routine execution stack. The reason was in that there was no check if a new statement started at time of resetting. The artifact affects most of binlogable DML queries. Notice, that multi-update is wrapped up within bug@27716 fix, multi-delete bug@29136. Fixed with saving parent's statement flag of whether the statement modified non-transactional table, and unioning (merging) the value with that was gained in mysql_execute_command. Resettling thd->no_trans_update members into thd->transaction.`member`; Asserting code; Effectively the following properties are held. 1. At the end of a substatement thd->transaction.stmt.modified_non_trans_table reflects the fact if such a table got modified by the substatement. That also respects THD::really_abort_on_warnin() requirements. 2. Eventually thd->transaction.stmt.modified_non_trans_table will be computed as the union of the values of all invoked sub-statements. That fixes this bug#27417; Computing of thd->transaction.all.modified_non_trans_table is refined to base to the stmt's value for all the case including insert .. select statement which before the patch had an extra issue bug@28960. Minor issues are covered with mysql_load, mysql_delete, and binloggin of insert in to temp_table select. The supplied test verifies limitely, mostly asserts. The ultimate testing is defered for bug@13270, bug@23333.
This commit is contained in:
@@ -377,7 +377,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
table->file->start_bulk_insert((ha_rows) 0);
|
||||
table->copy_blobs=1;
|
||||
|
||||
thd->no_trans_update.stmt= FALSE;
|
||||
thd->abort_on_warning= (!ignore &&
|
||||
(thd->variables.sql_mode &
|
||||
(MODE_STRICT_TRANS_TABLES |
|
||||
@@ -411,7 +410,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
ha_autocommit_...
|
||||
*/
|
||||
query_cache_invalidate3(thd, table_list, 0);
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (read_file_from_client)
|
||||
@@ -466,8 +464,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted,
|
||||
(ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
|
||||
|
||||
if (!transactional_table)
|
||||
thd->no_trans_update.all= TRUE;
|
||||
if (thd->transaction.stmt.modified_non_trans_table)
|
||||
thd->transaction.all.modified_non_trans_table= TRUE;
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
@@ -488,6 +486,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
/* ok to client sent only after binlog write and engine commit */
|
||||
send_ok(thd, info.copied + info.deleted, 0L, name);
|
||||
err:
|
||||
DBUG_ASSERT(transactional_table || !(info.copied || info.deleted) ||
|
||||
thd->transaction.stmt.modified_non_trans_table);
|
||||
if (thd->lock)
|
||||
{
|
||||
mysql_unlock_tables(thd, thd->lock);
|
||||
@@ -532,7 +532,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
Item_field *sql_field;
|
||||
TABLE *table= table_list->table;
|
||||
ulonglong id;
|
||||
bool no_trans_update_stmt, err;
|
||||
bool err;
|
||||
DBUG_ENTER("read_fixed_length");
|
||||
|
||||
id= 0;
|
||||
@@ -560,7 +560,6 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
#ifdef HAVE_purify
|
||||
read_info.row_end[0]=0;
|
||||
#endif
|
||||
no_trans_update_stmt= !table->file->has_transactions();
|
||||
|
||||
restore_record(table, s->default_values);
|
||||
/*
|
||||
@@ -630,7 +629,6 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
table->auto_increment_field_not_null= FALSE;
|
||||
if (err)
|
||||
DBUG_RETURN(1);
|
||||
thd->no_trans_update.stmt= no_trans_update_stmt;
|
||||
|
||||
/*
|
||||
If auto_increment values are used, save the first one for
|
||||
@@ -673,12 +671,11 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
TABLE *table= table_list->table;
|
||||
uint enclosed_length;
|
||||
ulonglong id;
|
||||
bool no_trans_update_stmt, err;
|
||||
bool err;
|
||||
DBUG_ENTER("read_sep_field");
|
||||
|
||||
enclosed_length=enclosed.length();
|
||||
id= 0;
|
||||
no_trans_update_stmt= !table->file->has_transactions();
|
||||
|
||||
for (;;it.rewind())
|
||||
{
|
||||
@@ -821,7 +818,6 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
We don't need to reset auto-increment field since we are restoring
|
||||
its default value at the beginning of each loop iteration.
|
||||
*/
|
||||
thd->no_trans_update.stmt= no_trans_update_stmt;
|
||||
if (read_info.next_line()) // Skip to next line
|
||||
break;
|
||||
if (read_info.line_cuted)
|
||||
|
||||
Reference in New Issue
Block a user