summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <gkodinov/kgeorge@magare.gmz>2007-07-31 15:23:25 +0300
committerunknown <gkodinov/kgeorge@magare.gmz>2007-07-31 15:23:25 +0300
commit125bc936ac66ce20898311a20343292b8107e3eb (patch)
treea32fe617148b1f7930fc656c7fb3aad75bfeb99d /sql
parent6c589f90846cbaaeea9f0ff86f4b6011aa8622a9 (diff)
parent21d639e573d483a354c8ddbf17471ee468cce926 (diff)
downloadmariadb-git-125bc936ac66ce20898311a20343292b8107e3eb.tar.gz
Merge gkodinov@bk-internal.mysql.com:/home/bk/mysql-5.0-opt
into magare.gmz:/home/kgeorge/mysql/autopush/B27417-5.0-opt sql/handler.cc: Auto merged sql/sp_head.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_ndbcluster.cc2
-rw-r--r--sql/handler.cc2
-rw-r--r--sql/handler.h29
-rw-r--r--sql/log.cc4
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/sp_head.cc20
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_class.h6
-rw-r--r--sql/sql_delete.cc31
-rw-r--r--sql/sql_insert.cc43
-rw-r--r--sql/sql_load.cc16
-rw-r--r--sql/sql_parse.cc22
-rw-r--r--sql/sql_table.cc1
-rw-r--r--sql/sql_update.cc42
14 files changed, 136 insertions, 88 deletions
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 357b797ec75..a00dd6c505c 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -3732,7 +3732,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
{
m_transaction_on= FALSE;
/* Would be simpler if has_transactions() didn't always say "yes" */
- thd->no_trans_update.all= thd->no_trans_update.stmt= TRUE;
+ thd->transaction.all.modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table= TRUE;
}
else if (!thd->transaction.on)
m_transaction_on= FALSE;
diff --git a/sql/handler.cc b/sql/handler.cc
index 2285a190c8e..8ef14ce8906 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -833,7 +833,7 @@ int ha_rollback_trans(THD *thd, bool all)
the error log; but we don't want users to wonder why they have this
message in the error log, so we don't send it.
*/
- if (is_real_trans && thd->no_trans_update.all &&
+ if (is_real_trans && thd->transaction.all.modified_non_trans_table &&
!thd->slave_thread)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARNING_NOT_COMPLETE_ROLLBACK,
diff --git a/sql/handler.h b/sql/handler.h
index a3767573178..c44d7c7f846 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -420,6 +420,35 @@ typedef struct st_thd_trans
bool no_2pc;
/* storage engines that registered themselves for this transaction */
handlerton *ht[MAX_HA];
+ /*
+ The purpose of this flag is to keep track of non-transactional
+ tables that were modified in scope of:
+ - transaction, when the variable is a member of
+ THD::transaction.all
+ - top-level statement or sub-statement, when the variable is a
+ member of THD::transaction.stmt
+ This member has the following life cycle:
+ * stmt.modified_non_trans_table is used to keep track of
+ modified non-transactional tables of top-level statements. At
+ the end of the previous statement and at the beginning of the session,
+ it is reset to FALSE. If such functions
+ as mysql_insert, mysql_update, mysql_delete etc modify a
+ non-transactional table, they set this flag to TRUE. At the
+ end of the statement, the value of stmt.modified_non_trans_table
+ is merged with all.modified_non_trans_table and gets reset.
+ * all.modified_non_trans_table is reset at the end of transaction
+
+ * Since we do not have a dedicated context for execution of a
+ sub-statement, to keep track of non-transactional changes in a
+ sub-statement, we re-use stmt.modified_non_trans_table.
+ At entrance into a sub-statement, a copy of the value of
+ stmt.modified_non_trans_table (containing the changes of the
+ outer statement) is saved on stack. Then
+ stmt.modified_non_trans_table is reset to FALSE and the
+ substatement is executed. Then the new value is merged with the
+ saved value.
+ */
+ bool modified_non_trans_table;
} THD_TRANS;
enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
diff --git a/sql/log.cc b/sql/log.cc
index 6992f6c10ef..e9aa273676a 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -162,7 +162,7 @@ static int binlog_rollback(THD *thd, bool all)
table. Such cases should be rare (updating a
non-transactional table inside a transaction...)
*/
- if (unlikely(thd->no_trans_update.all))
+ if (unlikely(thd->transaction.all.modified_non_trans_table))
{
Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE);
qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
@@ -217,7 +217,7 @@ static int binlog_savepoint_rollback(THD *thd, void *sv)
non-transactional table. Otherwise, truncate the binlog cache starting
from the SAVEPOINT command.
*/
- if (unlikely(thd->no_trans_update.all))
+ if (unlikely(thd->transaction.all.modified_non_trans_table))
{
Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE);
DBUG_RETURN(mysql_bin_log.write(&qinfo));
diff --git a/sql/set_var.cc b/sql/set_var.cc
index b30aa008366..e1246617d84 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -2901,14 +2901,14 @@ static bool set_option_autocommit(THD *thd, set_var *var)
{
/* We changed to auto_commit mode */
thd->options&= ~(ulong) OPTION_BEGIN;
- thd->no_trans_update.all= FALSE;
+ thd->transaction.all.modified_non_trans_table= FALSE;
thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
if (ha_commit(thd))
return 1;
}
else
{
- thd->no_trans_update.all= FALSE;
+ thd->transaction.all.modified_non_trans_table= FALSE;
thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT;
}
}
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 8f4d407a5b0..5ad6625efb8 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -337,13 +337,13 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
bool save_abort_on_warning= thd->abort_on_warning;
- bool save_no_trans_update_stmt= thd->no_trans_update.stmt;
+ bool save_stmt_modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table;
thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
thd->abort_on_warning=
thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES);
- thd->no_trans_update.stmt= FALSE;
+ thd->transaction.stmt.modified_non_trans_table= FALSE;
/* Save the value in the field. Convert the value if needed. */
@@ -351,7 +351,7 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
thd->count_cuted_fields= save_count_cuted_fields;
thd->abort_on_warning= save_abort_on_warning;
- thd->no_trans_update.stmt= save_no_trans_update_stmt;
+ thd->transaction.stmt.modified_non_trans_table= save_stmt_modified_non_trans_table;
if (thd->net.report_error)
{
@@ -2400,7 +2400,13 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
bool open_tables, sp_instr* instr)
{
int res= 0;
-
+ /*
+ The flag is saved at the entry to the following substatement.
+ It's reset further in the common code part.
+ It's merged with the saved parent's value at the exit of this func.
+ */
+ bool parent_modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table;
+ thd->transaction.stmt.modified_non_trans_table= FALSE;
DBUG_ASSERT(!thd->derived_tables);
DBUG_ASSERT(thd->change_list.is_empty());
/*
@@ -2467,7 +2473,11 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
/* Update the state of the active arena. */
thd->stmt_arena->state= Query_arena::EXECUTED;
-
+ /*
+ Merge here with the saved parent's values
+ what is needed from the substatement gained
+ */
+ thd->transaction.stmt.modified_non_trans_table |= parent_modified_non_trans_table;
/*
Unlike for PS we should not call Item's destructors for newly created
items after execution of each instruction in stored routine. This is
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 0650d4ba8c9..2209dc157e3 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -340,7 +340,7 @@ void THD::init(void)
if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
options= thd_startup_options;
- no_trans_update.stmt= no_trans_update.all= FALSE;
+ transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= FALSE;
open_options=ha_open_options;
update_lock_default= (variables.low_priority_updates ?
TL_WRITE_LOW_PRIORITY :
diff --git a/sql/sql_class.h b/sql/sql_class.h
index ef719cdded7..1488c0c59c4 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1486,10 +1486,6 @@ public:
bool charset_is_system_charset, charset_is_collation_connection;
bool charset_is_character_set_filesystem;
bool enable_slow_log; /* enable slow log for current statement */
- struct {
- bool all:1;
- bool stmt:1;
- } no_trans_update;
bool abort_on_warning;
bool got_warning; /* Set on call to push_warning() */
bool no_warnings_for_error; /* no warnings on call to my_error() */
@@ -1740,7 +1736,7 @@ public:
inline bool really_abort_on_warning()
{
return (abort_on_warning &&
- (!no_trans_update.stmt ||
+ (!transaction.stmt.modified_non_trans_table ||
(variables.sql_mode & MODE_STRICT_ALL_TABLES)));
}
void set_status_var_init();
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index bccd4d4cafe..56edfa6c5b2 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -315,6 +315,9 @@ cleanup:
delete select;
transactional_table= table->file->has_transactions();
+ if (!transactional_table && deleted > 0)
+ thd->transaction.stmt.modified_non_trans_table= TRUE;
+
/* See similar binlogging code in sql_update.cc, for comments */
if ((error < 0) || (deleted && !transactional_table))
{
@@ -327,9 +330,10 @@ cleanup:
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
- 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;
}
+ DBUG_ASSERT(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table);
free_underlaid_joins(thd, select_lex);
if (transactional_table)
{
@@ -642,20 +646,22 @@ bool multi_delete::send_data(List<Item> &values)
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_BEFORE, FALSE))
- DBUG_RETURN(1);
+ DBUG_RETURN(1);
table->status|= STATUS_DELETED;
if (!(error=table->file->delete_row(table->record[0])))
{
- deleted++;
+ deleted++;
+ if (!table->file->has_transactions())
+ thd->transaction.stmt.modified_non_trans_table= TRUE;
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_AFTER, FALSE))
- DBUG_RETURN(1);
+ DBUG_RETURN(1);
}
else
{
- table->file->print_error(error,MYF(0));
- DBUG_RETURN(1);
+ table->file->print_error(error,MYF(0));
+ DBUG_RETURN(1);
}
}
else
@@ -705,6 +711,7 @@ void multi_delete::send_error(uint errcode,const char *err)
error= 1;
send_eof();
}
+ DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table);
DBUG_VOID_RETURN;
}
@@ -732,6 +739,7 @@ int multi_delete::do_deletes()
for (; table_being_deleted;
table_being_deleted= table_being_deleted->next_local, counter++)
{
+ ha_rows last_deleted= deleted;
TABLE *table = table_being_deleted->table;
if (tempfiles[counter]->get(table))
{
@@ -769,6 +777,8 @@ int multi_delete::do_deletes()
break;
}
}
+ if (last_deleted != deleted && !table->file->has_transactions())
+ thd->transaction.stmt.modified_non_trans_table= TRUE;
end_read_record(&info);
if (thd->killed && !local_error)
local_error= 1;
@@ -807,7 +817,6 @@ bool multi_delete::send_eof()
{
query_cache_invalidate3(thd, delete_tables, 1);
}
-
if ((local_error == 0) || (deleted && normal_tables))
{
if (mysql_bin_log.is_open())
@@ -819,9 +828,11 @@ bool multi_delete::send_eof()
if (mysql_bin_log.write(&qinfo) && !normal_tables)
local_error=1; // Log write failed: roll back the SQL statement
}
- if (!transactional_tables)
- thd->no_trans_update.all= TRUE;
+ if (thd->transaction.stmt.modified_non_trans_table)
+ thd->transaction.all.modified_non_trans_table= TRUE;
}
+ DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table);
+
/* Commit or rollback the current SQL statement */
if (transactional_tables)
if (ha_autocommit_or_rollback(thd,local_error > 0))
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 5ba1e766947..5edce08e481 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -733,7 +733,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
if (lock_type != TL_WRITE_DELAYED && !thd->prelocked_mode)
table->file->start_bulk_insert(values_list.elements);
- thd->no_trans_update.stmt= FALSE;
thd->abort_on_warning= (!ignore && (thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES |
MODE_STRICT_ALL_TABLES)));
@@ -907,10 +906,12 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
- if (!transactional_table && changed)
- thd->no_trans_update.all= TRUE;
+ if (thd->transaction.stmt.modified_non_trans_table)
+ thd->transaction.all.modified_non_trans_table= TRUE;
}
}
+ DBUG_ASSERT(transactional_table || !changed ||
+ thd->transaction.stmt.modified_non_trans_table);
if (transactional_table)
error=ha_autocommit_or_rollback(thd,error);
@@ -1311,7 +1312,7 @@ static int last_uniq_key(TABLE *table,uint keynr)
then both on update triggers will work instead. Similarly both on
delete triggers will be invoked if we will delete conflicting records.
- Sets thd->no_trans_update.stmt to TRUE if table which is updated didn't have
+ Sets thd->transaction.stmt.modified_non_trans_table to TRUE if table which is updated didn't have
transactions.
RETURN VALUE
@@ -1478,7 +1479,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
goto err;
info->deleted++;
if (!table->file->has_transactions())
- thd->no_trans_update.stmt= TRUE;
+ thd->transaction.stmt.modified_non_trans_table= TRUE;
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_AFTER, TRUE))
@@ -1510,7 +1511,7 @@ ok_or_after_trg_err:
if (key)
my_safe_afree(key,table->s->max_unique_length,MAX_KEY_LENGTH);
if (!table->file->has_transactions())
- thd->no_trans_update.stmt= TRUE;
+ thd->transaction.stmt.modified_non_trans_table= TRUE;
DBUG_RETURN(trg_error);
err:
@@ -2790,7 +2791,6 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
}
if (info.handle_duplicates == DUP_UPDATE)
table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
- thd->no_trans_update.stmt= FALSE;
thd->abort_on_warning= (!info.ignore &&
(thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES |
@@ -2927,7 +2927,8 @@ void select_insert::send_error(uint errcode,const char *err)
bool select_insert::send_eof()
{
- int error,error2;
+ int error, error2;
+ bool changed, transactional_table= table->file->has_transactions();
DBUG_ENTER("select_insert::send_eof");
error= (!thd->prelocked_mode) ? table->file->end_bulk_insert():0;
@@ -2939,12 +2940,14 @@ bool select_insert::send_eof()
and ha_autocommit_or_rollback
*/
- if (info.copied || info.deleted || info.updated)
+ if (changed= (info.copied || info.deleted || info.updated))
{
query_cache_invalidate3(thd, table, 1);
- if (!(table->file->has_transactions() || table->s->tmp_table))
- thd->no_trans_update.all= TRUE;
+ if (thd->transaction.stmt.modified_non_trans_table)
+ thd->transaction.all.modified_non_trans_table= TRUE;
}
+ DBUG_ASSERT(transactional_table || !changed ||
+ thd->transaction.stmt.modified_non_trans_table);
if (last_insert_id)
thd->insert_id(info.copied ? last_insert_id : 0); // For binary log
@@ -2954,7 +2957,7 @@ bool select_insert::send_eof()
if (!error)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- table->file->has_transactions(), FALSE);
+ transactional_table, FALSE);
mysql_bin_log.write(&qinfo);
}
if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error)
@@ -2980,6 +2983,7 @@ bool select_insert::send_eof()
void select_insert::abort()
{
+ bool changed, transactional_table;
DBUG_ENTER("select_insert::abort");
if (!table)
@@ -2990,6 +2994,7 @@ void select_insert::abort()
*/
DBUG_VOID_RETURN;
}
+ transactional_table= table->file->has_transactions();
if (!thd->prelocked_mode)
table->file->end_bulk_insert();
/*
@@ -2998,21 +3003,22 @@ void select_insert::abort()
error while inserting into a MyISAM table) we must write to the binlog (and
the error code will make the slave stop).
*/
- if ((info.copied || info.deleted || info.updated) &&
- !table->file->has_transactions())
+ if ((changed= info.copied || info.deleted || info.updated) &&
+ !transactional_table)
{
if (last_insert_id)
thd->insert_id(last_insert_id); // For binary log
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
- table->file->has_transactions(), FALSE);
+ transactional_table, FALSE);
mysql_bin_log.write(&qinfo);
}
- if (!table->s->tmp_table)
- thd->no_trans_update.all= TRUE;
+ if (thd->transaction.stmt.modified_non_trans_table)
+ thd->transaction.all.modified_non_trans_table= TRUE;
}
- if (info.copied || info.deleted || info.updated)
+ DBUG_ASSERT(transactional_table || !changed || thd->transaction.stmt.modified_non_trans_table);
+ if (changed)
{
query_cache_invalidate3(thd, table, 1);
}
@@ -3259,7 +3265,6 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
if (!thd->prelocked_mode)
table->file->start_bulk_insert((ha_rows) 0);
- thd->no_trans_update.stmt= FALSE;
thd->abort_on_warning= (!info.ignore &&
(thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES |
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 7b1799baaad..55cbbf1c540 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -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)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index ae3bc0f5597..7d723d3cd5b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -149,7 +149,7 @@ static bool end_active_trans(THD *thd)
if (ha_commit(thd))
error=1;
thd->options&= ~(ulong) OPTION_BEGIN;
- thd->no_trans_update.all= FALSE;
+ thd->transaction.all.modified_non_trans_table= FALSE;
}
DBUG_RETURN(error);
}
@@ -173,7 +173,7 @@ static bool begin_trans(THD *thd)
else
{
LEX *lex= thd->lex;
- thd->no_trans_update.all= FALSE;
+ thd->transaction.all.modified_non_trans_table= FALSE;
thd->options|= (ulong) OPTION_BEGIN;
thd->server_status|= SERVER_STATUS_IN_TRANS;
if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
@@ -1471,7 +1471,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion)
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
res= ha_commit(thd);
thd->options&= ~(ulong) OPTION_BEGIN;
- thd->no_trans_update.all= FALSE;
+ thd->transaction.all.modified_non_trans_table= FALSE;
break;
case COMMIT_RELEASE:
do_release= 1; /* fall through */
@@ -1489,7 +1489,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion)
if (ha_rollback(thd))
res= -1;
thd->options&= ~(ulong) OPTION_BEGIN;
- thd->no_trans_update.all= FALSE;
+ thd->transaction.all.modified_non_trans_table= FALSE;
if (!res && (completion == ROLLBACK_AND_CHAIN))
res= begin_trans(thd);
break;
@@ -2600,6 +2600,8 @@ mysql_execute_command(THD *thd)
statistic_increment(thd->status_var.com_stat[lex->sql_command],
&LOCK_status);
+ DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table == FALSE);
+
switch (lex->sql_command) {
case SQLCOM_SELECT:
{
@@ -2937,7 +2939,7 @@ mysql_execute_command(THD *thd)
else
{
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
- thd->no_trans_update.all= TRUE;
+ thd->transaction.all.modified_non_trans_table= TRUE;
}
DBUG_ASSERT(first_table == all_tables && first_table != 0);
bool link_to_local;
@@ -3720,7 +3722,7 @@ end_with_restore_list:
lex->drop_if_exists= 1;
/* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
- thd->no_trans_update.all= TRUE;
+ thd->transaction.all.modified_non_trans_table= TRUE;
}
/* DDL and binlog write order protected by LOCK_open */
res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
@@ -4322,7 +4324,7 @@ end_with_restore_list:
res= TRUE; // cannot happen
else
{
- if (thd->no_trans_update.all &&
+ if (thd->transaction.all.modified_non_trans_table &&
!thd->slave_thread)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARNING_NOT_COMPLETE_ROLLBACK,
@@ -4969,7 +4971,7 @@ create_sp_error:
thd->transaction.xid_state.xa_state=XA_ACTIVE;
thd->transaction.xid_state.xid.set(thd->lex->xid);
xid_cache_insert(&thd->transaction.xid_state);
- thd->no_trans_update.all= FALSE;
+ thd->transaction.all.modified_non_trans_table= FALSE;
thd->options|= (ulong) OPTION_BEGIN;
thd->server_status|= SERVER_STATUS_IN_TRANS;
send_ok(thd);
@@ -5064,7 +5066,7 @@ create_sp_error:
break;
}
thd->options&= ~(ulong) OPTION_BEGIN;
- thd->no_trans_update.all= FALSE;
+ thd->transaction.all.modified_non_trans_table= FALSE;
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
xid_cache_delete(&thd->transaction.xid_state);
thd->transaction.xid_state.xa_state=XA_NOTR;
@@ -5095,7 +5097,7 @@ create_sp_error:
else
send_ok(thd);
thd->options&= ~(ulong) OPTION_BEGIN;
- thd->no_trans_update.all= FALSE;
+ thd->transaction.all.modified_non_trans_table= FALSE;
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
xid_cache_delete(&thd->transaction.xid_state);
thd->transaction.xid_state.xa_state=XA_NOTR;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 7db79543016..d83100aa439 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4091,7 +4091,6 @@ copy_data_between_tables(TABLE *from,TABLE *to,
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
/* We can abort alter table for any table type */
- thd->no_trans_update.stmt= FALSE;
thd->abort_on_warning= !ignore && test(thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES |
MODE_STRICT_ALL_TABLES));
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index f4239afc4cd..c78e246f518 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -430,7 +430,6 @@ int mysql_update(THD *thd,
query_id=thd->query_id;
transactional_table= table->file->has_transactions();
- thd->no_trans_update.stmt= FALSE;
thd->abort_on_warning= test(!ignore &&
(thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES |
@@ -487,7 +486,6 @@ int mysql_update(THD *thd,
(byte*) table->record[0])))
{
updated++;
- thd->no_trans_update.stmt= !transactional_table;
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
@@ -522,6 +520,10 @@ int mysql_update(THD *thd,
thd->row_count++;
}
+ if (!transactional_table && updated > 0)
+ thd->transaction.stmt.modified_non_trans_table= TRUE;
+
+
/*
todo bug#27571: to avoid asynchronization of `error' and
`error_code' of binlog event constructor
@@ -589,9 +591,10 @@ int mysql_update(THD *thd,
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1; // Rollback update
}
- 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;
}
+ DBUG_ASSERT(transactional_table || !updated || thd->transaction.stmt.modified_non_trans_table);
free_underlaid_joins(thd, select_lex);
if (transactional_table)
{
@@ -955,7 +958,6 @@ bool mysql_multi_update(THD *thd,
handle_duplicates, ignore)))
DBUG_RETURN(TRUE);
- thd->no_trans_update.stmt= FALSE;
thd->abort_on_warning= test(thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES |
MODE_STRICT_ALL_TABLES));
@@ -1331,9 +1333,8 @@ multi_update::~multi_update()
if (copy_field)
delete [] copy_field;
thd->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting
- if (!trans_safe) // todo: remove since redundant
- thd->no_trans_update.all= TRUE;
- DBUG_ASSERT(trans_safe || thd->no_trans_update.all);
+ DBUG_ASSERT(trans_safe || !updated ||
+ thd->transaction.all.modified_non_trans_table);
}
@@ -1426,7 +1427,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
else
{
trans_safe= 0;
- thd->no_trans_update.stmt= TRUE;
+ thd->transaction.stmt.modified_non_trans_table= TRUE;
}
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
@@ -1489,7 +1490,6 @@ void multi_update::send_error(uint errcode,const char *err)
/* Something already updated so we have to invalidate cache */
query_cache_invalidate3(thd, update_tables, 1);
-
/*
If all tables that has been updated are trans safe then just do rollback.
If not attempt to do remaining updates.
@@ -1502,7 +1502,7 @@ void multi_update::send_error(uint errcode,const char *err)
}
else
{
- DBUG_ASSERT(thd->no_trans_update.stmt);
+ DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table);
if (do_update && table_count > 1)
{
/* Add warning here */
@@ -1513,7 +1513,7 @@ void multi_update::send_error(uint errcode,const char *err)
VOID(do_updates(0));
}
}
- if (thd->no_trans_update.stmt)
+ if (thd->transaction.stmt.modified_non_trans_table)
{
/*
The query has to binlog because there's a modified non-transactional table
@@ -1526,9 +1526,9 @@ void multi_update::send_error(uint errcode,const char *err)
mysql_bin_log.write(&qinfo);
}
if (!trans_safe)
- thd->no_trans_update.all= TRUE;
+ thd->transaction.all.modified_non_trans_table= TRUE;
}
- DBUG_ASSERT(trans_safe || !updated || thd->no_trans_update.stmt);
+ DBUG_ASSERT(trans_safe || !updated || thd->transaction.stmt.modified_non_trans_table);
if (transactional_tables)
{
@@ -1664,7 +1664,7 @@ int multi_update::do_updates(bool from_send_error)
else
{
trans_safe= 0; // Can't do safe rollback
- thd->no_trans_update.stmt= TRUE;
+ thd->transaction.stmt.modified_non_trans_table= TRUE;
}
}
(void) table->file->ha_rnd_end();
@@ -1697,7 +1697,7 @@ err2:
else
{
trans_safe= 0;
- thd->no_trans_update.stmt= TRUE;
+ thd->transaction.stmt.modified_non_trans_table= TRUE;
}
}
DBUG_RETURN(1);
@@ -1722,7 +1722,6 @@ bool multi_update::send_eof()
{
query_cache_invalidate3(thd, update_tables, 1);
}
-
/*
Write the SQL statement to the binlog if we updated
rows and we succeeded or if we updated some non
@@ -1732,8 +1731,9 @@ bool multi_update::send_eof()
either from the query's list or via a stored routine: bug#13270,23333
*/
- DBUG_ASSERT(trans_safe || !updated || thd->no_trans_update.stmt);
- if (local_error == 0 || thd->no_trans_update.stmt)
+ DBUG_ASSERT(trans_safe || !updated ||
+ thd->transaction.stmt.modified_non_trans_table);
+ if (local_error == 0 || thd->transaction.stmt.modified_non_trans_table)
{
if (mysql_bin_log.is_open())
{
@@ -1746,8 +1746,8 @@ bool multi_update::send_eof()
if (mysql_bin_log.write(&qinfo) && trans_safe)
local_error= 1; // Rollback update
}
- if (!trans_safe)
- thd->no_trans_update.all= TRUE;
+ if (thd->transaction.stmt.modified_non_trans_table)
+ thd->transaction.all.modified_non_trans_table= TRUE;
}
if (transactional_tables)