diff options
Diffstat (limited to 'sql/opt_range.cc')
-rw-r--r-- | sql/opt_range.cc | 432 |
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(¶m->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", |