mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
Merge dsl-hkibras1-ff5dc300-70.dhcp.inet.fi:/home/elkin/MySQL/TEAM/BARE/5.0
into dsl-hkibras1-ff5dc300-70.dhcp.inet.fi:/tmp/merge_5.0
This commit is contained in:
commit
798b38a447
4 changed files with 189 additions and 14 deletions
|
@ -604,3 +604,37 @@ id c1 c2
|
|||
2 test t ppc
|
||||
9 abc ppc
|
||||
drop table t1, t2;
|
||||
CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL auto_increment,
|
||||
`b` int(11) default NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
|
||||
CREATE TABLE `t2` (
|
||||
`a` int(11) NOT NULL auto_increment,
|
||||
`b` int(11) default NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
|
||||
insert into t1 values (1,1),(2,2);
|
||||
insert into t2 values (1,1),(4,4);
|
||||
reset master;
|
||||
UPDATE t2,t1 SET t2.a=t1.a+2;
|
||||
ERROR 23000: Duplicate entry '3' for key 1
|
||||
select * from t2 /* must be (3,1), (4,4) */;
|
||||
a b
|
||||
3 1
|
||||
4 4
|
||||
show master status /* there must be the UPDATE query event */;
|
||||
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||
master-bin.000001 189
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
insert into t1 values (1,2),(3,4),(4,4);
|
||||
insert into t2 values (1,2),(3,4),(4,4);
|
||||
reset master;
|
||||
UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a;
|
||||
ERROR 23000: Duplicate entry '4' for key 1
|
||||
show master status /* there must be the UPDATE query event */;
|
||||
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||
master-bin.000001 204
|
||||
drop table t1, t2;
|
||||
end of tests
|
||||
|
|
|
@ -754,6 +754,45 @@ select * from t1;
|
|||
select * from t2;
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
# Bug#27716 multi-update did partially and has not binlogged
|
||||
#
|
||||
|
||||
CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL auto_increment,
|
||||
`b` int(11) default NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
|
||||
|
||||
CREATE TABLE `t2` (
|
||||
`a` int(11) NOT NULL auto_increment,
|
||||
`b` int(11) default NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=INNODB DEFAULT CHARSET=latin1 ;
|
||||
|
||||
# A. testing multi_update::send_eof() execution branch
|
||||
insert into t1 values (1,1),(2,2);
|
||||
insert into t2 values (1,1),(4,4);
|
||||
reset master;
|
||||
--error ER_DUP_ENTRY
|
||||
UPDATE t2,t1 SET t2.a=t1.a+2;
|
||||
# check
|
||||
select * from t2 /* must be (3,1), (4,4) */;
|
||||
show master status /* there must no UPDATE in binlog */;
|
||||
|
||||
# B. testing multi_update::send_error() execution branch
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
insert into t1 values (1,2),(3,4),(4,4);
|
||||
insert into t2 values (1,2),(3,4),(4,4);
|
||||
reset master;
|
||||
--error ER_DUP_ENTRY
|
||||
UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a;
|
||||
show master status /* there must be no UPDATE query event */;
|
||||
|
||||
# cleanup bug#27716
|
||||
drop table t1, t2;
|
||||
|
||||
#
|
||||
# Testing of IFNULL
|
||||
#
|
||||
|
|
|
@ -570,3 +570,43 @@ delete t1.*,t2.* from t1,t2 where t1.i2=t2.id;
|
|||
select * from t1 order by i1;
|
||||
select * from t2 order by id;
|
||||
drop table t1, t2;
|
||||
#
|
||||
# Bug#27716 multi-update did partially and has not binlogged
|
||||
#
|
||||
|
||||
CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL auto_increment,
|
||||
`b` int(11) default NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
|
||||
|
||||
CREATE TABLE `t2` (
|
||||
`a` int(11) NOT NULL auto_increment,
|
||||
`b` int(11) default NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
|
||||
|
||||
# A. testing multi_update::send_eof() execution branch
|
||||
insert into t1 values (1,1),(2,2);
|
||||
insert into t2 values (1,1),(4,4);
|
||||
reset master;
|
||||
--error ER_DUP_ENTRY
|
||||
UPDATE t2,t1 SET t2.a=t1.a+2;
|
||||
# check
|
||||
select * from t2 /* must be (3,1), (4,4) */;
|
||||
show master status /* there must be the UPDATE query event */;
|
||||
|
||||
# B. testing multi_update::send_error() execution branch
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
insert into t1 values (1,2),(3,4),(4,4);
|
||||
insert into t2 values (1,2),(3,4),(4,4);
|
||||
reset master;
|
||||
--error ER_DUP_ENTRY
|
||||
UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a;
|
||||
show master status /* there must be the UPDATE query event */;
|
||||
|
||||
# cleanup bug#27716
|
||||
drop table t1, t2;
|
||||
|
||||
--echo end of tests
|
||||
|
|
|
@ -1069,6 +1069,7 @@ bool mysql_multi_update(THD *thd,
|
|||
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
|
||||
{
|
||||
multi_update *result;
|
||||
bool res;
|
||||
DBUG_ENTER("mysql_multi_update");
|
||||
|
||||
if (!(result= new multi_update(table_list,
|
||||
|
@ -1083,7 +1084,7 @@ bool mysql_multi_update(THD *thd,
|
|||
MODE_STRICT_ALL_TABLES));
|
||||
|
||||
List<Item> total_list;
|
||||
(void) mysql_select(thd, &select_lex->ref_pointer_array,
|
||||
res= mysql_select(thd, &select_lex->ref_pointer_array,
|
||||
table_list, select_lex->with_wild,
|
||||
total_list,
|
||||
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
|
||||
|
@ -1091,6 +1092,15 @@ bool mysql_multi_update(THD *thd,
|
|||
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
|
||||
OPTION_SETUP_TABLES_DONE,
|
||||
result, unit, select_lex);
|
||||
DBUG_PRINT("info",("res: %d report_error: %d", res,
|
||||
thd->net.report_error));
|
||||
res|= thd->net.report_error;
|
||||
if (unlikely(res))
|
||||
{
|
||||
/* If we had a another error reported earlier then this will be ignored */
|
||||
result->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR));
|
||||
result->abort();
|
||||
}
|
||||
delete result;
|
||||
thd->abort_on_warning= 0;
|
||||
DBUG_RETURN(FALSE);
|
||||
|
@ -1401,8 +1411,9 @@ multi_update::~multi_update()
|
|||
if (copy_field)
|
||||
delete [] copy_field;
|
||||
thd->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting
|
||||
if (!trans_safe)
|
||||
if (!trans_safe) // todo: remove since redundant
|
||||
thd->no_trans_update.all= TRUE;
|
||||
DBUG_ASSERT(trans_safe || thd->no_trans_update.all);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1491,8 +1502,15 @@ bool multi_update::send_data(List<Item> ¬_used_values)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!table->file->has_transactions())
|
||||
/* non-transactional or transactional table got modified */
|
||||
/* either multi_update class' flag is raised in its branch */
|
||||
if (table->file->has_transactions())
|
||||
transactional_tables= 1;
|
||||
else
|
||||
{
|
||||
trans_safe= 0;
|
||||
thd->no_trans_update.stmt= TRUE;
|
||||
}
|
||||
if (table->triggers &&
|
||||
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
||||
TRG_ACTION_AFTER, TRUE))
|
||||
|
@ -1534,8 +1552,8 @@ void multi_update::send_error(uint errcode,const char *err)
|
|||
my_error(errcode, MYF(0), err);
|
||||
|
||||
/* If nothing updated return */
|
||||
if (!updated)
|
||||
return;
|
||||
if (updated == 0) /* the counter might be reset in send_eof */
|
||||
return; /* and then the query has been binlogged */
|
||||
|
||||
/* Something already updated so we have to invalidate cache */
|
||||
query_cache_invalidate3(thd, update_tables, 1);
|
||||
|
@ -1546,11 +1564,43 @@ void multi_update::send_error(uint errcode,const char *err)
|
|||
*/
|
||||
|
||||
if (trans_safe)
|
||||
ha_rollback_stmt(thd);
|
||||
else if (do_update && table_count > 1)
|
||||
{
|
||||
/* Add warning here */
|
||||
VOID(do_updates(0));
|
||||
DBUG_ASSERT(transactional_tables);
|
||||
(void) ha_autocommit_or_rollback(thd, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(thd->no_trans_update.stmt);
|
||||
if (do_update && table_count > 1)
|
||||
{
|
||||
/* Add warning here */
|
||||
/*
|
||||
todo/fixme: do_update() is never called with the arg 1.
|
||||
should it change the signature to become argless?
|
||||
*/
|
||||
VOID(do_updates(0));
|
||||
}
|
||||
}
|
||||
if (thd->no_trans_update.stmt)
|
||||
{
|
||||
/*
|
||||
The query has to binlog because there's a modified non-transactional table
|
||||
either from the query's list or via a stored routine: bug#13270,23333
|
||||
*/
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
transactional_tables, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
if (!trans_safe)
|
||||
thd->no_trans_update.all= TRUE;
|
||||
}
|
||||
DBUG_ASSERT(trans_safe || !updated || thd->no_trans_update.stmt);
|
||||
|
||||
if (transactional_tables)
|
||||
{
|
||||
(void) ha_autocommit_or_rollback(thd, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1660,9 +1710,12 @@ int multi_update::do_updates(bool from_send_error)
|
|||
if (updated != org_updated)
|
||||
{
|
||||
if (table->file->has_transactions())
|
||||
transactional_tables= 1;
|
||||
transactional_tables= 1;
|
||||
else
|
||||
trans_safe= 0; // Can't do safe rollback
|
||||
{
|
||||
trans_safe= 0; // Can't do safe rollback
|
||||
thd->no_trans_update.stmt= TRUE;
|
||||
}
|
||||
}
|
||||
(void) table->file->ha_rnd_end();
|
||||
(void) tmp_table->file->ha_rnd_end();
|
||||
|
@ -1685,7 +1738,10 @@ err2:
|
|||
if (table->file->has_transactions())
|
||||
transactional_tables= 1;
|
||||
else
|
||||
{
|
||||
trans_safe= 0;
|
||||
thd->no_trans_update.stmt= TRUE;
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
@ -1715,14 +1771,20 @@ bool multi_update::send_eof()
|
|||
Write the SQL statement to the binlog if we updated
|
||||
rows and we succeeded or if we updated some non
|
||||
transactional tables.
|
||||
|
||||
The query has to binlog because there's a modified non-transactional table
|
||||
either from the query's list or via a stored routine: bug#13270,23333
|
||||
*/
|
||||
|
||||
if ((local_error == 0) || (updated && !trans_safe))
|
||||
DBUG_ASSERT(trans_safe || !updated || thd->no_trans_update.stmt);
|
||||
if (local_error == 0 || thd->no_trans_update.stmt)
|
||||
{
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
if (local_error == 0)
|
||||
thd->clear_error();
|
||||
else
|
||||
updated= 0; /* if there's an error binlog it here not in ::send_error */
|
||||
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
|
||||
thd->query, thd->query_length,
|
||||
transactional_tables, FALSE) &&
|
||||
|
@ -1731,7 +1793,7 @@ bool multi_update::send_eof()
|
|||
local_error= 1; // Rollback update
|
||||
}
|
||||
}
|
||||
if (!transactional_tables)
|
||||
if (!trans_safe)
|
||||
thd->no_trans_update.all= TRUE;
|
||||
}
|
||||
|
||||
|
@ -1743,7 +1805,7 @@ bool multi_update::send_eof()
|
|||
|
||||
if (local_error > 0) // if the above log write did not fail ...
|
||||
{
|
||||
/* Safety: If we haven't got an error before (should not happen) */
|
||||
/* Safety: If we haven't got an error before (can happen in do_updates) */
|
||||
my_message(ER_UNKNOWN_ERROR, "An error occured in multi-table update",
|
||||
MYF(0));
|
||||
return TRUE;
|
||||
|
|
Loading…
Reference in a new issue