diff options
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r-- | sql/sql_select.cc | 344 |
1 files changed, 247 insertions, 97 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 09d8be97eb4..d2a72bcb86b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -38,6 +38,12 @@ #include <my_bit.h> #include <hash.h> #include <ft_global.h> +//#if defined(WITH_ARIA_STORAGE_ENGINE) && defined(USE_MARIA_FOR_TMP_TABLES) +//#include "../storage/maria/ha_maria.h" +//#define TMP_ENGINE_HTON maria_hton +//#else +//#define TMP_ENGINE_HTON myisam_hton +//#endif const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref", "MAYBE_REF","ALL","range","index","fulltext", @@ -262,15 +268,15 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, setup_tables_done_option changed for next rexecution */ res= mysql_select(thd, &select_lex->ref_pointer_array, - (TABLE_LIST*) select_lex->table_list.first, + select_lex->table_list.first, select_lex->with_wild, select_lex->item_list, select_lex->where, select_lex->order_list.elements + select_lex->group_list.elements, - (ORDER*) select_lex->order_list.first, - (ORDER*) select_lex->group_list.first, + select_lex->order_list.first, + select_lex->group_list.first, select_lex->having, - (ORDER*) lex->proc_list.first, + lex->proc_list.first, select_lex->options | thd->options | setup_tables_done_option, result, unit, select_lex); @@ -561,13 +567,21 @@ JOIN::prepare(Item ***rref_pointer_array, { Item *item= *ord->item; /* - Disregard sort order if there's only "{VAR}CHAR(0) NOT NULL" fields - there. Such fields don't contain any data to sort. + Disregard sort order if there's only + zero length NOT NULL fields (e.g. {VAR}CHAR(0) NOT NULL") or + zero length NOT NULL string functions there. + Such tuples don't contain any data to sort. */ if (!real_order && - (item->type() != Item::FIELD_ITEM || - ((Item_field *) item)->field->maybe_null() || - ((Item_field *) item)->field->sort_length())) + /* Not a zero length NOT NULL field */ + ((item->type() != Item::FIELD_ITEM || + ((Item_field *) item)->field->maybe_null() || + ((Item_field *) item)->field->sort_length()) && + /* AND not a zero length NOT NULL string function. */ + (item->type() != Item::FUNC_ITEM || + item->maybe_null || + item->result_type() != STRING_RESULT || + item->max_length))) real_order= TRUE; if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) @@ -1038,6 +1052,30 @@ JOIN::optimize() { conds=new Item_int((longlong) 0,1); // Always false } + + /* + It's necessary to check const part of HAVING cond as there is a + chance that some cond parts may become const items after + make_join_statistics() (for example when Item is a reference to + cost table field from outer join). + + This check is performed only for those conditions which do not use + aggregate functions. In such case temporary table may not be used + and const condition elements may be lost during further having + condition transformation in JOIN::exec. + */ + if (having && const_table_map && !having->with_sum_func) + { + having->update_used_tables(); + having= remove_eq_conds(thd, having, &having_value); + if (having_value == Item::COND_FALSE) + { + having= new Item_int((longlong) 0,1); + zero_result_cause= "Impossible HAVING noticed after reading const tables"; + DBUG_RETURN(0); + } + } + if (make_join_select(this, select, conds)) { zero_result_cause= @@ -1664,6 +1702,16 @@ JOIN::reinit() func->clear(); } + if (no_rows_in_result_called) + { + /* Reset effect of possible no_rows_in_result() */ + List_iterator_fast<Item> it(fields_list); + Item *item; + + no_rows_in_result_called= 0; + while ((item= it++)) + item->restore_to_before_no_rows_in_result(); + } DBUG_RETURN(0); } @@ -2755,15 +2803,29 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, as well as allow us to catch illegal cross references/ Warshall's algorithm is used to build the transitive closure. As we use bitmaps to represent the relation the complexity - of the algorithm is O((number of tables)^2). + of the algorithm is O((number of tables)^2). + + The classic form of the Warshall's algorithm would look like: + for (i= 0; i < table_count; i++) + { + for (j= 0; j < table_count; j++) + { + for (k= 0; k < table_count; k++) + { + if (bitmap_is_set(stat[j].dependent, i) && + bitmap_is_set(stat[i].dependent, k)) + bitmap_set_bit(stat[j].dependent, k); + } + } */ - for (i= 0, s= stat ; i < table_count ; i++, s++) + + for (s= stat ; s < stat_end ; s++) { - for (uint j= 0 ; j < table_count ; j++) + table= s->table; + for (JOIN_TAB *t= stat ; t < stat_end ; t++) { - table= stat[j].table; - if (s->dependent & table->map) - s->dependent |= table->reginfo.join_tab->dependent; + if (t->dependent & table->map) + t->dependent |= table->reginfo.join_tab->dependent; } if (outer_join & s->table->map) s->table->maybe_null= 1; @@ -2926,8 +2988,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, !table->fulltext_searched && (!embedding || (embedding->sj_on_expr && !embedding->embedding))) { - if ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY)) - == HA_NOSAME) + if (table->key_info[key].flags & HA_NOSAME) { if (const_ref == eq_part) { // Found everything for ref. @@ -6154,8 +6215,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, DBUG_RETURN(0); if (j->type == JT_CONST) j->table->const_table= 1; - else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY | - HA_END_SPACE_KEY)) != HA_NOSAME) || + else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) != HA_NOSAME) || keyparts != keyinfo->key_parts || null_ref_key) { /* Must read with repeat */ @@ -6962,6 +7022,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) if (tmp_cond) { JOIN_TAB *cond_tab= tab < first_inner_tab ? first_inner_tab : tab; + Item **sel_cond_ref= tab < first_inner_tab ? + &first_inner_tab->on_precond : + &tab->select_cond; /* First add the guards for match variables of all embedding outer join operations. @@ -6984,15 +7047,15 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) tmp_cond->quick_fix_field(); /* Add the predicate to other pushed down predicates */ DBUG_PRINT("info", ("Item_cond_and")); - cond_tab->select_cond= !cond_tab->select_cond ? tmp_cond : - new Item_cond_and(cond_tab->select_cond, - tmp_cond); + *sel_cond_ref= !(*sel_cond_ref) ? + tmp_cond : + new Item_cond_and(*sel_cond_ref, tmp_cond); DBUG_PRINT("info", ("Item_cond_and 0x%lx", - (ulong)cond_tab->select_cond)); - if (!cond_tab->select_cond) - DBUG_RETURN(1); - cond_tab->select_cond->update_used_tables(); - cond_tab->select_cond->quick_fix_field(); + (ulong)(*sel_cond_ref))); + if (!(*sel_cond_ref)) + DBUG_RETURN(1); + (*sel_cond_ref)->update_used_tables(); + (*sel_cond_ref)->quick_fix_field(); if (cond_tab->select) cond_tab->select->cond= cond_tab->select_cond; } @@ -8126,8 +8189,6 @@ eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab) static bool only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables) { - if (specialflag & SPECIAL_SAFE_MODE) - return 0; // skip this optimize /* purecov: inspected */ tables&= ~PSEUDO_TABLE_BITS; for (JOIN_TAB **tab=join->map2table ; tables ; tab++, tables>>=1) { @@ -8248,7 +8309,8 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, *simple_order=0; // Must do a temp table to sort else if (!(order_tables & not_const_tables)) { - if (order->item[0]->with_subselect) + if (order->item[0]->with_subselect && + !(join->select_lex->options & SELECT_DESCRIBE)) order->item[0]->val_str(&order->item[0]->str_value); DBUG_PRINT("info",("removing: %s", order->item[0]->full_name())); continue; // skip const item @@ -9791,6 +9853,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top, NESTED_JOIN *nested_join; TABLE_LIST *prev_table= 0; List_iterator<TABLE_LIST> li(*join_list); + bool straight_join= test(join->select_options & SELECT_STRAIGHT_JOIN); DBUG_ENTER("simplify_joins"); /* @@ -9904,7 +9967,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top, if (prev_table) { /* The order of tables is reverse: prev_table follows table */ - if (prev_table->straight) + if (prev_table->straight || straight_join) prev_table->dep_tables|= used_tables; if (prev_table->on_expr) { @@ -10177,28 +10240,31 @@ static bool check_interleaving_with_nj(JOIN_TAB *next_tab) Do update counters for "pairs of brackets" that we've left (marked as X,Y,Z in the above picture) */ - for (;next_emb; next_emb= next_emb->embedding) + for (;next_emb && next_emb != join->emb_sjm_nest; next_emb= next_emb->embedding) { - next_emb->nested_join->counter++; - if (next_emb->nested_join->counter == 1) + if (!next_emb->sj_on_expr) { - /* - next_emb is the first table inside a nested join we've "entered". In - the picture above, we're looking at the 'X' bracket. Don't exit yet as - X bracket might have Y pair bracket. + next_emb->nested_join->counter++; + if (next_emb->nested_join->counter == 1) + { + /* + next_emb is the first table inside a nested join we've "entered". In + the picture above, we're looking at the 'X' bracket. Don't exit yet as + X bracket might have Y pair bracket. + */ + join->cur_embedding_map |= next_emb->nested_join->nj_map; + } + + if (next_emb->nested_join->n_tables != + next_emb->nested_join->counter) + break; + + /* + We're currently at Y or Z-bracket as depicted in the above picture. + Mark that we've left it and continue walking up the brackets hierarchy. */ - join->cur_embedding_map |= next_emb->nested_join->nj_map; + join->cur_embedding_map &= ~next_emb->nested_join->nj_map; } - - if (next_emb->nested_join->n_tables != - next_emb->nested_join->counter) - break; - - /* - We're currently at Y or Z-bracket as depicted in the above picture. - Mark that we've left it and continue walking up the brackets hierarchy. - */ - join->cur_embedding_map &= ~next_emb->nested_join->nj_map; } return FALSE; } @@ -10207,6 +10273,46 @@ static bool check_interleaving_with_nj(JOIN_TAB *next_tab) /** Nested joins perspective: Remove the last table from the join order. + The algorithm is the reciprocal of check_interleaving_with_nj(), hence + parent join nest nodes are updated only when the last table in its child + node is removed. The ASCII graphic below will clarify. + + %A table nesting such as <tt> t1 x [ ( t2 x t3 ) x ( t4 x t5 ) ] </tt>is + represented by the below join nest tree. + + @verbatim + NJ1 + _/ / \ + _/ / NJ2 + _/ / / \ + / / / \ + t1 x [ (t2 x t3) x (t4 x t5) ] + @endverbatim + + At the point in time when check_interleaving_with_nj() adds the table t5 to + the query execution plan, QEP, it also directs the node named NJ2 to mark + the table as covered. NJ2 does so by incrementing its @c counter + member. Since all of NJ2's tables are now covered by the QEP, the algorithm + proceeds up the tree to NJ1, incrementing its counter as well. All join + nests are now completely covered by the QEP. + + restore_prev_nj_state() does the above in reverse. As seen above, the node + NJ1 contains the nodes t2, t3, and NJ2. Its counter being equal to 3 means + that the plan covers t2, t3, and NJ2, @e and that the sub-plan (t4 x t5) + completely covers NJ2. The removal of t5 from the partial plan will first + decrement NJ2's counter to 1. It will then detect that NJ2 went from being + completely to partially covered, and hence the algorithm must continue + upwards to NJ1 and decrement its counter to 2. %A subsequent removal of t4 + will however not influence NJ1 since it did not un-cover the last table in + NJ2. + + SYNOPSIS + restore_prev_nj_state() + last join table to remove, it is assumed to be the last in current + partial join order. + + DESCRIPTION + Remove the last table from the partial join order and update the nested joins counters and join->cur_embedding_map. It is ok to call this function for the first table in join order (for which @@ -10220,19 +10326,24 @@ static void restore_prev_nj_state(JOIN_TAB *last) { TABLE_LIST *last_emb= last->table->pos_in_table_list->embedding; JOIN *join= last->join; - while (last_emb) + for (;last_emb != NULL && last_emb != join->emb_sjm_nest; + last_emb= last_emb->embedding) { - if (!(--last_emb->nested_join->counter)) - join->cur_embedding_map&= ~last_emb->nested_join->nj_map; - else if (last_emb->nested_join->n_tables-1 == - last_emb->nested_join->counter) + if (!last_emb->sj_on_expr) { - join->cur_embedding_map|= last_emb->nested_join->nj_map; - break; + NESTED_JOIN *nest= last_emb->nested_join; + DBUG_ASSERT(nest->counter > 0); + + bool was_fully_covered= nest->is_fully_covered(); + + if (--nest->counter == 0) + join->cur_embedding_map&= ~nest->nj_map; + + if (!was_fully_covered) + break; + + join->cur_embedding_map|= nest->nj_map; } - else - break; - last_emb= last_emb->embedding; } } @@ -10332,7 +10443,10 @@ optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list, DBUG_ENTER("optimize_cond"); if (!conds) + { *cond_value= Item::COND_TRUE; + build_equal_items(join->thd, NULL, NULL, join_list, &join->cond_equal); + } else { /* @@ -10690,6 +10804,8 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field, table->s->db_create_options|= HA_OPTION_PACK_RECORD; else if (org_field->type() == FIELD_TYPE_DOUBLE) ((Field_double *) new_field)->not_fixed= TRUE; + new_field->vcol_info= 0; + new_field->stored_in_db= TRUE; } return new_field; } @@ -11005,11 +11121,11 @@ void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps) uint field_count= table->s->fields; bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count, FALSE); - bitmap_init(&table->tmp_set, + bitmap_init(&table->def_vcol_set, (my_bitmap_map*) (bitmaps+ bitmap_buffer_size(field_count)), field_count, FALSE); - bitmap_init(&table->vcol_set, - (my_bitmap_map*) (bitmaps+ 2+bitmap_buffer_size(field_count)), + bitmap_init(&table->tmp_set, + (my_bitmap_map*) (bitmaps+ 2*bitmap_buffer_size(field_count)), field_count, FALSE); /* write_set and all_set are copies of read_set */ @@ -11107,7 +11223,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, /* No need to change table name to lower case as we are only creating - MyISAM, Maria or HEAP tables here + MyISAM, Aria or HEAP tables here */ fn_format(path, tmp_table_name, mysql_tmpdir, "", MY_REPLACE_EXT|MY_UNPACK_FILENAME); @@ -11474,7 +11590,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, table->null_flags= (uchar*) table->record[0]; share->null_fields= null_count+ hidden_null_count; - share->null_bytes= null_pack_length; + share->null_bytes= share->null_bytes_for_compare= null_pack_length; } null_count= (blob_count == 0) ? 1 : 0; hidden_field_count=param->hidden_field_count; @@ -11872,7 +11988,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list) { table->null_flags= (uchar*) table->record[0]; share->null_fields= null_count; - share->null_bytes= null_pack_length; + share->null_bytes= share->null_bytes_for_compare= null_pack_length; } table->in_use= thd; /* field->reset() may access table->in_use */ @@ -11926,7 +12042,7 @@ bool open_tmp_table(TABLE *table) } -#if defined(WITH_MARIA_STORAGE_ENGINE) && defined(USE_MARIA_FOR_TMP_TABLES) +#if defined(WITH_ARIA_STORAGE_ENGINE) && defined(USE_MARIA_FOR_TMP_TABLES) /* Create internal (MyISAM or Maria) temporary table @@ -11958,7 +12074,6 @@ bool open_tmp_table(TABLE *table) TRUE - Error */ -/* Create internal Maria temporary table */ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, ENGINE_COLUMNDEF *start_recinfo, @@ -12039,7 +12154,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]); /* We are using a GROUP BY on something that contains NULL - In this case we have to tell Maria that two NULL should + In this case we have to tell Aria that two NULL should on INSERT be regarded at the same value */ if (!using_unique_constraint) @@ -12087,7 +12202,7 @@ bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, start_recinfo, recinfo, error, ignore_last_dupp_key_error, maria_hton, - "converting HEAP to Maria"); + "converting HEAP to Aria"); } #else @@ -12308,7 +12423,8 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table, if (table->file->indexes_are_disabled()) new_table.file->ha_disable_indexes(HA_KEY_SWITCH_ALL); table->file->ha_index_or_rnd_end(); - table->file->ha_rnd_init(1); + if (table->file->ha_rnd_init_with_error(1)) + DBUG_RETURN(1); if (table->no_rows) { new_table.file->extra(HA_EXTRA_NO_ROWS); @@ -12985,7 +13101,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) DBUG_RETURN(nls); } int error; - enum_nested_loop_state rc; + enum_nested_loop_state rc= NESTED_LOOP_OK; READ_RECORD *info= &join_tab->read_record; if (join_tab->flush_weedout_table) @@ -13018,18 +13134,23 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) /* Set first_unmatched for the last inner table of this group */ join_tab->last_inner->first_unmatched= join_tab; + if (join_tab->on_precond && !join_tab->on_precond->val_int()) + rc= NESTED_LOOP_NO_MORE_ROWS; } join->thd->row_count= 0; if (join_tab->loosescan_match_tab) join_tab->loosescan_match_tab->found_match= FALSE; + if (rc != NESTED_LOOP_NO_MORE_ROWS) + { - error= (*join_tab->read_first_record)(join_tab); + error= (*join_tab->read_first_record)(join_tab); if (join_tab->keep_current_rowid) join_tab->table->file->position(join_tab->table->record[0]); - rc= evaluate_join_record(join, join_tab, error); + rc= evaluate_join_record(join, join_tab, error); + } } /* @@ -13119,7 +13240,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */ } - update_virtual_fields(join_tab->table); + update_virtual_fields(join->thd, join_tab->table); if (select_cond) { @@ -13137,6 +13258,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, condition is true => a match is found. */ bool found= 1; + bool use_not_exists_opt= 0; while (join_tab->first_unmatched && found) { /* @@ -13153,7 +13275,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++) { if (tab->table->reginfo.not_exists_optimize) - DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); + use_not_exists_opt= 1; /* Check all predicates that has just been activated. */ /* Actually all predicates non-guarded by first_unmatched->found @@ -13186,6 +13308,8 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, join_tab->first_unmatched= first_unmatched; } + if (use_not_exists_opt) + DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); JOIN_TAB *return_tab= join->return_tab; join_tab->found_match= TRUE; @@ -13320,13 +13444,22 @@ evaluate_null_complemented_join_record(JOIN *join, JOIN_TAB *join_tab) #ifdef MERGE_JUNK //psergey3-merge: remove: + SQL_SELECT *select; + select= join_tab->select; + int err= 0; (err= join_tab->cache.select->skip_record(join->thd)) != 0 )) + { + reset_cache_write(&join_tab->cache); return NESTED_LOOP_ERROR; - rc= NESTED_LOOP_OK; + } + if (!select || (err= select->skip_record(join->thd)) != 0) if (err < 0) + { + reset_cache_write(&join_tab->cache); return NESTED_LOOP_ERROR; + } rc= NESTED_LOOP_OK; #endif @@ -13476,7 +13609,7 @@ join_read_system(JOIN_TAB *tab) empty_record(table); // Make empty record return -1; } - update_virtual_fields(table); + update_virtual_fields(tab->join->thd, table); store_record(table,record[1]); } else if (!table->status) // Only happens with left join @@ -13525,7 +13658,7 @@ join_read_const(JOIN_TAB *tab) return report_error(table, error); return -1; } - update_virtual_fields(table); + update_virtual_fields(tab->join->thd, table); store_record(table,record[1]); } else if (!(table->status & ~STATUS_NULL_ROW)) // Only happens with left join @@ -13783,7 +13916,7 @@ join_init_quick_read_record(JOIN_TAB *tab) int init_read_record_seq(JOIN_TAB *tab) { tab->read_record.read_record= rr_sequential; - if (tab->read_record.file->ha_rnd_init(1)) + if (tab->read_record.file->ha_rnd_init_with_error(1)) return 1; return (*tab->read_record.read_record)(&tab->read_record); } @@ -13809,8 +13942,9 @@ int join_init_read_record(JOIN_TAB *tab) { if (tab->select && tab->select->quick && tab->select->quick->reset()) return 1; - init_read_record(&tab->read_record, tab->join->thd, tab->table, - tab->select,1,1, FALSE); + if (init_read_record(&tab->read_record, tab->join->thd, tab->table, + tab->select,1,1, FALSE)) + return 1; return (*tab->read_record.read_record)(&tab->read_record); } @@ -14103,8 +14237,11 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { List_iterator_fast<Item> it(*join->fields); Item *item; + DBUG_PRINT("info", ("no matching rows")); + /* No matching rows for group function */ join->clear(); + join->no_rows_in_result_called= 1; while ((item= it++)) item->no_rows_in_result(); @@ -15297,6 +15434,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, uint nr; key_map keys; uint best_key_parts; + uint saved_best_key_parts= 0; int best_key_direction; ha_rows best_records; double read_time; @@ -15498,6 +15636,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, { best_key= nr; best_key_parts= keyinfo->key_parts; + saved_best_key_parts= used_key_parts; best_records= quick_records; is_best_covering= is_covering; best_key_direction= direction; @@ -15596,8 +15735,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, */ } } - used_key_parts= best_key_parts; order_direction= best_key_direction; + /* + saved_best_key_parts is actual number of used keyparts found by the + test_if_order_by_key function. It could differ from keyinfo->key_parts, + thus we have to restore it in case of desc order as it affects + QUICK_SELECT_DESC behaviour. + */ + used_key_parts= (order_direction == -1) ? + saved_best_key_parts : best_key_parts; } else goto use_filesort; @@ -15952,7 +16098,9 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field, org_record=(char*) (record=table->record[0])+offset; new_record=(char*) table->record[1]+offset; - file->ha_rnd_init(1); + if (file->ha_rnd_init_with_error(1)) + DBUG_RETURN(1); + error= file->ha_rnd_next(record); for (;;) { @@ -16081,7 +16229,9 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table, DBUG_RETURN(1); } - file->ha_rnd_init(1); + if ((error= file->ha_rnd_init(1))) + goto err; + key_pos=key_buffer; for (;;) { @@ -18103,7 +18253,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, the UNION to provide precise EXPLAIN information will hardly be appreciated :) */ - char table_name_buffer[NAME_LEN]; + char table_name_buffer[SAFE_NAME_LEN]; item_list.empty(); /* id */ item_list.push_back(new Item_null); @@ -18185,7 +18335,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, char keylen_str_buf[64]; my_bool key_read; String extra(buff, sizeof(buff),cs); - char table_name_buffer[NAME_LEN]; + char table_name_buffer[SAFE_NAME_LEN]; String tmp1(buff1,sizeof(buff1),cs); String tmp2(buff2,sizeof(buff2),cs); String tmp3(buff3,sizeof(buff3),cs); @@ -18247,7 +18397,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, item_list.push_back(new Item_string("unique_key", strlen("unique_key"), cs)); /* key_len */ uint klen= tab->emb_sj_nest->sj_mat_info->table->key_info[0].key_length; - uint buflen= longlong2str(klen, keylen_str_buf, 10) - keylen_str_buf; + uint buflen= longlong10_to_str(klen, keylen_str_buf, 10) - keylen_str_buf; item_list.push_back(new Item_string(keylen_str_buf, buflen, cs)); /* ref */ item_list.push_back(new Item_string("func", strlen("func"), cs)); @@ -18367,8 +18517,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, item_list.push_back(new Item_string(key_info->name, strlen(key_info->name), system_charset_info)); - length= longlong2str(tab->ref.key_length, keylen_str_buf, 10) - - keylen_str_buf; + length= (longlong10_to_str(tab->ref.key_length, keylen_str_buf, 10) - + keylen_str_buf); item_list.push_back(new Item_string(keylen_str_buf, length, system_charset_info)); for (store_key **ref=tab->ref.key_copy ; *ref ; ref++) @@ -18386,8 +18536,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, register uint length; item_list.push_back(new Item_string(key_info->name, strlen(key_info->name),cs)); - length= longlong2str(key_info->key_length, keylen_str_buf, 10) - - keylen_str_buf; + length= (longlong10_to_str(key_info->key_length, keylen_str_buf, 10) - + keylen_str_buf); item_list.push_back(new Item_string(keylen_str_buf, length, system_charset_info)); @@ -18765,15 +18915,15 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) thd->lex->current_select= first; unit->set_limit(unit->global_parameters); res= mysql_select(thd, &first->ref_pointer_array, - (TABLE_LIST*) first->table_list.first, + first->table_list.first, first->with_wild, first->item_list, first->where, first->order_list.elements + first->group_list.elements, - (ORDER*) first->order_list.first, - (ORDER*) first->group_list.first, + first->order_list.first, + first->group_list.first, first->having, - (ORDER*) thd->lex->proc_list.first, + thd->lex->proc_list.first, first->options | thd->options | SELECT_DESCRIBE, result, unit, first); } @@ -19113,7 +19263,7 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) if (group_list.elements) { str->append(STRING_WITH_LEN(" group by ")); - print_order(str, (ORDER *) group_list.first, query_type); + print_order(str, group_list.first, query_type); switch (olap) { case CUBE_TYPE: @@ -19144,7 +19294,7 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) if (order_list.elements) { str->append(STRING_WITH_LEN(" order by ")); - print_order(str, (ORDER *) order_list.first, query_type); + print_order(str, order_list.first, query_type); } // limit |