mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MariaDB 5.2 -> MariaDB 5.3 merge
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
|
||||
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright (c) 2009-2010 Monty Program Ab
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -294,6 +295,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
|
||||
all_fields List of all fields used in select
|
||||
select Current select
|
||||
ref_pointer_array Array of references to Items used in current select
|
||||
group_list GROUP BY list (is NULL by default)
|
||||
|
||||
DESCRIPTION
|
||||
The function serves 3 purposes - adds fields referenced from inner
|
||||
@ -312,6 +314,8 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
|
||||
function is aggregated in the select where the outer field was
|
||||
resolved or in some more inner select then the Item_direct_ref
|
||||
class should be used.
|
||||
It used used also if we are grouping by a subquery that refers
|
||||
this outer field.
|
||||
The resolution is done here and not at the fix_fields() stage as
|
||||
it can be done only after sum functions are fixed and pulled up to
|
||||
selects where they are have to be aggregated.
|
||||
@ -334,7 +338,19 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
|
||||
bool res= FALSE;
|
||||
bool direct_ref= FALSE;
|
||||
|
||||
List_iterator<Item_outer_ref> ref_it(select->inner_refs_list);
|
||||
/*
|
||||
Mark the references from the inner_refs_list that are occurred in
|
||||
the group by expressions. Those references will contain direct
|
||||
references to the referred fields. The markers are set in
|
||||
the found_in_group_by field of the references from the list.
|
||||
*/
|
||||
List_iterator_fast <Item_outer_ref> ref_it(select->inner_refs_list);
|
||||
for (ORDER *group= select->join->group_list; group; group= group->next)
|
||||
{
|
||||
(*group->item)->walk(&Item::check_inner_refs_processor,
|
||||
TRUE, (uchar *) &ref_it);
|
||||
}
|
||||
|
||||
while ((ref= ref_it++))
|
||||
{
|
||||
Item *item= ref->outer_ref;
|
||||
@ -378,6 +394,9 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ref->found_in_group_by)
|
||||
direct_ref= TRUE;
|
||||
|
||||
new_ref= direct_ref ?
|
||||
new Item_direct_ref(ref->context, item_ref, ref->table_name,
|
||||
ref->field_name, ref->alias_name_used) :
|
||||
@ -1015,9 +1034,8 @@ JOIN::optimize()
|
||||
}
|
||||
}
|
||||
|
||||
if (conds &&!outer_join && const_table_map != found_const_table_map &&
|
||||
(select_options & SELECT_DESCRIBE) &&
|
||||
select_lex->master_unit() == &thd->lex->unit) // upper level SELECT
|
||||
if (conds && const_table_map != found_const_table_map &&
|
||||
(select_options & SELECT_DESCRIBE))
|
||||
{
|
||||
conds=new Item_int((longlong) 0,1); // Always false
|
||||
}
|
||||
@ -2055,7 +2073,7 @@ JOIN::exec()
|
||||
|
||||
Item* sort_table_cond= make_cond_for_table(curr_join->tmp_having,
|
||||
used_tables,
|
||||
used_tables, FALSE);
|
||||
(table_map)0, FALSE);
|
||||
if (sort_table_cond)
|
||||
{
|
||||
if (!curr_table->select)
|
||||
@ -2226,7 +2244,13 @@ JOIN::destroy()
|
||||
tab->cleanup();
|
||||
}
|
||||
tmp_join->tmp_join= 0;
|
||||
/*
|
||||
We need to clean up tmp_table_param for reusable JOINs (having non-zero
|
||||
and different from self tmp_join) because it's not being cleaned up
|
||||
anywhere else (as we need to keep the join is reusable).
|
||||
*/
|
||||
tmp_table_param.cleanup();
|
||||
tmp_join->tmp_table_param.copy_field= 0;
|
||||
DBUG_RETURN(tmp_join->destroy());
|
||||
}
|
||||
cond_equal= 0;
|
||||
@ -4439,7 +4463,7 @@ best_access_path(JOIN *join,
|
||||
if (table->covering_keys.is_set(key))
|
||||
{
|
||||
/* we can use only index tree */
|
||||
tmp= record_count * table->file->index_only_read_time(key, tmp);
|
||||
tmp= record_count * table->file->keyread_read_time(key, 1, tmp);
|
||||
}
|
||||
else
|
||||
tmp= record_count*min(tmp,s->worst_seeks);
|
||||
@ -4604,7 +4628,7 @@ best_access_path(JOIN *join,
|
||||
if (table->covering_keys.is_set(key))
|
||||
{
|
||||
/* we can use only index tree */
|
||||
tmp= record_count * table->file->index_only_read_time(key, tmp);
|
||||
tmp= record_count * table->file->keyread_read_time(key, 1, tmp);
|
||||
}
|
||||
else
|
||||
tmp= record_count * min(tmp,s->worst_seeks);
|
||||
@ -5202,6 +5226,11 @@ greedy_search(JOIN *join,
|
||||
if (best_extension_by_limited_search(join, remaining_tables, idx, record_count,
|
||||
read_time, search_depth, prune_level))
|
||||
DBUG_RETURN(TRUE);
|
||||
/*
|
||||
'best_read < DBL_MAX' means that optimizer managed to find
|
||||
some plan and updated 'best_positions' array accordingly.
|
||||
*/
|
||||
DBUG_ASSERT(join->best_read < DBL_MAX);
|
||||
|
||||
if (size_remain <= search_depth)
|
||||
{
|
||||
@ -6127,7 +6156,7 @@ store_val_in_field(Field *field, Item *item, enum_check_fields check_flag)
|
||||
@retval TRUE error occurred
|
||||
*/
|
||||
bool
|
||||
JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
|
||||
JOIN::make_simple_join(JOIN *parent, TABLE *temp_table)
|
||||
{
|
||||
DBUG_ENTER("JOIN::make_simple_join");
|
||||
|
||||
@ -6140,13 +6169,19 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
|
||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||
|
||||
join_tab= parent->join_tab_reexec;
|
||||
table= &parent->table_reexec[0]; parent->table_reexec[0]= tmp_table;
|
||||
table= &parent->table_reexec[0]; parent->table_reexec[0]= temp_table;
|
||||
tables= 1;
|
||||
const_tables= 0;
|
||||
const_table_map= 0;
|
||||
eliminated_tables= 0;
|
||||
tmp_table_param.field_count= tmp_table_param.sum_func_count=
|
||||
tmp_table_param.func_count= 0;
|
||||
/*
|
||||
We need to destruct the copy_field (allocated in create_tmp_table())
|
||||
before setting it to 0 if the join is not "reusable".
|
||||
*/
|
||||
if (!tmp_join || tmp_join != this)
|
||||
tmp_table_param.cleanup();
|
||||
tmp_table_param.copy_field= tmp_table_param.copy_field_end=0;
|
||||
first_record= sort_and_group=0;
|
||||
send_records= (ha_rows) 0;
|
||||
@ -6156,8 +6191,8 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
|
||||
|
||||
join_tab->use_join_cache= FALSE;
|
||||
join_tab->cache=0; /* No caching */
|
||||
join_tab->table=temp_table;
|
||||
join_tab->cache_select= 0;
|
||||
join_tab->table=tmp_table;
|
||||
join_tab->select=0;
|
||||
join_tab->set_select_cond(NULL, __LINE__);
|
||||
join_tab->select_cond=0;
|
||||
@ -6180,8 +6215,8 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
|
||||
join_tab->loosescan_match_tab= NULL;
|
||||
join_tab->emb_sj_nest= NULL;
|
||||
bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
|
||||
tmp_table->status=0;
|
||||
tmp_table->null_row=0;
|
||||
temp_table->status=0;
|
||||
temp_table->null_row=0;
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
@ -7486,10 +7521,7 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
|
||||
}
|
||||
if (table->covering_keys.is_set(tab->ref.key) &&
|
||||
!table->no_keyread)
|
||||
{
|
||||
table->key_read=1;
|
||||
table->file->extra(HA_EXTRA_KEYREAD);
|
||||
}
|
||||
table->enable_keyread();
|
||||
else
|
||||
push_index_cond(tab, tab->ref.key, icp_other_tables_ok);
|
||||
break;
|
||||
@ -7556,10 +7588,7 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
|
||||
if (tab->select && tab->select->quick &&
|
||||
tab->select->quick->index != MAX_KEY && //not index_merge
|
||||
table->covering_keys.is_set(tab->select->quick->index))
|
||||
{
|
||||
table->key_read=1;
|
||||
table->file->extra(HA_EXTRA_KEYREAD);
|
||||
}
|
||||
table->enable_keyread();
|
||||
else if (!table->covering_keys.is_clear_all() &&
|
||||
!(tab->select && tab->select->quick))
|
||||
{ // Only read index tree
|
||||
@ -7673,11 +7702,7 @@ void JOIN_TAB::cleanup()
|
||||
limit= 0;
|
||||
if (table)
|
||||
{
|
||||
if (table->key_read)
|
||||
{
|
||||
table->key_read= 0;
|
||||
table->file->extra(HA_EXTRA_NO_KEYREAD);
|
||||
}
|
||||
table->disable_keyread();
|
||||
table->file->ha_index_or_rnd_end();
|
||||
/*
|
||||
We need to reset this for next select
|
||||
@ -7921,9 +7946,11 @@ eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab)
|
||||
}
|
||||
if (order)
|
||||
{
|
||||
found++;
|
||||
DBUG_ASSERT(!(order->used & map));
|
||||
order->used|=map;
|
||||
if (!(order->used & map))
|
||||
{
|
||||
found++;
|
||||
order->used|= map;
|
||||
}
|
||||
continue; // Used in ORDER BY
|
||||
}
|
||||
if (!only_eq_ref_tables(join,start_order, (*ref_item)->used_tables()))
|
||||
@ -9065,6 +9092,8 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
|
||||
Item *item_const= item_equal->get_const();
|
||||
Item_equal_iterator it(*item_equal);
|
||||
Item *head;
|
||||
DBUG_ASSERT(!cond || cond->type() == Item::COND_ITEM);
|
||||
|
||||
TABLE_LIST *current_sjm= NULL;
|
||||
Item *current_sjm_head= NULL;
|
||||
|
||||
@ -9142,23 +9171,27 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
|
||||
current_sjm= field_sjm;
|
||||
}
|
||||
|
||||
if (!cond && !eq_list.head())
|
||||
{
|
||||
if (!eq_item)
|
||||
return new Item_int((longlong) 1,1);
|
||||
return eq_item;
|
||||
}
|
||||
|
||||
if (eq_item)
|
||||
eq_list.push_back(eq_item);
|
||||
if (!cond)
|
||||
cond= new Item_cond_and(eq_list);
|
||||
{
|
||||
if (eq_list.is_empty())
|
||||
{
|
||||
if (eq_item)
|
||||
return eq_item;
|
||||
return new Item_int((longlong) 1, 1);
|
||||
}
|
||||
/* eq_item is always set if list is not empty */
|
||||
DBUG_ASSERT(eq_item);
|
||||
eq_list.push_back(eq_item);
|
||||
if (!(cond= new Item_cond_and(eq_list)))
|
||||
return 0; // Error
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(cond->type() == Item::COND_ITEM);
|
||||
((Item_cond *) cond)->add_at_head(&eq_list);
|
||||
if (eq_item)
|
||||
eq_list.push_back(eq_item);
|
||||
if (!eq_list.is_empty())
|
||||
((Item_cond *) cond)->add_at_head(&eq_list);
|
||||
}
|
||||
|
||||
cond->quick_fix_field();
|
||||
cond->update_used_tables();
|
||||
|
||||
@ -9198,6 +9231,7 @@ static COND* substitute_for_best_equal_field(COND *cond,
|
||||
void *table_join_idx)
|
||||
{
|
||||
Item_equal *item_equal;
|
||||
COND *org_cond= cond; // Return this in case of fatal error
|
||||
|
||||
if (cond->type() == Item::COND_ITEM)
|
||||
{
|
||||
@ -9221,7 +9255,7 @@ static COND* substitute_for_best_equal_field(COND *cond,
|
||||
Item *item;
|
||||
while ((item= li++))
|
||||
{
|
||||
Item *new_item =substitute_for_best_equal_field(item, cond_equal,
|
||||
Item *new_item= substitute_for_best_equal_field(item, cond_equal,
|
||||
table_join_idx);
|
||||
/*
|
||||
This works OK with PS/SP re-execution as changes are made to
|
||||
@ -9240,6 +9274,8 @@ static COND* substitute_for_best_equal_field(COND *cond,
|
||||
// This occurs when eliminate_item_equal() founds that cond is
|
||||
// always false and substitutes it with Item_int 0.
|
||||
// Due to this, value of item_equal will be 0, so just return it.
|
||||
if (!cond)
|
||||
return org_cond; // Error
|
||||
if (cond->type() != Item::COND_ITEM)
|
||||
break;
|
||||
}
|
||||
@ -9256,7 +9292,8 @@ static COND* substitute_for_best_equal_field(COND *cond,
|
||||
item_equal->sort(&compare_fields_by_table_order, table_join_idx);
|
||||
if (cond_equal && cond_equal->current_level.head() == item_equal)
|
||||
cond_equal= 0;
|
||||
return eliminate_item_equal(0, cond_equal, item_equal);
|
||||
cond= eliminate_item_equal(0, cond_equal, item_equal);
|
||||
return cond ? cond : org_cond;
|
||||
}
|
||||
else
|
||||
cond->transform(&Item::replace_equal_field, 0);
|
||||
@ -9729,8 +9766,15 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top,
|
||||
we still make the inner tables dependent on the outer tables.
|
||||
It would be enough to set dependency only on one outer table
|
||||
for them. Yet this is really a rare case.
|
||||
Note:
|
||||
RAND_TABLE_BIT mask should not be counted as it
|
||||
prevents update of inner table dependences.
|
||||
For example it might happen if RAND() function
|
||||
is used in JOIN ON clause.
|
||||
*/
|
||||
if (!(prev_table->on_expr->used_tables() & ~prev_used_tables))
|
||||
if (!((prev_table->on_expr->used_tables() &
|
||||
~(OUTER_REF_TABLE_BIT | RAND_TABLE_BIT)) &
|
||||
~prev_used_tables))
|
||||
prev_table->dep_tables|= used_tables;
|
||||
}
|
||||
}
|
||||
@ -10878,7 +10922,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
KEY_PART_INFO *key_part_info;
|
||||
Item **copy_func;
|
||||
ENGINE_COLUMNDEF *recinfo;
|
||||
uint total_uneven_bit_length= 0;
|
||||
/*
|
||||
total_uneven_bit_length is uneven bit length for visible fields
|
||||
hidden_uneven_bit_length is uneven bit length for hidden fields
|
||||
*/
|
||||
uint total_uneven_bit_length= 0, hidden_uneven_bit_length= 0;
|
||||
bool force_copy_fields= param->force_copy_fields;
|
||||
/* Treat sum functions as normal ones when loose index scan is used. */
|
||||
save_sum_fields|= param->precomputed_group_by;
|
||||
@ -11176,6 +11224,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
*/
|
||||
param->hidden_field_count= fieldnr;
|
||||
null_count= 0;
|
||||
/*
|
||||
On last hidden field we store uneven bit length in
|
||||
hidden_uneven_bit_length and proceed calculation of
|
||||
uneven bits for visible fields into
|
||||
total_uneven_bit_length variable.
|
||||
*/
|
||||
hidden_uneven_bit_length= total_uneven_bit_length;
|
||||
total_uneven_bit_length= 0;
|
||||
}
|
||||
}
|
||||
DBUG_ASSERT(fieldnr == (uint) (reg_field - table->field));
|
||||
@ -11221,7 +11277,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
else
|
||||
null_count++;
|
||||
}
|
||||
hidden_null_pack_length=(hidden_null_count+7)/8;
|
||||
hidden_null_pack_length= (hidden_null_count + 7 +
|
||||
hidden_uneven_bit_length) / 8;
|
||||
null_pack_length= (hidden_null_pack_length +
|
||||
(null_count + total_uneven_bit_length + 7) / 8);
|
||||
reclength+=null_pack_length;
|
||||
@ -12067,6 +12124,11 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table,
|
||||
if (table->s->db_type() != heap_hton ||
|
||||
error != HA_ERR_RECORD_FILE_FULL)
|
||||
{
|
||||
/*
|
||||
We don't want this error to be converted to a warning, e.g. in case of
|
||||
INSERT IGNORE ... SELECT.
|
||||
*/
|
||||
thd->fatal_error();
|
||||
table->file->print_error(error,MYF(0));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
@ -13088,7 +13150,18 @@ evaluate_null_complemented_join_record(JOIN *join, JOIN_TAB *join_tab)
|
||||
return (*join_tab->next_select)(join, join_tab+1, 0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef MERGE_JUNK
|
||||
//psergey3-merge: remove:
|
||||
int err= 0;
|
||||
(err= join_tab->cache.select->skip_record(join->thd)) != 0 ))
|
||||
return NESTED_LOOP_ERROR;
|
||||
rc= NESTED_LOOP_OK;
|
||||
if (!select || (err= select->skip_record(join->thd)) != 0)
|
||||
if (err < 0)
|
||||
return NESTED_LOOP_ERROR;
|
||||
|
||||
rc= NESTED_LOOP_OK;
|
||||
#endif
|
||||
/*****************************************************************************
|
||||
The different ways to read a record
|
||||
Returns -1 if row was not found, 0 if row was found and 1 on errors
|
||||
@ -13161,16 +13234,11 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
|
||||
!table->no_keyread &&
|
||||
(int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY)
|
||||
{
|
||||
table->key_read=1;
|
||||
table->file->extra(HA_EXTRA_KEYREAD);
|
||||
table->enable_keyread();
|
||||
tab->index= tab->ref.key;
|
||||
}
|
||||
error=join_read_const(tab);
|
||||
if (table->key_read)
|
||||
{
|
||||
table->key_read=0;
|
||||
table->file->extra(HA_EXTRA_NO_KEYREAD);
|
||||
}
|
||||
table->disable_keyread();
|
||||
if (error)
|
||||
{
|
||||
tab->info="unique row not found";
|
||||
@ -13476,9 +13544,10 @@ join_read_last_key(JOIN_TAB *tab)
|
||||
}
|
||||
if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref))
|
||||
return -1;
|
||||
if ((error= table->file->ha_index_read_last_map(table->record[0],
|
||||
tab->ref.key_buff,
|
||||
make_prev_keypart_map(tab->ref.key_parts))))
|
||||
if ((error= table->file->ha_index_read_map(table->record[0],
|
||||
tab->ref.key_buff,
|
||||
make_prev_keypart_map(tab->ref.key_parts),
|
||||
HA_READ_PREFIX_LAST)))
|
||||
{
|
||||
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
||||
return report_error(table, error);
|
||||
@ -13590,12 +13659,9 @@ join_read_first(JOIN_TAB *tab)
|
||||
{
|
||||
int error= 0;
|
||||
TABLE *table=tab->table;
|
||||
if (!table->key_read && table->covering_keys.is_set(tab->index) &&
|
||||
!table->no_keyread)
|
||||
{
|
||||
table->key_read=1;
|
||||
table->file->extra(HA_EXTRA_KEYREAD);
|
||||
}
|
||||
if (table->covering_keys.is_set(tab->index) && !table->no_keyread &&
|
||||
!table->key_read)
|
||||
table->enable_keyread();
|
||||
tab->table->status=0;
|
||||
tab->read_record.read_record=join_read_next;
|
||||
tab->read_record.table=table;
|
||||
@ -13632,12 +13698,9 @@ join_read_last(JOIN_TAB *tab)
|
||||
{
|
||||
TABLE *table=tab->table;
|
||||
int error= 0;
|
||||
if (!table->key_read && table->covering_keys.is_set(tab->index) &&
|
||||
!table->no_keyread)
|
||||
{
|
||||
table->key_read=1;
|
||||
table->file->extra(HA_EXTRA_KEYREAD);
|
||||
}
|
||||
if (table->covering_keys.is_set(tab->index) && !table->no_keyread &&
|
||||
!table->key_read)
|
||||
table->enable_keyread();
|
||||
tab->table->status=0;
|
||||
tab->read_record.read_record=join_read_prev;
|
||||
tab->read_record.table=table;
|
||||
@ -14597,7 +14660,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
|
||||
key_part_end=key_part+table->key_info[idx].key_parts;
|
||||
key_part_map const_key_parts=table->const_key_parts[idx];
|
||||
int reverse=0;
|
||||
my_bool on_primary_key= FALSE;
|
||||
my_bool on_pk_suffix= FALSE;
|
||||
DBUG_ENTER("test_if_order_by_key");
|
||||
|
||||
for (; order ; order=order->next, const_key_parts>>=1)
|
||||
@ -14619,11 +14682,12 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
|
||||
key as a suffix to the secondary keys. If it has continue to check
|
||||
the primary key as a suffix.
|
||||
*/
|
||||
if (!on_primary_key &&
|
||||
if (!on_pk_suffix &&
|
||||
(table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
|
||||
table->s->primary_key != MAX_KEY)
|
||||
table->s->primary_key != MAX_KEY &&
|
||||
table->s->primary_key != idx)
|
||||
{
|
||||
on_primary_key= TRUE;
|
||||
on_pk_suffix= TRUE;
|
||||
key_part= table->key_info[table->s->primary_key].key_part;
|
||||
key_part_end=key_part+table->key_info[table->s->primary_key].key_parts;
|
||||
const_key_parts=table->const_key_parts[table->s->primary_key];
|
||||
@ -14655,7 +14719,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
|
||||
reverse=flag; // Remember if reverse
|
||||
key_part++;
|
||||
}
|
||||
if (on_primary_key)
|
||||
if (on_pk_suffix)
|
||||
{
|
||||
uint used_key_parts_secondary= table->key_info[idx].key_parts;
|
||||
uint used_key_parts_pk=
|
||||
@ -15088,12 +15152,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||
*/
|
||||
if (select_limit >= table_records)
|
||||
{
|
||||
/*
|
||||
filesort() and join cache are usually faster than reading in
|
||||
index order and not using join cache
|
||||
*/
|
||||
if (tab->type == JT_ALL && tab->join->tables > tab->join->const_tables + 1)
|
||||
goto use_filesort;
|
||||
keys= *table->file->keys_to_use_for_scanning();
|
||||
keys.merge(table->covering_keys);
|
||||
|
||||
@ -15155,9 +15213,54 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||
select_limit= table_records;
|
||||
if (group)
|
||||
{
|
||||
rec_per_key= used_key_parts ? keyinfo->rec_per_key[used_key_parts-1]
|
||||
: 1;
|
||||
set_if_bigger(rec_per_key, 1);
|
||||
/*
|
||||
Used_key_parts can be larger than keyinfo->key_parts
|
||||
when using a secondary index clustered with a primary
|
||||
key (e.g. as in Innodb).
|
||||
See Bug #28591 for details.
|
||||
*/
|
||||
uint used_index_parts= keyinfo->key_parts;
|
||||
uint used_pk_parts= 0;
|
||||
if (used_key_parts > used_index_parts)
|
||||
used_pk_parts= used_key_parts-used_index_parts;
|
||||
rec_per_key= keyinfo->rec_per_key[used_key_parts-1];
|
||||
/* Take into account the selectivity of the used pk prefix */
|
||||
if (used_pk_parts)
|
||||
{
|
||||
KEY *pkinfo=tab->table->key_info+table->s->primary_key;
|
||||
/*
|
||||
If the values of of records per key for the prefixes
|
||||
of the primary key are considered unknown we assume
|
||||
they are equal to 1.
|
||||
*/
|
||||
if (used_key_parts == pkinfo->key_parts ||
|
||||
pkinfo->rec_per_key[0] == 0)
|
||||
rec_per_key= 1;
|
||||
if (rec_per_key > 1)
|
||||
{
|
||||
rec_per_key*= pkinfo->rec_per_key[used_pk_parts-1];
|
||||
rec_per_key/= pkinfo->rec_per_key[0];
|
||||
/*
|
||||
The value of rec_per_key for the extended key has
|
||||
to be adjusted accordingly if some components of
|
||||
the secondary key are included in the primary key.
|
||||
*/
|
||||
for(uint i= 0; i < used_pk_parts; i++)
|
||||
{
|
||||
if (pkinfo->key_part[i].field->key_start.is_set(nr))
|
||||
{
|
||||
/*
|
||||
We presume here that for any index rec_per_key[i] != 0
|
||||
if rec_per_key[0] != 0.
|
||||
*/
|
||||
DBUG_ASSERT(pkinfo->rec_per_key[i]);
|
||||
rec_per_key*= pkinfo->rec_per_key[i-1];
|
||||
rec_per_key/= pkinfo->rec_per_key[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
set_if_bigger(rec_per_key, 1);
|
||||
/*
|
||||
With a grouping query each group containing on average
|
||||
rec_per_key records produces only one row that will
|
||||
@ -15236,6 +15339,19 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
filesort() and join cache are usually faster than reading in
|
||||
index order and not using join cache, except in case that chosen
|
||||
index is clustered primary key.
|
||||
*/
|
||||
if ((select_limit >= table_records) &&
|
||||
(tab->type == JT_ALL &&
|
||||
tab->join->tables > tab->join->const_tables + 1) &&
|
||||
((unsigned) best_key != table->s->primary_key ||
|
||||
!table->file->primary_key_is_clustered()))
|
||||
DBUG_RETURN(0);
|
||||
|
||||
if (best_key >= 0)
|
||||
{
|
||||
bool quick_created= FALSE;
|
||||
@ -15257,11 +15373,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||
If ref_key used index tree reading only ('Using index' in EXPLAIN),
|
||||
and best_key doesn't, then revert the decision.
|
||||
*/
|
||||
if (!table->covering_keys.is_set(best_key) && table->key_read)
|
||||
{
|
||||
table->key_read= 0;
|
||||
table->file->extra(HA_EXTRA_NO_KEYREAD);
|
||||
}
|
||||
if (!table->covering_keys.is_set(best_key))
|
||||
table->disable_keyread();
|
||||
if (!quick_created)
|
||||
{
|
||||
tab->index= best_key;
|
||||
@ -15273,11 +15386,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||
delete select->quick;
|
||||
select->quick= 0;
|
||||
}
|
||||
if (table->covering_keys.is_set(best_key))
|
||||
{
|
||||
table->key_read=1;
|
||||
table->file->extra(HA_EXTRA_KEYREAD);
|
||||
}
|
||||
if (table->covering_keys.is_set(best_key) && ! table->key_read)
|
||||
table->enable_keyread();
|
||||
if (tab->pre_idx_push_select_cond)
|
||||
{
|
||||
COND *tmp_cond= tab->pre_idx_push_select_cond;
|
||||
@ -15470,11 +15580,8 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
|
||||
We can only use 'Only index' if quick key is same as ref_key
|
||||
and in index_merge 'Only index' cannot be used
|
||||
*/
|
||||
if (table->key_read && ((uint) tab->ref.key != select->quick->index))
|
||||
{
|
||||
table->key_read=0;
|
||||
table->file->extra(HA_EXTRA_NO_KEYREAD);
|
||||
}
|
||||
if (((uint) tab->ref.key != select->quick->index))
|
||||
table->disable_keyread();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -15530,11 +15637,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
|
||||
tab->type=JT_ALL; // Read with normal read_record
|
||||
tab->read_first_record= join_init_read_record;
|
||||
tab->join->examined_rows+=examined_rows;
|
||||
if (table->key_read) // Restore if we used indexes
|
||||
{
|
||||
table->key_read=0;
|
||||
table->file->extra(HA_EXTRA_NO_KEYREAD);
|
||||
}
|
||||
table->disable_keyread(); // Restore if we used indexes
|
||||
DBUG_RETURN(table->sort.found_records == HA_POS_ERROR);
|
||||
err:
|
||||
DBUG_RETURN(-1);
|
||||
@ -15915,9 +16018,13 @@ SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
eq_ref: Create the lookup key and check if it is the same as saved key
|
||||
|
||||
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
cmp_buffer_with_ref()
|
||||
tab Join tab of the accessed table
|
||||
@ -16135,7 +16242,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
time.
|
||||
|
||||
We check order_item->fixed because Item_func_group_concat can put
|
||||
arguments for which fix_fields already was called.
|
||||
arguments for which fix_fields already was called.
|
||||
*/
|
||||
if (!order_item->fixed &&
|
||||
(order_item->fix_fields(thd, order->item) ||
|
||||
@ -16212,6 +16319,8 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
uint org_fields=all_fields.elements;
|
||||
|
||||
thd->where="group statement";
|
||||
enum_parsing_place save_place= thd->lex->current_select->parsing_place;
|
||||
thd->lex->current_select->parsing_place= IN_GROUP_BY;
|
||||
for (ord= order; ord; ord= ord->next)
|
||||
{
|
||||
if (find_order_in_list(thd, ref_pointer_array, tables, ord, fields,
|
||||
@ -16224,6 +16333,8 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
thd->lex->current_select->parsing_place= save_place;
|
||||
|
||||
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
|
||||
{
|
||||
/*
|
||||
@ -17254,7 +17365,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
|
||||
|
||||
Item_cond_and *cond=new Item_cond_and();
|
||||
TABLE *table=join_tab->table;
|
||||
int error;
|
||||
int error= 0;
|
||||
if (!cond)
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
@ -17276,7 +17387,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
|
||||
}
|
||||
if (join_tab->select)
|
||||
{
|
||||
error=(int) cond->add(join_tab->select->cond);
|
||||
if (join_tab->select->cond)
|
||||
error=(int) cond->add(join_tab->select->cond);
|
||||
join_tab->select->cond= cond;
|
||||
join_tab->set_select_cond(cond, __LINE__);
|
||||
}
|
||||
@ -18783,7 +18895,17 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
|
||||
first= 0;
|
||||
else
|
||||
str->append(',');
|
||||
item->print_item_w_name(str, query_type);
|
||||
|
||||
if (is_subquery_function() && item->is_autogenerated_name)
|
||||
{
|
||||
/*
|
||||
Do not print auto-generated aliases in subqueries. It has no purpose
|
||||
in a view definition or other contexts where the query is printed.
|
||||
*/
|
||||
item->print(str, query_type);
|
||||
}
|
||||
else
|
||||
item->print_item_w_name(str, query_type);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user