mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 13:32:33 +01:00
Merge rkalimullin@bk-internal.mysql.com:/home/bk/mysql-4.0
into gw.mysql.r18.ru:/usr/home/ram/work/4.0.b6000
This commit is contained in:
commit
f998d1ef00
6 changed files with 192 additions and 19 deletions
42
mysql-test/r/rpl_multi_update2.result
Normal file
42
mysql-test/r/rpl_multi_update2.result
Normal file
|
@ -0,0 +1,42 @@
|
|||
slave stop;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
slave start;
|
||||
CREATE TABLE t1 (
|
||||
a int unsigned not null auto_increment primary key,
|
||||
b int unsigned
|
||||
) TYPE=MyISAM;
|
||||
CREATE TABLE t2 (
|
||||
a int unsigned not null auto_increment primary key,
|
||||
b int unsigned
|
||||
) TYPE=MyISAM;
|
||||
INSERT INTO t1 VALUES (NULL, 0);
|
||||
INSERT INTO t1 SELECT NULL, 0 FROM t1;
|
||||
INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a b
|
||||
1 0
|
||||
2 0
|
||||
SELECT * FROM t2 ORDER BY a;
|
||||
a b
|
||||
1 0
|
||||
2 1
|
||||
UPDATE t1, t2 SET t1.b = (t2.b+4) WHERE t1.a = t2.a;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a b
|
||||
1 4
|
||||
2 5
|
||||
SELECT * FROM t2 ORDER BY a;
|
||||
a b
|
||||
1 0
|
||||
2 1
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a b
|
||||
1 4
|
||||
2 5
|
||||
SELECT * FROM t2 ORDER BY a;
|
||||
a b
|
||||
1 0
|
||||
2 1
|
1
mysql-test/t/rpl_multi_update2-slave.opt
Normal file
1
mysql-test/t/rpl_multi_update2-slave.opt
Normal file
|
@ -0,0 +1 @@
|
|||
--replicate-ignore-table=nothing.sensible
|
33
mysql-test/t/rpl_multi_update2.test
Normal file
33
mysql-test/t/rpl_multi_update2.test
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Let's verify that multi-update is not always skipped by slave if
|
||||
# some replicate-* rules exist.
|
||||
# (BUG#7011)
|
||||
|
||||
source include/master-slave.inc;
|
||||
|
||||
CREATE TABLE t1 (
|
||||
a int unsigned not null auto_increment primary key,
|
||||
b int unsigned
|
||||
) TYPE=MyISAM;
|
||||
|
||||
CREATE TABLE t2 (
|
||||
a int unsigned not null auto_increment primary key,
|
||||
b int unsigned
|
||||
) TYPE=MyISAM;
|
||||
|
||||
INSERT INTO t1 VALUES (NULL, 0);
|
||||
INSERT INTO t1 SELECT NULL, 0 FROM t1;
|
||||
|
||||
INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
|
||||
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
SELECT * FROM t2 ORDER BY a;
|
||||
|
||||
UPDATE t1, t2 SET t1.b = (t2.b+4) WHERE t1.a = t2.a;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
SELECT * FROM t2 ORDER BY a;
|
||||
|
||||
save_master_pos;
|
||||
connection slave;
|
||||
sync_with_master;
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
SELECT * FROM t2 ORDER BY a;
|
|
@ -469,6 +469,9 @@ int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
|||
List<Item> &values,COND *conds,
|
||||
ORDER *order, ha_rows limit,
|
||||
enum enum_duplicates handle_duplicates);
|
||||
int mysql_multi_update_lock(THD *thd,
|
||||
TABLE_LIST *table_list,
|
||||
List<Item> *fields);
|
||||
int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
|
||||
List<Item> *fields, List<Item> *values,
|
||||
COND *conds, ulong options,
|
||||
|
|
|
@ -56,6 +56,8 @@ static int check_for_max_user_connections(USER_CONN *uc);
|
|||
static void decrease_user_connections(USER_CONN *uc);
|
||||
static bool check_db_used(THD *thd,TABLE_LIST *tables);
|
||||
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
|
||||
static bool check_multi_update_lock(THD *thd, TABLE_LIST *tables,
|
||||
List<Item> *fields);
|
||||
static void mysql_init_query(THD *thd);
|
||||
static void remove_escape(char *name);
|
||||
static void refresh_status(void);
|
||||
|
@ -1338,10 +1340,28 @@ mysql_execute_command(void)
|
|||
LEX *lex= &thd->lex;
|
||||
TABLE_LIST *tables=(TABLE_LIST*) lex->select_lex.table_list.first;
|
||||
SELECT_LEX *select_lex = lex->select;
|
||||
bool slave_fake_lock= 0;
|
||||
MYSQL_LOCK *fake_prev_lock= 0;
|
||||
DBUG_ENTER("mysql_execute_command");
|
||||
|
||||
if (thd->slave_thread)
|
||||
{
|
||||
if (lex->sql_command == SQLCOM_MULTI_UPDATE)
|
||||
{
|
||||
DBUG_PRINT("info",("need faked locked tables"));
|
||||
|
||||
if (check_multi_update_lock(thd, tables, &select_lex->item_list))
|
||||
goto error;
|
||||
|
||||
/* Fix for replication, the tables are opened and locked,
|
||||
now we pretend that we have performed a LOCK TABLES action */
|
||||
|
||||
fake_prev_lock= thd->locked_tables;
|
||||
if (thd->lock)
|
||||
thd->locked_tables= thd->lock;
|
||||
thd->lock= 0;
|
||||
slave_fake_lock= 1;
|
||||
}
|
||||
/*
|
||||
Skip if we are in the slave thread, some table rules have been
|
||||
given and the table list says the query should not be replicated
|
||||
|
@ -1949,7 +1969,7 @@ mysql_execute_command(void)
|
|||
if (select_lex->item_list.elements != lex->value_list.elements)
|
||||
{
|
||||
send_error(&thd->net,ER_WRONG_VALUE_COUNT);
|
||||
DBUG_VOID_RETURN;
|
||||
goto error;
|
||||
}
|
||||
{
|
||||
const char *msg= 0;
|
||||
|
@ -2641,6 +2661,14 @@ mysql_execute_command(void)
|
|||
send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0);
|
||||
|
||||
error:
|
||||
if (unlikely(slave_fake_lock))
|
||||
{
|
||||
DBUG_PRINT("info",("undoing faked lock"));
|
||||
thd->lock= thd->locked_tables;
|
||||
thd->locked_tables= fake_prev_lock;
|
||||
if (thd->lock == thd->locked_tables)
|
||||
thd->lock= 0;
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -3907,3 +3935,54 @@ bool check_simple_select()
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Setup locking for multi-table updates. Used by the replication slave.
|
||||
Replication slave SQL thread examines (all_tables_not_ok()) the
|
||||
locking state of referenced tables to determine if the query has to
|
||||
be executed or ignored. Since in multi-table update, the
|
||||
'default' lock is read-only, this lock is corrected early enough by
|
||||
calling this function, before the slave decides to execute/ignore.
|
||||
|
||||
SYNOPSIS
|
||||
check_multi_update_lock()
|
||||
thd Current thread
|
||||
tables List of user-supplied tables
|
||||
fields List of fields requiring update
|
||||
|
||||
RETURN VALUES
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
static bool check_multi_update_lock(THD *thd, TABLE_LIST *tables,
|
||||
List<Item> *fields)
|
||||
{
|
||||
bool res= 1;
|
||||
TABLE_LIST *table;
|
||||
DBUG_ENTER("check_multi_update_lock");
|
||||
|
||||
if (check_db_used(thd, tables))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
Ensure that we have UPDATE or SELECT privilege for each table
|
||||
The exact privilege is checked in mysql_multi_update()
|
||||
*/
|
||||
for (table= tables ; table ; table= table->next)
|
||||
{
|
||||
TABLE_LIST *save= table->next;
|
||||
table->next= 0;
|
||||
if (check_one_table_access(thd, UPDATE_ACL, table, 1) &&
|
||||
check_one_table_access(thd, SELECT_ACL, table, 0))
|
||||
goto error;
|
||||
table->next= save;
|
||||
}
|
||||
|
||||
if (mysql_multi_update_lock(thd, tables, fields))
|
||||
goto error;
|
||||
|
||||
res= 0;
|
||||
|
||||
error:
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
|
|
@ -403,26 +403,20 @@ static table_map get_table_map(List<Item> *items)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Setup multi-update handling and call SELECT to do the join
|
||||
Prepare tables for multi-update
|
||||
Analyse which tables need specific privileges and perform locking
|
||||
as required
|
||||
*/
|
||||
|
||||
int mysql_multi_update(THD *thd,
|
||||
TABLE_LIST *table_list,
|
||||
List<Item> *fields,
|
||||
List<Item> *values,
|
||||
COND *conds,
|
||||
ulong options,
|
||||
enum enum_duplicates handle_duplicates)
|
||||
int mysql_multi_update_lock(THD *thd,
|
||||
TABLE_LIST *table_list,
|
||||
List<Item> *fields)
|
||||
{
|
||||
int res;
|
||||
multi_update *result;
|
||||
TABLE_LIST *tl;
|
||||
const bool using_lock_tables= thd->locked_tables != 0;
|
||||
DBUG_ENTER("mysql_multi_update");
|
||||
|
||||
thd->select_limit= HA_POS_ERROR;
|
||||
DBUG_ENTER("mysql_multi_update_lock");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
@ -490,7 +484,7 @@ int mysql_multi_update(THD *thd,
|
|||
(grant_option && check_grant(thd, wants, tl, 0, 0)))
|
||||
{
|
||||
tl->next= save;
|
||||
DBUG_RETURN(0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
tl->next= save;
|
||||
}
|
||||
|
@ -498,11 +492,7 @@ int mysql_multi_update(THD *thd,
|
|||
/* Relock the tables with the correct modes */
|
||||
res= lock_tables(thd,table_list);
|
||||
if (using_lock_tables)
|
||||
{
|
||||
if (res)
|
||||
DBUG_RETURN(res);
|
||||
break; // Don't have to do setup_field()
|
||||
}
|
||||
|
||||
/*
|
||||
We must setup fields again as the file may have been reopened
|
||||
|
@ -535,6 +525,31 @@ int mysql_multi_update(THD *thd,
|
|||
*/
|
||||
close_thread_tables(thd);
|
||||
}
|
||||
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
/*
|
||||
Setup multi-update handling and call SELECT to do the join
|
||||
*/
|
||||
|
||||
int mysql_multi_update(THD *thd,
|
||||
TABLE_LIST *table_list,
|
||||
List<Item> *fields,
|
||||
List<Item> *values,
|
||||
COND *conds,
|
||||
ulong options,
|
||||
enum enum_duplicates handle_duplicates)
|
||||
{
|
||||
int res;
|
||||
TABLE_LIST *tl;
|
||||
multi_update *result;
|
||||
DBUG_ENTER("mysql_multi_update");
|
||||
|
||||
thd->select_limit= HA_POS_ERROR;
|
||||
|
||||
if ((res= mysql_multi_update_lock(thd, table_list, fields)))
|
||||
DBUG_RETURN(res);
|
||||
|
||||
/*
|
||||
Count tables and setup timestamp handling
|
||||
|
|
Loading…
Reference in a new issue