Commit b6414f79 authored by sasha@asksasha.com's avatar sasha@asksasha.com

Merge spachev@bk-internal.mysql.com:/home/bk/mysql-4.1

into  asksasha.com:/reiser-data/mysql-dev/mysql-4.1-bug11139
parents b4d4e7a3 a9a612f1
...@@ -4,6 +4,26 @@ reset master; ...@@ -4,6 +4,26 @@ reset master;
reset slave; reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave; start slave;
set sql_log_bin=0;
create database mysqltest_from;
set sql_log_bin=1;
create database mysqltest_to;
use mysqltest_from;
drop table if exists a;
CREATE TABLE a (i INT);
INSERT INTO a VALUES(1);
DELETE alias FROM a alias WHERE alias.i=1;
SELECT * FROM a;
i
insert into a values(2),(3);
delete a alias FROM a alias where alias.i=2;
select * from a;
i
3
use mysqltest_to;
select * from a;
i
3
create table t1 (a int); create table t1 (a int);
create table t2 (a int); create table t2 (a int);
insert into t1 values (1); insert into t1 values (1);
...@@ -15,7 +35,10 @@ select * from t2; ...@@ -15,7 +35,10 @@ select * from t2;
a a
1 1
select * from t1; select * from t1;
ERROR 42S02: Table 'test.t1' doesn't exist ERROR 42S02: Table 'mysqltest_to.t1' doesn't exist
select * from t2; select * from t2;
ERROR 42S02: Table 'test.t2' doesn't exist ERROR 42S02: Table 'mysqltest_to.t2' doesn't exist
drop table t1,t2; set sql_log_bin=0;
drop database mysqltest_from;
set sql_log_bin=1;
drop database mysqltest_to;
--replicate-wild-ignore-table=test.% "--replicate-rewrite-db=mysqltest_from->mysqltest_to" --replicate-do-table=mysqltest_to.a
#multi delete replication bugs
source include/master-slave.inc; source include/master-slave.inc;
#BUG#11139 - improper wild-table and table rules
#checking for multi deletes with an alias
connection master;
set sql_log_bin=0;
create database mysqltest_from;
set sql_log_bin=1;
connection slave;
create database mysqltest_to;
connection master;
use mysqltest_from;
--disable_warnings
drop table if exists a;
--enable_warnings
CREATE TABLE a (i INT);
INSERT INTO a VALUES(1);
DELETE alias FROM a alias WHERE alias.i=1;
SELECT * FROM a;
insert into a values(2),(3);
delete a alias FROM a alias where alias.i=2;
select * from a;
save_master_pos;
connection slave;
use mysqltest_to;
sync_with_master;
select * from a;
# BUG#3461
connection master;
create table t1 (a int); create table t1 (a int);
create table t2 (a int); create table t2 (a int);
...@@ -19,7 +56,13 @@ select * from t1; ...@@ -19,7 +56,13 @@ select * from t1;
error 1146; error 1146;
select * from t2; select * from t2;
# cleanup
connection master; connection master;
drop table t1,t2; set sql_log_bin=0;
drop database mysqltest_from;
set sql_log_bin=1;
connection slave;
drop database mysqltest_to;
# End of 4.1 tests # End of 4.1 tests
...@@ -59,6 +59,7 @@ void kill_one_thread(THD *thd, ulong id); ...@@ -59,6 +59,7 @@ void kill_one_thread(THD *thd, ulong id);
bool net_request_file(NET* net, const char* fname); bool net_request_file(NET* net, const char* fname);
char* query_table_status(THD *thd,const char *db,const char *table_name); char* query_table_status(THD *thd,const char *db,const char *table_name);
#define x_free(A) { my_free((gptr) (A),MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); } #define x_free(A) { my_free((gptr) (A),MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); }
#define safeFree(x) { if(x) { my_free((gptr) x,MYF(0)); x = NULL; } } #define safeFree(x) { if(x) { my_free((gptr) x,MYF(0)); x = NULL; } }
#define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1)) #define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1))
...@@ -464,6 +465,7 @@ void mysql_reset_thd_for_next_command(THD *thd); ...@@ -464,6 +465,7 @@ void mysql_reset_thd_for_next_command(THD *thd);
bool mysql_new_select(LEX *lex, bool move_down); bool mysql_new_select(LEX *lex, bool move_down);
void create_select_for_variable(const char *var_name); void create_select_for_variable(const char *var_name);
void mysql_init_multi_delete(LEX *lex); void mysql_init_multi_delete(LEX *lex);
void fix_multi_delete_lex(LEX* lex);
void init_max_user_conn(void); void init_max_user_conn(void);
void init_update_queries(void); void init_update_queries(void);
void free_max_user_conn(void); void free_max_user_conn(void);
......
...@@ -746,14 +746,7 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len) ...@@ -746,14 +746,7 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
rules (see code below). For that reason, users should not set conflicting rules (see code below). For that reason, users should not set conflicting
rules because they may get unpredicted results (precedence order is rules because they may get unpredicted results (precedence order is
explained in the manual). explained in the manual).
If no table of the list is marked "updating" (so far this can only happen
if the statement is a multi-delete (SQLCOM_DELETE_MULTI) and the "tables"
is the tables in the FROM): then we always return 0, because there is no
reason we play this statement on this slave if it updates nothing. In the
case of SQLCOM_DELETE_MULTI, there will be a second call to tables_ok(),
with tables having "updating==TRUE" (those after the DELETE), so this
second call will make the decision (because
all_tables_not_ok() = !tables_ok(1st_list) && !tables_ok(2nd_list)).
RETURN VALUES RETURN VALUES
0 should not be logged/replicated 0 should not be logged/replicated
......
...@@ -60,6 +60,9 @@ static void refresh_status(void); ...@@ -60,6 +60,9 @@ static void refresh_status(void);
static bool append_file_to_dir(THD *thd, const char **filename_ptr, static bool append_file_to_dir(THD *thd, const char **filename_ptr,
const char *table_name); const char *table_name);
static TABLE_LIST* get_table_by_alias(TABLE_LIST* tl, const char* db,
const char* alias);
const char *any_db="*any*"; // Special symbol for check_access const char *any_db="*any*"; // Special symbol for check_access
const char *command_name[]={ const char *command_name[]={
...@@ -125,10 +128,7 @@ static bool end_active_trans(THD *thd) ...@@ -125,10 +128,7 @@ static bool end_active_trans(THD *thd)
*/ */
inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables) inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
{ {
return (table_rules_on && tables && !tables_ok(thd,tables) && return (table_rules_on && tables && !tables_ok(thd,tables));
((thd->lex->sql_command != SQLCOM_DELETE_MULTI) ||
!tables_ok(thd,
(TABLE_LIST *)thd->lex->auxilliary_table_list.first)));
} }
#endif #endif
...@@ -4245,6 +4245,40 @@ void create_select_for_variable(const char *var_name) ...@@ -4245,6 +4245,40 @@ void create_select_for_variable(const char *var_name)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
static TABLE_LIST* get_table_by_alias(TABLE_LIST* tl, const char* db,
const char* alias)
{
for (;tl;tl= tl->next)
{
if (!strcmp(db,tl->db) &&
tl->alias && !my_strcasecmp(table_alias_charset,tl->alias,alias))
return tl;
}
return 0;
}
/* Sets up lex->auxilliary_table_list */
void fix_multi_delete_lex(LEX* lex)
{
TABLE_LIST *tl;
TABLE_LIST *good_list= (TABLE_LIST*)lex->select_lex.table_list.first;
for (tl= (TABLE_LIST*)lex->auxilliary_table_list.first; tl; tl= tl->next)
{
TABLE_LIST* good_table= get_table_by_alias(good_list,tl->db,tl->alias);
if (good_table && !good_table->derived)
{
/*
real_name points to a member of Table_ident which is
allocated via thd->strmake() from THD memroot
*/
tl->real_name= good_table->real_name;
tl->real_name_length= good_table->real_name_length;
good_table->updating= tl->updating;
}
}
}
void mysql_init_multi_delete(LEX *lex) void mysql_init_multi_delete(LEX *lex)
{ {
...@@ -5567,13 +5601,7 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count) ...@@ -5567,13 +5601,7 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
(*table_count)++; (*table_count)++;
/* All tables in aux_tables must be found in FROM PART */ /* All tables in aux_tables must be found in FROM PART */
TABLE_LIST *walk; TABLE_LIST *walk;
for (walk= delete_tables; walk; walk= walk->next) walk= get_table_by_alias(delete_tables,target_tbl->db,target_tbl->alias);
{
if (!my_strcasecmp(table_alias_charset,
target_tbl->alias, walk->alias) &&
!strcmp(walk->db, target_tbl->db))
break;
}
if (!walk) if (!walk)
{ {
my_error(ER_UNKNOWN_TABLE, MYF(0), target_tbl->real_name, my_error(ER_UNKNOWN_TABLE, MYF(0), target_tbl->real_name,
......
...@@ -4295,12 +4295,10 @@ single_multi: ...@@ -4295,12 +4295,10 @@ single_multi:
} }
where_clause opt_order_clause where_clause opt_order_clause
delete_limit_clause {} delete_limit_clause {}
| table_wild_list | table_wild_list {mysql_init_multi_delete(Lex);}
{ mysql_init_multi_delete(Lex); } FROM join_table_list {fix_multi_delete_lex(Lex);} where_clause
FROM join_table_list where_clause | FROM table_wild_list { mysql_init_multi_delete(Lex);}
| FROM table_wild_list USING join_table_list {fix_multi_delete_lex(Lex);} where_clause
{ mysql_init_multi_delete(Lex); }
USING join_table_list where_clause
{} {}
; ;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment