mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 04:53:01 +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
|
2 test t ppc
|
||||||
9 abc ppc
|
9 abc ppc
|
||||||
drop table t1, t2;
|
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;
|
select * from t2;
|
||||||
drop table t1,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
|
# 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 t1 order by i1;
|
||||||
select * from t2 order by id;
|
select * from t2 order by id;
|
||||||
drop table t1, 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=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)
|
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
|
||||||
{
|
{
|
||||||
multi_update *result;
|
multi_update *result;
|
||||||
|
bool res;
|
||||||
DBUG_ENTER("mysql_multi_update");
|
DBUG_ENTER("mysql_multi_update");
|
||||||
|
|
||||||
if (!(result= new multi_update(table_list,
|
if (!(result= new multi_update(table_list,
|
||||||
|
@ -1083,7 +1084,7 @@ bool mysql_multi_update(THD *thd,
|
||||||
MODE_STRICT_ALL_TABLES));
|
MODE_STRICT_ALL_TABLES));
|
||||||
|
|
||||||
List<Item> total_list;
|
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,
|
table_list, select_lex->with_wild,
|
||||||
total_list,
|
total_list,
|
||||||
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
|
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 |
|
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
|
||||||
OPTION_SETUP_TABLES_DONE,
|
OPTION_SETUP_TABLES_DONE,
|
||||||
result, unit, select_lex);
|
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;
|
delete result;
|
||||||
thd->abort_on_warning= 0;
|
thd->abort_on_warning= 0;
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
@ -1401,8 +1411,9 @@ 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)
|
if (!trans_safe) // todo: remove since redundant
|
||||||
thd->no_trans_update.all= TRUE;
|
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
|
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;
|
thd->no_trans_update.stmt= TRUE;
|
||||||
|
}
|
||||||
if (table->triggers &&
|
if (table->triggers &&
|
||||||
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
||||||
TRG_ACTION_AFTER, TRUE))
|
TRG_ACTION_AFTER, TRUE))
|
||||||
|
@ -1534,8 +1552,8 @@ void multi_update::send_error(uint errcode,const char *err)
|
||||||
my_error(errcode, MYF(0), err);
|
my_error(errcode, MYF(0), err);
|
||||||
|
|
||||||
/* If nothing updated return */
|
/* If nothing updated return */
|
||||||
if (!updated)
|
if (updated == 0) /* the counter might be reset in send_eof */
|
||||||
return;
|
return; /* and then the query has been binlogged */
|
||||||
|
|
||||||
/* 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);
|
||||||
|
@ -1546,11 +1564,43 @@ void multi_update::send_error(uint errcode,const char *err)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (trans_safe)
|
if (trans_safe)
|
||||||
ha_rollback_stmt(thd);
|
|
||||||
else if (do_update && table_count > 1)
|
|
||||||
{
|
{
|
||||||
/* Add warning here */
|
DBUG_ASSERT(transactional_tables);
|
||||||
VOID(do_updates(0));
|
(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 (updated != org_updated)
|
||||||
{
|
{
|
||||||
if (table->file->has_transactions())
|
if (table->file->has_transactions())
|
||||||
transactional_tables= 1;
|
transactional_tables= 1;
|
||||||
else
|
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) table->file->ha_rnd_end();
|
||||||
(void) tmp_table->file->ha_rnd_end();
|
(void) tmp_table->file->ha_rnd_end();
|
||||||
|
@ -1685,7 +1738,10 @@ err2:
|
||||||
if (table->file->has_transactions())
|
if (table->file->has_transactions())
|
||||||
transactional_tables= 1;
|
transactional_tables= 1;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
trans_safe= 0;
|
trans_safe= 0;
|
||||||
|
thd->no_trans_update.stmt= TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
@ -1715,14 +1771,20 @@ bool multi_update::send_eof()
|
||||||
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
|
||||||
transactional tables.
|
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 (mysql_bin_log.is_open())
|
||||||
{
|
{
|
||||||
if (local_error == 0)
|
if (local_error == 0)
|
||||||
thd->clear_error();
|
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,
|
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
|
||||||
thd->query, thd->query_length,
|
thd->query, thd->query_length,
|
||||||
transactional_tables, FALSE) &&
|
transactional_tables, FALSE) &&
|
||||||
|
@ -1731,7 +1793,7 @@ bool multi_update::send_eof()
|
||||||
local_error= 1; // Rollback update
|
local_error= 1; // Rollback update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!transactional_tables)
|
if (!trans_safe)
|
||||||
thd->no_trans_update.all= TRUE;
|
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 ...
|
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",
|
my_message(ER_UNKNOWN_ERROR, "An error occured in multi-table update",
|
||||||
MYF(0));
|
MYF(0));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
Loading…
Reference in a new issue