mirror of
https://github.com/MariaDB/server.git
synced 2025-07-08 17:02:21 +03:00
Fix for BUG#4177:
* Make index merge quick selects code allow perform several scans. * Delay additional handler objects creation till row retrieval is started. include/queues.h: Added trivial queue_remove_all macro mysql-test/r/index_merge.result: Testcase for BUG#4177 mysql-test/t/index_merge.test: Testcase for BUG#4177 sql/opt_range.cc: Fix for BUG#4177: * For any quick select, row retrieval can be performed several times. Now all index_merge quick selects code handles such cases properly. * In QUICK_INDEX_MERGE_SELECT we use one handler object for all merged scans, and it was possible that in destructor several cleanup functions were called * Additionally - Removed redundant QUICK_INDEX_MERGE_SELECT members. - Now QUICK_ROR_*_SELECTs create additional handler objects only when row retrieval is started So if join optimizer chooses other access method, we don't create/delete handlers.
This commit is contained in:
@ -53,6 +53,7 @@ int resize_queue(QUEUE *queue, uint max_elements);
|
||||
void delete_queue(QUEUE *queue);
|
||||
void queue_insert(QUEUE *queue,byte *element);
|
||||
byte *queue_remove(QUEUE *queue,uint idx);
|
||||
#define queue_remove_all(queue) { (queue)->elements= 0; }
|
||||
void _downheap(QUEUE *queue,uint idx);
|
||||
void queue_fix(QUEUE *queue);
|
||||
#define is_queue_inited(queue) ((queue)->root != 0)
|
||||
|
@ -1,4 +1,4 @@
|
||||
drop table if exists t0, t1, t2, t3,t4;
|
||||
drop table if exists t0, t1, t2, t3, t4;
|
||||
create table t0
|
||||
(
|
||||
key1 int not null,
|
||||
@ -335,4 +335,55 @@ key1 key2 key3 key4 key5 key6 key7 key8
|
||||
select count(*) from t0;
|
||||
count(*)
|
||||
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;
|
||||
|
@ -1,9 +1,8 @@
|
||||
#
|
||||
# Index merge tests
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t0, t1, t2, t3,t4;
|
||||
drop table if exists t0, t1, t2, t3, t4;
|
||||
--enable_warnings
|
||||
|
||||
# Create and fill a table with simple keys
|
||||
@ -278,4 +277,48 @@ delete from t0 where key1 < 3 or key2 < 4;
|
||||
select * from t0 where key1 < 3 or key2 < 4;
|
||||
select count(*) from t0;
|
||||
|
||||
drop table t0, t1, t2, t3, t4;
|
||||
# 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;
|
||||
|
||||
|
114
sql/opt_range.cc
114
sql/opt_range.cc
@ -777,8 +777,7 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT()
|
||||
|
||||
QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param,
|
||||
TABLE *table)
|
||||
:cur_quick_it(quick_selects),pk_quick_select(NULL),unique(NULL),
|
||||
thd(thd_param)
|
||||
:pk_quick_select(NULL), thd(thd_param)
|
||||
{
|
||||
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT");
|
||||
index= MAX_KEY;
|
||||
@ -790,17 +789,14 @@ QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param,
|
||||
|
||||
int QUICK_INDEX_MERGE_SELECT::init()
|
||||
{
|
||||
cur_quick_it.rewind();
|
||||
cur_quick_select= cur_quick_it++;
|
||||
return 0;
|
||||
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::init");
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
int QUICK_INDEX_MERGE_SELECT::reset()
|
||||
{
|
||||
int result;
|
||||
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::reset");
|
||||
result= cur_quick_select->reset() || prepare_unique();
|
||||
DBUG_RETURN(result);
|
||||
DBUG_RETURN(read_keys_and_merge());
|
||||
}
|
||||
|
||||
bool
|
||||
@ -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()
|
||||
{
|
||||
List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects);
|
||||
QUICK_RANGE_SELECT* quick;
|
||||
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();
|
||||
delete pk_quick_select;
|
||||
free_root(&alloc,MYF(0));
|
||||
@ -833,7 +833,8 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param,
|
||||
TABLE *table,
|
||||
bool retrieve_full_rows,
|
||||
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;
|
||||
head= table;
|
||||
@ -859,8 +860,9 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param,
|
||||
|
||||
int QUICK_ROR_INTERSECT_SELECT::init()
|
||||
{
|
||||
/* Check if last_rowid was successfully allocated in ctor */
|
||||
return !last_rowid;
|
||||
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::init");
|
||||
/* Check if last_rowid was successfully allocated in ctor */
|
||||
DBUG_RETURN(!last_rowid);
|
||||
}
|
||||
|
||||
|
||||
@ -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");
|
||||
|
||||
/* 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)
|
||||
{
|
||||
quick= quick_it++;
|
||||
@ -995,7 +997,14 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
|
||||
int 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()
|
||||
|
||||
QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
|
||||
TABLE *table)
|
||||
:thd(thd_param)
|
||||
: thd(thd_param), scans_inited(false)
|
||||
{
|
||||
index= MAX_KEY;
|
||||
head= table;
|
||||
@ -1057,18 +1066,19 @@ QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
|
||||
|
||||
int QUICK_ROR_UNION_SELECT::init()
|
||||
{
|
||||
DBUG_ENTER("QUICK_ROR_UNION_SELECT::init");
|
||||
if (init_queue(&queue, quick_selects.elements, 0,
|
||||
FALSE , QUICK_ROR_UNION_SELECT::queue_cmp,
|
||||
(void*) this))
|
||||
{
|
||||
bzero(&queue, sizeof(QUEUE));
|
||||
return 1;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
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;
|
||||
return 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
@ -1106,6 +1116,18 @@ int QUICK_ROR_UNION_SELECT::reset()
|
||||
int error;
|
||||
DBUG_ENTER("QUICK_ROR_UNION_SELECT::reset");
|
||||
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
|
||||
selects into the queue.
|
||||
@ -1113,7 +1135,7 @@ int QUICK_ROR_UNION_SELECT::reset()
|
||||
List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
|
||||
while ((quick= it++))
|
||||
{
|
||||
if (quick->init_ror_merged_scan(FALSE))
|
||||
if (quick->reset())
|
||||
DBUG_RETURN(1);
|
||||
if ((error= quick->get_next()))
|
||||
{
|
||||
@ -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",
|
||||
keys_to_use.to_ulonglong(), (ulong) prev_tables,
|
||||
(ulong) const_tables));
|
||||
|
||||
delete quick;
|
||||
quick=0;
|
||||
needed_reg.clear_all();
|
||||
@ -5545,22 +5566,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
|
||||
and innodb currently) and one of the index_merge scans is a scan on PK,
|
||||
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
|
||||
rows that will be retrieved by PK scan are not put into Unique and
|
||||
primary key scan is not performed here, it is performed later separately.
|
||||
|
||||
RETURN
|
||||
0 OK
|
||||
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;
|
||||
Unique *unique;
|
||||
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::prepare_unique");
|
||||
|
||||
/* We're going to just read rowids. */
|
||||
@ -5575,7 +5603,17 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique()
|
||||
*/
|
||||
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,
|
||||
head->file->ref_length,
|
||||
@ -5584,24 +5622,28 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique()
|
||||
DBUG_RETURN(1);
|
||||
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_select= cur_quick_it++;
|
||||
if (!cur_quick_select)
|
||||
cur_quick->range_end();
|
||||
cur_quick= cur_quick_it++;
|
||||
if (!cur_quick)
|
||||
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);
|
||||
|
||||
/* QUICK_RANGE_SELECT::reset never fails */
|
||||
cur_quick_select->reset();
|
||||
cur_quick->reset();
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (result != HA_ERR_END_OF_FILE)
|
||||
{
|
||||
cur_quick->range_end();
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -5612,8 +5654,8 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique()
|
||||
if (pk_quick_select && pk_quick_select->row_in_ranges())
|
||||
continue;
|
||||
|
||||
cur_quick_select->file->position(cur_quick_select->record);
|
||||
result= unique->unique_add((char*)cur_quick_select->file->ref);
|
||||
cur_quick->file->position(cur_quick->record);
|
||||
result= unique->unique_add((char*)cur_quick->file->ref);
|
||||
if (result)
|
||||
DBUG_RETURN(1);
|
||||
|
||||
@ -5621,6 +5663,7 @@ int QUICK_INDEX_MERGE_SELECT::prepare_unique()
|
||||
|
||||
/* ok, all row ids are in Unique */
|
||||
result= unique->get(head);
|
||||
delete unique;
|
||||
doing_pk_scan= FALSE;
|
||||
/* start table scan */
|
||||
init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1, 1);
|
||||
@ -5660,6 +5703,7 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
|
||||
doing_pk_scan= TRUE;
|
||||
if ((result= pk_quick_select->init()))
|
||||
DBUG_RETURN(result);
|
||||
pk_quick_select->reset();
|
||||
DBUG_RETURN(pk_quick_select->get_next());
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,8 @@ public:
|
||||
reset() should be called when it is certain that row retrieval will be
|
||||
necessary. This call may do heavyweight initialization like buffering first
|
||||
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
|
||||
0 OK
|
||||
other Error code
|
||||
@ -274,6 +275,10 @@ public:
|
||||
next=0;
|
||||
range= NULL;
|
||||
cur_range= NULL;
|
||||
/*
|
||||
Note: in opt_range.cc there are places where it is assumed that this
|
||||
function always succeeds
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
int init();
|
||||
@ -388,21 +393,15 @@ public:
|
||||
/* range quick selects this index_merge read consists of */
|
||||
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_RANGE_SELECT* pk_quick_select;
|
||||
|
||||
/* true if this select is currently doing a clustered PK scan */
|
||||
bool doing_pk_scan;
|
||||
|
||||
Unique *unique;
|
||||
MEM_ROOT alloc;
|
||||
|
||||
THD *thd;
|
||||
int prepare_unique();
|
||||
int read_keys_and_merge();
|
||||
|
||||
/* used to get rows collected in Unique */
|
||||
READ_RECORD read_record;
|
||||
@ -465,6 +464,8 @@ public:
|
||||
MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */
|
||||
THD *thd; /* current thread */
|
||||
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:
|
||||
uint rowid_length; /* table rowid length */
|
||||
private:
|
||||
static int queue_cmp(void *arg, byte *val1, byte *val2);
|
||||
bool scans_inited;
|
||||
};
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user