(Pushing for Andrei)
Merge magare.gmz:/home/kgeorge/mysql/work/B27417-5.0-opt into magare.gmz:/home/kgeorge/mysql/work/B27417-5.1-opt mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result: Auto merged sql/ha_ndbcluster.cc: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_table.cc: Auto merged mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test: merge of bug 27471 from 5.0-opt to 5.1-opt sql/log.cc: merge of bug 27471 from 5.0-opt to 5.1-opt sql/set_var.cc: merge of bug 27471 from 5.0-opt to 5.1-opt sql/sp_head.cc: merge of bug 27471 from 5.0-opt to 5.1-opt sql/sql_delete.cc: merge of bug 27471 from 5.0-opt to 5.1-opt sql/sql_insert.cc: merge of bug 27471 from 5.0-opt to 5.1-opt sql/sql_load.cc: merge of bug 27471 from 5.0-opt to 5.1-opt sql/sql_parse.cc: merge of bug 27471 from 5.0-opt to 5.1-opt sql/sql_update.cc: merge of bug 27471 from 5.0-opt to 5.1-opt
This commit is contained in:
commit
e5fd6b3c71
@ -316,3 +316,121 @@ disconnect con3;
|
|||||||
connection con4;
|
connection con4;
|
||||||
select get_lock("a",10); # wait for rollback to finish
|
select get_lock("a",10); # wait for rollback to finish
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack
|
||||||
|
# bug #28960 non-trans temp table changes with insert .. select
|
||||||
|
# not binlogged after rollback
|
||||||
|
#
|
||||||
|
# testing appearence of insert into temp_table in binlog.
|
||||||
|
# There are two branches of execution that require different setup.
|
||||||
|
|
||||||
|
## send_eof() branch
|
||||||
|
|
||||||
|
# prepare
|
||||||
|
|
||||||
|
create temporary table tt (a int unique);
|
||||||
|
create table ti (a int) engine=innodb;
|
||||||
|
reset master;
|
||||||
|
show master status;
|
||||||
|
|
||||||
|
# action
|
||||||
|
|
||||||
|
begin;
|
||||||
|
insert into ti values (1);
|
||||||
|
insert into ti values (2) ;
|
||||||
|
insert into tt select * from ti;
|
||||||
|
rollback;
|
||||||
|
|
||||||
|
# check
|
||||||
|
|
||||||
|
select count(*) from tt /* 2 */;
|
||||||
|
show master status;
|
||||||
|
--replace_column 2 # 5 #
|
||||||
|
show binlog events from 98;
|
||||||
|
select count(*) from ti /* zero */;
|
||||||
|
insert into ti select * from tt;
|
||||||
|
select * from ti /* that is what slave would miss - a bug */;
|
||||||
|
|
||||||
|
|
||||||
|
## send_error() branch
|
||||||
|
delete from ti;
|
||||||
|
delete from tt where a=1;
|
||||||
|
reset master;
|
||||||
|
show master status;
|
||||||
|
|
||||||
|
# action
|
||||||
|
|
||||||
|
begin;
|
||||||
|
insert into ti values (1);
|
||||||
|
insert into ti values (2) /* to make the dup error in the following */;
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
insert into tt select * from ti /* one affected and error */;
|
||||||
|
rollback;
|
||||||
|
|
||||||
|
# check
|
||||||
|
|
||||||
|
show master status;
|
||||||
|
--replace_column 2 # 5 #
|
||||||
|
show binlog events from 98;
|
||||||
|
select count(*) from ti /* zero */;
|
||||||
|
insert into ti select * from tt;
|
||||||
|
select * from tt /* that is what otherwise slave missed - the bug */;
|
||||||
|
|
||||||
|
drop table ti;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack
|
||||||
|
#
|
||||||
|
# Testing asserts: if there is a side effect of modifying non-transactional
|
||||||
|
# table thd->no_trans_update.stmt must be TRUE;
|
||||||
|
# the assert is active with debug build
|
||||||
|
#
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop function if exists bug27417;
|
||||||
|
drop table if exists t1,t2;
|
||||||
|
--enable_warnings
|
||||||
|
# side effect table
|
||||||
|
CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM;
|
||||||
|
# target tables
|
||||||
|
CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a));
|
||||||
|
|
||||||
|
delimiter |;
|
||||||
|
create function bug27417(n int)
|
||||||
|
RETURNS int(11)
|
||||||
|
begin
|
||||||
|
insert into t1 values (null);
|
||||||
|
return n;
|
||||||
|
end|
|
||||||
|
delimiter ;|
|
||||||
|
|
||||||
|
reset master;
|
||||||
|
|
||||||
|
# execute
|
||||||
|
|
||||||
|
insert into t2 values (bug27417(1));
|
||||||
|
insert into t2 select bug27417(2);
|
||||||
|
reset master;
|
||||||
|
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
insert into t2 values (bug27417(2));
|
||||||
|
show master status; /* only (!) with fixes for #23333 will show there is the query */;
|
||||||
|
select count(*) from t1 /* must be 3 */;
|
||||||
|
|
||||||
|
reset master;
|
||||||
|
select count(*) from t2;
|
||||||
|
delete from t2 where a=bug27417(3);
|
||||||
|
select count(*) from t2 /* nothing got deleted */;
|
||||||
|
show master status; /* the query must be in regardless of #23333 */;
|
||||||
|
select count(*) from t1 /* must be 5 */;
|
||||||
|
|
||||||
|
--enable_info
|
||||||
|
delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */;
|
||||||
|
--disable_info
|
||||||
|
select count(*) from t1 /* must be 7 */;
|
||||||
|
|
||||||
|
drop function bug27417;
|
||||||
|
drop table t1,t2;
|
||||||
|
|
||||||
|
--echo end of tests
|
||||||
|
@ -380,3 +380,116 @@ select
|
|||||||
@a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%" @a not like "%#%error_code=%error_code=%"
|
@a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%" @a not like "%#%error_code=%error_code=%"
|
||||||
1 1
|
1 1
|
||||||
drop table t1, t2;
|
drop table t1, t2;
|
||||||
|
create temporary table tt (a int unique);
|
||||||
|
create table ti (a int) engine=innodb;
|
||||||
|
reset master;
|
||||||
|
show master status;
|
||||||
|
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||||
|
master-bin.000001 98
|
||||||
|
begin;
|
||||||
|
insert into ti values (1);
|
||||||
|
insert into ti values (2) ;
|
||||||
|
insert into tt select * from ti;
|
||||||
|
rollback;
|
||||||
|
Warnings:
|
||||||
|
Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
||||||
|
select count(*) from tt /* 2 */;
|
||||||
|
count(*)
|
||||||
|
2
|
||||||
|
show master status;
|
||||||
|
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||||
|
master-bin.000001 507
|
||||||
|
show binlog events from 98;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||||
|
master-bin.000001 # Query 1 # use `test`; insert into ti values (1)
|
||||||
|
master-bin.000001 # Query 1 # use `test`; insert into ti values (2)
|
||||||
|
master-bin.000001 # Query 1 # use `test`; insert into tt select * from ti
|
||||||
|
master-bin.000001 # Query 1 # use `test`; ROLLBACK
|
||||||
|
select count(*) from ti /* zero */;
|
||||||
|
count(*)
|
||||||
|
0
|
||||||
|
insert into ti select * from tt;
|
||||||
|
select * from ti /* that is what slave would miss - a bug */;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
2
|
||||||
|
delete from ti;
|
||||||
|
delete from tt where a=1;
|
||||||
|
reset master;
|
||||||
|
show master status;
|
||||||
|
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||||
|
master-bin.000001 98
|
||||||
|
begin;
|
||||||
|
insert into ti values (1);
|
||||||
|
insert into ti values (2) /* to make the dup error in the following */;
|
||||||
|
insert into tt select * from ti /* one affected and error */;
|
||||||
|
ERROR 23000: Duplicate entry '2' for key 1
|
||||||
|
rollback;
|
||||||
|
Warnings:
|
||||||
|
Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
||||||
|
show master status;
|
||||||
|
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||||
|
master-bin.000001 581
|
||||||
|
show binlog events from 98;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||||
|
master-bin.000001 # Query 1 # use `test`; insert into ti values (1)
|
||||||
|
master-bin.000001 # Query 1 # use `test`; insert into ti values (2) /* to make the dup error in the following */
|
||||||
|
master-bin.000001 # Query 1 # use `test`; insert into tt select * from ti /* one affected and error */
|
||||||
|
master-bin.000001 # Query 1 # use `test`; ROLLBACK
|
||||||
|
select count(*) from ti /* zero */;
|
||||||
|
count(*)
|
||||||
|
0
|
||||||
|
insert into ti select * from tt;
|
||||||
|
select * from tt /* that is what otherwise slave missed - the bug */;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
2
|
||||||
|
drop table ti;
|
||||||
|
drop function if exists bug27417;
|
||||||
|
drop table if exists t1,t2;
|
||||||
|
CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM;
|
||||||
|
CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a));
|
||||||
|
create function bug27417(n int)
|
||||||
|
RETURNS int(11)
|
||||||
|
begin
|
||||||
|
insert into t1 values (null);
|
||||||
|
return n;
|
||||||
|
end|
|
||||||
|
reset master;
|
||||||
|
insert into t2 values (bug27417(1));
|
||||||
|
insert into t2 select bug27417(2);
|
||||||
|
reset master;
|
||||||
|
insert into t2 values (bug27417(2));
|
||||||
|
ERROR 23000: Duplicate entry '2' for key 1
|
||||||
|
show master status;
|
||||||
|
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||||
|
master-bin.000001 98
|
||||||
|
/* only (!) with fixes for #23333 will show there is the query */;
|
||||||
|
select count(*) from t1 /* must be 3 */;
|
||||||
|
count(*)
|
||||||
|
3
|
||||||
|
reset master;
|
||||||
|
select count(*) from t2;
|
||||||
|
count(*)
|
||||||
|
2
|
||||||
|
delete from t2 where a=bug27417(3);
|
||||||
|
select count(*) from t2 /* nothing got deleted */;
|
||||||
|
count(*)
|
||||||
|
2
|
||||||
|
show master status;
|
||||||
|
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||||
|
master-bin.000001 195
|
||||||
|
/* the query must be in regardless of #23333 */;
|
||||||
|
select count(*) from t1 /* must be 5 */;
|
||||||
|
count(*)
|
||||||
|
5
|
||||||
|
delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */;
|
||||||
|
affected rows: 0
|
||||||
|
select count(*) from t1 /* must be 7 */;
|
||||||
|
count(*)
|
||||||
|
7
|
||||||
|
drop function bug27417;
|
||||||
|
drop table t1,t2;
|
||||||
|
end of tests
|
||||||
|
@ -4366,7 +4366,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
|
|||||||
{
|
{
|
||||||
m_transaction_on= FALSE;
|
m_transaction_on= FALSE;
|
||||||
/* Would be simpler if has_transactions() didn't always say "yes" */
|
/* 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)
|
else if (!thd->transaction.on)
|
||||||
m_transaction_on= FALSE;
|
m_transaction_on= FALSE;
|
||||||
|
@ -860,7 +860,7 @@ int ha_rollback_trans(THD *thd, bool all)
|
|||||||
the error log; but we don't want users to wonder why they have this
|
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.
|
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 && thd->killed != THD::KILL_CONNECTION)
|
!thd->slave_thread && thd->killed != THD::KILL_CONNECTION)
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
ER_WARNING_NOT_COMPLETE_ROLLBACK,
|
ER_WARNING_NOT_COMPLETE_ROLLBACK,
|
||||||
|
@ -728,6 +728,35 @@ typedef struct st_thd_trans
|
|||||||
bool no_2pc;
|
bool no_2pc;
|
||||||
/* storage engines that registered themselves for this transaction */
|
/* storage engines that registered themselves for this transaction */
|
||||||
handlerton *ht[MAX_HA];
|
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;
|
} THD_TRANS;
|
||||||
|
|
||||||
enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
|
enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
|
||||||
|
@ -1609,7 +1609,8 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
|
|||||||
table. Such cases should be rare (updating a
|
table. Such cases should be rare (updating a
|
||||||
non-transactional table inside a transaction...)
|
non-transactional table inside a transaction...)
|
||||||
*/
|
*/
|
||||||
if (unlikely(thd->no_trans_update.all || (thd->options & OPTION_KEEP_LOG)))
|
if (unlikely(thd->transaction.all.modified_non_trans_table ||
|
||||||
|
(thd->options & OPTION_KEEP_LOG)))
|
||||||
{
|
{
|
||||||
Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE);
|
Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE);
|
||||||
qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
|
qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
|
||||||
@ -1663,7 +1664,8 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
|
|||||||
non-transactional table. Otherwise, truncate the binlog cache starting
|
non-transactional table. Otherwise, truncate the binlog cache starting
|
||||||
from the SAVEPOINT command.
|
from the SAVEPOINT command.
|
||||||
*/
|
*/
|
||||||
if (unlikely(thd->no_trans_update.all || (thd->options & OPTION_KEEP_LOG)))
|
if (unlikely(thd->transaction.all.modified_non_trans_table ||
|
||||||
|
(thd->options & OPTION_KEEP_LOG)))
|
||||||
{
|
{
|
||||||
int error=
|
int error=
|
||||||
thd->binlog_query(THD::STMT_QUERY_TYPE,
|
thd->binlog_query(THD::STMT_QUERY_TYPE,
|
||||||
@ -4094,6 +4096,7 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
|
|||||||
/* NULL would represent nothing to replicate after ROLLBACK */
|
/* NULL would represent nothing to replicate after ROLLBACK */
|
||||||
DBUG_ASSERT(commit_event != NULL);
|
DBUG_ASSERT(commit_event != NULL);
|
||||||
|
|
||||||
|
DBUG_ASSERT(is_open());
|
||||||
if (likely(is_open())) // Should always be true
|
if (likely(is_open())) // Should always be true
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -2564,14 +2564,14 @@ static bool set_option_autocommit(THD *thd, set_var *var)
|
|||||||
{
|
{
|
||||||
/* We changed to auto_commit mode */
|
/* We changed to auto_commit mode */
|
||||||
thd->options&= ~(ulonglong) (OPTION_BEGIN | OPTION_KEEP_LOG);
|
thd->options&= ~(ulonglong) (OPTION_BEGIN | OPTION_KEEP_LOG);
|
||||||
thd->no_trans_update.all= FALSE;
|
thd->transaction.all.modified_non_trans_table= FALSE;
|
||||||
thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
|
thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
|
||||||
if (ha_commit(thd))
|
if (ha_commit(thd))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
thd->no_trans_update.all= FALSE;
|
thd->transaction.all.modified_non_trans_table= FALSE;
|
||||||
thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT;
|
thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -349,13 +349,13 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
|
|||||||
|
|
||||||
enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
|
enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
|
||||||
bool save_abort_on_warning= thd->abort_on_warning;
|
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->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
|
||||||
thd->abort_on_warning=
|
thd->abort_on_warning=
|
||||||
thd->variables.sql_mode &
|
thd->variables.sql_mode &
|
||||||
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES);
|
(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. */
|
/* Save the value in the field. Convert the value if needed. */
|
||||||
|
|
||||||
@ -363,7 +363,7 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
|
|||||||
|
|
||||||
thd->count_cuted_fields= save_count_cuted_fields;
|
thd->count_cuted_fields= save_count_cuted_fields;
|
||||||
thd->abort_on_warning= save_abort_on_warning;
|
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)
|
if (thd->net.report_error)
|
||||||
{
|
{
|
||||||
@ -2547,6 +2547,13 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
|
|||||||
int res= 0;
|
int res= 0;
|
||||||
DBUG_ENTER("reset_lex_and_exec_core");
|
DBUG_ENTER("reset_lex_and_exec_core");
|
||||||
|
|
||||||
|
/*
|
||||||
|
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->derived_tables);
|
||||||
DBUG_ASSERT(thd->change_list.is_empty());
|
DBUG_ASSERT(thd->change_list.is_empty());
|
||||||
/*
|
/*
|
||||||
@ -2616,7 +2623,11 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
|
|||||||
/* Update the state of the active arena. */
|
/* Update the state of the active arena. */
|
||||||
thd->stmt_arena->state= Query_arena::EXECUTED;
|
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
|
Unlike for PS we should not call Item's destructors for newly created
|
||||||
items after execution of each instruction in stored routine. This is
|
items after execution of each instruction in stored routine. This is
|
||||||
|
@ -582,7 +582,7 @@ void THD::init(void)
|
|||||||
if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
|
if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
|
||||||
server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
|
server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
|
||||||
options= thd_startup_options;
|
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;
|
open_options=ha_open_options;
|
||||||
update_lock_default= (variables.low_priority_updates ?
|
update_lock_default= (variables.low_priority_updates ?
|
||||||
TL_WRITE_LOW_PRIORITY :
|
TL_WRITE_LOW_PRIORITY :
|
||||||
|
@ -1409,10 +1409,6 @@ public:
|
|||||||
bool charset_is_system_charset, charset_is_collation_connection;
|
bool charset_is_system_charset, charset_is_collation_connection;
|
||||||
bool charset_is_character_set_filesystem;
|
bool charset_is_character_set_filesystem;
|
||||||
bool enable_slow_log; /* enable slow log for current statement */
|
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 abort_on_warning;
|
||||||
bool got_warning; /* Set on call to push_warning() */
|
bool got_warning; /* Set on call to push_warning() */
|
||||||
bool no_warnings_for_error; /* no warnings on call to my_error() */
|
bool no_warnings_for_error; /* no warnings on call to my_error() */
|
||||||
@ -1699,7 +1695,7 @@ public:
|
|||||||
inline bool really_abort_on_warning()
|
inline bool really_abort_on_warning()
|
||||||
{
|
{
|
||||||
return (abort_on_warning &&
|
return (abort_on_warning &&
|
||||||
(!no_trans_update.stmt ||
|
(!transaction.stmt.modified_non_trans_table ||
|
||||||
(variables.sql_mode & MODE_STRICT_ALL_TABLES)));
|
(variables.sql_mode & MODE_STRICT_ALL_TABLES)));
|
||||||
}
|
}
|
||||||
void set_status_var_init();
|
void set_status_var_init();
|
||||||
|
@ -341,6 +341,9 @@ cleanup:
|
|||||||
delete select;
|
delete select;
|
||||||
transactional_table= table->file->has_transactions();
|
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 */
|
/* See similar binlogging code in sql_update.cc, for comments */
|
||||||
if ((error < 0) || (deleted && !transactional_table))
|
if ((error < 0) || (deleted && !transactional_table))
|
||||||
{
|
{
|
||||||
@ -364,9 +367,10 @@ cleanup:
|
|||||||
error=1;
|
error=1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!transactional_table)
|
if (thd->transaction.stmt.modified_non_trans_table)
|
||||||
thd->no_trans_update.all= TRUE;
|
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);
|
free_underlaid_joins(thd, select_lex);
|
||||||
if (transactional_table)
|
if (transactional_table)
|
||||||
{
|
{
|
||||||
@ -677,20 +681,22 @@ bool multi_delete::send_data(List<Item> &values)
|
|||||||
if (table->triggers &&
|
if (table->triggers &&
|
||||||
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
|
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
|
||||||
TRG_ACTION_BEFORE, FALSE))
|
TRG_ACTION_BEFORE, FALSE))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
table->status|= STATUS_DELETED;
|
table->status|= STATUS_DELETED;
|
||||||
if (!(error=table->file->ha_delete_row(table->record[0])))
|
if (!(error=table->file->ha_delete_row(table->record[0])))
|
||||||
{
|
{
|
||||||
deleted++;
|
deleted++;
|
||||||
|
if (!table->file->has_transactions())
|
||||||
|
thd->transaction.stmt.modified_non_trans_table= TRUE;
|
||||||
if (table->triggers &&
|
if (table->triggers &&
|
||||||
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
|
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
|
||||||
TRG_ACTION_AFTER, FALSE))
|
TRG_ACTION_AFTER, FALSE))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
table->file->print_error(error,MYF(0));
|
table->file->print_error(error,MYF(0));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -740,6 +746,7 @@ void multi_delete::send_error(uint errcode,const char *err)
|
|||||||
error= 1;
|
error= 1;
|
||||||
send_eof();
|
send_eof();
|
||||||
}
|
}
|
||||||
|
DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -768,6 +775,7 @@ int multi_delete::do_deletes()
|
|||||||
for (; table_being_deleted;
|
for (; table_being_deleted;
|
||||||
table_being_deleted= table_being_deleted->next_local, counter++)
|
table_being_deleted= table_being_deleted->next_local, counter++)
|
||||||
{
|
{
|
||||||
|
ha_rows last_deleted= deleted;
|
||||||
TABLE *table = table_being_deleted->table;
|
TABLE *table = table_being_deleted->table;
|
||||||
if (tempfiles[counter]->get(table))
|
if (tempfiles[counter]->get(table))
|
||||||
{
|
{
|
||||||
@ -814,6 +822,8 @@ int multi_delete::do_deletes()
|
|||||||
table->file->print_error(local_error,MYF(0));
|
table->file->print_error(local_error,MYF(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (last_deleted != deleted && !table->file->has_transactions())
|
||||||
|
thd->transaction.stmt.modified_non_trans_table= TRUE;
|
||||||
end_read_record(&info);
|
end_read_record(&info);
|
||||||
if (thd->killed && !local_error)
|
if (thd->killed && !local_error)
|
||||||
local_error= 1;
|
local_error= 1;
|
||||||
@ -852,7 +862,6 @@ bool multi_delete::send_eof()
|
|||||||
{
|
{
|
||||||
query_cache_invalidate3(thd, delete_tables, 1);
|
query_cache_invalidate3(thd, delete_tables, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((local_error == 0) || (deleted && normal_tables))
|
if ((local_error == 0) || (deleted && normal_tables))
|
||||||
{
|
{
|
||||||
if (mysql_bin_log.is_open())
|
if (mysql_bin_log.is_open())
|
||||||
@ -867,9 +876,11 @@ bool multi_delete::send_eof()
|
|||||||
local_error=1; // Log write failed: roll back the SQL statement
|
local_error=1; // Log write failed: roll back the SQL statement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!transactional_tables)
|
if (thd->transaction.stmt.modified_non_trans_table)
|
||||||
thd->no_trans_update.all= TRUE;
|
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 */
|
/* Commit or rollback the current SQL statement */
|
||||||
if (transactional_tables)
|
if (transactional_tables)
|
||||||
if (ha_autocommit_or_rollback(thd,local_error > 0))
|
if (ha_autocommit_or_rollback(thd,local_error > 0))
|
||||||
|
@ -713,7 +713,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
if (lock_type != TL_WRITE_DELAYED && !thd->prelocked_mode)
|
if (lock_type != TL_WRITE_DELAYED && !thd->prelocked_mode)
|
||||||
table->file->ha_start_bulk_insert(values_list.elements);
|
table->file->ha_start_bulk_insert(values_list.elements);
|
||||||
|
|
||||||
thd->no_trans_update.stmt= FALSE;
|
|
||||||
thd->abort_on_warning= (!ignore && (thd->variables.sql_mode &
|
thd->abort_on_warning= (!ignore && (thd->variables.sql_mode &
|
||||||
(MODE_STRICT_TRANS_TABLES |
|
(MODE_STRICT_TRANS_TABLES |
|
||||||
MODE_STRICT_ALL_TABLES)));
|
MODE_STRICT_ALL_TABLES)));
|
||||||
@ -883,10 +882,12 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
error=1;
|
error=1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!transactional_table && changed)
|
if (thd->transaction.stmt.modified_non_trans_table)
|
||||||
thd->no_trans_update.all= TRUE;
|
thd->transaction.all.modified_non_trans_table= TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DBUG_ASSERT(transactional_table || !changed ||
|
||||||
|
thd->transaction.stmt.modified_non_trans_table);
|
||||||
if (transactional_table)
|
if (transactional_table)
|
||||||
error=ha_autocommit_or_rollback(thd,error);
|
error=ha_autocommit_or_rollback(thd,error);
|
||||||
|
|
||||||
@ -1296,7 +1297,7 @@ static int last_uniq_key(TABLE *table,uint keynr)
|
|||||||
then both on update triggers will work instead. Similarly both on
|
then both on update triggers will work instead. Similarly both on
|
||||||
delete triggers will be invoked if we will delete conflicting records.
|
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.
|
transactions.
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
@ -1516,7 +1517,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||||||
goto err;
|
goto err;
|
||||||
info->deleted++;
|
info->deleted++;
|
||||||
if (!table->file->has_transactions())
|
if (!table->file->has_transactions())
|
||||||
thd->no_trans_update.stmt= TRUE;
|
thd->transaction.stmt.modified_non_trans_table= TRUE;
|
||||||
if (table->triggers &&
|
if (table->triggers &&
|
||||||
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
|
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
|
||||||
TRG_ACTION_AFTER, TRUE))
|
TRG_ACTION_AFTER, TRUE))
|
||||||
@ -1557,7 +1558,7 @@ ok_or_after_trg_err:
|
|||||||
if (key)
|
if (key)
|
||||||
my_safe_afree(key,table->s->max_unique_length,MAX_KEY_LENGTH);
|
my_safe_afree(key,table->s->max_unique_length,MAX_KEY_LENGTH);
|
||||||
if (!table->file->has_transactions())
|
if (!table->file->has_transactions())
|
||||||
thd->no_trans_update.stmt= TRUE;
|
thd->transaction.stmt.modified_non_trans_table= TRUE;
|
||||||
DBUG_RETURN(trg_error);
|
DBUG_RETURN(trg_error);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@ -2922,7 +2923,6 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||||||
table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
|
table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
|
||||||
if (info.handle_duplicates == DUP_UPDATE)
|
if (info.handle_duplicates == DUP_UPDATE)
|
||||||
table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
|
table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
|
||||||
thd->no_trans_update.stmt= FALSE;
|
|
||||||
thd->abort_on_warning= (!info.ignore &&
|
thd->abort_on_warning= (!info.ignore &&
|
||||||
(thd->variables.sql_mode &
|
(thd->variables.sql_mode &
|
||||||
(MODE_STRICT_TRANS_TABLES |
|
(MODE_STRICT_TRANS_TABLES |
|
||||||
@ -3071,6 +3071,7 @@ bool select_insert::send_eof()
|
|||||||
int error;
|
int error;
|
||||||
bool const trans_table= table->file->has_transactions();
|
bool const trans_table= table->file->has_transactions();
|
||||||
ulonglong id;
|
ulonglong id;
|
||||||
|
bool changed;
|
||||||
DBUG_ENTER("select_insert::send_eof");
|
DBUG_ENTER("select_insert::send_eof");
|
||||||
DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'",
|
DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'",
|
||||||
trans_table, table->file->table_type()));
|
trans_table, table->file->table_type()));
|
||||||
@ -3079,24 +3080,18 @@ bool select_insert::send_eof()
|
|||||||
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||||
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
|
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
|
||||||
|
|
||||||
if (info.copied || info.deleted || info.updated)
|
if (changed= (info.copied || info.deleted || info.updated))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We must invalidate the table in the query cache before binlog writing
|
We must invalidate the table in the query cache before binlog writing
|
||||||
and ha_autocommit_or_rollback.
|
and ha_autocommit_or_rollback.
|
||||||
*/
|
*/
|
||||||
query_cache_invalidate3(thd, table, 1);
|
query_cache_invalidate3(thd, table, 1);
|
||||||
/*
|
if (thd->transaction.stmt.modified_non_trans_table)
|
||||||
Mark that we have done permanent changes if all of the below is true
|
thd->transaction.all.modified_non_trans_table= TRUE;
|
||||||
- Table doesn't support transactions
|
}
|
||||||
- It's a normal (not temporary) table. (Changes to temporary tables
|
DBUG_ASSERT(trans_table || !changed ||
|
||||||
are not logged in RBR)
|
thd->transaction.stmt.modified_non_trans_table);
|
||||||
- We are using statement based replication
|
|
||||||
*/
|
|
||||||
if (!trans_table &&
|
|
||||||
(!table->s->tmp_table || !thd->current_stmt_binlog_row_based))
|
|
||||||
thd->no_trans_update.all= TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Write to binlog before commiting transaction. No statement will
|
Write to binlog before commiting transaction. No statement will
|
||||||
@ -3517,7 +3512,6 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||||||
table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
|
table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
|
||||||
if (!thd->prelocked_mode)
|
if (!thd->prelocked_mode)
|
||||||
table->file->ha_start_bulk_insert((ha_rows) 0);
|
table->file->ha_start_bulk_insert((ha_rows) 0);
|
||||||
thd->no_trans_update.stmt= FALSE;
|
|
||||||
thd->abort_on_warning= (!info.ignore &&
|
thd->abort_on_warning= (!info.ignore &&
|
||||||
(thd->variables.sql_mode &
|
(thd->variables.sql_mode &
|
||||||
(MODE_STRICT_TRANS_TABLES |
|
(MODE_STRICT_TRANS_TABLES |
|
||||||
|
@ -376,7 +376,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
table->file->ha_start_bulk_insert((ha_rows) 0);
|
table->file->ha_start_bulk_insert((ha_rows) 0);
|
||||||
table->copy_blobs=1;
|
table->copy_blobs=1;
|
||||||
|
|
||||||
thd->no_trans_update.stmt= FALSE;
|
|
||||||
thd->abort_on_warning= (!ignore &&
|
thd->abort_on_warning= (!ignore &&
|
||||||
(thd->variables.sql_mode &
|
(thd->variables.sql_mode &
|
||||||
(MODE_STRICT_TRANS_TABLES |
|
(MODE_STRICT_TRANS_TABLES |
|
||||||
@ -410,7 +409,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
ha_autocommit_...
|
ha_autocommit_...
|
||||||
*/
|
*/
|
||||||
query_cache_invalidate3(thd, table_list, 0);
|
query_cache_invalidate3(thd, table_list, 0);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
if (read_file_from_client)
|
if (read_file_from_client)
|
||||||
@ -469,8 +467,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,
|
sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted,
|
||||||
(ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
|
(ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
|
||||||
|
|
||||||
if (!transactional_table)
|
if (thd->transaction.stmt.modified_non_trans_table)
|
||||||
thd->no_trans_update.all= TRUE;
|
thd->transaction.all.modified_non_trans_table= TRUE;
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
if (mysql_bin_log.is_open())
|
if (mysql_bin_log.is_open())
|
||||||
{
|
{
|
||||||
@ -506,6 +504,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
/* ok to client sent only after binlog write and engine commit */
|
/* ok to client sent only after binlog write and engine commit */
|
||||||
send_ok(thd, info.copied + info.deleted, 0L, name);
|
send_ok(thd, info.copied + info.deleted, 0L, name);
|
||||||
err:
|
err:
|
||||||
|
DBUG_ASSERT(transactional_table || !(info.copied || info.deleted) ||
|
||||||
|
thd->transaction.stmt.modified_non_trans_table);
|
||||||
table->file->ha_release_auto_increment();
|
table->file->ha_release_auto_increment();
|
||||||
if (thd->lock)
|
if (thd->lock)
|
||||||
{
|
{
|
||||||
@ -552,7 +552,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
Item_field *sql_field;
|
Item_field *sql_field;
|
||||||
TABLE *table= table_list->table;
|
TABLE *table= table_list->table;
|
||||||
ulonglong id;
|
ulonglong id;
|
||||||
bool no_trans_update_stmt, err;
|
bool err;
|
||||||
DBUG_ENTER("read_fixed_length");
|
DBUG_ENTER("read_fixed_length");
|
||||||
|
|
||||||
id= 0;
|
id= 0;
|
||||||
@ -580,7 +580,6 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
#ifdef HAVE_purify
|
#ifdef HAVE_purify
|
||||||
read_info.row_end[0]=0;
|
read_info.row_end[0]=0;
|
||||||
#endif
|
#endif
|
||||||
no_trans_update_stmt= !table->file->has_transactions();
|
|
||||||
|
|
||||||
restore_record(table, s->default_values);
|
restore_record(table, s->default_values);
|
||||||
/*
|
/*
|
||||||
@ -650,7 +649,6 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
table->auto_increment_field_not_null= FALSE;
|
table->auto_increment_field_not_null= FALSE;
|
||||||
if (err)
|
if (err)
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
thd->no_trans_update.stmt= no_trans_update_stmt;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We don't need to reset auto-increment field since we are restoring
|
We don't need to reset auto-increment field since we are restoring
|
||||||
@ -685,12 +683,11 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
TABLE *table= table_list->table;
|
TABLE *table= table_list->table;
|
||||||
uint enclosed_length;
|
uint enclosed_length;
|
||||||
ulonglong id;
|
ulonglong id;
|
||||||
bool no_trans_update_stmt, err;
|
bool err;
|
||||||
DBUG_ENTER("read_sep_field");
|
DBUG_ENTER("read_sep_field");
|
||||||
|
|
||||||
enclosed_length=enclosed.length();
|
enclosed_length=enclosed.length();
|
||||||
id= 0;
|
id= 0;
|
||||||
no_trans_update_stmt= !table->file->has_transactions();
|
|
||||||
|
|
||||||
for (;;it.rewind())
|
for (;;it.rewind())
|
||||||
{
|
{
|
||||||
@ -827,7 +824,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
|
We don't need to reset auto-increment field since we are restoring
|
||||||
its default value at the beginning of each loop iteration.
|
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
|
if (read_info.next_line()) // Skip to next line
|
||||||
break;
|
break;
|
||||||
if (read_info.line_cuted)
|
if (read_info.line_cuted)
|
||||||
|
@ -120,7 +120,7 @@ bool end_active_trans(THD *thd)
|
|||||||
error=1;
|
error=1;
|
||||||
}
|
}
|
||||||
thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
|
thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
|
||||||
thd->no_trans_update.all= FALSE;
|
thd->transaction.all.modified_non_trans_table= FALSE;
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,7 +578,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion)
|
|||||||
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
|
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
|
||||||
res= ha_commit(thd);
|
res= ha_commit(thd);
|
||||||
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_KEEP_LOG);
|
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_KEEP_LOG);
|
||||||
thd->no_trans_update.all= FALSE;
|
thd->transaction.all.modified_non_trans_table= FALSE;
|
||||||
break;
|
break;
|
||||||
case COMMIT_RELEASE:
|
case COMMIT_RELEASE:
|
||||||
do_release= 1; /* fall through */
|
do_release= 1; /* fall through */
|
||||||
@ -596,7 +596,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion)
|
|||||||
if (ha_rollback(thd))
|
if (ha_rollback(thd))
|
||||||
res= -1;
|
res= -1;
|
||||||
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_KEEP_LOG);
|
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_KEEP_LOG);
|
||||||
thd->no_trans_update.all= FALSE;
|
thd->transaction.all.modified_non_trans_table= FALSE;
|
||||||
if (!res && (completion == ROLLBACK_AND_CHAIN))
|
if (!res && (completion == ROLLBACK_AND_CHAIN))
|
||||||
res= begin_trans(thd);
|
res= begin_trans(thd);
|
||||||
break;
|
break;
|
||||||
@ -1806,6 +1806,8 @@ mysql_execute_command(THD *thd)
|
|||||||
#endif
|
#endif
|
||||||
status_var_increment(thd->status_var.com_stat[lex->sql_command]);
|
status_var_increment(thd->status_var.com_stat[lex->sql_command]);
|
||||||
|
|
||||||
|
DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table == FALSE);
|
||||||
|
|
||||||
switch (lex->sql_command) {
|
switch (lex->sql_command) {
|
||||||
case SQLCOM_SHOW_EVENTS:
|
case SQLCOM_SHOW_EVENTS:
|
||||||
if ((res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
|
if ((res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
|
||||||
@ -3620,7 +3622,8 @@ end_with_restore_list:
|
|||||||
res= TRUE; // cannot happen
|
res= TRUE; // cannot happen
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (((thd->options & OPTION_KEEP_LOG) || thd->no_trans_update.all) &&
|
if (((thd->options & OPTION_KEEP_LOG) ||
|
||||||
|
thd->transaction.all.modified_non_trans_table) &&
|
||||||
!thd->slave_thread)
|
!thd->slave_thread)
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
ER_WARNING_NOT_COMPLETE_ROLLBACK,
|
ER_WARNING_NOT_COMPLETE_ROLLBACK,
|
||||||
@ -4200,8 +4203,8 @@ create_sp_error:
|
|||||||
thd->transaction.xid_state.xa_state=XA_ACTIVE;
|
thd->transaction.xid_state.xa_state=XA_ACTIVE;
|
||||||
thd->transaction.xid_state.xid.set(thd->lex->xid);
|
thd->transaction.xid_state.xid.set(thd->lex->xid);
|
||||||
xid_cache_insert(&thd->transaction.xid_state);
|
xid_cache_insert(&thd->transaction.xid_state);
|
||||||
|
thd->transaction.all.modified_non_trans_table= FALSE;
|
||||||
thd->options= ((thd->options & ~(OPTION_KEEP_LOG)) | OPTION_BEGIN);
|
thd->options= ((thd->options & ~(OPTION_KEEP_LOG)) | OPTION_BEGIN);
|
||||||
thd->no_trans_update.all= FALSE;
|
|
||||||
thd->server_status|= SERVER_STATUS_IN_TRANS;
|
thd->server_status|= SERVER_STATUS_IN_TRANS;
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
break;
|
break;
|
||||||
@ -4295,7 +4298,7 @@ create_sp_error:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
|
thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
|
||||||
thd->no_trans_update.all= FALSE;
|
thd->transaction.all.modified_non_trans_table= FALSE;
|
||||||
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
|
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
|
||||||
xid_cache_delete(&thd->transaction.xid_state);
|
xid_cache_delete(&thd->transaction.xid_state);
|
||||||
thd->transaction.xid_state.xa_state=XA_NOTR;
|
thd->transaction.xid_state.xa_state=XA_NOTR;
|
||||||
@ -4326,7 +4329,7 @@ create_sp_error:
|
|||||||
else
|
else
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
|
thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
|
||||||
thd->no_trans_update.all= FALSE;
|
thd->transaction.all.modified_non_trans_table= FALSE;
|
||||||
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
|
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
|
||||||
xid_cache_delete(&thd->transaction.xid_state);
|
xid_cache_delete(&thd->transaction.xid_state);
|
||||||
thd->transaction.xid_state.xa_state=XA_NOTR;
|
thd->transaction.xid_state.xa_state=XA_NOTR;
|
||||||
|
@ -6766,7 +6766,6 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
|||||||
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
|
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
|
||||||
|
|
||||||
/* We can abort alter table for any table type */
|
/* 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 &
|
thd->abort_on_warning= !ignore && test(thd->variables.sql_mode &
|
||||||
(MODE_STRICT_TRANS_TABLES |
|
(MODE_STRICT_TRANS_TABLES |
|
||||||
MODE_STRICT_ALL_TABLES));
|
MODE_STRICT_ALL_TABLES));
|
||||||
|
@ -530,7 +530,6 @@ int mysql_update(THD *thd,
|
|||||||
thd->proc_info="Updating";
|
thd->proc_info="Updating";
|
||||||
|
|
||||||
transactional_table= table->file->has_transactions();
|
transactional_table= table->file->has_transactions();
|
||||||
thd->no_trans_update.stmt= FALSE;
|
|
||||||
thd->abort_on_warning= test(!ignore &&
|
thd->abort_on_warning= test(!ignore &&
|
||||||
(thd->variables.sql_mode &
|
(thd->variables.sql_mode &
|
||||||
(MODE_STRICT_TRANS_TABLES |
|
(MODE_STRICT_TRANS_TABLES |
|
||||||
@ -641,7 +640,6 @@ int mysql_update(THD *thd,
|
|||||||
updated++;
|
updated++;
|
||||||
else
|
else
|
||||||
error= 0;
|
error= 0;
|
||||||
thd->no_trans_update.stmt= !transactional_table;
|
|
||||||
|
|
||||||
if (table->triggers &&
|
if (table->triggers &&
|
||||||
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
||||||
@ -717,6 +715,10 @@ int mysql_update(THD *thd,
|
|||||||
}
|
}
|
||||||
dup_key_found= 0;
|
dup_key_found= 0;
|
||||||
|
|
||||||
|
if (!transactional_table && updated > 0)
|
||||||
|
thd->transaction.stmt.modified_non_trans_table= TRUE;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
todo bug#27571: to avoid asynchronization of `error' and
|
todo bug#27571: to avoid asynchronization of `error' and
|
||||||
`error_code' of binlog event constructor
|
`error_code' of binlog event constructor
|
||||||
@ -809,9 +811,10 @@ int mysql_update(THD *thd,
|
|||||||
error=1; // Rollback update
|
error=1; // Rollback update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!transactional_table)
|
if (thd->transaction.stmt.modified_non_trans_table)
|
||||||
thd->no_trans_update.all= TRUE;
|
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);
|
free_underlaid_joins(thd, select_lex);
|
||||||
if (transactional_table)
|
if (transactional_table)
|
||||||
{
|
{
|
||||||
@ -1176,7 +1179,6 @@ bool mysql_multi_update(THD *thd,
|
|||||||
handle_duplicates, ignore)))
|
handle_duplicates, ignore)))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
thd->no_trans_update.stmt= FALSE;
|
|
||||||
thd->abort_on_warning= test(thd->variables.sql_mode &
|
thd->abort_on_warning= test(thd->variables.sql_mode &
|
||||||
(MODE_STRICT_TRANS_TABLES |
|
(MODE_STRICT_TRANS_TABLES |
|
||||||
MODE_STRICT_ALL_TABLES));
|
MODE_STRICT_ALL_TABLES));
|
||||||
@ -1549,9 +1551,7 @@ multi_update::~multi_update()
|
|||||||
if (copy_field)
|
if (copy_field)
|
||||||
delete [] copy_field;
|
delete [] copy_field;
|
||||||
thd->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting
|
thd->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting
|
||||||
if (!trans_safe) // todo: remove since redundant
|
DBUG_ASSERT(trans_safe || thd->transaction.all.modified_non_trans_table);
|
||||||
thd->no_trans_update.all= TRUE;
|
|
||||||
DBUG_ASSERT(trans_safe || thd->no_trans_update.all);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1655,7 +1655,7 @@ bool multi_update::send_data(List<Item> ¬_used_values)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
trans_safe= 0;
|
trans_safe= 0;
|
||||||
thd->no_trans_update.stmt= TRUE;
|
thd->transaction.stmt.modified_non_trans_table= TRUE;
|
||||||
}
|
}
|
||||||
if (table->triggers &&
|
if (table->triggers &&
|
||||||
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
||||||
@ -1718,7 +1718,6 @@ void multi_update::send_error(uint errcode,const char *err)
|
|||||||
|
|
||||||
/* Something already updated so we have to invalidate cache */
|
/* Something already updated so we have to invalidate cache */
|
||||||
query_cache_invalidate3(thd, update_tables, 1);
|
query_cache_invalidate3(thd, update_tables, 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If all tables that has been updated are trans safe then just do rollback.
|
If all tables that has been updated are trans safe then just do rollback.
|
||||||
If not attempt to do remaining updates.
|
If not attempt to do remaining updates.
|
||||||
@ -1731,7 +1730,7 @@ void multi_update::send_error(uint errcode,const char *err)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(thd->no_trans_update.stmt);
|
DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table);
|
||||||
if (do_update && table_count > 1)
|
if (do_update && table_count > 1)
|
||||||
{
|
{
|
||||||
/* Add warning here */
|
/* Add warning here */
|
||||||
@ -1742,7 +1741,7 @@ void multi_update::send_error(uint errcode,const char *err)
|
|||||||
VOID(do_updates(0));
|
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
|
The query has to binlog because there's a modified non-transactional table
|
||||||
@ -1755,9 +1754,9 @@ void multi_update::send_error(uint errcode,const char *err)
|
|||||||
transactional_tables, FALSE);
|
transactional_tables, FALSE);
|
||||||
}
|
}
|
||||||
if (!trans_safe)
|
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)
|
if (transactional_tables)
|
||||||
{
|
{
|
||||||
@ -1900,7 +1899,7 @@ int multi_update::do_updates(bool from_send_error)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
trans_safe= 0; // Can't do safe rollback
|
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();
|
(void) table->file->ha_rnd_end();
|
||||||
@ -1934,7 +1933,7 @@ err2:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
trans_safe= 0;
|
trans_safe= 0;
|
||||||
thd->no_trans_update.stmt= TRUE;
|
thd->transaction.stmt.modified_non_trans_table= TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
@ -1961,7 +1960,6 @@ bool multi_update::send_eof()
|
|||||||
{
|
{
|
||||||
query_cache_invalidate3(thd, update_tables, 1);
|
query_cache_invalidate3(thd, update_tables, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Write the SQL statement to the binlog if we updated
|
Write the SQL statement to the binlog if we updated
|
||||||
rows and we succeeded or if we updated some non
|
rows and we succeeded or if we updated some non
|
||||||
@ -1971,8 +1969,9 @@ bool multi_update::send_eof()
|
|||||||
either from the query's list or via a stored routine: bug#13270,23333
|
either from the query's list or via a stored routine: bug#13270,23333
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DBUG_ASSERT(trans_safe || !updated || thd->no_trans_update.stmt);
|
DBUG_ASSERT(trans_safe || !updated ||
|
||||||
if (local_error == 0 || thd->no_trans_update.stmt)
|
thd->transaction.stmt.modified_non_trans_table);
|
||||||
|
if (local_error == 0 || thd->transaction.stmt.modified_non_trans_table)
|
||||||
{
|
{
|
||||||
if (mysql_bin_log.is_open())
|
if (mysql_bin_log.is_open())
|
||||||
{
|
{
|
||||||
@ -1988,8 +1987,8 @@ bool multi_update::send_eof()
|
|||||||
local_error= 1; // Rollback update
|
local_error= 1; // Rollback update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!trans_safe)
|
if (thd->transaction.stmt.modified_non_trans_table)
|
||||||
thd->no_trans_update.all= TRUE;
|
thd->transaction.all.modified_non_trans_table= TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transactional_tables)
|
if (transactional_tables)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user