summaryrefslogtreecommitdiff
path: root/sql/opt_range.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/opt_range.cc')
-rw-r--r--sql/opt_range.cc142
1 files changed, 96 insertions, 46 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index f9149f10a30..e47c7e147a7 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -746,7 +746,7 @@ int QUICK_RANGE_SELECT::init()
void QUICK_RANGE_SELECT::range_end()
{
if (file->inited != handler::NONE)
- file->ha_index_end();
+ file->ha_index_or_rnd_end();
}
@@ -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();
@@ -3687,7 +3708,8 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
}
/* Get local copy of key */
copies= 1;
- if (field->key_type() == HA_KEYTYPE_VARTEXT)
+ if (field->key_type() == HA_KEYTYPE_VARTEXT1 ||
+ field->key_type() == HA_KEYTYPE_VARTEXT2)
copies= 2;
str= str2= (char*) alloc_root(param->mem_root,
(key_part->store_length)*copies+1);
@@ -4999,7 +5021,9 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
char *min_key,uint min_key_flag, char *max_key,
uint max_key_flag)
{
- ha_rows records=0,tmp;
+ ha_rows records=0, tmp;
+ uint tmp_min_flag, tmp_max_flag, keynr, min_key_length, max_key_length;
+ char *tmp_min_key, *tmp_max_key;
param->max_key_part=max(param->max_key_part,key_tree->part);
if (key_tree->left != &null_element)
@@ -5017,13 +5041,12 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
return records;
}
- uint tmp_min_flag,tmp_max_flag,keynr;
- char *tmp_min_key=min_key,*tmp_max_key=max_key;
-
+ tmp_min_key= min_key;
+ tmp_max_key= max_key;
key_tree->store(param->key[idx][key_tree->part].store_length,
&tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
- uint min_key_length= (uint) (tmp_min_key- param->min_key);
- uint max_key_length= (uint) (tmp_max_key- param->max_key);
+ min_key_length= (uint) (tmp_min_key- param->min_key);
+ max_key_length= (uint) (tmp_max_key- param->max_key);
if (param->is_ror_scan)
{
@@ -5551,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
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. */
@@ -5581,7 +5611,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,
@@ -5590,24 +5630,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;
}
@@ -5618,8 +5662,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);
@@ -5627,6 +5671,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);
@@ -5666,6 +5711,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());
}
}
@@ -5888,7 +5934,7 @@ int QUICK_RANGE_SELECT::get_next()
SYNOPSIS
QUICK_RANGE_SELECT::get_next_prefix()
prefix_length length of cur_prefix
- cur_prefix prefix of a key to be searached for
+ cur_prefix prefix of a key to be searched for
DESCRIPTION
Each subsequent call to the method retrieves the first record that has a
@@ -7402,7 +7448,8 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
quick->quick_prefix_select= NULL; /* Can't construct a quick select. */
else
/* Make a QUICK_RANGE_SELECT to be used for group prefix retrieval. */
- quick->quick_prefix_select= get_quick_select(param, param_idx, index_tree,
+ quick->quick_prefix_select= get_quick_select(param, param_idx,
+ index_tree,
&quick->alloc);
/*
@@ -8446,7 +8493,10 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
store_length--;
}
field->set_key_image((char*) key, key_part->length);
- field->val_str(&tmp);
+ if (field->type() == MYSQL_TYPE_BIT)
+ (void) field->val_int_as_str(&tmp, 1);
+ else
+ field->val_str(&tmp);
fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE);
if (key+store_length < key_end)
fputc('/',DBUG_FILE);