Merging index_merge/Unique into 5.0
This commit is contained in:
commit
5f9718adfb
@ -48,7 +48,8 @@ static int merge_index(SORTPARAM *param,uchar *sort_buffer,
|
|||||||
BUFFPEK *buffpek,
|
BUFFPEK *buffpek,
|
||||||
uint maxbuffer,IO_CACHE *tempfile,
|
uint maxbuffer,IO_CACHE *tempfile,
|
||||||
IO_CACHE *outfile);
|
IO_CACHE *outfile);
|
||||||
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
|
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count,
|
||||||
|
FILESORT_INFO *table_sort);
|
||||||
static uint sortlength(SORT_FIELD *sortorder, uint s_length,
|
static uint sortlength(SORT_FIELD *sortorder, uint s_length,
|
||||||
bool *multi_byte_charset);
|
bool *multi_byte_charset);
|
||||||
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
|
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
|
||||||
@ -85,6 +86,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
|
|||||||
#ifdef SKIP_DBUG_IN_FILESORT
|
#ifdef SKIP_DBUG_IN_FILESORT
|
||||||
DBUG_PUSH(""); /* No DBUG here */
|
DBUG_PUSH(""); /* No DBUG here */
|
||||||
#endif
|
#endif
|
||||||
|
FILESORT_INFO table_sort;
|
||||||
|
bzero(&table_sort, sizeof(FILESORT_INFO));
|
||||||
|
|
||||||
outfile= table->sort.io_cache;
|
outfile= table->sort.io_cache;
|
||||||
my_b_clear(&tempfile);
|
my_b_clear(&tempfile);
|
||||||
@ -107,14 +110,15 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
|
|||||||
param.sort_length,
|
param.sort_length,
|
||||||
¶m.addon_length);
|
¶m.addon_length);
|
||||||
}
|
}
|
||||||
table->sort.addon_buf= 0;
|
|
||||||
table->sort.addon_length= param.addon_length;
|
table_sort.addon_buf= 0;
|
||||||
table->sort.addon_field= param.addon_field;
|
table_sort.addon_length= param.addon_length;
|
||||||
table->sort.unpack= unpack_addon_fields;
|
table_sort.addon_field= param.addon_field;
|
||||||
|
table_sort.unpack= unpack_addon_fields;
|
||||||
if (param.addon_field)
|
if (param.addon_field)
|
||||||
{
|
{
|
||||||
param.res_length= param.addon_length;
|
param.res_length= param.addon_length;
|
||||||
if (!(table->sort.addon_buf= (byte *) my_malloc(param.addon_length,
|
if (!(table_sort.addon_buf= (byte *) my_malloc(param.addon_length,
|
||||||
MYF(MY_WME))))
|
MYF(MY_WME))))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -193,7 +197,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
|
|||||||
|
|
||||||
if (maxbuffer == 0) // The whole set is in memory
|
if (maxbuffer == 0) // The whole set is in memory
|
||||||
{
|
{
|
||||||
if (save_index(¶m,sort_keys,(uint) records))
|
if (save_index(¶m,sort_keys,(uint) records, &table_sort))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -256,6 +260,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
|
|||||||
#ifdef SKIP_DBUG_IN_FILESORT
|
#ifdef SKIP_DBUG_IN_FILESORT
|
||||||
DBUG_POP(); /* Ok to DBUG */
|
DBUG_POP(); /* Ok to DBUG */
|
||||||
#endif
|
#endif
|
||||||
|
memcpy(&table->sort, &table_sort, sizeof(FILESORT_INFO));
|
||||||
|
table->sort.io_cache= outfile;
|
||||||
DBUG_PRINT("exit",("records: %ld",records));
|
DBUG_PRINT("exit",("records: %ld",records));
|
||||||
DBUG_RETURN(error ? HA_POS_ERROR : records);
|
DBUG_RETURN(error ? HA_POS_ERROR : records);
|
||||||
} /* filesort */
|
} /* filesort */
|
||||||
@ -359,12 +365,24 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
|
|||||||
current_thd->variables.read_buff_size);
|
current_thd->variables.read_buff_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
READ_RECORD read_record_info;
|
||||||
|
if (quick_select)
|
||||||
|
{
|
||||||
|
if (select->quick->reset())
|
||||||
|
DBUG_RETURN(HA_POS_ERROR);
|
||||||
|
init_read_record(&read_record_info, current_thd, select->quick->head,
|
||||||
|
select, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (quick_select)
|
if (quick_select)
|
||||||
{
|
{
|
||||||
if ((error=select->quick->get_next()))
|
if ((error= read_record_info.read_record(&read_record_info)))
|
||||||
|
{
|
||||||
|
error= HA_ERR_END_OF_FILE;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
file->position(sort_form->record[0]);
|
file->position(sort_form->record[0]);
|
||||||
}
|
}
|
||||||
else /* Not quick-select */
|
else /* Not quick-select */
|
||||||
@ -392,6 +410,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
|
|||||||
if (error && error != HA_ERR_RECORD_DELETED)
|
if (error && error != HA_ERR_RECORD_DELETED)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*killed)
|
if (*killed)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info",("Sort killed by user"));
|
DBUG_PRINT("info",("Sort killed by user"));
|
||||||
@ -425,8 +444,14 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
|
|||||||
else
|
else
|
||||||
file->unlock_row();
|
file->unlock_row();
|
||||||
}
|
}
|
||||||
|
if (quick_select)
|
||||||
|
end_read_record(&read_record_info);
|
||||||
|
else
|
||||||
|
{
|
||||||
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
|
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
|
||||||
file->rnd_end();
|
file->rnd_end();
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos));
|
DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos));
|
||||||
if (error != HA_ERR_END_OF_FILE)
|
if (error != HA_ERR_END_OF_FILE)
|
||||||
{
|
{
|
||||||
@ -664,8 +689,8 @@ static void make_sortkey(register SORTPARAM *param,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count,
|
||||||
static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count)
|
FILESORT_INFO *table_sort)
|
||||||
{
|
{
|
||||||
uint offset,res_length;
|
uint offset,res_length;
|
||||||
byte *to;
|
byte *to;
|
||||||
@ -676,7 +701,7 @@ static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count)
|
|||||||
offset= param->rec_length-res_length;
|
offset= param->rec_length-res_length;
|
||||||
if ((ha_rows) count > param->max_rows)
|
if ((ha_rows) count > param->max_rows)
|
||||||
count=(uint) param->max_rows;
|
count=(uint) param->max_rows;
|
||||||
if (!(to= param->sort_form->sort.record_pointers=
|
if (!(to= table_sort->record_pointers=
|
||||||
(byte*) my_malloc(res_length*count, MYF(MY_WME))))
|
(byte*) my_malloc(res_length*count, MYF(MY_WME))))
|
||||||
DBUG_RETURN(1); /* purecov: inspected */
|
DBUG_RETURN(1); /* purecov: inspected */
|
||||||
for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
|
for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
|
||||||
|
236
sql/opt_range.cc
236
sql/opt_range.cc
@ -649,27 +649,32 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd, TABLE *table)
|
QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param, TABLE *table)
|
||||||
:cur_quick_it(quick_selects), index_merge(thd)
|
:cur_quick_it(quick_selects), thd(thd_param), unique(NULL)
|
||||||
{
|
{
|
||||||
index= MAX_KEY;
|
index= MAX_KEY;
|
||||||
head= table;
|
head= table;
|
||||||
|
reset_called= false;
|
||||||
init_sql_alloc(&alloc,1024,0);
|
init_sql_alloc(&alloc,1024,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int QUICK_INDEX_MERGE_SELECT::init()
|
int QUICK_INDEX_MERGE_SELECT::init()
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
cur_quick_it.rewind();
|
cur_quick_it.rewind();
|
||||||
cur_quick_select= cur_quick_it++;
|
cur_quick_select= cur_quick_it++;
|
||||||
if ((error= index_merge.init(head)))
|
|
||||||
return error;
|
|
||||||
return cur_quick_select->init();
|
return cur_quick_select->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QUICK_INDEX_MERGE_SELECT::reset()
|
int QUICK_INDEX_MERGE_SELECT::reset()
|
||||||
{
|
{
|
||||||
cur_quick_select->reset();
|
int result;
|
||||||
|
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::reset");
|
||||||
|
if (reset_called)
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
reset_called= true;
|
||||||
|
result = cur_quick_select->reset() && prepare_unique();
|
||||||
|
DBUG_RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1150,12 +1155,6 @@ imerge_fail:;
|
|||||||
("Failed to allocate index merge structures,"
|
("Failed to allocate index merge structures,"
|
||||||
"falling back to full scan."));
|
"falling back to full scan."));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* with 'using filesort' quick->reset() is not called */
|
|
||||||
quick->reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1170,9 +1169,9 @@ end:
|
|||||||
DBUG_EXECUTE("info",
|
DBUG_EXECUTE("info",
|
||||||
{
|
{
|
||||||
if (quick_imerge)
|
if (quick_imerge)
|
||||||
print_quick_sel_imerge(quick_imerge, &needed_reg);
|
print_quick_sel_imerge(quick_imerge, needed_reg);
|
||||||
else
|
else
|
||||||
print_quick_sel_range((QUICK_RANGE_SELECT*)quick, &needed_reg);
|
print_quick_sel_range((QUICK_RANGE_SELECT*)quick, needed_reg);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1721,6 +1720,7 @@ tree_and(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
|
|||||||
uint flag=0;
|
uint flag=0;
|
||||||
if (*key1 || *key2)
|
if (*key1 || *key2)
|
||||||
{
|
{
|
||||||
|
trees_have_key = true;
|
||||||
if (*key1 && !(*key1)->simple_key())
|
if (*key1 && !(*key1)->simple_key())
|
||||||
flag|=CLONE_KEY1_MAYBE;
|
flag|=CLONE_KEY1_MAYBE;
|
||||||
if (*key2 && !(*key2)->simple_key())
|
if (*key2 && !(*key2)->simple_key())
|
||||||
@ -3079,165 +3079,24 @@ err:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
INDEX_MERGE::INDEX_MERGE(THD *thd_arg) :
|
|
||||||
dont_save(false), thd(thd_arg)
|
|
||||||
{}
|
|
||||||
|
|
||||||
String *INDEX_MERGE::Item_rowid::val_str(String *str)
|
|
||||||
{
|
|
||||||
str->set_quick((char*)head->file->ref, head->file->ref_length, collation.collation);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
|
||||||
/*
|
/*
|
||||||
Initialize index_merge operation.
|
Fetch all row ids into unique.
|
||||||
RETURN
|
|
||||||
0 - OK
|
|
||||||
other - error.
|
|
||||||
*/
|
*/
|
||||||
|
int QUICK_INDEX_MERGE_SELECT::prepare_unique()
|
||||||
int INDEX_MERGE::init(TABLE *table)
|
|
||||||
{
|
|
||||||
DBUG_ENTER("INDEX_MERGE::init");
|
|
||||||
|
|
||||||
head= table;
|
|
||||||
if (!(rowid_item= new Item_rowid(table)))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
|
|
||||||
tmp_table_param.copy_field= 0;
|
|
||||||
tmp_table_param.end_write_records= HA_POS_ERROR;
|
|
||||||
tmp_table_param.group_length= table->file->ref_length;
|
|
||||||
tmp_table_param.group_parts= 1;
|
|
||||||
tmp_table_param.group_null_parts= 0;
|
|
||||||
tmp_table_param.hidden_field_count= 0;
|
|
||||||
tmp_table_param.field_count= 0;
|
|
||||||
tmp_table_param.func_count= 1;
|
|
||||||
tmp_table_param.sum_func_count= 0;
|
|
||||||
tmp_table_param.quick_group= 1;
|
|
||||||
|
|
||||||
bzero(&order, sizeof(ORDER));
|
|
||||||
order.item= (Item**)&rowid_item;
|
|
||||||
order.asc= 1;
|
|
||||||
|
|
||||||
fields.push_back(rowid_item);
|
|
||||||
|
|
||||||
temp_table= create_tmp_table(thd,
|
|
||||||
&tmp_table_param,
|
|
||||||
fields,
|
|
||||||
&order,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
SELECT_DISTINCT,
|
|
||||||
HA_POS_ERROR,
|
|
||||||
(char *)"");
|
|
||||||
DBUG_RETURN(!temp_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check if record with ROWID record_pos has already been processed and
|
|
||||||
if not - store the ROWID value.
|
|
||||||
|
|
||||||
RETURN
|
|
||||||
0 - record has not been processed yet
|
|
||||||
1 - record has already been processed.
|
|
||||||
-1 - an error occurred and query processing should be terminated.
|
|
||||||
Error code is stored in INDEX_MERGE::error
|
|
||||||
*/
|
|
||||||
|
|
||||||
int INDEX_MERGE::check_record_in()
|
|
||||||
{
|
|
||||||
return (dont_save)?
|
|
||||||
check_record() :
|
|
||||||
put_record();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Stop remembering records in check().
|
|
||||||
(this should be called just before the last key scan)
|
|
||||||
|
|
||||||
RETURN
|
|
||||||
0 - OK
|
|
||||||
1 - error occurred initializing table index.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int INDEX_MERGE::start_last_quick_select()
|
|
||||||
{
|
|
||||||
int result= 0;
|
|
||||||
if (!temp_table->uniques)
|
|
||||||
{
|
|
||||||
dont_save= true;
|
|
||||||
result= temp_table->file->index_init(0);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline int INDEX_MERGE::put_record()
|
|
||||||
{
|
|
||||||
DBUG_ENTER("INDEX_MERGE::put_record");
|
|
||||||
|
|
||||||
copy_funcs(tmp_table_param.items_to_copy);
|
|
||||||
|
|
||||||
if ((error= temp_table->file->write_row(temp_table->record[0])))
|
|
||||||
{
|
|
||||||
if (error == HA_ERR_FOUND_DUPP_KEY ||
|
|
||||||
error == HA_ERR_FOUND_DUPP_UNIQUE)
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
|
|
||||||
DBUG_PRINT("info",
|
|
||||||
("Error writing row to temp. table: %d, converting to myisam",
|
|
||||||
error));
|
|
||||||
if (create_myisam_from_heap(current_thd, temp_table, &tmp_table_param,
|
|
||||||
error,1))
|
|
||||||
{
|
|
||||||
DBUG_PRINT("info", ("Table conversion failed, bailing out"));
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int INDEX_MERGE::check_record()
|
|
||||||
{
|
|
||||||
int result= 1;
|
|
||||||
DBUG_ENTER("INDEX_MERGE::check_record");
|
|
||||||
|
|
||||||
if ((error= temp_table->file->index_read(temp_table->record[0],
|
|
||||||
head->file->ref,
|
|
||||||
head->file->ref_length,
|
|
||||||
HA_READ_KEY_EXACT)))
|
|
||||||
{
|
|
||||||
if (error != HA_ERR_KEY_NOT_FOUND)
|
|
||||||
result= -1;
|
|
||||||
else
|
|
||||||
result= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBUG_RETURN(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
INDEX_MERGE::~INDEX_MERGE()
|
|
||||||
{
|
|
||||||
if (temp_table)
|
|
||||||
{
|
|
||||||
DBUG_PRINT("info", ("Freeing temp. table"));
|
|
||||||
free_tmp_table(current_thd, temp_table);
|
|
||||||
}
|
|
||||||
/* rowid_item is freed automatically */
|
|
||||||
list_node* node;
|
|
||||||
node= fields.first_node();
|
|
||||||
fields.remove(&node);
|
|
||||||
}
|
|
||||||
|
|
||||||
int QUICK_INDEX_MERGE_SELECT::get_next()
|
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
int put_result;
|
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::prepare_unique");
|
||||||
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::get_next");
|
|
||||||
|
|
||||||
|
/* we're going to just read rowids */
|
||||||
|
head->file->extra(HA_EXTRA_KEYREAD);
|
||||||
|
|
||||||
|
unique= new Unique(refposcmp2, (void *) &head->file->ref_length,
|
||||||
|
head->file->ref_length,
|
||||||
|
MEM_STRIP_BUF_SIZE);
|
||||||
|
if (!unique)
|
||||||
|
DBUG_RETURN(1);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
while ((result= cur_quick_select->get_next()) == HA_ERR_END_OF_FILE)
|
while ((result= cur_quick_select->get_next()) == HA_ERR_END_OF_FILE)
|
||||||
@ -3245,15 +3104,9 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
|
|||||||
cur_quick_select= cur_quick_it++;
|
cur_quick_select= cur_quick_it++;
|
||||||
if (!cur_quick_select)
|
if (!cur_quick_select)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cur_quick_select->init();
|
cur_quick_select->init();
|
||||||
cur_quick_select->reset();
|
if (cur_quick_select->reset())
|
||||||
|
DBUG_RETURN(1);
|
||||||
if (last_quick_select == cur_quick_select)
|
|
||||||
{
|
|
||||||
if ((result= index_merge.start_last_quick_select()))
|
|
||||||
DBUG_RETURN(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
@ -3262,14 +3115,39 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
|
|||||||
table read error (including HA_ERR_END_OF_FILE on last quick select
|
table read error (including HA_ERR_END_OF_FILE on last quick select
|
||||||
in index_merge)
|
in index_merge)
|
||||||
*/
|
*/
|
||||||
|
if (result != HA_ERR_END_OF_FILE)
|
||||||
|
{
|
||||||
DBUG_RETURN(result);
|
DBUG_RETURN(result);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thd->killed)
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
cur_quick_select->file->position(cur_quick_select->record);
|
cur_quick_select->file->position(cur_quick_select->record);
|
||||||
put_result= index_merge.check_record_in();
|
if (unique->unique_add((char*)cur_quick_select->file->ref))
|
||||||
}while(put_result == 1); /* While record is processed */
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
DBUG_RETURN((put_result != -1) ? result : index_merge.error);
|
}while(true);
|
||||||
|
|
||||||
|
/* ok, all row ids are in Unique */
|
||||||
|
result= unique->get(head);
|
||||||
|
|
||||||
|
/* index_merge currently doesn't support "using index" at all */
|
||||||
|
head->file->extra(HA_EXTRA_NO_KEYREAD);
|
||||||
|
DBUG_RETURN(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int QUICK_INDEX_MERGE_SELECT::get_next()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::get_next");
|
||||||
|
|
||||||
|
DBUG_PRINT("QUICK_INDEX_MERGE_SELECT",
|
||||||
|
("ERROR: index merge error: get_next should not be called "));
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
DBUG_RETURN(HA_ERR_END_OF_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get next possible record using quick-struct */
|
/* get next possible record using quick-struct */
|
||||||
|
@ -65,7 +65,6 @@ class QUICK_RANGE :public Sql_alloc {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class INDEX_MERGE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Quick select interface.
|
Quick select interface.
|
||||||
@ -149,64 +148,6 @@ public:
|
|||||||
int get_type() { return QS_TYPE_RANGE; }
|
int get_type() { return QS_TYPE_RANGE; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Helper class for keeping track of rows that have been passed to output
|
|
||||||
in index_merge access method.
|
|
||||||
|
|
||||||
NOTES
|
|
||||||
Current implementation uses a temporary table to store ROWIDs of rows that
|
|
||||||
have been passed to output. In the future it might be changed to use more
|
|
||||||
efficient mechanisms, like Unique class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class INDEX_MERGE
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
INDEX_MERGE(THD *thd_arg);
|
|
||||||
~INDEX_MERGE();
|
|
||||||
|
|
||||||
int init(TABLE *table);
|
|
||||||
int check_record_in();
|
|
||||||
int start_last_quick_select();
|
|
||||||
int error;
|
|
||||||
private:
|
|
||||||
/* The only field in temporary table */
|
|
||||||
class Item_rowid : public Item_str_func
|
|
||||||
{
|
|
||||||
TABLE *head; /* source table */
|
|
||||||
public:
|
|
||||||
Item_rowid(TABLE *table) : head(table)
|
|
||||||
{
|
|
||||||
max_length= table->file->ref_length;
|
|
||||||
collation.set(&my_charset_bin);
|
|
||||||
};
|
|
||||||
const char *func_name() const { return "rowid"; }
|
|
||||||
bool const_item() const { return 0; }
|
|
||||||
String *val_str(String *);
|
|
||||||
void fix_length_and_dec()
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Check if record has been processed and save it if it wasn't */
|
|
||||||
inline int put_record();
|
|
||||||
|
|
||||||
/* Check if record has been processed without saving it */
|
|
||||||
inline int check_record();
|
|
||||||
|
|
||||||
/* If true, check_record_in does't store ROWIDs it is passed. */
|
|
||||||
bool dont_save;
|
|
||||||
|
|
||||||
THD *thd;
|
|
||||||
TABLE *head; /* source table */
|
|
||||||
TABLE *temp_table; /* temp. table used for values storage */
|
|
||||||
TMP_TABLE_PARAM tmp_table_param; /* temp. table creation parameters */
|
|
||||||
Item_rowid *rowid_item; /* the only field in temp. table */
|
|
||||||
List<Item> fields; /* temp. table fields list
|
|
||||||
(the only element is rowid_item) */
|
|
||||||
ORDER order; /* key for temp. table (rowid_item) */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Index merge quick select.
|
Index merge quick select.
|
||||||
It is implemented as a container for several QUICK_RANGE_SELECTs.
|
It is implemented as a container for several QUICK_RANGE_SELECTs.
|
||||||
@ -219,7 +160,7 @@ public:
|
|||||||
~QUICK_INDEX_MERGE_SELECT();
|
~QUICK_INDEX_MERGE_SELECT();
|
||||||
|
|
||||||
int init();
|
int init();
|
||||||
void reset(void);
|
int reset(void);
|
||||||
int get_next();
|
int get_next();
|
||||||
bool reverse_sorted() { return false; }
|
bool reverse_sorted() { return false; }
|
||||||
bool unique_key_range() { return false; }
|
bool unique_key_range() { return false; }
|
||||||
@ -234,20 +175,15 @@ public:
|
|||||||
List_iterator_fast<QUICK_RANGE_SELECT> cur_quick_it;
|
List_iterator_fast<QUICK_RANGE_SELECT> cur_quick_it;
|
||||||
QUICK_RANGE_SELECT* cur_quick_select;
|
QUICK_RANGE_SELECT* cur_quick_select;
|
||||||
|
|
||||||
/*
|
/* last element in quick_selects list. */
|
||||||
Last element in quick_selects list.
|
|
||||||
INDEX_MERGE::start_last_quick_select is called before retrieving
|
|
||||||
rows for it.
|
|
||||||
*/
|
|
||||||
QUICK_RANGE_SELECT* last_quick_select;
|
QUICK_RANGE_SELECT* last_quick_select;
|
||||||
|
|
||||||
/*
|
Unique *unique;
|
||||||
Used to keep track of what records have been already passed to output
|
|
||||||
when doing index_merge access (NULL means no index_merge)
|
|
||||||
*/
|
|
||||||
INDEX_MERGE index_merge;
|
|
||||||
|
|
||||||
MEM_ROOT alloc;
|
MEM_ROOT alloc;
|
||||||
|
|
||||||
|
THD *thd;
|
||||||
|
int prepare_unique();
|
||||||
|
bool reset_called;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QUICK_SELECT_DESC: public QUICK_RANGE_SELECT
|
class QUICK_SELECT_DESC: public QUICK_RANGE_SELECT
|
||||||
@ -263,7 +199,7 @@ private:
|
|||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
bool test_if_null_range(QUICK_RANGE *range, uint used_key_parts);
|
bool test_if_null_range(QUICK_RANGE *range, uint used_key_parts);
|
||||||
#endif
|
#endif
|
||||||
void reset(void) { next=0; rev_it.rewind(); }
|
int reset(void) { next=0; rev_it.rewind(); return 0; }
|
||||||
List<QUICK_RANGE> rev_ranges;
|
List<QUICK_RANGE> rev_ranges;
|
||||||
List_iterator<QUICK_RANGE> rev_it;
|
List_iterator<QUICK_RANGE> rev_it;
|
||||||
};
|
};
|
||||||
|
@ -97,7 +97,8 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (select && select->quick)
|
else if (select && select->quick &&
|
||||||
|
(select->quick->get_type() != QUICK_SELECT_I::QS_TYPE_INDEX_MERGE))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info",("using rr_quick"));
|
DBUG_PRINT("info",("using rr_quick"));
|
||||||
info->read_record=rr_quick;
|
info->read_record=rr_quick;
|
||||||
|
@ -5998,8 +5998,8 @@ test_if_quick_select(JOIN_TAB *tab)
|
|||||||
static int
|
static int
|
||||||
join_init_read_record(JOIN_TAB *tab)
|
join_init_read_record(JOIN_TAB *tab)
|
||||||
{
|
{
|
||||||
if (tab->select && tab->select->quick)
|
if (tab->select && tab->select->quick && tab->select->quick->reset())
|
||||||
tab->select->quick->reset();
|
return 1;
|
||||||
init_read_record(&tab->read_record, tab->join->thd, tab->table,
|
init_read_record(&tab->read_record, tab->join->thd, tab->table,
|
||||||
tab->select,1,1);
|
tab->select,1,1);
|
||||||
return (*tab->read_record.read_record)(&tab->read_record);
|
return (*tab->read_record.read_record)(&tab->read_record);
|
||||||
|
@ -316,6 +316,9 @@ uint find_shortest_key(TABLE *table, const key_map *usable_keys);
|
|||||||
/* functions from opt_sum.cc */
|
/* functions from opt_sum.cc */
|
||||||
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds);
|
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds);
|
||||||
|
|
||||||
|
/* from sql_delete.cc, used by opt_range.cc */
|
||||||
|
extern "C" int refposcmp2(void* arg, const void *a,const void *b);
|
||||||
|
|
||||||
/* class to copying an field/item to a key struct */
|
/* class to copying an field/item to a key struct */
|
||||||
|
|
||||||
class store_key :public Sql_alloc
|
class store_key :public Sql_alloc
|
||||||
|
@ -192,7 +192,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
|
|||||||
union_result->not_describe=1;
|
union_result->not_describe=1;
|
||||||
union_result->tmp_table_param=tmp_table_param;
|
union_result->tmp_table_param=tmp_table_param;
|
||||||
|
|
||||||
for (;sl; sl= sl->next_select())
|
for (sl= select_cursor; sl; sl= sl->next_select())
|
||||||
{
|
{
|
||||||
JOIN *join= new JOIN(thd, sl->item_list,
|
JOIN *join= new JOIN(thd, sl->item_list,
|
||||||
sl->options | thd->options | SELECT_NO_UNLOCK,
|
sl->options | thd->options | SELECT_NO_UNLOCK,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user