Below is the list of changes that have just been committed into a local
4.0 repository of mydev. When mydev does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2162 05/11/29 19:17:39 ingo@stripped +8 -0
BUG#5390 - problems with merge tables
Problem #1: INSERT...SELECT
INSERT ... SELECT with the same table on both sides (hidden
below a MERGE table) does now work by buffering the select result.
The duplicate detection works now after open_and_lock_tables()
on the locks.
I did not find a test case that failed without the change in
sql_update.cc. I made the change anyway as it should in theory
fix a possible MERGE table problem with multi-table update.
sql/sql_update.cc
1.108 05/11/29 19:17:37 ingo@stripped +1 -1
BUG#5390 - problems with merge tables
Changed the duplicate tables detection for UPDATE
to use the new function, which does also work for MERGE tables.
sql/sql_parse.cc
1.394 05/11/29 19:17:37 ingo@stripped +6 -5
BUG#5390 - problems with merge tables
Problem #1: INSERT...SELECT
Changed the duplicate tables detection for INSERT ... SELECT
to use the new function, which does also work for MERGE tables.
sql/mysql_priv.h
1.239 05/11/29 19:17:37 ingo@stripped +1 -0
BUG#5390 - problems with merge tables
Problem #1: INSERT...SELECT
Added a declaration for the new function.
sql/lock.cc
1.55 05/11/29 19:17:37 ingo@stripped +86 -3
BUG#5390 - problems with merge tables
Problem #1: INSERT...SELECT
Added a new function to find a duplicate lock in a list of tables.
mysql-test/t/merge.test
1.26 05/11/29 19:17:37 ingo@stripped +26 -0
BUG#5390 - problems with merge tables
Problem #1: INSERT...SELECT
Added tests.
mysql-test/t/create.test
1.23 05/11/29 19:17:37 ingo@stripped +0 -7
BUG#5390 - problems with merge tables
Removed a duplicate test.
mysql-test/r/merge.result
1.28 05/11/29 19:17:37 ingo@stripped +49 -0
BUG#5390 - problems with merge tables
Problem #1: INSERT...SELECT
Added test results.
mysql-test/r/create.result
1.26 05/11/29 19:17:36 ingo@stripped +0 -11
BUG#5390 - problems with merge tables
Removed a duplicate test.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: ingo
# Host: chilla.local
# Root: /home/mydev/mysql-4.0-bug5390
--- 1.54/sql/lock.cc 2005-07-26 16:53:32 +02:00
+++ 1.55/sql/lock.cc 2005-11-29 19:17:37 +01:00
@@ -390,6 +390,88 @@
}
+/*
+ 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 @@
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 @@
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 @@
{
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);
}
/*****************************************************************************
--- 1.238/sql/mysql_priv.h 2005-11-22 09:55:04 +01:00
+++ 1.239/sql/mysql_priv.h 2005-11-29 19:17:37 +01:00
@@ -788,6 +788,7 @@
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);
--- 1.393/sql/sql_parse.cc 2005-05-31 11:08:12 +02:00
+++ 1.394/sql/sql_parse.cc 2005-11-29 19:17:37 +01:00
@@ -2078,11 +2078,6 @@
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;
@@ -2095,6 +2090,12 @@
(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);
--- 1.107/sql/sql_update.cc 2005-02-18 13:50:18 +01:00
+++ 1.108/sql/sql_update.cc 2005-11-29 19:17:37 +01:00
@@ -712,7 +712,7 @@
{
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);
--- 1.25/mysql-test/r/create.result 2005-05-31 11:08:12 +02:00
+++ 1.26/mysql-test/r/create.result 2005-11-29 19:17:36 +01:00
@@ -189,17 +189,6 @@
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;
--- 1.27/mysql-test/r/merge.result 2005-09-29 13:37:27 +02:00
+++ 1.28/mysql-test/r/merge.result 2005-11-29 19:17:37 +01:00
@@ -645,3 +645,52 @@
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;
--- 1.22/mysql-test/t/create.test 2005-05-31 11:08:12 +02:00
+++ 1.23/mysql-test/t/create.test 2005-11-29 19:17:37 +01:00
@@ -158,13 +158,6 @@
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
-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;
#
# Test create table if not exists with duplicate key error
--- 1.25/mysql-test/t/merge.test 2005-09-29 13:37:27 +02:00
+++ 1.26/mysql-test/t/merge.test 2005-11-29 19:17:37 +01:00
@@ -297,3 +297,29 @@
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;
+
| Thread |
|---|
| • bk commit into 4.0 tree (ingo:1.2162) BUG#5390 | ingo | 29 Nov |