1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Merge branch '10.4' into 10.4-mdev16188

This commit is contained in:
Igor Babaev
2018-11-10 14:52:57 -08:00
1883 changed files with 72584 additions and 264686 deletions

View File

@ -293,6 +293,9 @@ static bool find_order_in_list(THD *, Ref_ptr_array, TABLE_LIST *, ORDER *,
static double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
table_map rem_tables);
void set_postjoin_aggr_write_func(JOIN_TAB *tab);
static Item **get_sargable_cond(JOIN *join, TABLE *table);
#ifndef DBUG_OFF
/*
@ -643,7 +646,7 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
const bool saved_non_agg_field_used= select->non_agg_field_used();
DBUG_ENTER("setup_without_group");
thd->lex->allow_sum_func&= ~((nesting_map)1 << select->nest_level);
thd->lex->allow_sum_func.clear_bit(select->nest_level);
res= setup_conds(thd, tables, leaves, conds);
if (thd->lex->current_select->first_cond_optimization)
{
@ -656,18 +659,18 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
/* it's not wrong to have non-aggregated columns in a WHERE */
select->set_non_agg_field_used(saved_non_agg_field_used);
thd->lex->allow_sum_func|= (nesting_map)1 << select->nest_level;
thd->lex->allow_sum_func.set_bit(select->nest_level);
save_place= thd->lex->current_select->context_analysis_place;
thd->lex->current_select->context_analysis_place= IN_ORDER_BY;
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
order);
thd->lex->allow_sum_func&= ~((nesting_map)1 << select->nest_level);
thd->lex->allow_sum_func.clear_bit(select->nest_level);
thd->lex->current_select->context_analysis_place= IN_GROUP_BY;
res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields,
group, hidden_group_fields);
thd->lex->current_select->context_analysis_place= save_place;
thd->lex->allow_sum_func|= (nesting_map)1 << select->nest_level;
thd->lex->allow_sum_func.set_bit(select->nest_level);
res= res || setup_windows(thd, ref_pointer_array, tables, fields, all_fields,
win_specs, win_funcs);
thd->lex->allow_sum_func= save_allow_sum_func;
@ -1115,7 +1118,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
select_lex->master_unit()->global_parameters())
{
nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
thd->lex->allow_sum_func|= (nesting_map)1 << select_lex->nest_level;
thd->lex->allow_sum_func.set_bit(select_lex->nest_level);
thd->where= "order clause";
for (ORDER *order= select_lex->order_list.first; order; order= order->next)
{
@ -1133,7 +1136,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
{
nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
thd->where="having clause";
thd->lex->allow_sum_func|= (nesting_map)1 << select_lex_arg->nest_level;
thd->lex->allow_sum_func.set_bit(select_lex_arg->nest_level);
select_lex->having_fix_field= 1;
/*
Wrap alone field in HAVING clause in case it will be outer field
@ -1643,6 +1646,13 @@ JOIN::optimize_inner()
if (optimize_constant_subqueries())
DBUG_RETURN(1);
if (conds && conds->with_subquery())
(void) conds->walk(&Item::cleanup_is_expensive_cache_processor,
0, (void *) 0);
if (having && having->with_subquery())
(void) having->walk(&Item::cleanup_is_expensive_cache_processor,
0, (void *) 0);
List<Item> eq_list;
if (setup_degenerate_jtbm_semi_joins(this, join_list, eq_list))
@ -1688,8 +1698,14 @@ JOIN::optimize_inner()
conds= optimize_cond(this, conds, join_list, FALSE,
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
if (thd->lex->sql_command == SQLCOM_SELECT &&
optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY))
if (thd->is_error())
{
error= 1;
DBUG_PRINT("error",("Error from optimize_cond"));
DBUG_RETURN(1);
}
if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY))
{
TABLE_LIST *tbl;
List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
@ -1714,8 +1730,7 @@ JOIN::optimize_inner()
DBUG_RETURN(TRUE);
}
if (thd->lex->sql_command == SQLCOM_SELECT &&
optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED))
if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED))
{
TABLE_LIST *tbl;
List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
@ -1753,13 +1768,6 @@ JOIN::optimize_inner()
DBUG_RETURN(1);
}
if (unlikely(thd->is_error()))
{
error= 1;
DBUG_PRINT("error",("Error from optimize_cond"));
DBUG_RETURN(1);
}
{
having= optimize_cond(this, having, join_list, TRUE,
&having_value, &having_equal);
@ -1810,19 +1818,9 @@ JOIN::optimize_inner()
List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
while ((tbl= li++))
{
/*
If tbl->embedding!=NULL that means that this table is in the inner
part of the nested outer join, and we can't do partition pruning
(TODO: check if this limitation can be lifted)
*/
if (!tbl->embedding ||
(tbl->embedding && tbl->embedding->sj_on_expr))
{
Item *prune_cond= tbl->on_expr? tbl->on_expr : conds;
tbl->table->all_partitions_pruned_away= prune_partitions(thd,
tbl->table,
prune_cond);
}
Item **prune_cond= get_sargable_cond(this, tbl->table);
tbl->table->all_partitions_pruned_away=
prune_partitions(thd, tbl->table, *prune_cond);
}
}
#endif
@ -1919,6 +1917,14 @@ JOIN::optimize_inner()
error= 1;
DBUG_RETURN(1);
}
if (!group_list)
{
/* The output has only one row */
order=0;
simple_order=1;
group_optimized_away= 1;
select_distinct=0;
}
}
/* Calculate how to do the join */
@ -3159,7 +3165,7 @@ bool JOIN::make_aggr_tables_info()
remove_duplicates() assumes there is a preceding computation step (and
in the degenerate join, there's none)
*/
if (top_join_tab_count)
if (top_join_tab_count && tables_list)
curr_tab->distinct= true;
having= NULL;
@ -3805,7 +3811,7 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
If there is SELECT in this statement with the same number it must be the
same SELECT
*/
DBUG_ASSERT(select_lex->select_number == UINT_MAX ||
DBUG_SLOW_ASSERT(select_lex->select_number == UINT_MAX ||
select_lex->select_number == INT_MAX ||
!output ||
!output->get_select(select_lex->select_number) ||
@ -4342,6 +4348,84 @@ struct SARGABLE_PARAM
};
/*
Mark all tables inside a join nest as constant.
@detail This is called when there is a local "Impossible WHERE" inside
a multi-table LEFT JOIN.
*/
void mark_join_nest_as_const(JOIN *join,
TABLE_LIST *join_nest,
table_map *found_const_table_map,
uint *const_count)
{
List_iterator<TABLE_LIST> it(join_nest->nested_join->join_list);
TABLE_LIST *tbl;
while ((tbl= it++))
{
if (tbl->nested_join)
{
mark_join_nest_as_const(join, tbl, found_const_table_map, const_count);
continue;
}
JOIN_TAB *tab= tbl->table->reginfo.join_tab;
if (!(join->const_table_map & tab->table->map))
{
tab->type= JT_CONST;
tab->info= ET_IMPOSSIBLE_ON_CONDITION;
tab->table->const_table= 1;
join->const_table_map|= tab->table->map;
*found_const_table_map|= tab->table->map;
set_position(join,(*const_count)++,tab,(KEYUSE*) 0);
mark_as_null_row(tab->table); // All fields are NULL
}
}
}
/*
@brief Get the condition that can be used to do range analysis/partition
pruning/etc
@detail
Figure out which condition we can use:
- For INNER JOIN, we use the WHERE,
- "t1 LEFT JOIN t2 ON ..." uses t2's ON expression
- "t1 LEFT JOIN (...) ON ..." uses the join nest's ON expression.
*/
static Item **get_sargable_cond(JOIN *join, TABLE *table)
{
Item **retval;
if (table->pos_in_table_list->on_expr)
{
/*
This is an inner table from a single-table LEFT JOIN, "t1 LEFT JOIN
t2 ON cond". Use the condition cond.
*/
retval= &table->pos_in_table_list->on_expr;
}
else if (table->pos_in_table_list->embedding &&
!table->pos_in_table_list->embedding->sj_on_expr)
{
/*
This is the inner side of a multi-table outer join. Use the
appropriate ON expression.
*/
retval= &(table->pos_in_table_list->embedding->on_expr);
}
else
{
/* The table is not inner wrt some LEFT JOIN. Use the WHERE clause */
retval= &join->conds;
}
return retval;
}
/**
Calculate the best possible join and initialize the join structure.
@ -4619,8 +4703,8 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
int ref_changed;
do
{
more_const_tables_found:
ref_changed = 0;
more_const_tables_found:
found_ref=0;
/*
@ -4789,7 +4873,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
}
}
}
} while (join->const_table_map & found_ref && ref_changed);
} while (ref_changed);
join->sort_by_table= get_sort_by_table(join->order, join->group_list,
join->select_lex->leaf_tables,
@ -4913,39 +4997,38 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
/*
Perform range analysis if there are keys it could use (1).
Don't do range analysis if we're on the inner side of an outer join (2).
Do range analysis if we're on the inner side of a semi-join (3).
Don't do range analysis for materialized subqueries (4).
Don't do range analysis for materialized derived tables (5)
Don't do range analysis for materialized subqueries (2).
Don't do range analysis for materialized derived tables (3)
*/
if ((!s->const_keys.is_clear_all() ||
!bitmap_is_clear_all(&s->table->cond_set)) && // (1)
(!s->table->pos_in_table_list->embedding || // (2)
(s->table->pos_in_table_list->embedding && // (3)
s->table->pos_in_table_list->embedding->sj_on_expr)) && // (3)
!s->table->is_filled_at_execution() && // (4)
!(s->table->pos_in_table_list->derived && // (5)
s->table->pos_in_table_list->is_materialized_derived())) // (5)
!s->table->is_filled_at_execution() && // (2)
!(s->table->pos_in_table_list->derived && // (3)
s->table->pos_in_table_list->is_materialized_derived())) // (3)
{
bool impossible_range= FALSE;
ha_rows records= HA_POS_ERROR;
SQL_SELECT *select= 0;
Item **sargable_cond= NULL;
if (!s->const_keys.is_clear_all())
{
sargable_cond= get_sargable_cond(join, s->table);
select= make_select(s->table, found_const_table_map,
found_const_table_map,
*s->on_expr_ref ? *s->on_expr_ref : join->conds,
*sargable_cond,
(SORT_INFO*) 0,
1, &error);
if (!select)
goto error;
records= get_quick_record_count(join->thd, select, s->table,
&s->const_keys, join->row_limit);
/* Range analyzer could modify the condition. */
if (*s->on_expr_ref)
*s->on_expr_ref= select->cond;
else
join->conds= select->cond;
/*
Range analyzer might have modified the condition. Put it the new
condition to where we got it from.
*/
*sargable_cond= select->cond;
s->quick=select->quick;
s->needed_reg=select->needed_reg;
@ -4958,10 +5041,11 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
}
if (!impossible_range)
{
if (!sargable_cond)
sargable_cond= get_sargable_cond(join, s->table);
if (join->thd->variables.optimizer_use_condition_selectivity > 1)
calculate_cond_selectivity_for_table(join->thd, s->table,
*s->on_expr_ref ?
s->on_expr_ref : &join->conds);
sargable_cond);
if (s->table->reginfo.impossible_range)
{
impossible_range= TRUE;
@ -4970,23 +5054,33 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
}
if (impossible_range)
{
/*
Impossible WHERE or ON expression
In case of ON, we mark that the we match one empty NULL row.
In case of WHERE, don't set found_const_table_map to get the
caller to abort with a zero row result.
*/
join->const_table_map|= s->table->map;
set_position(join,const_count++,s,(KEYUSE*) 0);
s->type= JT_CONST;
s->table->const_table= 1;
if (*s->on_expr_ref)
{
/* Generate empty row */
s->info= ET_IMPOSSIBLE_ON_CONDITION;
found_const_table_map|= s->table->map;
mark_as_null_row(s->table); // All fields are NULL
}
/*
Impossible WHERE or ON expression
In case of ON, we mark that the we match one empty NULL row.
In case of WHERE, don't set found_const_table_map to get the
caller to abort with a zero row result.
*/
TABLE_LIST *emb= s->table->pos_in_table_list->embedding;
if (emb && !emb->sj_on_expr)
{
/* Mark all tables in a multi-table join nest as const */
mark_join_nest_as_const(join, emb, &found_const_table_map,
&const_count);
}
else
{
join->const_table_map|= s->table->map;
set_position(join,const_count++,s,(KEYUSE*) 0);
s->type= JT_CONST;
s->table->const_table= 1;
if (*s->on_expr_ref)
{
/* Generate empty row */
s->info= ET_IMPOSSIBLE_ON_CONDITION;
found_const_table_map|= s->table->map;
mark_as_null_row(s->table); // All fields are NULL
}
}
}
if (records != HA_POS_ERROR)
{
@ -6575,7 +6669,7 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab)
Item_field *cur_item;
key_map possible_keys(0);
if (join->group_list || join->simple_group)
if (join->group_list)
{ /* Collect all query fields referenced in the GROUP clause. */
for (cur_group= join->group_list; cur_group; cur_group= cur_group->next)
(*cur_group->item)->walk(&Item::collect_item_field_processor, 0,
@ -7310,8 +7404,13 @@ best_access_path(JOIN *join,
tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
}
}
double best_records= rnd_records;
tmp += s->startup_cost;
/* Splitting technique cannot be used with join cache */
if (s->table->is_splittable())
tmp+= s->table->get_materialization_cost();
else
tmp+= s->startup_cost;
filter= s->table->best_filter_for_current_join_order(MAX_KEY,
rnd_records,
@ -7341,6 +7440,7 @@ best_access_path(JOIN *join,
best_ref_depends_map= 0;
best_uses_jbuf= MY_TEST(!disable_jbuf && !((s->table->map &
join->outer_join)));
spl_plan= 0;
}
}
@ -9050,8 +9150,13 @@ bool JOIN_TAB::keyuse_is_valid_for_access_in_chosen_plan(JOIN *join,
st_select_lex *sjm_sel= emb_sj_nest->sj_subq_pred->unit->first_select();
for (uint i= 0; i < sjm_sel->item_list.elements; i++)
{
if (sjm_sel->ref_pointer_array[i] == keyuse->val)
return true;
DBUG_ASSERT(sjm_sel->ref_pointer_array[i]->real_item()->type() == Item::FIELD_ITEM);
if (keyuse->val->real_item()->type() == Item::FIELD_ITEM)
{
Field *field = ((Item_field*)sjm_sel->ref_pointer_array[i]->real_item())->field;
if (field->eq(((Item_field*)keyuse->val->real_item())->field))
return true;
}
}
return false;
}
@ -9702,7 +9807,6 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
if (first_keyuse)
{
key_parts++;
first_keyuse= FALSE;
}
else
{
@ -9712,7 +9816,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
if (curr->keypart == keyuse->keypart &&
!(~used_tables & curr->used_tables) &&
join_tab->keyuse_is_valid_for_access_in_chosen_plan(join,
keyuse) &&
curr) &&
are_tables_local(join_tab, curr->used_tables))
break;
}
@ -9720,6 +9824,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
key_parts++;
}
}
first_keyuse= FALSE;
keyuse++;
} while (keyuse->table == table && keyuse->is_for_hash_join());
if (!key_parts)
@ -11677,7 +11782,15 @@ uint check_join_cache_usage(JOIN_TAB *tab,
effort now.
*/
if (tab->table->pos_in_table_list->is_materialized_derived())
{
no_bka_cache= true;
/*
Don't use hash join algorithm if the temporary table for the rows
of the derived table will be created with an equi-join key.
*/
if (tab->table->s->keys)
no_hashed_cache= true;
}
/*
Don't use join buffering if we're dictated not to by no_jbuf_after
@ -22111,11 +22224,30 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
tmp_map.clear_all(); // Force the creation of quick select
tmp_map.set_bit(best_key); // only best_key.
select->quick= 0;
bool cond_saved= false;
Item *saved_cond;
/*
Index Condition Pushdown may have removed parts of the condition for
this table. Temporarily put them back because we want the whole
condition for the range analysis.
*/
if (select->pre_idx_push_select_cond)
{
saved_cond= select->cond;
select->cond= select->pre_idx_push_select_cond;
cond_saved= true;
}
select->test_quick_select(join->thd, tmp_map, 0,
join->select_options & OPTION_FOUND_ROWS ?
HA_POS_ERROR :
join->unit->select_limit_cnt,
TRUE, FALSE, FALSE);
if (cond_saved)
select->cond= saved_cond;
}
order_direction= best_key_direction;
/*
@ -23119,7 +23251,8 @@ setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
return 1;
}
}
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
context_analysis_place == IN_GROUP_BY)
{
/*
Don't allow one to use fields that is not used in GROUP BY
@ -26087,7 +26220,7 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str,
LEX_CSTRING t_alias= alias;
str->append(' ');
if (lower_case_table_names== 1)
if (lower_case_table_names == 1)
{
if (alias.str && alias.str[0])
{
@ -27292,9 +27425,10 @@ AGGR_OP::end_send()
// Update ref array
join_tab->join->set_items_ref_array(*join_tab->ref_array);
bool keep_last_filesort_result = join_tab->filesort ? false : true;
if (join_tab->window_funcs_step)
{
if (join_tab->window_funcs_step->exec(join))
if (join_tab->window_funcs_step->exec(join, keep_last_filesort_result))
return NESTED_LOOP_ERROR;
}
@ -27348,6 +27482,12 @@ AGGR_OP::end_send()
}
}
if (keep_last_filesort_result)
{
delete join_tab->filesort_result;
join_tab->filesort_result= NULL;
}
// Finish rnd scn after sending records
if (join_tab->table->file->inited)
join_tab->table->file->ha_rnd_end();