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.2168 06/01/06 16:37:22 ingo@stripped +2 -0
BUG#5390 - problems with merge tables
Optimizations suggested by Monty.
We assume that mysql_lock_have_duplicate() is called
when all tables are locked. Then we have no need to
call get_lock_data() again. We just work on the existing lock.
sql/sql_class.h
1.192 06/01/06 16:37:21 ingo@stripped +1 -0
BUG#5390 - problems with merge tables
Optimizations suggested by Monty.
We do now store where the THR_LOCK_DATA for each table start.
sql/lock.cc
1.56 06/01/06 16:37:21 ingo@stripped +91 -64
BUG#5390 - problems with merge tables
Optimizations suggested by Monty.
We assume that mysql_lock_have_duplicate() is called
when all tables are locked. Then we have no need to
call get_lock_data() again. We just work on the existing lock.
# 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.55/sql/lock.cc 2005-11-29 19:17:37 +01:00
+++ 1.56/sql/lock.cc 2006-01-06 16:37:21 +01:00
@@ -303,6 +303,9 @@
bmove((char*) (locked->table+i),
(char*) (locked->table+i+1),
(locked->table_count-i)* sizeof(TABLE*));
+ bmove((char*) (locked->table_lock_starts + i),
+ (char*) (locked->table_lock_starts + i + 1),
+ (locked->table_count - i) * sizeof(uint));
break;
}
}
@@ -391,6 +394,40 @@
/*
+ Get the range of lock data for a table in a lock.
+
+ SYNOPSIS
+ mysql_lock_data_range()
+ mylock The lock.
+ table The table.
+ start_p OUT Start of range.
+ end_p OUT End of range.
+
+ RETURN
+ void
+*/
+
+void mysql_lock_data_range(MYSQL_LOCK *mylock, TABLE *table,
+ uint *start_p, uint *end_p)
+{
+ uint idx;
+
+ /* Find table in lock. */
+ for (idx= 0; idx < mylock->table_count; idx++)
+ {
+ if (mylock->table[idx] == table)
+ break;
+ }
+ DBUG_ASSERT(idx < mylock->table_count);
+
+ /* Compute the lock data range for table. */
+ *start_p= mylock->table_lock_starts[idx++]; /* Note: idx ++ here */
+ *end_p= ((idx < mylock->table_count) ?
+ mylock->table_lock_starts[idx] : mylock->table_count);
+}
+
+
+/*
Find duplicate lock in tables.
SYNOPSIS
@@ -402,73 +439,58 @@
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.
+ the table is opened. This function assumes that the tables are
+ already locked.
RETURN
1 A table from 'tables' matches a lock on 'table'.
- 0 No duplicate lock is present.
- -1 Error.
+ 0 No duplicate lock found.
*/
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;
+ uint idx1;
+ uint beg1;
+ uint end1;
+ uint idx2;
+ uint beg2;
+ uint end2;
+ MYSQL_LOCK *mylock;
+ TABLE_LIST *tablist;
THR_LOCK *lock1;
DBUG_ENTER("mysql_lock_have_duplicate");
- if (! (sql_lock1= get_lock_data(thd, tables1, 1, 1, &write_lock_used)))
- goto err0;
+ /* Get command lock or LOCK TABLES lock. */
+ mylock= thd->lock ? thd->lock : thd->locked_tables;
+ DBUG_ASSERT(mylock);
+
+ /* If we have less than one table, we cannot have duplicates. */
+ if (mylock->table_count < 2)
+ DBUG_RETURN(0);
+
+ /* Get the lock data range for table. */
+ mysql_lock_data_range(mylock, table, &beg1, &end1);
- 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++)
+ /* Compare all tables locks against this range. */
+ for (tablist = tables; tablist; tablist= tablist->next)
+ {
+ /* Get the lock data range for the current table in the list. */
+ mysql_lock_data_range(mylock, tablist->table, &beg2, &end2);
+
+ /* Compare all locks in the lock data range for table ... */
+ for (idx1= beg1; idx1 < end1; idx1++)
{
- if ((*lock_data2)->lock == lock1)
- goto end;
+ lock1= mylock->locks[idx1]->lock;
+
+ /* ... against all locks in the lock data range for the listed table. */
+ for (idx2= beg2; idx2 < end2; idx2++)
+ {
+ if (mylock->locks[idx2]->lock == lock1)
+ DBUG_RETURN(1);
+ }
}
}
- 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);
+ DBUG_RETURN(0);
}
@@ -504,31 +526,35 @@
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
bool get_old_locks, TABLE **write_lock_used)
{
- uint i,tables,lock_count;
+ uint i, table_count, lock_count;
+ uint *start;
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++)
+ for (i= table_count= lock_count= 0 ; i < count ; i++)
{
if (table_ptr[i]->tmp_table != TMP_TABLE)
{
- tables+=table_ptr[i]->file->lock_count();
- lock_count++;
+ lock_count+= table_ptr[i]->file->lock_count();
+ table_count++;
}
}
if (!(sql_lock= (MYSQL_LOCK*)
- my_malloc(sizeof(*sql_lock)+
- sizeof(THR_LOCK_DATA*)*tables+sizeof(table_ptr)*lock_count,
- MYF(0))))
+ my_malloc(sizeof(*sql_lock) +
+ sizeof(THR_LOCK_DATA*) * lock_count +
+ (sizeof(table_ptr) + sizeof(uint)) * table_count, MYF(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;
- sql_lock->lock_count=tables;
+
+ locks= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1);
+ to= sql_lock->table= (TABLE**) (locks + lock_count);
+ start= sql_lock->table_lock_starts= (uint*) (to + table_count);
+
+ sql_lock->table_count= table_count;
+ sql_lock->lock_count= lock_count;
for (i=0 ; i < count ; i++)
{
@@ -536,6 +562,7 @@
if ((table=table_ptr[i])->tmp_table == TMP_TABLE)
continue;
*to++=table;
+ *(start++)= locks - sql_lock->locks;
enum thr_lock_type lock_type= table->reginfo.lock_type;
if (lock_type >= TL_WRITE_ALLOW_WRITE)
{
--- 1.191/sql/sql_class.h 2004-12-03 00:02:39 +01:00
+++ 1.192/sql/sql_class.h 2006-01-06 16:37:21 +01:00
@@ -254,6 +254,7 @@
typedef struct st_mysql_lock
{
TABLE **table;
+ uint *table_lock_starts;
uint table_count,lock_count;
THR_LOCK_DATA **locks;
} MYSQL_LOCK;
| Thread |
|---|
| • bk commit into 4.0 tree (ingo:1.2168) BUG#5390 | ingo | 6 Jan |