mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
10.0-base merge
This commit is contained in:
100
sql/opt_range.cc
100
sql/opt_range.cc
@ -117,6 +117,7 @@
|
||||
#include "records.h" // init_read_record, end_read_record
|
||||
#include <m_ctype.h>
|
||||
#include "sql_select.h"
|
||||
#include "filesort.h" // filesort_free_buffers
|
||||
|
||||
#ifndef EXTRA_DEBUG
|
||||
#define test_rb_tree(A,B) {}
|
||||
@ -1772,7 +1773,8 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
|
||||
index= key_nr;
|
||||
head= table;
|
||||
key_part_info= head->key_info[index].key_part;
|
||||
my_init_dynamic_array(&ranges, sizeof(QUICK_RANGE*), 16, 16);
|
||||
my_init_dynamic_array(&ranges, sizeof(QUICK_RANGE*), 16, 16,
|
||||
MYF(MY_THREAD_SPECIFIC));
|
||||
|
||||
/* 'thd' is not accessible in QUICK_RANGE_SELECT::reset(). */
|
||||
mrr_buf_size= thd->variables.mrr_buff_size;
|
||||
@ -1781,7 +1783,8 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
|
||||
if (!no_alloc && !parent_alloc)
|
||||
{
|
||||
// Allocates everything through the internal memroot
|
||||
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
|
||||
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
|
||||
MYF(MY_THREAD_SPECIFIC));
|
||||
thd->mem_root= &alloc;
|
||||
}
|
||||
else
|
||||
@ -1791,7 +1794,7 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
|
||||
|
||||
/* Allocate a bitmap for used columns (Q: why not on MEM_ROOT?) */
|
||||
if (!(bitmap= (my_bitmap_map*) my_malloc(head->s->column_bitmap_size,
|
||||
MYF(MY_WME))))
|
||||
MYF(MY_WME | MY_THREAD_SPECIFIC))))
|
||||
{
|
||||
column_bitmap.bitmap= 0;
|
||||
*create_error= 1;
|
||||
@ -1876,7 +1879,8 @@ QUICK_INDEX_SORT_SELECT::QUICK_INDEX_SORT_SELECT(THD *thd_param,
|
||||
index= MAX_KEY;
|
||||
head= table;
|
||||
bzero(&read_record, sizeof(read_record));
|
||||
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
|
||||
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
|
||||
MYF(MY_THREAD_SPECIFIC));
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@ -1889,7 +1893,8 @@ int QUICK_INDEX_SORT_SELECT::init()
|
||||
int QUICK_INDEX_SORT_SELECT::reset()
|
||||
{
|
||||
DBUG_ENTER("QUICK_INDEX_SORT_SELECT::reset");
|
||||
DBUG_RETURN(read_keys_and_merge());
|
||||
const int retval= read_keys_and_merge();
|
||||
DBUG_RETURN(retval);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1946,7 +1951,8 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param,
|
||||
head= table;
|
||||
record= head->record[0];
|
||||
if (!parent_alloc)
|
||||
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
|
||||
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
|
||||
MYF(MY_THREAD_SPECIFIC));
|
||||
else
|
||||
bzero(&alloc, sizeof(MEM_ROOT));
|
||||
last_rowid= (uchar*) alloc_root(parent_alloc? parent_alloc : &alloc,
|
||||
@ -2140,8 +2146,9 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
|
||||
There is no use of this->file. Use it for the first of merged range
|
||||
selects.
|
||||
*/
|
||||
if (quick->init_ror_merged_scan(TRUE))
|
||||
DBUG_RETURN(1);
|
||||
int error= quick->init_ror_merged_scan(TRUE);
|
||||
if (error)
|
||||
DBUG_RETURN(error);
|
||||
quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
|
||||
}
|
||||
while ((cur= quick_it++))
|
||||
@ -2244,7 +2251,8 @@ QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
|
||||
head= table;
|
||||
rowid_length= table->file->ref_length;
|
||||
record= head->record[0];
|
||||
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
|
||||
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
|
||||
MYF(MY_THREAD_SPECIFIC));
|
||||
thd_param->mem_root= &alloc;
|
||||
}
|
||||
|
||||
@ -2334,8 +2342,8 @@ int QUICK_ROR_UNION_SELECT::reset()
|
||||
List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
|
||||
while ((quick= it++))
|
||||
{
|
||||
if (quick->reset())
|
||||
DBUG_RETURN(1);
|
||||
if ((error= quick->reset()))
|
||||
DBUG_RETURN(error);
|
||||
if ((error= quick->get_next()))
|
||||
{
|
||||
if (error == HA_ERR_END_OF_FILE)
|
||||
@ -2346,10 +2354,10 @@ int QUICK_ROR_UNION_SELECT::reset()
|
||||
queue_insert(&queue, (uchar*)quick);
|
||||
}
|
||||
|
||||
if (head->file->ha_rnd_init_with_error(1))
|
||||
if ((error= head->file->ha_rnd_init(1)))
|
||||
{
|
||||
DBUG_PRINT("error", ("ROR index_merge rnd_init call failed"));
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
DBUG_RETURN(0);
|
||||
@ -2978,7 +2986,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
||||
param.force_default_mrr= ordered_output;
|
||||
|
||||
thd->no_errors=1; // Don't warn about NULL
|
||||
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
|
||||
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
|
||||
MYF(MY_THREAD_SPECIFIC));
|
||||
if (!(param.key_parts=
|
||||
(KEY_PART*) alloc_root(&alloc,
|
||||
sizeof(KEY_PART) *
|
||||
@ -3423,7 +3432,8 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
|
||||
my_bitmap_map *old_sets[2];
|
||||
|
||||
prune_param.part_info= part_info;
|
||||
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
|
||||
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
|
||||
MYF(MY_THREAD_SPECIFIC));
|
||||
range_par->mem_root= &alloc;
|
||||
range_par->old_root= thd->mem_root;
|
||||
|
||||
@ -10615,7 +10625,10 @@ int read_keys_and_merge_scans(THD *thd,
|
||||
*unique_ptr= unique;
|
||||
}
|
||||
else
|
||||
{
|
||||
unique->reset();
|
||||
filesort_free_buffers(head, false);
|
||||
}
|
||||
|
||||
DBUG_ASSERT(file->ref_length == unique->get_size());
|
||||
DBUG_ASSERT(thd->variables.sortbuff_size == unique->get_max_in_memory_size());
|
||||
@ -10774,6 +10787,13 @@ int QUICK_INDEX_INTERSECT_SELECT::get_next()
|
||||
If a Clustered PK scan is present, it is used only to check if row
|
||||
satisfies its condition (and never used for row retrieval).
|
||||
|
||||
Locking: to ensure that exclusive locks are only set on records that
|
||||
are included in the final result we must release the lock
|
||||
on all rows we read but do not include in the final result. This
|
||||
must be done on each index that reads the record and the lock
|
||||
must be released using the same handler (the same quick object) as
|
||||
used when reading the record.
|
||||
|
||||
RETURN
|
||||
0 - Ok
|
||||
other - Error code if any error occurred.
|
||||
@ -10784,6 +10804,12 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
|
||||
List_iterator_fast<QUICK_SELECT_WITH_RECORD> quick_it(quick_selects);
|
||||
QUICK_SELECT_WITH_RECORD *qr;
|
||||
QUICK_RANGE_SELECT* quick;
|
||||
|
||||
/* quick that reads the given rowid first. This is needed in order
|
||||
to be able to unlock the row using the same handler object that locked
|
||||
it */
|
||||
QUICK_RANGE_SELECT* quick_with_last_rowid;
|
||||
|
||||
int error, cmp;
|
||||
uint last_rowid_count=0;
|
||||
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::get_next");
|
||||
@ -10797,7 +10823,10 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
|
||||
if (cpk_quick)
|
||||
{
|
||||
while (!error && !cpk_quick->row_in_ranges())
|
||||
{
|
||||
quick->file->unlock_row(); /* row not in range; unlock */
|
||||
error= quick->get_next();
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
DBUG_RETURN(error);
|
||||
@ -10809,6 +10838,7 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
|
||||
quick->file->position(quick->record);
|
||||
memcpy(last_rowid, quick->file->ref, head->file->ref_length);
|
||||
last_rowid_count= 1;
|
||||
quick_with_last_rowid= quick;
|
||||
|
||||
while (last_rowid_count < quick_selects.elements)
|
||||
{
|
||||
@ -10822,9 +10852,17 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
|
||||
do
|
||||
{
|
||||
if ((error= quick->get_next()))
|
||||
{
|
||||
quick_with_last_rowid->file->unlock_row();
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
quick->file->position(quick->record);
|
||||
cmp= head->file->cmp_ref(quick->file->ref, last_rowid);
|
||||
if (cmp < 0)
|
||||
{
|
||||
/* This row is being skipped. Release lock on it. */
|
||||
quick->file->unlock_row();
|
||||
}
|
||||
} while (cmp < 0);
|
||||
|
||||
key_copy(qr->key_tuple, record, head->key_info + quick->index,
|
||||
@ -10838,13 +10876,19 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
|
||||
{
|
||||
while (!cpk_quick->row_in_ranges())
|
||||
{
|
||||
quick->file->unlock_row(); /* row not in range; unlock */
|
||||
if ((error= quick->get_next()))
|
||||
{
|
||||
quick_with_last_rowid->file->unlock_row();
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
}
|
||||
quick->file->position(quick->record);
|
||||
}
|
||||
memcpy(last_rowid, quick->file->ref, head->file->ref_length);
|
||||
quick_with_last_rowid->file->unlock_row();
|
||||
last_rowid_count= 1;
|
||||
quick_with_last_rowid= quick;
|
||||
|
||||
//save the fields here
|
||||
key_copy(qr->key_tuple, record, head->key_info + quick->index,
|
||||
@ -10971,8 +11015,13 @@ int QUICK_RANGE_SELECT::reset()
|
||||
|
||||
if (file->inited == handler::NONE)
|
||||
{
|
||||
DBUG_EXECUTE_IF("bug14365043_2",
|
||||
DBUG_SET("+d,ha_index_init_fail"););
|
||||
if ((error= file->ha_index_init(index,1)))
|
||||
goto err;
|
||||
{
|
||||
file->print_error(error, MYF(0));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate buffer if we need one but haven't allocated it yet */
|
||||
@ -11014,7 +11063,7 @@ err:
|
||||
/* Restore bitmaps set on entry */
|
||||
if (in_ror_merged_scan)
|
||||
head->column_bitmaps_set_no_signal(save_read_set, save_write_set);
|
||||
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
@ -12882,7 +12931,8 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
|
||||
DBUG_ASSERT(!parent_alloc);
|
||||
if (!parent_alloc)
|
||||
{
|
||||
init_sql_alloc(&alloc, join->thd->variables.range_alloc_block_size, 0);
|
||||
init_sql_alloc(&alloc, join->thd->variables.range_alloc_block_size, 0,
|
||||
MYF(MY_THREAD_SPECIFIC));
|
||||
join->thd->mem_root= &alloc;
|
||||
}
|
||||
else
|
||||
@ -12937,7 +12987,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::init()
|
||||
|
||||
if (min_max_arg_part)
|
||||
{
|
||||
if (my_init_dynamic_array(&min_max_ranges, sizeof(QUICK_RANGE*), 16, 16))
|
||||
if (my_init_dynamic_array(&min_max_ranges, sizeof(QUICK_RANGE*), 16, 16,
|
||||
MYF(MY_THREAD_SPECIFIC)))
|
||||
return 1;
|
||||
|
||||
if (have_min)
|
||||
@ -13183,7 +13234,10 @@ int QUICK_GROUP_MIN_MAX_SELECT::reset(void)
|
||||
head->enable_keyread(); /* We need only the key attributes */
|
||||
}
|
||||
if ((result= file->ha_index_init(index,1)))
|
||||
{
|
||||
head->file->print_error(result, MYF(0));
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
if (quick_prefix_select && quick_prefix_select->reset())
|
||||
DBUG_RETURN(1);
|
||||
result= file->ha_index_last(record);
|
||||
@ -13358,9 +13412,10 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
|
||||
*/
|
||||
if (min_max_arg_part && min_max_arg_part->field->is_null())
|
||||
{
|
||||
uchar *tmp_key_buff= (uchar*)my_alloca(max_used_key_length);
|
||||
/* Find the first subsequent record without NULL in the MIN/MAX field. */
|
||||
key_copy(tmp_record, record, index_info, max_used_key_length);
|
||||
result= file->ha_index_read_map(record, tmp_record,
|
||||
key_copy(tmp_key_buff, record, index_info, max_used_key_length);
|
||||
result= file->ha_index_read_map(record, tmp_key_buff,
|
||||
make_keypart_map(real_key_parts),
|
||||
HA_READ_AFTER_KEY);
|
||||
/*
|
||||
@ -13376,10 +13431,11 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
|
||||
if (!result)
|
||||
{
|
||||
if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
|
||||
key_restore(record, tmp_record, index_info, 0);
|
||||
key_restore(record, tmp_key_buff, index_info, 0);
|
||||
}
|
||||
else if (result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE)
|
||||
result= 0; /* There is a result in any case. */
|
||||
my_afree(tmp_key_buff);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user