1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

Merge neptunus.(none):/home/msvensson/mysql/mysql-5.1

into  neptunus.(none):/home/msvensson/mysql/mysql-5.1-maint
This commit is contained in:
msvensson@neptunus.(none)
2007-02-06 15:46:17 +01:00
305 changed files with 6041 additions and 3924 deletions

View File

@ -109,7 +109,6 @@ static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list,
static COND *optimize_cond(JOIN *join, COND *conds,
List<TABLE_LIST> *join_list,
Item::cond_result *cond_value);
static bool resolve_nested_join (TABLE_LIST *table);
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
static bool open_tmp_table(TABLE *table);
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
@ -717,11 +716,20 @@ JOIN::optimize()
{
int res;
/*
opt_sum_query() returns -1 if no rows match to the WHERE conditions,
or 1 if all items were resolved, or 0, or an error number HA_ERR_...
opt_sum_query() returns HA_ERR_KEY_NOT_FOUND if no rows match
to the WHERE conditions,
or 1 if all items were resolved,
or 0, or an error number HA_ERR_...
*/
if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds)))
{
if (res == HA_ERR_KEY_NOT_FOUND)
{
DBUG_PRINT("info",("No matching min/max row"));
zero_result_cause= "No matching min/max row";
error=0;
DBUG_RETURN(0);
}
if (res > 1)
{
thd->fatal_error();
@ -729,13 +737,6 @@ JOIN::optimize()
DBUG_PRINT("error",("Error from opt_sum_query"));
DBUG_RETURN(1);
}
if (res < 0)
{
DBUG_PRINT("info",("No matching min/max row"));
zero_result_cause= "No matching min/max row";
error=0;
DBUG_RETURN(0);
}
DBUG_PRINT("info",("Select tables optimized away"));
zero_result_cause= "Select tables optimized away";
tables_list= 0; // All tables resolved
@ -865,6 +866,13 @@ JOIN::optimize()
{
ORDER *org_order= order;
order=remove_const(this, order,conds,1, &simple_order);
if (thd->net.report_error)
{
error= 1;
DBUG_PRINT("error",("Error from remove_const"));
DBUG_RETURN(1);
}
/*
If we are using ORDER BY NULL or ORDER BY const_expression,
return result in any order (even if we are using a GROUP BY)
@ -874,10 +882,11 @@ JOIN::optimize()
}
/*
Check if we can optimize away GROUP BY/DISTINCT.
We can do that if there are no aggregate functions and the
We can do that if there are no aggregate functions, the
fields in DISTINCT clause (if present) and/or columns in GROUP BY
(if present) contain direct references to all key parts of
an unique index (in whatever order).
an unique index (in whatever order) and if the key parts of the
unique index cannot contain NULLs.
Note that the unique keys for DISTINCT and GROUP BY should not
be the same (as long as they are unique).
@ -972,6 +981,12 @@ JOIN::optimize()
group_list= remove_const(this, (old_group_list= group_list), conds,
rollup.state == ROLLUP::STATE_NONE,
&simple_group);
if (thd->net.report_error)
{
error= 1;
DBUG_PRINT("error",("Error from remove_const"));
DBUG_RETURN(1);
}
if (old_group_list && !group_list)
select_distinct= 0;
}
@ -988,6 +1003,12 @@ JOIN::optimize()
{
group_list= procedure->group= remove_const(this, procedure->group, conds,
1, &simple_group);
if (thd->net.report_error)
{
error= 1;
DBUG_PRINT("error",("Error from remove_const"));
DBUG_RETURN(1);
}
calc_group_buffer(this, group_list);
}
@ -2469,14 +2490,14 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
for( ; sargables->field ; sargables++)
{
Field *field= sargables->field;
JOIN_TAB *stat= field->table->reginfo.join_tab;
JOIN_TAB *join_tab= field->table->reginfo.join_tab;
key_map possible_keys= field->key_start;
possible_keys.intersect(field->table->keys_in_use_for_query);
bool is_const= 1;
for (uint i=0; i< sargables->num_values; i++)
is_const&= sargables->arg_value[i]->const_item();
for (uint j=0; j < sargables->num_values; j++)
is_const&= sargables->arg_value[j]->const_item();
if (is_const)
stat[0].const_keys.merge(possible_keys);
join_tab[0].const_keys.merge(possible_keys);
}
}
@ -3472,16 +3493,16 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
*/
if (keyuse->elements)
{
KEYUSE end,*prev,*save_pos,*use;
KEYUSE key_end,*prev,*save_pos,*use;
qsort(keyuse->buffer,keyuse->elements,sizeof(KEYUSE),
(qsort_cmp) sort_keyuse);
bzero((char*) &end,sizeof(end)); /* Add for easy testing */
VOID(insert_dynamic(keyuse,(gptr) &end));
bzero((char*) &key_end,sizeof(key_end)); /* Add for easy testing */
VOID(insert_dynamic(keyuse,(gptr) &key_end));
use=save_pos=dynamic_element(keyuse,0,KEYUSE*);
prev=&end;
prev= &key_end;
found_eq_constant=0;
for (i=0 ; i < keyuse->elements-1 ; i++,use++)
{
@ -3509,7 +3530,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
save_pos++;
}
i=(uint) (save_pos-(KEYUSE*) keyuse->buffer);
VOID(set_dynamic(keyuse,(gptr) &end,i));
VOID(set_dynamic(keyuse,(gptr) &key_end,i));
keyuse->elements=i;
}
return FALSE;
@ -3694,7 +3715,6 @@ best_access_path(JOIN *join,
table_map best_ref_depends_map= 0;
double tmp;
ha_rows rec;
DBUG_ENTER("best_access_path");
if (s->keyuse)
@ -3742,12 +3762,12 @@ best_access_path(JOIN *join,
if (!(keyuse->used_tables & ~join->const_table_map))
const_part|= keyuse->keypart_map;
double tmp= prev_record_reads(join, idx, (found_ref |
double tmp2= prev_record_reads(join, idx, (found_ref |
keyuse->used_tables));
if (tmp < best_prev_record_reads)
if (tmp2 < best_prev_record_reads)
{
best_part_found_ref= keyuse->used_tables & ~join->const_table_map;
best_prev_record_reads= tmp;
best_prev_record_reads= tmp2;
}
if (rec > keyuse->ref_table_rows)
rec= keyuse->ref_table_rows;
@ -5917,37 +5937,42 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
*/
COND *on_expr= *first_inner_tab->on_expr_ref;
table_map used_tables= join->const_table_map |
OUTER_REF_TABLE_BIT | RAND_TABLE_BIT;
table_map used_tables2= (join->const_table_map |
OUTER_REF_TABLE_BIT | RAND_TABLE_BIT);
for (tab= join->join_tab+join->const_tables; tab <= last_tab ; tab++)
{
current_map= tab->table->map;
used_tables|= current_map;
COND *tmp= make_cond_for_table(on_expr, used_tables, current_map);
if (tmp)
used_tables2|= current_map;
COND *tmp_cond= make_cond_for_table(on_expr, used_tables2,
current_map);
if (tmp_cond)
{
JOIN_TAB *cond_tab= tab < first_inner_tab ? first_inner_tab : tab;
/*
First add the guards for match variables of
all embedding outer join operations.
*/
if (!(tmp= add_found_match_trig_cond(cond_tab->first_inner,
tmp, first_inner_tab)))
if (!(tmp_cond= add_found_match_trig_cond(cond_tab->first_inner,
tmp_cond,
first_inner_tab)))
DBUG_RETURN(1);
/*
Now add the guard turning the predicate off for
the null complemented row.
*/
DBUG_PRINT("info", ("Item_func_trig_cond"));
tmp= new Item_func_trig_cond(tmp,
&first_inner_tab->not_null_compl);
DBUG_PRINT("info", ("Item_func_trig_cond 0x%lx", (ulong) tmp));
if (tmp)
tmp->quick_fix_field();
tmp_cond= new Item_func_trig_cond(tmp_cond,
&first_inner_tab->
not_null_compl);
DBUG_PRINT("info", ("Item_func_trig_cond 0x%lx",
(ulong) tmp_cond));
if (tmp_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 :
new Item_cond_and(cond_tab->select_cond,tmp);
cond_tab->select_cond= !cond_tab->select_cond ? tmp_cond :
new Item_cond_and(cond_tab->select_cond,
tmp_cond);
DBUG_PRINT("info", ("Item_cond_and 0x%lx",
(ulong)cond_tab->select_cond));
if (!cond_tab->select_cond)
@ -6266,7 +6291,7 @@ void JOIN_TAB::cleanup()
void JOIN::join_free()
{
SELECT_LEX_UNIT *unit;
SELECT_LEX_UNIT *tmp_unit;
SELECT_LEX *sl;
/*
Optimization: if not EXPLAIN and we are done with the JOIN,
@ -6278,8 +6303,10 @@ void JOIN::join_free()
cleanup(full);
for (unit= select_lex->first_inner_unit(); unit; unit= unit->next_unit())
for (sl= unit->first_select(); sl; sl= sl->next_select())
for (tmp_unit= select_lex->first_inner_unit();
tmp_unit;
tmp_unit= tmp_unit->next_unit())
for (sl= tmp_unit->first_select(); sl; sl= sl->next_select())
{
Item_subselect *subselect= sl->master_unit()->item;
bool full_local= full && (!subselect || subselect->is_evaluated());
@ -6578,6 +6605,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)
order->item[0]->val_str(&order->item[0]->str_value);
DBUG_PRINT("info",("removing: %s", order->item[0]->full_name()));
continue; // skip const item
}
@ -6915,9 +6944,9 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
else
{
/* None of the fields was found in multiple equalities */
Item_equal *item= new Item_equal((Item_field *) left_item,
(Item_field *) right_item);
cond_equal->current_level.push_back(item);
Item_equal *item_equal= new Item_equal((Item_field *) left_item,
(Item_field *) right_item);
cond_equal->current_level.push_back(item_equal);
}
}
return TRUE;
@ -7024,8 +7053,8 @@ static bool check_row_equality(Item *left_row, Item_row *right_row,
for (uint i= 0 ; i < n; i++)
{
bool is_converted;
Item *left_item= left_row->el(i);
Item *right_item= right_row->el(i);
Item *left_item= left_row->element_index(i);
Item *right_item= right_row->element_index(i);
if (left_item->type() == Item::ROW_ITEM &&
right_item->type() == Item::ROW_ITEM)
is_converted= check_row_equality((Item_row *) left_item,
@ -7415,14 +7444,15 @@ static COND *build_equal_items(THD *thd, COND *cond,
{
if (table->on_expr)
{
List<TABLE_LIST> *join_list= table->nested_join ?
&table->nested_join->join_list : NULL;
List<TABLE_LIST> *nested_join_list= table->nested_join ?
&table->nested_join->join_list : NULL;
/*
We can modify table->on_expr because its old value will
be restored before re-execution of PS/SP.
*/
table->on_expr= build_equal_items(thd, table->on_expr, inherited,
join_list, &table->cond_equal);
nested_join_list,
&table->cond_equal);
}
}
}
@ -7795,7 +7825,7 @@ change_cond_ref_to_const(THD *thd, I_List<COND_CMP> *save_list,
value->result_type() != STRING_RESULT ||
left_item->collation.collation == value->collation.collation))
{
Item *tmp=value->new_item();
Item *tmp=value->clone_item();
tmp->collation.set(right_item->collation);
if (tmp)
@ -7819,7 +7849,7 @@ change_cond_ref_to_const(THD *thd, I_List<COND_CMP> *save_list,
value->result_type() != STRING_RESULT ||
right_item->collation.collation == value->collation.collation))
{
Item *tmp=value->new_item();
Item *tmp= value->clone_item();
tmp->collation.set(left_item->collation);
if (tmp)
@ -8440,7 +8470,6 @@ optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list,
Item::cond_result *cond_value)
{
THD *thd= join->thd;
SELECT_LEX *select= thd->lex->current_select;
DBUG_ENTER("optimize_cond");
if (!conds)
@ -12109,7 +12138,7 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
/*
Check if GROUP BY/DISTINCT can be optimized away because the set is
Check if GROUP BY/DISTINCT can be optimized away because the set is
already known to be distinct.
SYNOPSIS
@ -12117,7 +12146,7 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
table The table to operate on.
find_func function to iterate over the list and search
for a field
DESCRIPTION
Used in removing the GROUP BY/DISTINCT of the following types of
statements:
@ -12128,12 +12157,13 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
then <any combination of a,b,c>,{whatever} is also distinct
This function checks if all the key parts of any of the unique keys
of the table are referenced by a list : either the select list
of the table are referenced by a list : either the select list
through find_field_in_item_list or GROUP BY list through
find_field_in_order_list.
If the above holds then we can safely remove the GROUP BY/DISTINCT,
If the above holds and the key parts cannot contain NULLs then we
can safely remove the GROUP BY/DISTINCT,
as no result set can be more distinct than an unique key.
RETURN VALUE
1 found
0 not found.
@ -12156,7 +12186,8 @@ list_contains_unique_index(TABLE *table,
key_part < key_part_end;
key_part++)
{
if (!find_func(key_part->field, data))
if (key_part->field->maybe_null() ||
!find_func(key_part->field, data))
break;
}
if (key_part == key_part_end)
@ -12264,13 +12295,14 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
DBUG_ENTER("test_if_skip_sort_order");
LINT_INIT(ref_key_parts);
/* Check which keys can be used to resolve ORDER BY. */
usable_keys= table->keys_in_use_for_query;
/*
Check which keys can be used to resolve ORDER BY.
We must not try to use disabled keys.
Keys disabled by ALTER TABLE ... DISABLE KEYS should have already
been taken into account.
*/
usable_keys= table->s->keys_in_use;
/* we must not consider keys that are disabled by IGNORE INDEX */
usable_keys.intersect(table->keys_in_use_for_query);
DBUG_ASSERT(usable_keys.is_subset(table->s->keys_in_use));
for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
{
@ -14826,7 +14858,7 @@ int JOIN::rollup_send_data(uint idx)
1 if write_data_failed()
*/
int JOIN::rollup_write_data(uint idx, TABLE *table)
int JOIN::rollup_write_data(uint idx, TABLE *table_arg)
{
uint i;
for (i= send_group_parts ; i-- > idx ; )
@ -14837,7 +14869,7 @@ int JOIN::rollup_write_data(uint idx, TABLE *table)
ref_pointer_array_size);
if ((!having || having->val_int()))
{
int error;
int write_error;
Item *item;
List_iterator_fast<Item> it(rollup.fields[i]);
while ((item= it++))
@ -14846,10 +14878,10 @@ int JOIN::rollup_write_data(uint idx, TABLE *table)
item->save_in_result_field(1);
}
copy_sum_funcs(sum_funcs_end[i+1], sum_funcs_end[i]);
if ((error= table->file->write_row(table->record[0])))
if ((write_error= table_arg->file->write_row(table_arg->record[0])))
{
if (create_myisam_from_heap(thd, table, &tmp_table_param,
error, 0))
if (create_myisam_from_heap(thd, table_arg, &tmp_table_param,
write_error, 0))
return 1;
}
}
@ -15045,9 +15077,9 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
}
else
{
TABLE_LIST *tab=table->pos_in_table_list;
item_list.push_back(new Item_string(tab->alias,
strlen(tab->alias),
TABLE_LIST *real_table= table->pos_in_table_list;
item_list.push_back(new Item_string(real_table->alias,
strlen(real_table->alias),
cs));
}
/* "partitions" column */