Commit 1071273b authored by joreland@mysql.com's avatar joreland@mysql.com

Merge joreland@bk-internal.mysql.com:/home/bk/mysql-5.0

into mysql.com:/home/jonas/src/mysql-5.0
parents 5703971f 88b63ab6
...@@ -53,6 +53,7 @@ int resize_queue(QUEUE *queue, uint max_elements); ...@@ -53,6 +53,7 @@ int resize_queue(QUEUE *queue, uint max_elements);
void delete_queue(QUEUE *queue); void delete_queue(QUEUE *queue);
void queue_insert(QUEUE *queue,byte *element); void queue_insert(QUEUE *queue,byte *element);
byte *queue_remove(QUEUE *queue,uint idx); byte *queue_remove(QUEUE *queue,uint idx);
#define queue_remove_all(queue) { (queue)->elements= 0; }
void _downheap(QUEUE *queue,uint idx); void _downheap(QUEUE *queue,uint idx);
void queue_fix(QUEUE *queue); void queue_fix(QUEUE *queue);
#define is_queue_inited(queue) ((queue)->root != 0) #define is_queue_inited(queue) ((queue)->root != 0)
......
...@@ -532,7 +532,7 @@ os_mem_alloc_large( ...@@ -532,7 +532,7 @@ os_mem_alloc_large(
ibool assert_on_error) /* in: if TRUE, we crash mysqld if the memory ibool assert_on_error) /* in: if TRUE, we crash mysqld if the memory
cannot be allocated */ cannot be allocated */
{ {
#ifdef UNIV_LINUX #ifdef HAVE_LARGE_PAGES
ulint size; ulint size;
int shmid; int shmid;
void *ptr = NULL; void *ptr = NULL;
...@@ -542,6 +542,7 @@ os_mem_alloc_large( ...@@ -542,6 +542,7 @@ os_mem_alloc_large(
goto skip; goto skip;
} }
#ifdef UNIV_LINUX
/* Align block size to os_large_page_size */ /* Align block size to os_large_page_size */
size = ((n - 1) & ~(os_large_page_size - 1)) + os_large_page_size; size = ((n - 1) & ~(os_large_page_size - 1)) + os_large_page_size;
...@@ -561,6 +562,7 @@ os_mem_alloc_large( ...@@ -561,6 +562,7 @@ os_mem_alloc_large(
*/ */
shmctl(shmid, IPC_RMID, &buf); shmctl(shmid, IPC_RMID, &buf);
} }
#endif
if (ptr) { if (ptr) {
if (set_to_zero) { if (set_to_zero) {
...@@ -573,8 +575,8 @@ os_mem_alloc_large( ...@@ -573,8 +575,8 @@ os_mem_alloc_large(
} }
fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional memory pool\n"); fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional memory pool\n");
#endif
skip: skip:
#endif /* HAVE_LARGE_PAGES */
return(ut_malloc_low(n, set_to_zero, assert_on_error)); return(ut_malloc_low(n, set_to_zero, assert_on_error));
} }
...@@ -587,8 +589,12 @@ os_mem_free_large( ...@@ -587,8 +589,12 @@ os_mem_free_large(
/*=================*/ /*=================*/
void *ptr) /* in: number of bytes */ void *ptr) /* in: number of bytes */
{ {
#ifdef HAVE_LARGE_PAGES
if (os_use_large_pages && os_large_page_size
#ifdef UNIV_LINUX #ifdef UNIV_LINUX
if (os_use_large_pages && os_large_page_size && !shmdt(ptr)) { && !shmdt(ptr)
#endif
) {
return; return;
} }
#endif #endif
......
drop table if exists t0, t1, t2, t3,t4; drop table if exists t0, t1, t2, t3, t4;
create table t0 create table t0
( (
key1 int not null, key1 int not null,
...@@ -335,4 +335,55 @@ key1 key2 key3 key4 key5 key6 key7 key8 ...@@ -335,4 +335,55 @@ key1 key2 key3 key4 key5 key6 key7 key8
select count(*) from t0; select count(*) from t0;
count(*) count(*)
1021 1021
drop table t4;
create table t4 (a int);
insert into t4 values (1),(4),(3);
set @save_join_buffer_size=@@join_buffer_size;
set join_buffer_size= 4000;
show variables like 'join_buffer_size';
Variable_name Value
join_buffer_size 8228
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
where (A.key1 < 500000 or A.key2 < 3)
and (B.key1 < 500000 or B.key2 < 3);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE A index_merge i1,i2 i1,i2 4,4 NULL 1016 Using sort_union(i1,i2); Using where
1 SIMPLE B index_merge i1,i2 i1,i2 4,4 NULL 1016 Using sort_union(i1,i2); Using where
select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
where (A.key1 < 500000 or A.key2 < 3)
and (B.key1 < 500000 or B.key2 < 3);
max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
10240
update t0 set key1=1;
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
where (A.key1 = 1 or A.key2 = 1)
and (B.key1 = 1 or B.key2 = 1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE A index_merge i1,i2 i1,i2 4,4 NULL 1020 Using union(i1,i2); Using where
1 SIMPLE B index_merge i1,i2 i1,i2 4,4 NULL 1020 Using union(i1,i2); Using where
select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
where (A.key1 = 1 or A.key2 = 1)
and (B.key1 = 1 or B.key2 = 1);
max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
8194
alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(200);
update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500;
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A, t0 as B
where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE A index_merge i1,i2,i3,i4,i5,i6,i7,i8 i2,i3,i4,i5,i6,i8 4,4,4,4,4,4 NULL 16 Using union(intersect(i2,i3,i4,i5,i6),i8); Using where
1 SIMPLE B index_merge i1,i2,i3,i4,i5,i6,i7,i8 i2,i3,i4,i5,i6,i8 4,4,4,4,4,4 NULL 16 Using union(intersect(i2,i3,i4,i5,i6),i8); Using where
select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A, t0 as B
where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1);
max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
8186
set join_buffer_size= @save_join_buffer_size;
drop table t0, t1, t2, t3, t4; drop table t0, t1, t2, t3, t4;
...@@ -853,4 +853,19 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -853,4 +853,19 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index 1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 1 SIMPLE t2 ALL NULL NULL NULL NULL 2
1 SIMPLE t3 ALL NULL NULL NULL NULL 2 1 SIMPLE t3 ALL NULL NULL NULL NULL 2
drop table t1,t2;
create table t1 (a int, b int);
insert into t1 values (1,1),(2,2),(3,3);
create table t2 (a int, b int);
insert into t2 values (1,1), (2,2);
select * from t2 right join t1 on t2.a=t1.a;
a b a b
1 1 1 1
2 2 2 2
NULL NULL 3 3
select straight_join * from t2 right join t1 on t2.a=t1.a;
a b a b
1 1 1 1
2 2 2 2
NULL NULL 3 3
DROP TABLE t0,t1,t2,t3; DROP TABLE t0,t1,t2,t3;
# #
# Index merge tests # Index merge tests
# #
--disable_warnings --disable_warnings
drop table if exists t0, t1, t2, t3,t4; drop table if exists t0, t1, t2, t3, t4;
--enable_warnings --enable_warnings
# Create and fill a table with simple keys # Create and fill a table with simple keys
...@@ -278,4 +277,48 @@ delete from t0 where key1 < 3 or key2 < 4; ...@@ -278,4 +277,48 @@ delete from t0 where key1 < 3 or key2 < 4;
select * from t0 where key1 < 3 or key2 < 4; select * from t0 where key1 < 3 or key2 < 4;
select count(*) from t0; select count(*) from t0;
# Test for BUG#4177
drop table t4;
create table t4 (a int);
insert into t4 values (1),(4),(3);
set @save_join_buffer_size=@@join_buffer_size;
set join_buffer_size= 4000;
show variables like 'join_buffer_size';
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
where (A.key1 < 500000 or A.key2 < 3)
and (B.key1 < 500000 or B.key2 < 3);
select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
where (A.key1 < 500000 or A.key2 < 3)
and (B.key1 < 500000 or B.key2 < 3);
update t0 set key1=1;
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
where (A.key1 = 1 or A.key2 = 1)
and (B.key1 = 1 or B.key2 = 1);
select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
where (A.key1 = 1 or A.key2 = 1)
and (B.key1 = 1 or B.key2 = 1);
alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(200);
update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500;
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A, t0 as B
where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1);
select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A, t0 as B
where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1);
set join_buffer_size= @save_join_buffer_size;
# Test for BUG#4177 ends
drop table t0, t1, t2, t3, t4; drop table t0, t1, t2, t3, t4;
...@@ -606,4 +606,14 @@ INSERT INTO t1 VALUES (0); ...@@ -606,4 +606,14 @@ INSERT INTO t1 VALUES (0);
SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1; SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1;
EXPLAIN SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1; EXPLAIN SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1;
# Test for BUG#4480
drop table t1,t2;
create table t1 (a int, b int);
insert into t1 values (1,1),(2,2),(3,3);
create table t2 (a int, b int);
insert into t2 values (1,1), (2,2);
select * from t2 right join t1 on t2.a=t1.a;
select straight_join * from t2 right join t1 on t2.a=t1.a;
DROP TABLE t0,t1,t2,t3; DROP TABLE t0,t1,t2,t3;
...@@ -777,8 +777,7 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT() ...@@ -777,8 +777,7 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT()
QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param, QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param,
TABLE *table) TABLE *table)
:cur_quick_it(quick_selects),pk_quick_select(NULL),unique(NULL), :pk_quick_select(NULL), thd(thd_param)
thd(thd_param)
{ {
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT"); DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT");
index= MAX_KEY; index= MAX_KEY;
...@@ -790,17 +789,14 @@ QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param, ...@@ -790,17 +789,14 @@ QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param,
int QUICK_INDEX_MERGE_SELECT::init() int QUICK_INDEX_MERGE_SELECT::init()
{ {
cur_quick_it.rewind(); DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::init");
cur_quick_select= cur_quick_it++; DBUG_RETURN(0);
return 0;
} }
int QUICK_INDEX_MERGE_SELECT::reset() int QUICK_INDEX_MERGE_SELECT::reset()
{ {
int result;
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::reset"); DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::reset");
result= cur_quick_select->reset() || prepare_unique(); DBUG_RETURN(read_keys_and_merge());
DBUG_RETURN(result);
} }
bool bool
...@@ -820,8 +816,12 @@ QUICK_INDEX_MERGE_SELECT::push_quick_back(QUICK_RANGE_SELECT *quick_sel_range) ...@@ -820,8 +816,12 @@ QUICK_INDEX_MERGE_SELECT::push_quick_back(QUICK_RANGE_SELECT *quick_sel_range)
QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT() QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT()
{ {
List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects);
QUICK_RANGE_SELECT* quick;
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT"); DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT");
delete unique; quick_it.rewind();
while ((quick= quick_it++))
quick->file= NULL;
quick_selects.delete_elements(); quick_selects.delete_elements();
delete pk_quick_select; delete pk_quick_select;
free_root(&alloc,MYF(0)); free_root(&alloc,MYF(0));
...@@ -833,7 +833,8 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param, ...@@ -833,7 +833,8 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param,
TABLE *table, TABLE *table,
bool retrieve_full_rows, bool retrieve_full_rows,
MEM_ROOT *parent_alloc) MEM_ROOT *parent_alloc)
: cpk_quick(NULL), thd(thd_param), need_to_fetch_row(retrieve_full_rows) : cpk_quick(NULL), thd(thd_param), need_to_fetch_row(retrieve_full_rows),
scans_inited(false)
{ {
index= MAX_KEY; index= MAX_KEY;
head= table; head= table;
...@@ -859,8 +860,9 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param, ...@@ -859,8 +860,9 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param,
int QUICK_ROR_INTERSECT_SELECT::init() int QUICK_ROR_INTERSECT_SELECT::init()
{ {
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::init");
/* Check if last_rowid was successfully allocated in ctor */ /* Check if last_rowid was successfully allocated in ctor */
return !last_rowid; DBUG_RETURN(!last_rowid);
} }
...@@ -953,7 +955,7 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler) ...@@ -953,7 +955,7 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan"); DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan");
/* Initialize all merged "children" quick selects */ /* Initialize all merged "children" quick selects */
DBUG_ASSERT(!(need_to_fetch_row && !reuse_handler)); DBUG_ASSERT(!need_to_fetch_row || reuse_handler);
if (!need_to_fetch_row && reuse_handler) if (!need_to_fetch_row && reuse_handler)
{ {
quick= quick_it++; quick= quick_it++;
...@@ -995,7 +997,14 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler) ...@@ -995,7 +997,14 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
int QUICK_ROR_INTERSECT_SELECT::reset() int QUICK_ROR_INTERSECT_SELECT::reset()
{ {
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::reset"); DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::reset");
DBUG_RETURN(init_ror_merged_scan(TRUE)); if (!scans_inited && init_ror_merged_scan(TRUE))
DBUG_RETURN(1);
scans_inited= true;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
QUICK_RANGE_SELECT *quick;
while ((quick= it++))
quick->reset();
DBUG_RETURN(0);
} }
...@@ -1034,7 +1043,7 @@ QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT() ...@@ -1034,7 +1043,7 @@ QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT()
QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param, QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
TABLE *table) TABLE *table)
:thd(thd_param) : thd(thd_param), scans_inited(false)
{ {
index= MAX_KEY; index= MAX_KEY;
head= table; head= table;
...@@ -1057,18 +1066,19 @@ QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param, ...@@ -1057,18 +1066,19 @@ QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
int QUICK_ROR_UNION_SELECT::init() int QUICK_ROR_UNION_SELECT::init()
{ {
DBUG_ENTER("QUICK_ROR_UNION_SELECT::init");
if (init_queue(&queue, quick_selects.elements, 0, if (init_queue(&queue, quick_selects.elements, 0,
FALSE , QUICK_ROR_UNION_SELECT::queue_cmp, FALSE , QUICK_ROR_UNION_SELECT::queue_cmp,
(void*) this)) (void*) this))
{ {
bzero(&queue, sizeof(QUEUE)); bzero(&queue, sizeof(QUEUE));
return 1; DBUG_RETURN(1);
} }
if (!(cur_rowid= (byte*)alloc_root(&alloc, 2*head->file->ref_length))) if (!(cur_rowid= (byte*)alloc_root(&alloc, 2*head->file->ref_length)))
return 1; DBUG_RETURN(1);
prev_rowid= cur_rowid + head->file->ref_length; prev_rowid= cur_rowid + head->file->ref_length;
return 0; DBUG_RETURN(0);
} }
...@@ -1106,6 +1116,18 @@ int QUICK_ROR_UNION_SELECT::reset() ...@@ -1106,6 +1116,18 @@ int QUICK_ROR_UNION_SELECT::reset()
int error; int error;
DBUG_ENTER("QUICK_ROR_UNION_SELECT::reset"); DBUG_ENTER("QUICK_ROR_UNION_SELECT::reset");
have_prev_rowid= FALSE; have_prev_rowid= FALSE;
if (!scans_inited)
{
QUICK_SELECT_I *quick;
List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
while ((quick= it++))
{
if (quick->init_ror_merged_scan(FALSE))
DBUG_RETURN(1);
}
scans_inited= true;
}
queue_remove_all(&queue);
/* /*
Initialize scans for merged quick selects and put all merged quick Initialize scans for merged quick selects and put all merged quick
selects into the queue. selects into the queue.
...@@ -1113,7 +1135,7 @@ int QUICK_ROR_UNION_SELECT::reset() ...@@ -1113,7 +1135,7 @@ int QUICK_ROR_UNION_SELECT::reset()
List_iterator_fast<QUICK_SELECT_I> it(quick_selects); List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
while ((quick= it++)) while ((quick= it++))
{ {
if (quick->init_ror_merged_scan(FALSE)) if (quick->reset())
DBUG_RETURN(1); DBUG_RETURN(1);
if ((error= quick->get_next())) if ((error= quick->get_next()))
{ {
...@@ -1591,7 +1613,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -1591,7 +1613,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu", DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
keys_to_use.to_ulonglong(), (ulong) prev_tables, keys_to_use.to_ulonglong(), (ulong) prev_tables,
(ulong) const_tables)); (ulong) const_tables));
delete quick; delete quick;
quick=0; quick=0;
needed_reg.clear_all(); needed_reg.clear_all();
...@@ -5553,22 +5574,29 @@ err: ...@@ -5553,22 +5574,29 @@ err:
/* /*
Fetch all row ids into unique. Perform key scans for all used indexes (except CPK), get rowids and merge
them into an ordered non-recurrent sequence of rowids.
The merge/duplicate removal is performed using Unique class. We put all
rowids into Unique, get the sorted sequence and destroy the Unique.
If table has a clustered primary key that covers all rows (TRUE for bdb If table has a clustered primary key that covers all rows (TRUE for bdb
and innodb currently) and one of the index_merge scans is a scan on PK, and innodb currently) and one of the index_merge scans is a scan on PK,
then then
primary key scan rowids are not put into Unique and also rows that will be retrieved by PK scan are not put into Unique and
rows that will be retrieved by PK scan are not put into Unique primary key scan is not performed here, it is performed later separately.
RETURN RETURN
0 OK 0 OK
other error other error
*/ */
int QUICK_INDEX_MERGE_SELECT::prepare_unique() int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
{ {
List_iterator_fast<QUICK_RANGE_SELECT> cur_quick_it(quick_selects);
QUICK_RANGE_SELECT* cur_quick;
int result; int result;
Unique *unique;
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::prepare_unique"); DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::prepare_unique");
/* We're going to just read rowids. */ /* We're going to just read rowids. */
...@@ -5583,7 +5611,17 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique() ...@@ -5583,7 +5611,17 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique()
*/ */
head->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); head->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
cur_quick_select->init(); cur_quick_it.rewind();
cur_quick= cur_quick_it++;
DBUG_ASSERT(cur_quick);
/*
We reuse the same instance of handler so we need to call both init and
reset here.
*/
if (cur_quick->init())
DBUG_RETURN(1);
cur_quick->reset();
unique= new Unique(refpos_order_cmp, (void *)head->file, unique= new Unique(refpos_order_cmp, (void *)head->file,
head->file->ref_length, head->file->ref_length,
...@@ -5592,24 +5630,28 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique() ...@@ -5592,24 +5630,28 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique()
DBUG_RETURN(1); DBUG_RETURN(1);
for (;;) for (;;)
{ {
while ((result= cur_quick_select->get_next()) == HA_ERR_END_OF_FILE) while ((result= cur_quick->get_next()) == HA_ERR_END_OF_FILE)
{ {
cur_quick_select->range_end(); cur_quick->range_end();
cur_quick_select= cur_quick_it++; cur_quick= cur_quick_it++;
if (!cur_quick_select) if (!cur_quick)
break; break;
if (cur_quick_select->init()) if (cur_quick->file->inited != handler::NONE)
cur_quick->file->ha_index_end();
if (cur_quick->init())
DBUG_RETURN(1); DBUG_RETURN(1);
/* QUICK_RANGE_SELECT::reset never fails */ /* QUICK_RANGE_SELECT::reset never fails */
cur_quick_select->reset(); cur_quick->reset();
} }
if (result) if (result)
{ {
if (result != HA_ERR_END_OF_FILE) if (result != HA_ERR_END_OF_FILE)
{
cur_quick->range_end();
DBUG_RETURN(result); DBUG_RETURN(result);
}
break; break;
} }
...@@ -5620,8 +5662,8 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique() ...@@ -5620,8 +5662,8 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique()
if (pk_quick_select && pk_quick_select->row_in_ranges()) if (pk_quick_select && pk_quick_select->row_in_ranges())
continue; continue;
cur_quick_select->file->position(cur_quick_select->record); cur_quick->file->position(cur_quick->record);
result= unique->unique_add((char*)cur_quick_select->file->ref); result= unique->unique_add((char*)cur_quick->file->ref);
if (result) if (result)
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -5629,6 +5671,7 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique() ...@@ -5629,6 +5671,7 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique()
/* ok, all row ids are in Unique */ /* ok, all row ids are in Unique */
result= unique->get(head); result= unique->get(head);
delete unique;
doing_pk_scan= FALSE; doing_pk_scan= FALSE;
/* start table scan */ /* start table scan */
init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1, 1); init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1, 1);
...@@ -5668,6 +5711,7 @@ int QUICK_INDEX_MERGE_SELECT::get_next() ...@@ -5668,6 +5711,7 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
doing_pk_scan= TRUE; doing_pk_scan= TRUE;
if ((result= pk_quick_select->init())) if ((result= pk_quick_select->init()))
DBUG_RETURN(result); DBUG_RETURN(result);
pk_quick_select->reset();
DBUG_RETURN(pk_quick_select->get_next()); DBUG_RETURN(pk_quick_select->get_next());
} }
} }
......
...@@ -127,7 +127,8 @@ public: ...@@ -127,7 +127,8 @@ public:
reset() should be called when it is certain that row retrieval will be reset() should be called when it is certain that row retrieval will be
necessary. This call may do heavyweight initialization like buffering first necessary. This call may do heavyweight initialization like buffering first
N records etc. If reset() call fails get_next() must not be called. N records etc. If reset() call fails get_next() must not be called.
Note that reset() may be called several times if this quick select
executes in a subselect.
RETURN RETURN
0 OK 0 OK
other Error code other Error code
...@@ -274,6 +275,10 @@ public: ...@@ -274,6 +275,10 @@ public:
next=0; next=0;
range= NULL; range= NULL;
cur_range= NULL; cur_range= NULL;
/*
Note: in opt_range.cc there are places where it is assumed that this
function always succeeds
*/
return 0; return 0;
} }
int init(); int init();
...@@ -388,21 +393,15 @@ public: ...@@ -388,21 +393,15 @@ public:
/* range quick selects this index_merge read consists of */ /* range quick selects this index_merge read consists of */
List<QUICK_RANGE_SELECT> quick_selects; List<QUICK_RANGE_SELECT> quick_selects;
/* quick select which is currently used for rows retrieval */
List_iterator_fast<QUICK_RANGE_SELECT> cur_quick_it;
QUICK_RANGE_SELECT* cur_quick_select;
/* quick select that uses clustered primary key (NULL if none) */ /* quick select that uses clustered primary key (NULL if none) */
QUICK_RANGE_SELECT* pk_quick_select; QUICK_RANGE_SELECT* pk_quick_select;
/* true if this select is currently doing a clustered PK scan */ /* true if this select is currently doing a clustered PK scan */
bool doing_pk_scan; bool doing_pk_scan;
Unique *unique;
MEM_ROOT alloc; MEM_ROOT alloc;
THD *thd; THD *thd;
int prepare_unique(); int read_keys_and_merge();
/* used to get rows collected in Unique */ /* used to get rows collected in Unique */
READ_RECORD read_record; READ_RECORD read_record;
...@@ -465,6 +464,8 @@ public: ...@@ -465,6 +464,8 @@ public:
MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */ MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */
THD *thd; /* current thread */ THD *thd; /* current thread */
bool need_to_fetch_row; /* if true, do retrieve full table records. */ bool need_to_fetch_row; /* if true, do retrieve full table records. */
/* in top-level quick select, true if merged scans where initialized */
bool scans_inited;
}; };
...@@ -514,6 +515,7 @@ public: ...@@ -514,6 +515,7 @@ public:
uint rowid_length; /* table rowid length */ uint rowid_length; /* table rowid length */
private: private:
static int queue_cmp(void *arg, byte *val1, byte *val2); static int queue_cmp(void *arg, byte *val1, byte *val2);
bool scans_inited;
}; };
......
...@@ -64,6 +64,7 @@ static void best_extension_by_limited_search(JOIN *join, ...@@ -64,6 +64,7 @@ static void best_extension_by_limited_search(JOIN *join,
uint prune_level); uint prune_level);
static uint determine_search_depth(JOIN* join); static uint determine_search_depth(JOIN* join);
static int join_tab_cmp(const void* ptr1, const void* ptr2); static int join_tab_cmp(const void* ptr1, const void* ptr2);
static int join_tab_cmp_straight(const void* ptr1, const void* ptr2);
/* /*
TODO: 'find_best' is here only temporarily until 'greedy_search' is TODO: 'find_best' is here only temporarily until 'greedy_search' is
tested and approved. tested and approved.
...@@ -3678,22 +3679,26 @@ choose_plan(JOIN *join, table_map join_tables) ...@@ -3678,22 +3679,26 @@ choose_plan(JOIN *join, table_map join_tables)
{ {
uint search_depth= join->thd->variables.optimizer_search_depth; uint search_depth= join->thd->variables.optimizer_search_depth;
uint prune_level= join->thd->variables.optimizer_prune_level; uint prune_level= join->thd->variables.optimizer_prune_level;
bool straight_join= join->select_options & SELECT_STRAIGHT_JOIN;
DBUG_ENTER("choose_plan"); DBUG_ENTER("choose_plan");
if (join->select_options & SELECT_STRAIGHT_JOIN)
{
optimize_straight_join(join, join_tables);
}
else
{
/* /*
Heuristic: pre-sort all access plans with respect to the number of if (SELECT_STRAIGHT_JOIN option is set)
reorder tables so dependent tables come after tables they depend
on, otherwise keep tables in the order they were specified in the query
else
Apply heuristic: pre-sort all access plans with respect to the number of
records accessed. records accessed.
*/ */
qsort(join->best_ref + join->const_tables, join->tables - join->const_tables, qsort(join->best_ref + join->const_tables, join->tables - join->const_tables,
sizeof(JOIN_TAB*), join_tab_cmp); sizeof(JOIN_TAB*), straight_join?join_tab_cmp_straight:join_tab_cmp);
if (straight_join)
{
optimize_straight_join(join, join_tables);
}
else
{
if (search_depth == MAX_TABLES+2) if (search_depth == MAX_TABLES+2)
{ /* { /*
TODO: 'MAX_TABLES+2' denotes the old implementation of find_best before TODO: 'MAX_TABLES+2' denotes the old implementation of find_best before
...@@ -3750,6 +3755,23 @@ join_tab_cmp(const void* ptr1, const void* ptr2) ...@@ -3750,6 +3755,23 @@ join_tab_cmp(const void* ptr1, const void* ptr2)
} }
/*
Same as join_tab_cmp, but for use with SELECT_STRAIGHT_JOIN.
*/
static int
join_tab_cmp_straight(const void* ptr1, const void* ptr2)
{
JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;
if (jt1->dependent & jt2->table->map)
return 1;
if (jt2->dependent & jt1->table->map)
return -1;
return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
}
/* /*
Heuristic procedure to automatically guess a reasonable degree of Heuristic procedure to automatically guess a reasonable degree of
exhaustiveness for the greedy search procedure. exhaustiveness for the greedy search procedure.
......
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