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.cc432
1 files changed, 234 insertions, 198 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index f3f184367c9..8f8767c10b3 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -108,7 +108,7 @@
#pragma implementation // gcc: Class implementation
#endif
-#include <my_global.h>
+#include "mariadb.h"
#include "sql_priv.h"
#include "key.h" // is_key_used, key_copy, key_cmp, key_restore
#include "sql_parse.h" // check_stack_overrun
@@ -1236,7 +1236,8 @@ QUICK_SELECT_I::QUICK_SELECT_I()
QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
bool no_alloc, MEM_ROOT *parent_alloc,
bool *create_error)
- :free_file(0),cur_range(NULL),last_range(0),dont_free(0)
+ :thd(thd), no_alloc(no_alloc), parent_alloc(parent_alloc),
+ free_file(0),cur_range(NULL),last_range(0),dont_free(0)
{
my_bitmap_map *bitmap;
DBUG_ENTER("QUICK_RANGE_SELECT::QUICK_RANGE_SELECT");
@@ -1253,7 +1254,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, "QUICK_RANGE_SELECT",
+ thd->variables.range_alloc_block_size, 0,
MYF(MY_THREAD_SPECIFIC));
thd->mem_root= &alloc;
}
@@ -1348,7 +1350,8 @@ QUICK_INDEX_SORT_SELECT::QUICK_INDEX_SORT_SELECT(THD *thd_param, TABLE *table)
DBUG_ENTER("QUICK_INDEX_SORT_SELECT::QUICK_INDEX_SORT_SELECT");
index= MAX_KEY;
head= table;
- init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
+ init_sql_alloc(&alloc, "QUICK_INDEX_SORT_SELECT",
+ thd->variables.range_alloc_block_size, 0,
MYF(MY_THREAD_SPECIFIC));
DBUG_VOID_RETURN;
}
@@ -1419,7 +1422,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, "QUICK_ROR_INTERSECT_SELECT",
+ thd->variables.range_alloc_block_size, 0,
MYF(MY_THREAD_SPECIFIC));
else
bzero(&alloc, sizeof(MEM_ROOT));
@@ -1590,7 +1594,7 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler,
selects.
*/
int error= quick->init_ror_merged_scan(TRUE, local_alloc);
- if (error)
+ if (unlikely(error))
DBUG_RETURN(error);
quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
}
@@ -1614,7 +1618,8 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler,
quick->record= head->record[0];
}
- if (need_to_fetch_row && head->file->ha_rnd_init_with_error(false))
+ if (need_to_fetch_row &&
+ unlikely(head->file->ha_rnd_init_with_error(false)))
{
DBUG_PRINT("error", ("ROR index_merge rnd_init call failed"));
DBUG_RETURN(1);
@@ -1696,7 +1701,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, "QUICK_ROR_UNION_SELECT",
+ thd->variables.range_alloc_block_size, 0,
MYF(MY_THREAD_SPECIFIC));
thd_param->mem_root= &alloc;
}
@@ -1787,9 +1793,9 @@ int QUICK_ROR_UNION_SELECT::reset()
List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
while ((quick= it++))
{
- if ((error= quick->reset()))
+ if (unlikely((error= quick->reset())))
DBUG_RETURN(error);
- if ((error= quick->get_next()))
+ if (unlikely((error= quick->get_next())))
{
if (error == HA_ERR_END_OF_FILE)
continue;
@@ -1799,12 +1805,12 @@ int QUICK_ROR_UNION_SELECT::reset()
queue_insert(&queue, (uchar*)quick);
}
/* Prepare for ha_rnd_pos calls. */
- if (head->file->inited && (error= head->file->ha_rnd_end()))
+ if (head->file->inited && unlikely((error= head->file->ha_rnd_end())))
{
DBUG_PRINT("error", ("ROR index_merge rnd_end call failed"));
DBUG_RETURN(error);
}
- if ((error= head->file->ha_rnd_init(false)))
+ if (unlikely((error= head->file->ha_rnd_init(false))))
{
DBUG_PRINT("error", ("ROR index_merge rnd_init call failed"));
DBUG_RETURN(error);
@@ -2383,7 +2389,7 @@ static int fill_used_fields_bitmap(PARAM *param)
force_quick_range is really needed.
RETURN
- -1 if impossible select (i.e. certainly no rows will be selected)
+ -1 if error or impossible select (i.e. certainly no rows will be selected)
0 if can't use quick_select
1 if found usable ranges and quick select has been successfully created.
*/
@@ -2454,12 +2460,14 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
param.imerge_cost_buff_size= 0;
param.using_real_indexes= TRUE;
param.remove_jump_scans= TRUE;
+ param.is_ror_scan= 0;
param.remove_false_where_parts= remove_false_parts_of_where;
param.force_default_mrr= ordered_output;
param.possible_keys.clear_all();
thd->no_errors=1; // Don't warn about NULL
- init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
+ init_sql_alloc(&alloc, "test_quick_select",
+ thd->variables.range_alloc_block_size, 0,
MYF(MY_THREAD_SPECIFIC));
if (!(param.key_parts=
(KEY_PART*) alloc_root(&alloc,
@@ -2469,7 +2477,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{
thd->no_errors=0;
free_root(&alloc,MYF(0)); // Return memory & allocator
- DBUG_RETURN(0); // Can't use range
+ DBUG_RETURN(-1); // Error
}
key_parts= param.key_parts;
@@ -2520,7 +2528,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{
thd->no_errors=0;
free_root(&alloc,MYF(0)); // Return memory & allocator
- DBUG_RETURN(0); // Can't use range
+ DBUG_RETURN(-1); // Error
}
thd->mem_root= &alloc;
@@ -2557,6 +2565,13 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (tree->type != SEL_TREE::KEY && tree->type != SEL_TREE::KEY_SMALLER)
tree= NULL;
}
+ else if (thd->is_error())
+ {
+ thd->no_errors=0;
+ thd->mem_root= param.old_root;
+ free_root(&alloc, MYF(0));
+ DBUG_RETURN(-1);
+ }
}
/*
@@ -3059,7 +3074,8 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
SEL_TREE *tree;
double rows;
- init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
+ init_sql_alloc(&alloc, "calculate_cond_selectivity_for_table",
+ thd->variables.range_alloc_block_size, 0,
MYF(MY_THREAD_SPECIFIC));
param.thd= thd;
param.mem_root= &alloc;
@@ -3481,7 +3497,8 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
MY_BITMAP *old_sets[2];
prune_param.part_info= part_info;
- init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
+ init_sql_alloc(&alloc, "prune_partitions",
+ thd->variables.range_alloc_block_size, 0,
MYF(MY_THREAD_SPECIFIC));
range_par->mem_root= &alloc;
range_par->old_root= thd->mem_root;
@@ -3492,7 +3509,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
free_root(&alloc,MYF(0)); // Return memory & allocator
DBUG_RETURN(FALSE);
}
-
+
dbug_tmp_use_all_columns(table, old_sets,
&table->read_set, &table->write_set);
range_par->thd= thd;
@@ -4018,7 +4035,7 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
simply set res= -1 as if the mapper had returned that.
TODO: What to do here is defined in WL#4065.
*/
- if (ppar->arg_stack[0]->part == 0)
+ if (ppar->arg_stack[0]->part == 0 || ppar->part_info->part_type == VERSIONING_PARTITION)
{
uint32 i;
uint32 store_length_array[MAX_KEY];
@@ -4436,7 +4453,7 @@ static void print_partitioning_index(KEY_PART *parts, KEY_PART *parts_end)
fprintf(DBUG_FILE, "partitioning INDEX(");
for (KEY_PART *p=parts; p != parts_end; p++)
{
- fprintf(DBUG_FILE, "%s%s", p==parts?"":" ,", p->field->field_name);
+ fprintf(DBUG_FILE, "%s%s", p==parts?"":" ,", p->field->field_name.str);
}
fputs(");\n", DBUG_FILE);
DBUG_UNLOCK_FILE;
@@ -4475,7 +4492,7 @@ static void dbug_print_segment_range(SEL_ARG *arg, KEY_PART *part)
fputs(" <= ", DBUG_FILE);
}
- fprintf(DBUG_FILE, "%s", part->field->field_name);
+ fprintf(DBUG_FILE, "%s", part->field->field_name.str);
if (!(arg->max_flag & NO_MAX_RANGE))
{
@@ -4514,7 +4531,7 @@ static void dbug_print_singlepoint_range(SEL_ARG **start, uint num)
for (SEL_ARG **arg= start; arg != end; arg++)
{
Field *field= (*arg)->field;
- fprintf(DBUG_FILE, "%s%s=", (arg==start)?"":", ", field->field_name);
+ fprintf(DBUG_FILE, "%s%s=", (arg==start)?"":", ", field->field_name.str);
dbug_print_field(field);
}
fputs("\n", DBUG_FILE);
@@ -6250,7 +6267,7 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
&key_ptr, 0);
keypart_map= (keypart_map << 1) | 1;
}
- min_range.length= max_range.length= (size_t) (key_ptr - key_val);
+ min_range.length= max_range.length= (uint) (key_ptr - key_val);
min_range.keypart_map= max_range.keypart_map= keypart_map;
records= (info->param->table->file->
records_in_range(scan->keynr, &min_range, &max_range));
@@ -6326,7 +6343,7 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info,
DBUG_ENTER("ror_intersect_add");
DBUG_PRINT("info", ("Current out_rows= %g", info->out_rows));
DBUG_PRINT("info", ("Adding scan on %s",
- info->param->table->key_info[ror_scan->keynr].name));
+ info->param->table->key_info[ror_scan->keynr].name.str));
DBUG_PRINT("info", ("is_cpk_scan: %d",is_cpk_scan));
selectivity_mult = ror_scan_selectivity(info, ror_scan);
@@ -6711,7 +6728,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
total_cost += (*ror_scan_mark)->index_read_cost;
records += (*ror_scan_mark)->records;
DBUG_PRINT("info", ("Adding scan on %s",
- param->table->key_info[(*ror_scan_mark)->keynr].name));
+ param->table->key_info[(*ror_scan_mark)->keynr].name.str));
if (total_cost > read_time)
DBUG_RETURN(NULL);
/* F=F-covered by first(I) */
@@ -6882,7 +6899,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
read_plan->mrr_buf_size= best_buf_size;
DBUG_PRINT("info",
("Returning range plan for key %s, cost %g, records %lu",
- param->table->key_info[param->real_keynr[best_idx]].name,
+ param->table->key_info[param->real_keynr[best_idx]].name.str,
read_plan->read_cost, (ulong) read_plan->records));
}
}
@@ -7111,7 +7128,7 @@ SEL_TREE *Item_func_in::get_func_mm_tree(RANGE_OPT_PARAM *param,
if (negated)
{
- if (array && array->result_type() != ROW_RESULT)
+ if (array && array->type_handler()->result_type() != ROW_RESULT)
{
/*
We get here for conditions in form "t.key NOT IN (c1, c2, ...)",
@@ -7367,9 +7384,19 @@ SEL_TREE *Item_func_in::get_func_row_mm_tree(RANGE_OPT_PARAM *param,
param->current_table);
uint row_cols= key_row->cols();
Dynamic_array <Key_col_info> key_cols_info(row_cols);
- cmp_item_row *row_cmp_item= (cmp_item_row *)
- (array ? ((in_row *) array)->get_cmp_item() :
- cmp_items[(uint) ROW_RESULT]);
+ cmp_item_row *row_cmp_item;
+
+ if (array)
+ {
+ in_row *row= static_cast<in_row*>(array);
+ row_cmp_item= static_cast<cmp_item_row*>(row->get_cmp_item());
+ }
+ else
+ {
+ DBUG_ASSERT(get_comparator_type_handler(0) == &type_handler_row);
+ row_cmp_item= static_cast<cmp_item_row*>(get_comparator_cmp_item(0));
+ }
+ DBUG_ASSERT(row_cmp_item);
Item **key_col_ptr= key_row->addr(0);
for(uint i= 0; i < row_cols; i++, key_col_ptr++)
@@ -7416,6 +7443,7 @@ SEL_TREE *Item_func_in::get_func_row_mm_tree(RANGE_OPT_PARAM *param,
key_col->bring_value();
key_col_info.comparator= row_cmp_item->get_comparator(i);
+ DBUG_ASSERT(key_col_info.comparator);
key_col_info.comparator->store_value(key_col);
col_comparators++;
@@ -8010,7 +8038,9 @@ Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param,
if (!(res= value->val_str(&tmp)))
DBUG_RETURN(&null_element);
- if (field->cmp_type() != STRING_RESULT)
+ if (field->cmp_type() != STRING_RESULT ||
+ field->type_handler() == &type_handler_enum ||
+ field->type_handler() == &type_handler_set)
DBUG_RETURN(0);
/*
@@ -8025,7 +8055,7 @@ Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param,
}
uint maybe_null= (uint) field->real_maybe_null();
- uint field_length= field->pack_length() + maybe_null;
+ size_t field_length= field->pack_length() + maybe_null;
size_t offset= maybe_null;
size_t length= key_part->store_length;
@@ -8106,27 +8136,59 @@ Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param,
goto end;
err= value->save_in_field_no_warnings(field, 1);
- if (err == 2 && field->cmp_type() == STRING_RESULT)
+ if (err > 0)
{
- if (type == EQ_FUNC || type == EQUAL_FUNC)
+ if (field->type_handler() == &type_handler_enum ||
+ field->type_handler() == &type_handler_set)
{
- tree= new (alloc) SEL_ARG(field, 0, 0);
- tree->type= SEL_ARG::IMPOSSIBLE;
+ if (type == EQ_FUNC || type == EQUAL_FUNC)
+ tree= new (alloc) SEL_ARG_IMPOSSIBLE(field);
+ goto end;
}
- else
- tree= NULL; /* Cannot infer anything */
- goto end;
- }
- if (err > 0)
- {
- if (field->cmp_type() != value->result_type())
+
+ if (err == 2 && field->cmp_type() == STRING_RESULT)
+ {
+ if (type == EQ_FUNC || type == EQUAL_FUNC)
+ tree= new (alloc) SEL_ARG_IMPOSSIBLE(field);
+ else
+ tree= NULL; /* Cannot infer anything */
+ goto end;
+ }
+
+ if (err == 3 && field->type() == FIELD_TYPE_DATE)
+ {
+ /*
+ We were saving DATETIME into a DATE column, the conversion went ok
+ but a non-zero time part was cut off.
+
+ In MySQL's SQL dialect, DATE and DATETIME are compared as datetime
+ values. Index over a DATE column uses DATE comparison. Changing
+ from one comparison to the other is possible:
+
+ datetime(date_col)< '2007-12-10 12:34:55' -> date_col<='2007-12-10'
+ datetime(date_col)<='2007-12-10 12:34:55' -> date_col<='2007-12-10'
+
+ datetime(date_col)> '2007-12-10 12:34:55' -> date_col>='2007-12-10'
+ datetime(date_col)>='2007-12-10 12:34:55' -> date_col>='2007-12-10'
+
+ but we'll need to convert '>' to '>=' and '<' to '<='. This will
+ be done together with other types at the end of this function
+ (grep for stored_field_cmp_to_item)
+ */
+ if (type == EQ_FUNC || type == EQUAL_FUNC)
+ {
+ tree= new (alloc) SEL_ARG_IMPOSSIBLE(field);
+ goto end;
+ }
+ // Continue with processing non-equality ranges
+ }
+ else if (field->cmp_type() != value->result_type())
{
if ((type == EQ_FUNC || type == EQUAL_FUNC) &&
value->result_type() == item_cmp_type(field->result_type(),
value->result_type()))
{
- tree= new (alloc) SEL_ARG(field, 0, 0);
- tree->type= SEL_ARG::IMPOSSIBLE;
+ tree= new (alloc) SEL_ARG_IMPOSSIBLE(field);
goto end;
}
else
@@ -8136,31 +8198,7 @@ Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param,
for the cases like int_field > 999999999999999999999999 as well.
*/
tree= 0;
- if (err == 3 && field->type() == FIELD_TYPE_DATE &&
- (type == GT_FUNC || type == GE_FUNC ||
- type == LT_FUNC || type == LE_FUNC) )
- {
- /*
- We were saving DATETIME into a DATE column, the conversion went ok
- but a non-zero time part was cut off.
-
- In MySQL's SQL dialect, DATE and DATETIME are compared as datetime
- values. Index over a DATE column uses DATE comparison. Changing
- from one comparison to the other is possible:
-
- datetime(date_col)< '2007-12-10 12:34:55' -> date_col<='2007-12-10'
- datetime(date_col)<='2007-12-10 12:34:55' -> date_col<='2007-12-10'
-
- datetime(date_col)> '2007-12-10 12:34:55' -> date_col>='2007-12-10'
- datetime(date_col)>='2007-12-10 12:34:55' -> date_col>='2007-12-10'
-
- but we'll need to convert '>' to '>=' and '<' to '<='. This will
- be done together with other types at the end of this function
- (grep for stored_field_cmp_to_item)
- */
- }
- else
- goto end;
+ goto end;
}
}
@@ -9011,6 +9049,8 @@ and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2,
}
if (key1->type == SEL_ARG::MAYBE_KEY)
{
+ if (key2->type == SEL_ARG::KEY_RANGE)
+ return key2;
key1->right= key1->left= &null_element;
key1->next= key1->prev= 0;
}
@@ -10906,8 +10946,9 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
goto err;
quick->records= records;
- if ((cp_buffer_from_ref(thd, table, ref) && thd->is_fatal_error) ||
- !(range= new(alloc) QUICK_RANGE()))
+ if ((cp_buffer_from_ref(thd, table, ref) &&
+ unlikely(thd->is_fatal_error)) ||
+ unlikely(!(range= new(alloc) QUICK_RANGE())))
goto err; // out of memory
range->min_key= range->max_key= ref->key_buff;
@@ -10916,8 +10957,8 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
make_prev_keypart_map(ref->key_parts);
range->flag= EQ_RANGE;
- if (!(quick->key_parts=key_part=(KEY_PART *)
- alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts)))
+ if (unlikely(!(quick->key_parts=key_part=(KEY_PART *)
+ alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts))))
goto err;
max_used_key_len=0;
@@ -11032,7 +11073,7 @@ int read_keys_and_merge_scans(THD *thd,
if (unique == NULL)
{
- DBUG_EXECUTE_IF("index_merge_may_not_create_a_Unique", DBUG_ABORT(); );
+ DBUG_EXECUTE_IF("index_merge_may_not_create_a_Unique", DBUG_SUICIDE(); );
DBUG_EXECUTE_IF("only_one_Unique_may_be_created",
DBUG_SET("+d,index_merge_may_not_create_a_Unique"); );
@@ -11146,7 +11187,7 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
if (doing_pk_scan)
DBUG_RETURN(pk_quick_select->get_next());
- if ((result= read_record.read_record(&read_record)) == -1)
+ if ((result= read_record.read_record()) == -1)
{
result= HA_ERR_END_OF_FILE;
end_read_record(&read_record);
@@ -11182,7 +11223,7 @@ int QUICK_INDEX_INTERSECT_SELECT::get_next()
int result;
DBUG_ENTER("QUICK_INDEX_INTERSECT_SELECT::get_next");
- if ((result= read_record.read_record(&read_record)) == -1)
+ if ((result= read_record.read_record()) == -1)
{
result= HA_ERR_END_OF_FILE;
end_read_record(&read_record);
@@ -11235,103 +11276,100 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
uint last_rowid_count=0;
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::get_next");
- do
+ /* Get a rowid for first quick and save it as a 'candidate' */
+ qr= quick_it++;
+ quick= qr->quick;
+ error= quick->get_next();
+ if (cpk_quick)
{
- /* Get a rowid for first quick and save it as a 'candidate' */
- qr= quick_it++;
- quick= qr->quick;
- error= quick->get_next();
- if (cpk_quick)
+ while (!error && !cpk_quick->row_in_ranges())
{
- while (!error && !cpk_quick->row_in_ranges())
- {
- quick->file->unlock_row(); /* row not in range; unlock */
- error= quick->get_next();
- }
+ quick->file->unlock_row(); /* row not in range; unlock */
+ error= quick->get_next();
}
- if (error)
- DBUG_RETURN(error);
+ }
+ if (unlikely(error))
+ DBUG_RETURN(error);
- /* Save the read key tuple */
- key_copy(qr->key_tuple, record, head->key_info + quick->index,
- quick->max_used_key_length);
+ /* Save the read key tuple */
+ key_copy(qr->key_tuple, record, head->key_info + quick->index,
+ quick->max_used_key_length);
- quick->file->position(quick->record);
- memcpy(last_rowid, quick->file->ref, head->file->ref_length);
- last_rowid_count= 1;
- quick_with_last_rowid= quick;
+ 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)
+ {
+ if (!(qr= quick_it++))
+ {
+ quick_it.rewind();
+ qr= quick_it++;
+ }
+ quick= qr->quick;
- while (last_rowid_count < quick_selects.elements)
+ do
{
- if (!(qr= quick_it++))
+ DBUG_EXECUTE_IF("innodb_quick_report_deadlock",
+ DBUG_SET("+d,innodb_report_deadlock"););
+ if (unlikely((error= quick->get_next())))
{
- quick_it.rewind();
- qr= quick_it++;
+ /* On certain errors like deadlock, trx might be rolled back.*/
+ if (!thd->transaction_rollback_request)
+ quick_with_last_rowid->file->unlock_row();
+ DBUG_RETURN(error);
}
- quick= qr->quick;
-
- do
+ quick->file->position(quick->record);
+ cmp= head->file->cmp_ref(quick->file->ref, last_rowid);
+ if (cmp < 0)
{
- DBUG_EXECUTE_IF("innodb_quick_report_deadlock",
- DBUG_SET("+d,innodb_report_deadlock"););
- if ((error= quick->get_next()))
- {
- /* On certain errors like deadlock, trx might be rolled back.*/
- if (!thd->transaction_rollback_request)
- 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);
+ /* 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,
- quick->max_used_key_length);
+ key_copy(qr->key_tuple, record, head->key_info + quick->index,
+ quick->max_used_key_length);
- /* Ok, current select 'caught up' and returned ref >= cur_ref */
- if (cmp > 0)
+ /* Ok, current select 'caught up' and returned ref >= cur_ref */
+ if (cmp > 0)
+ {
+ /* Found a row with ref > cur_ref. Make it a new 'candidate' */
+ if (cpk_quick)
{
- /* Found a row with ref > cur_ref. Make it a new 'candidate' */
- if (cpk_quick)
+ while (!cpk_quick->row_in_ranges())
{
- while (!cpk_quick->row_in_ranges())
+ quick->file->unlock_row(); /* row not in range; unlock */
+ if (unlikely((error= quick->get_next())))
{
- quick->file->unlock_row(); /* row not in range; unlock */
- if ((error= quick->get_next()))
- {
- /* On certain errors like deadlock, trx might be rolled back.*/
- if (!thd->transaction_rollback_request)
- quick_with_last_rowid->file->unlock_row();
- DBUG_RETURN(error);
- }
+ /* On certain errors like deadlock, trx might be rolled back.*/
+ if (!thd->transaction_rollback_request)
+ 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,
- quick->max_used_key_length);
- }
- else
- {
- /* current 'candidate' row confirmed by this select */
- last_rowid_count++;
+ 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,
+ quick->max_used_key_length);
}
+ else
+ {
+ /* current 'candidate' row confirmed by this select */
+ last_rowid_count++;
+ }
+ }
- /* We get here if we got the same row ref in all scans. */
- if (need_to_fetch_row)
- error= head->file->ha_rnd_pos(head->record[0], last_rowid);
- } while (error == HA_ERR_RECORD_DELETED);
+ /* We get here if we got the same row ref in all scans. */
+ if (need_to_fetch_row)
+ error= head->file->ha_rnd_pos(head->record[0], last_rowid);
if (!need_to_fetch_row)
{
@@ -11375,44 +11413,41 @@ int QUICK_ROR_UNION_SELECT::get_next()
do
{
- do
- {
- if (!queue.elements)
- DBUG_RETURN(HA_ERR_END_OF_FILE);
- /* Ok, we have a queue with >= 1 scans */
+ if (!queue.elements)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ /* Ok, we have a queue with >= 1 scans */
- quick= (QUICK_SELECT_I*)queue_top(&queue);
- memcpy(cur_rowid, quick->last_rowid, rowid_length);
+ quick= (QUICK_SELECT_I*)queue_top(&queue);
+ memcpy(cur_rowid, quick->last_rowid, rowid_length);
- /* put into queue rowid from the same stream as top element */
- if ((error= quick->get_next()))
- {
- if (error != HA_ERR_END_OF_FILE)
- DBUG_RETURN(error);
- queue_remove_top(&queue);
- }
- else
- {
- quick->save_last_pos();
- queue_replace_top(&queue);
- }
+ /* put into queue rowid from the same stream as top element */
+ if ((error= quick->get_next()))
+ {
+ if (error != HA_ERR_END_OF_FILE)
+ DBUG_RETURN(error);
+ queue_remove_top(&queue);
+ }
+ else
+ {
+ quick->save_last_pos();
+ queue_replace_top(&queue);
+ }
- if (!have_prev_rowid)
- {
- /* No rows have been returned yet */
- dup_row= FALSE;
- have_prev_rowid= TRUE;
- }
- else
- dup_row= !head->file->cmp_ref(cur_rowid, prev_rowid);
- } while (dup_row);
+ if (!have_prev_rowid)
+ {
+ /* No rows have been returned yet */
+ dup_row= FALSE;
+ have_prev_rowid= TRUE;
+ }
+ else
+ dup_row= !head->file->cmp_ref(cur_rowid, prev_rowid);
+ } while (dup_row);
- tmp= cur_rowid;
- cur_rowid= prev_rowid;
- prev_rowid= tmp;
+ tmp= cur_rowid;
+ cur_rowid= prev_rowid;
+ prev_rowid= tmp;
- error= head->file->ha_rnd_pos(quick->record, prev_rowid);
- } while (error == HA_ERR_RECORD_DELETED);
+ error= head->file->ha_rnd_pos(quick->record, prev_rowid);
DBUG_RETURN(error);
}
@@ -11434,7 +11469,7 @@ int QUICK_RANGE_SELECT::reset()
if (file->inited == handler::RND)
{
/* Handler could be left in this state by MRR */
- if ((error= file->ha_rnd_end()))
+ if (unlikely((error= file->ha_rnd_end())))
DBUG_RETURN(error);
}
@@ -11446,7 +11481,7 @@ int QUICK_RANGE_SELECT::reset()
{
DBUG_EXECUTE_IF("bug14365043_2",
DBUG_SET("+d,ha_index_init_fail"););
- if ((error= file->ha_index_init(index,1)))
+ if (unlikely((error= file->ha_index_init(index,1))))
{
file->print_error(error, MYF(0));
goto err;
@@ -11804,7 +11839,7 @@ int QUICK_SELECT_DESC::get_next()
if (last_range->flag & NO_MAX_RANGE) // Read last record
{
int local_error;
- if ((local_error= file->ha_index_last(record)))
+ if (unlikely((local_error= file->ha_index_last(record))))
DBUG_RETURN(local_error); // Empty table
if (cmp_prev(last_range) == 0)
DBUG_RETURN(0);
@@ -11952,7 +11987,7 @@ void QUICK_SELECT_I::add_key_name(String *str, bool *first)
*first= FALSE;
else
str->append(',');
- str->append(key_info->name);
+ str->append(&key_info->name);
}
@@ -12107,7 +12142,7 @@ void QUICK_SELECT_I::add_key_and_length(String *key_names,
key_names->append(',');
used_lengths->append(',');
}
- key_names->append(key_info->name);
+ key_names->append(&key_info->name);
length= longlong10_to_str(max_used_key_length, buf, 10) - buf;
used_lengths->append(buf, length);
}
@@ -13706,7 +13741,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, "QUICK_GROUP_MIN_MAX_SELECT",
+ join->thd->variables.range_alloc_block_size, 0,
MYF(MY_THREAD_SPECIFIC));
join->thd->mem_root= &alloc;
}
@@ -14776,7 +14812,7 @@ static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,
uint keynr= param->real_keynr[idx];
if (tmp.length())
tmp.append(',');
- tmp.append(param->table->key_info[keynr].name);
+ tmp.append(&param->table->key_info[keynr].name);
}
}
if (!tmp.length())
@@ -14802,7 +14838,7 @@ static void print_ror_scans_arr(TABLE *table, const char *msg,
{
if (tmp.length())
tmp.append(',');
- tmp.append(table->key_info[(*start)->keynr].name);
+ tmp.append(&table->key_info[(*start)->keynr].name);
}
if (!tmp.length())
tmp.append(STRING_WITH_LEN("(empty)"));
@@ -14991,7 +15027,7 @@ void QUICK_RANGE_SELECT::dbug_dump(int indent, bool verbose)
{
/* purecov: begin inspected */
fprintf(DBUG_FILE, "%*squick range select, key %s, length: %d\n",
- indent, "", head->key_info[index].name, max_used_key_length);
+ indent, "", head->key_info[index].name.str, max_used_key_length);
if (verbose)
{
@@ -15095,7 +15131,7 @@ void QUICK_GROUP_MIN_MAX_SELECT::dbug_dump(int indent, bool verbose)
{
fprintf(DBUG_FILE,
"%*squick_group_min_max_select: index %s (%d), length: %d\n",
- indent, "", index_info->name, index, max_used_key_length);
+ indent, "", index_info->name.str, index, max_used_key_length);
if (key_infix_len > 0)
{
fprintf(DBUG_FILE, "%*susing key_infix with length %d:\n",