Merge mysql.com:/home/mydev/mysql-4.0

into  mysql.com:/home/mydev/mysql-4.0-bug5390
This commit is contained in:
unknown 2005-12-27 10:35:33 +01:00
commit 409a472905
8 changed files with 169 additions and 27 deletions

View File

@ -189,17 +189,6 @@ select * from t1;
0 1 2
0 0 1
drop table t1;
create table t1 select 1,2,3;
create table if not exists t1 select 1,2;
create table if not exists t1 select 1,2,3,4;
Column count doesn't match value count at row 1
create table if not exists t1 select 1;
select * from t1;
1 2 3
1 2 3
0 1 2
0 0 1
drop table t1;
create table t1 (a int not null, b int, primary key (a));
insert into t1 values (1,1);
create table if not exists t1 select 2;

View File

@ -645,3 +645,52 @@ select min(a), max(a) from t1;
min(a) max(a)
9999999999.9990 9999999999.9990
drop table t1, t2, t3;
create table t1(a int);
create table t2(a int);
insert into t1 values (1);
insert into t2 values (2);
create table t3 (a int) engine=merge union=(t1, t2) insert_method=first;
select * from t3;
a
1
2
insert t2 select * from t2;
select * from t2;
a
2
2
insert t3 select * from t1;
select * from t3;
a
1
1
2
2
insert t1 select * from t3;
select * from t1;
a
1
1
1
1
2
2
select * from t2;
a
2
2
select * from t3;
a
1
1
1
1
2
2
2
2
check table t1, t2;
Table Op Msg_type Msg_text
test.t1 check status OK
test.t2 check status OK
drop table t1, t2, t3;

View File

@ -151,13 +151,6 @@ drop table t1;
# bug #1434
#
create table t1 select 1,2,3;
create table if not exists t1 select 1,2;
--error 1136
create table if not exists t1 select 1,2,3,4;
create table if not exists t1 select 1;
select * from t1;
drop table t1;
create table t1 select 1,2,3;
create table if not exists t1 select 1,2;
--error 1136

View File

@ -297,3 +297,29 @@ select min(a), max(a) from t1;
flush tables;
select min(a), max(a) from t1;
drop table t1, t2, t3;
#
# BUG#5390 - problems with merge tables
# Problem #1: INSERT...SELECT
#
#drop table if exists t1, t2, t3;
create table t1(a int);
create table t2(a int);
insert into t1 values (1);
insert into t2 values (2);
create table t3 (a int) engine=merge union=(t1, t2) insert_method=first;
select * from t3;
#
insert t2 select * from t2;
select * from t2;
#
insert t3 select * from t1;
select * from t3;
#
insert t1 select * from t3;
select * from t1;
select * from t2;
select * from t3;
check table t1, t2;
drop table t1, t2, t3;

View File

@ -390,6 +390,88 @@ MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
}
/*
Find duplicate lock in tables.
SYNOPSIS
mysql_lock_have_duplicate()
thd The current thread.
table The table to check for duplicate lock.
tables The list of tables to search for the dup lock.
NOTE
This is mainly meant for MERGE tables in INSERT ... SELECT
situations. The 'real', underlying tables can be found only after
the table is opened. The easier way is to check this after the
tables are locked.
RETURN
1 A table from 'tables' matches a lock on 'table'.
0 No duplicate lock is present.
-1 Error.
*/
int mysql_lock_have_duplicate(THD *thd, TABLE *table, TABLE_LIST *tables)
{
uint count;
MYSQL_LOCK *sql_lock1;
MYSQL_LOCK *sql_lock2;
TABLE **tables1= &table;
TABLE **tables2;
TABLE **table_ptr;
TABLE_LIST *tablist2;
TABLE *write_lock_used;
THR_LOCK_DATA **lock_data1;
THR_LOCK_DATA **end_data1;
THR_LOCK_DATA **lock_data2;
THR_LOCK_DATA **end_data2;
THR_LOCK *lock1;
DBUG_ENTER("mysql_lock_have_duplicate");
if (! (sql_lock1= get_lock_data(thd, tables1, 1, 1, &write_lock_used)))
goto err0;
count=0;
for (tablist2 = tables; tablist2; tablist2= tablist2->next)
count++;
if (! (tables2= (TABLE**) sql_alloc(sizeof(TABLE*) * count)))
goto err1;
table_ptr= tables2;
for (tablist2 = tables; tablist2; tablist2= tablist2->next)
*(table_ptr++)= tablist2->table;
if (! (sql_lock2= get_lock_data(thd, tables2, count, 1, &write_lock_used)))
goto err1;
count= 1;
for (lock_data1= sql_lock1->locks,
end_data1= lock_data1 + sql_lock1->lock_count;
lock_data1 < end_data1;
lock_data1++)
{
lock1= (*lock_data1)->lock;
for (lock_data2= sql_lock2->locks,
end_data2= lock_data2 + sql_lock2->lock_count;
lock_data2 < end_data2;
lock_data2++)
{
if ((*lock_data2)->lock == lock1)
goto end;
}
}
count= 0;
end:
my_free((gptr) sql_lock2, MYF(0));
my_free((gptr) sql_lock1, MYF(0));
DBUG_RETURN(count);
err1:
my_free((gptr) sql_lock1, MYF(0));
err0:
DBUG_RETURN(-1);
}
/* unlock a set of external */
static int unlock_external(THD *thd, TABLE **table,uint count)
@ -426,6 +508,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
MYSQL_LOCK *sql_lock;
THR_LOCK_DATA **locks;
TABLE **to;
DBUG_ENTER("get_lock_data");
*write_lock_used=0;
for (i=tables=lock_count=0 ; i < count ; i++)
@ -441,7 +524,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
my_malloc(sizeof(*sql_lock)+
sizeof(THR_LOCK_DATA*)*tables+sizeof(table_ptr)*lock_count,
MYF(0))))
return 0;
DBUG_RETURN(0);
locks=sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1);
to=sql_lock->table=(TABLE**) (locks+tables);
sql_lock->table_count=lock_count;
@ -461,13 +544,13 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
{
my_error(ER_OPEN_AS_READONLY,MYF(0),table->table_name);
my_free((gptr) sql_lock,MYF(0));
return 0;
DBUG_RETURN(0);
}
}
locks=table->file->store_lock(thd, locks, get_old_locks ? TL_IGNORE :
lock_type);
}
return sql_lock;
DBUG_RETURN(sql_lock);
}
/*****************************************************************************

View File

@ -788,6 +788,7 @@ void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
void mysql_lock_abort(THD *thd, TABLE *table);
bool mysql_lock_abort_for_thread(THD *thd, TABLE *table);
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);
int mysql_lock_have_duplicate(THD *thd, TABLE *table, TABLE_LIST *tables);
bool lock_global_read_lock(THD *thd);
void unlock_global_read_lock(THD *thd);
bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, bool is_not_commit);

View File

@ -2081,11 +2081,6 @@ mysql_execute_command(void)
if (thd->select_limit < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // No limit
if (check_dup(tables->db, tables->real_name, tables->next))
{
/* Using same table for INSERT and SELECT */
select_lex->options |= OPTION_BUFFER_RESULT;
}
{
/* TODO: Delete the following loop when locks is set by sql_yacc */
TABLE_LIST *table;
@ -2098,6 +2093,12 @@ mysql_execute_command(void)
(byte*) (((TABLE_LIST *) lex->select_lex.table_list.first)->next);
if (!(res=open_and_lock_tables(thd, tables)))
{
/* MERGE sub-tables can only be detected after open. */
if (mysql_lock_have_duplicate(thd, tables->table, tables->next))
{
/* Using same table for INSERT and SELECT */
select_lex->options |= OPTION_BUFFER_RESULT;
}
if ((result=new select_insert(tables->table,&lex->field_list,
lex->duplicates)))
res=handle_select(thd,lex,result);

View File

@ -712,7 +712,7 @@ int multi_update::prepare(List<Item> &not_used_values)
{
TABLE *table=table_ref->table;
if (!(tables_to_update & table->map) &&
check_dup(table_ref->db, table_ref->real_name, update_tables))
mysql_lock_have_duplicate(thd, table, update_tables))
table->no_cache= 1; // Disable row cache
}
DBUG_RETURN(thd->fatal_error != 0);