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

System Versioning 1.0 pre8

Merge branch '10.3' into trunk
This commit is contained in:
Aleksey Midenkov
2018-01-10 12:36:55 +03:00
353 changed files with 12715 additions and 8094 deletions

View File

@ -89,7 +89,6 @@ LEX_CSTRING distinct_key= {STRING_WITH_LEN("distinct_key")};
struct st_sargable_param;
static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
static bool make_join_statistics(JOIN *join, List<TABLE_LIST> &leaves,
DYNAMIC_ARRAY *keyuse);
static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
@ -97,8 +96,6 @@ static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
uint tables, COND *conds,
table_map table_map, SELECT_LEX *select_lex,
SARGABLE_PARAM **sargables);
static bool sort_and_filter_keyuse(THD *thd, DYNAMIC_ARRAY *keyuse,
bool skip_unprefixed_keyparts);
static int sort_keyuse(KEYUSE *a,KEYUSE *b);
static bool are_tables_local(JOIN_TAB *jtab, table_map used_tables);
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
@ -1267,6 +1264,22 @@ JOIN::prepare(TABLE_LIST *tables_init,
}
}
/*
After setting up window functions, we may have discovered additional
used tables from the PARTITION BY and ORDER BY list. Update all items
that contain window functions.
*/
if (select_lex->have_window_funcs())
{
List_iterator_fast<Item> it(select_lex->item_list);
Item *item;
while ((item= it++))
{
if (item->with_window_func)
item->update_used_tables();
}
}
With_clause *with_clause=select_lex->get_with_clause();
if (with_clause && with_clause->prepare_unreferenced_elements(thd))
DBUG_RETURN(1);
@ -1533,7 +1546,6 @@ int JOIN::optimize()
if (optimization_state != JOIN::NOT_OPTIMIZED)
return FALSE;
optimization_state= JOIN::OPTIMIZATION_IN_PROGRESS;
is_for_splittable_grouping_derived= false;
res= optimize_inner();
}
if (!with_two_phase_optimization ||
@ -1605,7 +1617,7 @@ JOIN::optimize_inner()
/*
Needed in case optimizer short-cuts,
set properly in make_tmp_tables_info()
set properly in make_aggr_tables_info()
*/
fields= &select_lex->item_list;
@ -1979,9 +1991,6 @@ int JOIN::optimize_stage2()
if (subq_exit_fl)
goto setup_subq_exit;
if (select_lex->handle_derived(thd->lex, DT_OPTIMIZE))
DBUG_RETURN(1);
if (thd->check_killed())
DBUG_RETURN(1);
@ -1989,6 +1998,9 @@ int JOIN::optimize_stage2()
if (get_best_combination())
DBUG_RETURN(1);
if (select_lex->handle_derived(thd->lex, DT_OPTIMIZE))
DBUG_RETURN(1);
if (optimizer_flag(thd, OPTIMIZER_SWITCH_DERIVED_WITH_KEYS))
drop_unused_derived_keys();
@ -4090,7 +4102,11 @@ JOIN::destroy()
cleanup_item_list(tmp_all_fields1);
cleanup_item_list(tmp_all_fields3);
destroy_sj_tmp_tables(this);
delete_dynamic(&keyuse);
delete_dynamic(&keyuse);
if (save_qep)
delete(save_qep);
if (ext_keyuses_for_splitting)
delete(ext_keyuses_for_splitting);
delete procedure;
DBUG_RETURN(error);
}
@ -4544,6 +4560,12 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
DBUG_EXECUTE("opt", print_keyuse_array(keyuse_array););
}
for (s= stat; s < stat_end; s++)
{
if (s->table->is_splittable())
s->add_keyuses_for_splitting();
}
join->const_table_map= no_rows_const_tables;
join->const_tables= const_count;
eliminate_tables(join);
@ -5017,9 +5039,6 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
if (join->choose_subquery_plan(all_table_map & ~join->const_table_map))
goto error;
if (join->improve_chosen_plan(join->thd))
goto error;
DEBUG_SYNC(join->thd, "inside_make_join_statistics");
DBUG_RETURN(0);
@ -5049,23 +5068,6 @@ error:
keyuse Pointer to possible keys
*****************************************************************************/
/// Used when finding key fields
struct KEY_FIELD {
Field *field;
Item_bool_func *cond;
Item *val; ///< May be empty if diff constant
uint level;
uint optimize;
bool eq_func;
/**
If true, the condition this struct represents will not be satisfied
when val IS NULL.
*/
bool null_rejecting;
bool *cond_guard; /* See KEYUSE::cond_guard */
uint sj_pred_no; /* See KEYUSE::sj_pred_no */
};
/**
Merge new key definitions to old ones, remove those not used in both.
@ -5716,7 +5718,7 @@ Item_func_ne::add_key_fields(JOIN *join, KEY_FIELD **key_fields,
/*
QQ: perhaps test for !is_local_field(args[1]) is not really needed here.
Other comparison functions, e.g. Item_func_le, Item_func_gt, etc,
do not have this test. See Item_bool_func2::add_key_field_optimize_op().
do not have this test. See Item_bool_func2::add_key_fieldoptimize_op().
Check with the optimizer team.
*/
if (is_local_field(args[0]) && !is_local_field(args[1]))
@ -5899,6 +5901,7 @@ add_keyuse(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field,
keyuse.null_rejecting= key_field->null_rejecting;
keyuse.cond_guard= key_field->cond_guard;
keyuse.sj_pred_no= key_field->sj_pred_no;
keyuse.validity_ref= 0;
return (insert_dynamic(keyuse_array,(uchar*) &keyuse));
}
@ -5944,7 +5947,9 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field)
key_field->val->used_tables())
{
if (!field->can_optimize_hash_join(key_field->cond, key_field->val))
return false;
return false;
if (form->is_splittable())
form->add_splitting_info_for_key_field(key_field);
/*
If a key use is extracted from an equi-join predicate then it is
added not only as a key use for every index whose component can
@ -5958,7 +5963,6 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field)
return FALSE;
}
static bool
add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
JOIN_TAB *stat,COND *cond,table_map usable_tables)
@ -6020,6 +6024,7 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
keyuse.optimize= 0;
keyuse.keypart_map= 0;
keyuse.sj_pred_no= UINT_MAX;
keyuse.validity_ref= 0;
return insert_dynamic(keyuse_array,(uchar*) &keyuse);
}
@ -6307,8 +6312,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
Special treatment for ft-keys.
*/
static bool sort_and_filter_keyuse(THD *thd, DYNAMIC_ARRAY *keyuse,
bool skip_unprefixed_keyparts)
bool sort_and_filter_keyuse(THD *thd, DYNAMIC_ARRAY *keyuse,
bool skip_unprefixed_keyparts)
{
KEYUSE key_end, *prev, *save_pos, *use;
uint found_eq_constant, i;
@ -6376,7 +6381,7 @@ static bool sort_and_filter_keyuse(THD *thd, DYNAMIC_ARRAY *keyuse,
Update some values in keyuse for faster choose_plan() loop.
*/
static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
{
KEYUSE *end,*keyuse= dynamic_element(keyuse_array, 0, KEYUSE*);
@ -6417,7 +6422,6 @@ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
}
/**
Check for the presence of AGGFN(DISTINCT a) queries that may be subject
to loose index scan.
@ -6725,6 +6729,7 @@ best_access_path(JOIN *join,
bool best_uses_jbuf= FALSE;
MY_BITMAP *eq_join_set= &s->table->eq_join_set;
KEYUSE *hj_start_key= 0;
SplM_plan_info *spl_plan= 0;
disable_jbuf= disable_jbuf || idx == join->const_tables;
@ -6734,7 +6739,10 @@ best_access_path(JOIN *join,
bitmap_clear_all(eq_join_set);
loose_scan_opt.init(join, s, remaining_tables);
if (s->table->is_splittable())
spl_plan= s->choose_best_splitting(record_count, remaining_tables);
if (s->keyuse)
{ /* Use key if possible */
KEYUSE *keyuse;
@ -6799,6 +6807,7 @@ best_access_path(JOIN *join,
2. we won't get two ref-or-null's
*/
if (!(remaining_tables & keyuse->used_tables) &&
(!keyuse->validity_ref || *keyuse->validity_ref) &&
s->access_from_tables_is_allowed(keyuse->used_tables,
join->sjm_lookup_tables) &&
!(ref_or_null_part && (keyuse->optimize &
@ -7111,6 +7120,7 @@ best_access_path(JOIN *join,
tmp += s->startup_cost;
loose_scan_opt.check_ref_access_part2(key, start_key, records, tmp);
} /* not ft_key */
if (tmp + 0.0001 < best_time - records/(double) TIME_FOR_COMPARE)
{
best_time= tmp + records/(double) TIME_FOR_COMPARE;
@ -7298,6 +7308,7 @@ best_access_path(JOIN *join,
pos->ref_depend_map= best_ref_depends_map;
pos->loosescan_picker.loosescan_key= MAX_KEY;
pos->use_join_buffer= best_uses_jbuf;
pos->spl_plan= spl_plan;
loose_scan_opt.save_to_position(s, loose_scan_pos);
@ -9352,192 +9363,15 @@ JOIN_TAB *next_depth_first_tab(JOIN* join, JOIN_TAB* tab)
return tab;
}
static
bool key_can_be_used_to_split_by_fields(KEY *key_info, uint used_key_parts,
List<Field> &fields)
{
if (used_key_parts < fields.elements)
return false;
List_iterator_fast<Field> li(fields);
Field *fld;
KEY_PART_INFO *start= key_info->key_part;
KEY_PART_INFO *end= start + fields.elements;
while ((fld= li++))
{
KEY_PART_INFO *key_part;
for (key_part= start; key_part < end; key_part++)
{
if (key_part->fieldnr == fld->field_index + 1)
break;
}
if (key_part == end)
return false;
}
return true;
}
bool JOIN::check_for_splittable_grouping_derived(THD *thd)
{
partition_list= 0;
st_select_lex_unit *unit= select_lex->master_unit();
TABLE_LIST *derived= unit->derived;
if (!optimizer_flag(thd, OPTIMIZER_SWITCH_SPLIT_GROUPING_DERIVED))
return false;
if (!(derived && derived->is_materialized_derived()))
return false;
if (unit->first_select()->next_select())
return false;
if (derived->prohibit_cond_pushdown)
return false;
if (derived->is_recursive_with_table())
return false;
if (group_list)
{
if (!select_lex->have_window_funcs())
partition_list= group_list;
}
else if (select_lex->have_window_funcs() &&
select_lex->window_specs.elements == 1)
{
partition_list=
select_lex->window_specs.head()->partition_list->first;
}
if (!partition_list)
return false;
ORDER *ord;
TABLE *table= 0;
key_map ref_keys;
uint group_fields= 0;
ref_keys.set_all();
for (ord= partition_list; ord; ord= ord->next, group_fields++)
{
Item *ord_item= *ord->item;
if (ord_item->real_item()->type() != Item::FIELD_ITEM)
return false;
Field *ord_field= ((Item_field *) (ord_item->real_item()))->field;
if (!table)
table= ord_field->table;
else if (table != ord_field->table)
return false;
ref_keys.intersect(ord_field->part_of_key);
}
if (ref_keys.is_clear_all())
return false;
uint i;
List<Field> grouping_fields;
List<Field> splitting_fields;
List_iterator<Item> li(fields_list);
for (ord= partition_list; ord; ord= ord->next)
{
Item *item;
i= 0;
while ((item= li++))
{
if ((*ord->item)->eq(item, 0))
break;
i++;
}
if (!item)
return false;
if (splitting_fields.push_back(derived->table->field[i], thd->mem_root))
return false;
Item_field *ord_field= (Item_field *)(item->real_item());
if (grouping_fields.push_back(ord_field->field, thd->mem_root))
return false;
li.rewind();
}
for (i= 0; i < table->s->keys; i++)
{
if (!(ref_keys.is_set(i)))
continue;
KEY *key_info= table->key_info + i;
if (key_can_be_used_to_split_by_fields(key_info,
table->actual_n_key_parts(key_info),
grouping_fields))
break;
}
if (i == table->s->keys)
return false;
derived->table->splitting_fields= splitting_fields;
is_for_splittable_grouping_derived= true;
return true;
}
bool JOIN::check_two_phase_optimization(THD *thd)
{
if (!check_for_splittable_grouping_derived(thd))
return false;
return true;
if (check_for_splittable_materialized())
return true;
return false;
}
Item *JOIN_TAB::get_splitting_cond_for_grouping_derived(THD *thd)
{
/* this is a stub */
TABLE_LIST *derived= table->pos_in_table_list;
st_select_lex *sel= derived->get_unit()->first_select();
Item *cond= 0;
table_map used_tables= OUTER_REF_TABLE_BIT;
POSITION *pos= join->best_positions;
for (; pos->table != this; pos++)
{
used_tables|= pos->table->table->map;
}
if (!pos->key)
return 0;
KEY *key_info= table->key_info + pos->key->key;
if (!key_can_be_used_to_split_by_fields(key_info,
key_info->user_defined_key_parts,
table->splitting_fields))
return 0;
create_ref_for_key(join, this, pos->key,
false, used_tables);
List<Item> cond_list;
KEY_PART_INFO *start= key_info->key_part;
KEY_PART_INFO *end= start + table->splitting_fields.elements;
List_iterator_fast<Field> li(table->splitting_fields);
Field *fld= li++;
for (ORDER *ord= sel->join->partition_list; ord;
ord= ord->next, fld= li++)
{
Item *left_item= (*ord->item)->build_clone(thd);
uint i= 0;
for (KEY_PART_INFO *key_part= start; key_part < end; key_part++, i++)
{
if (key_part->fieldnr == fld->field_index + 1)
break;
}
Item *right_item= ref.items[i]->build_clone(thd);
Item_func_eq *eq_item= 0;
right_item= right_item->build_clone(thd);
if (left_item && right_item)
{
right_item->walk(&Item::set_fields_as_dependent_processor,
false, join->select_lex);
right_item->update_used_tables();
eq_item= new (thd->mem_root) Item_func_eq(thd, left_item, right_item);
}
if (!eq_item || cond_list.push_back(eq_item, thd->mem_root))
return 0;
}
switch (cond_list.elements) {
case 0: break;
case 1: cond= cond_list.head(); break;
default: cond= new (thd->mem_root) Item_cond_and(thd, cond_list);
}
if (cond)
cond->fix_fields(thd,0);
return cond;
}
bool JOIN::inject_cond_into_where(Item *injected_cond)
{
Item *where_item= injected_cond;
@ -9572,48 +9406,6 @@ bool JOIN::inject_cond_into_where(Item *injected_cond)
}
bool JOIN::push_splitting_cond_into_derived(THD *thd, Item *cond)
{
enum_reopt_result reopt_result= REOPT_NONE;
table_map all_table_map= 0;
for (JOIN_TAB *tab= join_tab;
tab < join_tab + top_join_tab_count; tab++)
all_table_map|= tab->table->map;
reopt_result= reoptimize(cond, all_table_map & ~const_table_map, NULL);
if (reopt_result == REOPT_ERROR)
return true;
if (inject_cond_into_where(cond))
return true;
if (cond->used_tables() & OUTER_REF_TABLE_BIT)
{
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT_INJECTED;
st_select_lex_unit *unit= select_lex->master_unit();
unit->uncacheable|= UNCACHEABLE_DEPENDENT_INJECTED;
}
return false;
}
bool JOIN::improve_chosen_plan(THD *thd)
{
for (JOIN_TAB *tab= join_tab + const_tables;
tab < join_tab + table_count; tab++)
{
TABLE_LIST *tbl= tab->table->pos_in_table_list;
if (tbl->is_materialized_derived())
{
st_select_lex *sel= tbl->get_unit()->first_select();
JOIN *derived_join= sel->join;
if (derived_join && derived_join->is_for_splittable_grouping_derived)
{
Item *cond= tab->get_splitting_cond_for_grouping_derived(thd);
if (cond && derived_join->push_splitting_cond_into_derived(thd, cond))
return true;
}
}
}
return false;
}
static Item * const null_ptr= NULL;
@ -9682,6 +9474,9 @@ bool JOIN::get_best_combination()
full_join=0;
hash_join= FALSE;
if (fix_all_splittings_in_plan())
DBUG_RETURN(TRUE);
fix_semijoin_strategies_for_picked_join_order(this);
JOIN_TAB_RANGE *root_range;
@ -10022,6 +9817,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
do
{
if (!(~used_tables & keyuse->used_tables) &&
(!keyuse->validity_ref || *keyuse->validity_ref) &&
j->keyuse_is_valid_for_access_in_chosen_plan(join, keyuse))
{
if (are_tables_local(j, keyuse->val->used_tables()))
@ -10092,6 +9888,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
for (i=0 ; i < keyparts ; keyuse++,i++)
{
while (((~used_tables) & keyuse->used_tables) ||
(keyuse->validity_ref && !(*keyuse->validity_ref)) ||
!j->keyuse_is_valid_for_access_in_chosen_plan(join, keyuse) ||
keyuse->keypart == NO_KEYPART ||
(keyuse->keypart !=
@ -18092,7 +17889,6 @@ err:
}
/****************************************************************************/
void *Virtual_tmp_table::operator new(size_t size, THD *thd) throw()