mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-03 14:33:32 +03:00 
			
		
		
		
	Merge spachev@bk-internal.mysql.com:/home/bk/mysql-4.1
into asksasha.com:/reiser-data/mysql-dev/mysql-4.1-bug11139
This commit is contained in:
		@@ -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;
 | 
				
			|||||||
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;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1 @@
 | 
				
			|||||||
--replicate-wild-ignore-table=test.%
 | 
					"--replicate-rewrite-db=mysqltest_from->mysqltest_to" --replicate-do-table=mysqltest_to.a
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,41 @@
 | 
				
			|||||||
 | 
					#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;
 | 
				
			|||||||
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);
 | 
				
			|||||||
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);
 | 
				
			|||||||
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)
 | 
				
			|||||||
    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);
 | 
				
			|||||||
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)
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
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)
 | 
				
			|||||||
  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)
 | 
				
			|||||||
    (*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:
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	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
 | 
					 | 
				
			||||||
	  {}
 | 
						  {}
 | 
				
			||||||
	;
 | 
						;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user