1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge branch '11.0' into 11.1

This commit is contained in:
Oleksandr Byelkin
2023-11-08 18:03:08 +01:00
598 changed files with 15367 additions and 9121 deletions

View File

@@ -141,9 +141,10 @@ 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,
bool allow_full_scan, table_map used_tables);
static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
static bool get_quick_record_count(THD *thd, SQL_SELECT *select,
TABLE *table,
const key_map *keys,ha_rows limit);
const key_map *keys,ha_rows limit,
ha_rows *quick_count);
static void optimize_straight_join(JOIN *join, table_map join_tables);
static bool greedy_search(JOIN *join, table_map remaining_tables,
uint depth, uint use_cond_selectivity);
@@ -241,8 +242,8 @@ static int join_read_last_key(JOIN_TAB *tab);
static int join_no_more_records(READ_RECORD *info);
static int join_read_next(READ_RECORD *info);
static int join_init_quick_read_record(JOIN_TAB *tab);
static int test_if_quick_select(JOIN_TAB *tab);
static bool test_if_use_dynamic_range_scan(JOIN_TAB *join_tab);
static quick_select_return test_if_quick_select(JOIN_TAB *tab);
static int test_if_use_dynamic_range_scan(JOIN_TAB *join_tab);
static int join_read_first(JOIN_TAB *tab);
static int join_read_next(READ_RECORD *info);
static int join_read_next_same(READ_RECORD *info);
@@ -279,7 +280,8 @@ static bool test_if_cheaper_ordering(const JOIN_TAB *tab,
static int test_if_order_by_key(JOIN *, ORDER *, TABLE *, uint, uint *);
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
ha_rows select_limit, bool no_changes,
const key_map *map);
const key_map *map,
bool *fatal_error);
static bool list_contains_unique_index(TABLE *table,
bool (*find_func) (Field *, void *), void *data);
static bool find_field_in_item_list (Field *field, void *data);
@@ -1974,7 +1976,8 @@ int JOIN::optimize()
object a pointer to which is set in the field JOIN_TAB::rowid_filter of
the joined table.
@retval false always
@retval false Ok
@retval true Error
*/
bool JOIN::make_range_rowid_filters()
@@ -2015,17 +2018,20 @@ bool JOIN::make_range_rowid_filters()
filter_map.clear_all();
filter_map.set_bit(tab->range_rowid_filter_info->get_key_no());
filter_map.merge(tab->table->with_impossible_ranges);
int rc= sel->test_quick_select(thd, filter_map, (table_map) 0,
(ha_rows) HA_POS_ERROR,
true /* force index */, false, true, true);
if (thd->is_error())
goto no_filter;
quick_select_return rc;
rc= sel->test_quick_select(thd, filter_map, (table_map) 0,
(ha_rows) HA_POS_ERROR, true, false, true,
true);
if (rc == SQL_SELECT::ERROR || thd->is_error())
{
DBUG_RETURN(true); /* Fatal error */
}
/*
If SUBS_IN_TO_EXISTS strtrategy is chosen for the subquery then
additional conditions are injected into WHERE/ON/HAVING and it may
happen that the call of test_quick_select() discovers impossible range.
*/
if (rc == -1)
if (rc == SQL_SELECT::IMPOSSIBLE_RANGE)
{
const_table_map|= tab->table->map;
goto no_filter;
@@ -3050,20 +3056,29 @@ int JOIN::optimize_stage2()
tab= &join_tab[const_tables];
if (order)
{
bool fatal_err;
skip_sort_order=
test_if_skip_sort_order(tab, order, select_limit,
true, // no_changes
&tab->table->keys_in_use_for_order_by);
&tab->table->keys_in_use_for_order_by,
&fatal_err);
if (fatal_err)
DBUG_RETURN(1);
}
if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array,
order, fields_list, all_fields,
&all_order_fields_used)))
{
bool fatal_err= 0;
const bool skip_group=
skip_sort_order &&
test_if_skip_sort_order(tab, group_list, select_limit,
true, // no_changes
&tab->table->keys_in_use_for_group_by);
true, // no_changes
&tab->table->keys_in_use_for_group_by,
&fatal_err);
if (fatal_err)
DBUG_RETURN(1);
count_field_types(select_lex, &tmp_table_param, all_fields, 0);
if ((skip_group && all_order_fields_used) ||
select_limit == HA_POS_ERROR ||
@@ -3328,12 +3343,16 @@ int JOIN::optimize_stage2()
'need_tmp' implies that there will be more postprocessing
so the specified 'limit' should not be enforced yet.
*/
bool fatal_err;
const ha_rows limit = need_tmp ? HA_POS_ERROR : select_limit;
if (test_if_skip_sort_order(tab, group_list, limit, false,
&tab->table->keys_in_use_for_group_by))
&tab->table->keys_in_use_for_group_by,
&fatal_err))
{
ordered_index_usage= ordered_index_group_by;
}
if (fatal_err)
DBUG_RETURN(1);
}
/*
@@ -3356,11 +3375,15 @@ int JOIN::optimize_stage2()
else if (order && // ORDER BY wo/ preceding GROUP BY
(simple_order || skip_sort_order)) // which is possibly skippable
{
bool fatal_err;
if (test_if_skip_sort_order(tab, order, select_limit, false,
&tab->table->keys_in_use_for_order_by))
&tab->table->keys_in_use_for_order_by,
&fatal_err))
{
ordered_index_usage= ordered_index_order_by;
}
if (fatal_err)
DBUG_RETURN(1);
}
}
@@ -5281,50 +5304,70 @@ err:
}
/*****************************************************************************
Create JOIN_TABS, make a guess about the table types,
Approximate how many records will be used in each table
*****************************************************************************/
/**
Approximate how many records are going to be returned by this table in this
select with this key.
static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
@param thd Thread handle
@param select Select to be examined
@param table The table of interest
@param keys The keys of interest
@param limit Maximum number of rows of interest
@param quick_count Pointer to where we want the estimate written
@return Status
@retval false Success
@retval true Error
*/
static bool get_quick_record_count(THD *thd, SQL_SELECT *select,
TABLE *table,
const key_map *keys,ha_rows limit)
const key_map *keys,ha_rows limit,
ha_rows *quick_count)
{
int error;
quick_select_return error;
DBUG_ENTER("get_quick_record_count");
uchar buff[STACK_BUFF_ALLOC];
if (unlikely(check_stack_overrun(thd, STACK_MIN_SIZE, buff)))
DBUG_RETURN(0); // Fatal error flag is set
DBUG_RETURN(false); // Fatal error flag is set
if (select)
{
{
select->head=table;
table->reginfo.impossible_range=0;
if (likely((error=
select->test_quick_select(thd, *(key_map *)keys,
(table_map) 0,
limit, 0, FALSE,
TRUE, /* remove_where_parts*/
FALSE, TRUE)) ==
1))
error= select->test_quick_select(thd, *(key_map *)keys, (table_map) 0,
limit, 0, FALSE,
TRUE, /* remove_where_parts*/
FALSE, TRUE);
if (error == SQL_SELECT::OK)
{
/*
opt_range_condition_rows was updated in test_quick_select to be
the smallest number of rows in any range.
select->quick->records is the number of rows in range with
smallest cost.
*/
DBUG_ASSERT(select->quick->records >=
table->opt_range_condition_rows);
DBUG_RETURN(table->opt_range_condition_rows);
if (select->quick)
{
/*
opt_range_condition_rows was updated in test_quick_select to be
the smallest number of rows in any range.
select->quick->records is the number of rows in range with
smallest cost.
*/
DBUG_ASSERT(select->quick->records >=
table->opt_range_condition_rows);
*quick_count= select->quick->records;
}
DBUG_RETURN(false);
}
if (unlikely(error == -1))
if (error == SQL_SELECT::IMPOSSIBLE_RANGE)
{
table->reginfo.impossible_range=1;
DBUG_RETURN(0);
*quick_count= 0;
DBUG_RETURN(false);
}
if (unlikely(error == SQL_SELECT::ERROR))
DBUG_RETURN(true);
DBUG_PRINT("warning",("Couldn't use record count on const keypart"));
}
DBUG_RETURN(HA_POS_ERROR); /* This shouldn't happend */
*quick_count= HA_POS_ERROR;
DBUG_RETURN(false); /* This shouldn't happen */
}
/*
@@ -5484,6 +5527,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
/* The following should be optimized to only clear critical things */
bzero((void*)stat, sizeof(JOIN_TAB)* table_count);
join->top_join_tab_count= table_count;
/* Initialize POSITION objects */
for (i=0 ; i <= table_count ; i++)
@@ -6066,11 +6110,10 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
(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);
if (join->thd->is_error())
if (get_quick_record_count(join->thd, select, s->table,
&s->const_keys, join->row_limit, &records))
{
/* get_quick_record_count generated an error */
/* There was an error in test_quick_select */
delete select;
goto error;
}
@@ -6087,8 +6130,8 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
join->cond_equal= &((Item_cond_and*) (join->conds))->m_cond_equal;
s->quick=select->quick;
s->needed_reg=select->needed_reg;
select->quick=0;
s->needed_reg=select->needed_reg;
impossible_range= records == 0 && s->table->reginfo.impossible_range;
if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER))
s->table->init_cost_info_for_usable_range_rowid_filters(join->thd);
@@ -14032,15 +14075,18 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
*/
if (sel->cond && !sel->cond->fixed())
sel->cond->quick_fix_field();
quick_select_return res;
if (sel->test_quick_select(thd, tab->keys,
((used_tables & ~ current_map) |
OUTER_REF_TABLE_BIT),
(join->select_options &
OPTION_FOUND_ROWS ?
HA_POS_ERROR :
join->unit->lim.get_select_limit()), 0,
FALSE, FALSE, FALSE) < 0)
if ((res= sel->test_quick_select(thd, tab->keys,
((used_tables & ~ current_map) |
OUTER_REF_TABLE_BIT),
(join->select_options &
OPTION_FOUND_ROWS ?
HA_POS_ERROR :
join->unit->lim.get_select_limit()),
0,
FALSE, FALSE, FALSE)) ==
SQL_SELECT::IMPOSSIBLE_RANGE)
{
/*
Before reporting "Impossible WHERE" for the whole query
@@ -14048,18 +14094,22 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
*/
sel->cond=orig_cond;
if (!*tab->on_expr_ref ||
sel->test_quick_select(thd, tab->keys,
used_tables & ~ current_map,
(join->select_options &
OPTION_FOUND_ROWS ?
HA_POS_ERROR :
join->unit->lim.get_select_limit()),0,
FALSE, FALSE, FALSE, TRUE) < 0)
(res= sel->test_quick_select(thd, tab->keys,
used_tables & ~ current_map,
(join->select_options &
OPTION_FOUND_ROWS ?
HA_POS_ERROR :
join->unit->lim.get_select_limit()),
0, FALSE, FALSE, FALSE, TRUE)) ==
SQL_SELECT::IMPOSSIBLE_RANGE)
DBUG_RETURN(1); // Impossible WHERE
}
else
sel->cond=orig_cond;
if (res == SQL_SELECT::ERROR)
DBUG_RETURN(1); /* Some error in one of test_quick_select calls */
/* Fix for EXPLAIN */
if (sel->quick)
{
@@ -15792,12 +15842,17 @@ bool error_if_full_join(JOIN *join)
build_range_rowid_filter()
Build range rowid filter. This function should only be called if
need_to_build_rowid_filter
is true
need_to_build_rowid_filter is true
@retval
0 ok
@retval
1 Error, transaction should be rolled back
*/
void JOIN_TAB::build_range_rowid_filter()
bool JOIN_TAB::build_range_rowid_filter()
{
DBUG_ASSERT(need_to_build_rowid_filter && rowid_filter);
/**
@@ -15813,8 +15868,8 @@ void JOIN_TAB::build_range_rowid_filter()
Rowid_filter_tracker *rowid_tracker= rowid_filter->get_tracker();
table->file->set_time_tracker(rowid_tracker->get_time_tracker());
rowid_tracker->start_tracking(join->thd);
if (rowid_filter->build())
Rowid_filter::build_return_code build_rc= rowid_filter->build();
if (build_rc != Rowid_filter::SUCCESS)
{
/* Failed building rowid filter */
clear_range_rowid_filter();
@@ -15822,9 +15877,11 @@ void JOIN_TAB::build_range_rowid_filter()
need_to_build_rowid_filter= false;
rowid_tracker->stop_tracking(join->thd);
table->file->set_time_tracker(table_tracker);
return (build_rc == Rowid_filter::FATAL_ERROR);
}
/*
Clear used rowid filter
@@ -15898,7 +15955,6 @@ void JOIN_TAB::cleanup()
*/
table->pos_in_table_list->table= NULL;
free_tmp_table(join->thd, table);
table= NULL;
}
else
{
@@ -15911,8 +15967,8 @@ void JOIN_TAB::cleanup()
multiple times (it may be)
*/
tmp->table= NULL;
table= NULL;
}
table= NULL;
DBUG_VOID_RETURN;
}
/*if (table->pos_in_table_list && table->pos_in_table_list->derived)
@@ -17275,7 +17331,8 @@ bool check_simple_equality(THD *thd, const Item::Context &ctx,
Field *left_field= ((Item_field*) left_item)->field;
Field *right_field= ((Item_field*) right_item)->field;
if (!left_field->eq_def(right_field))
if (!left_field->eq_def(right_field) &&
!fields_equal_using_narrowing(thd, left_field, right_field))
return FALSE;
/* Search for multiple equalities containing field1 and/or field2 */
@@ -23244,6 +23301,7 @@ sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
{
enum_nested_loop_state rc;
JOIN_CACHE *cache= join_tab->cache;
int err;
DBUG_ENTER("sub_select_cache");
/*
@@ -23269,7 +23327,7 @@ sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
}
join_tab->jbuf_loops_tracker->on_scan_init();
if (!test_if_use_dynamic_range_scan(join_tab))
if (!(err= test_if_use_dynamic_range_scan(join_tab)))
{
if (!cache->put_record())
DBUG_RETURN(NESTED_LOOP_OK);
@@ -23281,6 +23339,10 @@ sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
rc= cache->join_records(FALSE);
DBUG_RETURN(rc);
}
if (err < 0)
DBUG_RETURN(NESTED_LOOP_ERROR);
/*
TODO: Check whether we really need the call below and we can't do
without it. If it's not the case remove it.
@@ -23463,7 +23525,8 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
{
if (unlikely(join_tab->need_to_build_rowid_filter))
{
join_tab->build_range_rowid_filter();
if (join_tab->build_range_rowid_filter())
DBUG_RETURN(NESTED_LOOP_ERROR);
/*
We have to check join_tab->rowid_filter again as the above
function may have cleared it in case of errors.
@@ -24401,8 +24464,18 @@ join_read_prev_same(READ_RECORD *info)
static int
join_init_quick_read_record(JOIN_TAB *tab)
{
if (test_if_quick_select(tab) == -1)
return -1; /* No possible records */
quick_select_return res= test_if_quick_select(tab);
if (res == SQL_SELECT::ERROR)
return 1; /* Fatal error */
if (res == SQL_SELECT::IMPOSSIBLE_RANGE)
return -1; /* No possible records */
/*
Proceed to read rows. If we've created a quick select, use it, otherwise
do a full scan.
*/
return join_init_read_record(tab);
}
@@ -24414,7 +24487,13 @@ int read_first_record_seq(JOIN_TAB *tab)
return tab->read_record.read_record();
}
static int
/*
@brief
Create a new (dynamic) quick select.
*/
static quick_select_return
test_if_quick_select(JOIN_TAB *tab)
{
DBUG_EXECUTE_IF("show_explain_probe_test_if_quick_select",
@@ -24431,11 +24510,11 @@ test_if_quick_select(JOIN_TAB *tab)
if (tab->table->file->inited != handler::NONE)
tab->table->file->ha_index_or_rnd_end();
int res= tab->select->test_quick_select(tab->join->thd, tab->keys,
(table_map) 0, HA_POS_ERROR, 0,
FALSE, /*remove where parts*/FALSE,
FALSE,
/* no warnings */ TRUE);
quick_select_return res;
res= tab->select->test_quick_select(tab->join->thd, tab->keys,
(table_map) 0, HA_POS_ERROR, 0,
FALSE, /*remove where parts*/FALSE,
FALSE, /* no warnings */ TRUE);
if (tab->explain_plan && tab->explain_plan->range_checked_fer)
tab->explain_plan->range_checked_fer->collect_data(tab->select->quick);
@@ -24443,10 +24522,29 @@ test_if_quick_select(JOIN_TAB *tab)
}
static
bool test_if_use_dynamic_range_scan(JOIN_TAB *join_tab)
/*
@return
1 - Yes, use dynamically built range
0 - No, don't use dynamic range (but there's no error)
-1 - Fatal error
*/
static
int test_if_use_dynamic_range_scan(JOIN_TAB *join_tab)
{
return (join_tab->use_quick == 2 && test_if_quick_select(join_tab) > 0);
if (unlikely(join_tab->use_quick == 2))
{
quick_select_return res= test_if_quick_select(join_tab);
if (res == SQL_SELECT::ERROR)
return -1;
else
{
/* Both OK and IMPOSSIBLE_RANGE go here */
return join_tab->select->quick ? 1 : 0;
}
}
else
return 0;
}
@@ -24468,7 +24566,10 @@ int join_init_read_record(JOIN_TAB *tab)
}
if (tab->need_to_build_rowid_filter)
tab->build_range_rowid_filter();
{
if (tab->build_range_rowid_filter())
return 1; /* Fatal error */
}
if (tab->filesort && tab->sort_table()) // Sort table.
return 1;
@@ -26293,7 +26394,8 @@ void compute_part_of_sort_key_for_equals(JOIN *join, TABLE *table,
The index must cover all fields in <order>, or it will not be considered.
@param no_changes No changes will be made to the query plan.
@param no_changes No changes will be made to the query plan.
@param fatal_error OUT A fatal error occurred
@todo
- sergeyp: Results of all index merge selects actually are ordered
@@ -26307,7 +26409,7 @@ void compute_part_of_sort_key_for_equals(JOIN *join, TABLE *table,
static bool
test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
bool no_changes, const key_map *map)
bool no_changes, const key_map *map, bool *fatal_error)
{
int ref_key;
uint UNINIT_VAR(ref_key_parts);
@@ -26321,11 +26423,25 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
bool orig_cond_saved= false;
int best_key= -1;
bool changed_key= false;
THD *thd= tab->join->thd;
Json_writer_object trace_wrapper(thd);
Json_writer_array trace_arr(thd, "test_if_skip_sort_order");
DBUG_ENTER("test_if_skip_sort_order");
*fatal_error= false;
/* Check that we are always called with first non-const table */
DBUG_ASSERT(tab == tab->join->join_tab + tab->join->const_tables);
/* Sorting a single row can always be skipped */
if (tab->type == JT_EQ_REF ||
tab->type == JT_CONST ||
tab->type == JT_SYSTEM)
{
Json_writer_object trace_skip(thd);
trace_skip.add("skipped", "single row access method");
DBUG_RETURN(1);
}
/*
Keys disabled by ALTER TABLE ... DISABLE KEYS should have already
been taken into account.
@@ -26460,7 +26576,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
*/
key_map new_ref_key_map;
COND *save_cond;
bool res;
quick_select_return res;
new_ref_key_map.clear_all(); // Force the creation of quick select
new_ref_key_map.set_bit(new_ref_key); // only for new_ref_key.
@@ -26475,13 +26591,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
HA_POS_ERROR :
tab->join->unit->
lim.get_select_limit(),
TRUE, TRUE, FALSE, FALSE) <= 0;
if (res)
TRUE, TRUE, FALSE, FALSE);
// if we cannot use quick select
if (res != SQL_SELECT::OK || !tab->select->quick)
{
if (res == SQL_SELECT::ERROR)
*fatal_error= true;
select->cond= save_cond;
goto use_filesort;
}
DBUG_ASSERT(tab->select->quick);
tab->type= JT_RANGE;
tab->ref.key= -1;
tab->ref.key_parts= 0;
@@ -26572,11 +26690,17 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
cond_saved= true;
}
select->test_quick_select(join->thd, tmp_map, 0,
join->select_options & OPTION_FOUND_ROWS ?
HA_POS_ERROR :
join->unit->lim.get_select_limit(),
TRUE, FALSE, FALSE, FALSE);
quick_select_return res;
res = select->test_quick_select(join->thd, tmp_map, 0,
join->select_options & OPTION_FOUND_ROWS ?
HA_POS_ERROR :
join->unit->lim.get_select_limit(),
TRUE, FALSE, FALSE, FALSE);
if (res == SQL_SELECT::ERROR)
{
*fatal_error= true;
goto use_filesort;
}
if (cond_saved)
select->cond= saved_cond;
@@ -27415,12 +27539,15 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref)
enum_check_fields org_count_cuted_fields= thd->count_cuted_fields;
MY_BITMAP *old_map= dbug_tmp_use_all_columns(table, &table->write_set);
bool result= 0;
key_part_map map= 1;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
for (store_key **copy=ref->key_copy ; *copy ; copy++)
for (store_key **copy=ref->key_copy ; *copy ; copy++, map <<= 1)
{
while (map & ref->const_ref_part_map) // skip const ref parts
map <<= 1; // no store_key objects for them
if ((*copy)->copy(thd) & 1 ||
(ref->null_rejecting && (*copy)->null_key))
((ref->null_rejecting & map) && (*copy)->null_key))
{
result= 1;
break;