mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge 10.4 into 10.5
This commit is contained in:
@ -5900,18 +5900,16 @@ add_key_field(JOIN *join,
|
||||
(*key_fields)->level= and_level;
|
||||
(*key_fields)->optimize= optimize;
|
||||
/*
|
||||
If the condition has form "tbl.keypart = othertbl.field" and
|
||||
othertbl.field can be NULL, there will be no matches if othertbl.field
|
||||
has NULL value.
|
||||
We use null_rejecting in add_not_null_conds() to add
|
||||
'othertbl.field IS NOT NULL' to tab->select_cond.
|
||||
If the condition we are analyzing is NULL-rejecting and at least
|
||||
one side of the equalities is NULLable, mark the KEY_FIELD object as
|
||||
null-rejecting. This property is used by:
|
||||
- add_not_null_conds() to add "column IS NOT NULL" conditions
|
||||
- best_access_path() to produce better estimates for NULL-able unique keys.
|
||||
*/
|
||||
{
|
||||
Item *real= (*value)->real_item();
|
||||
if (((cond->functype() == Item_func::EQ_FUNC) ||
|
||||
(cond->functype() == Item_func::MULT_EQUAL_FUNC)) &&
|
||||
(real->type() == Item::FIELD_ITEM) &&
|
||||
((Item_field*)real)->field->maybe_null())
|
||||
if ((cond->functype() == Item_func::EQ_FUNC ||
|
||||
cond->functype() == Item_func::MULT_EQUAL_FUNC) &&
|
||||
((*value)->maybe_null || field->real_maybe_null()))
|
||||
(*key_fields)->null_rejecting= true;
|
||||
else
|
||||
(*key_fields)->null_rejecting= false;
|
||||
@ -7235,6 +7233,7 @@ best_access_path(JOIN *join,
|
||||
ulong key_flags;
|
||||
uint key_parts;
|
||||
key_part_map found_part= 0;
|
||||
key_part_map notnull_part=0; // key parts which won't have NULL in lookup tuple.
|
||||
table_map found_ref= 0;
|
||||
uint key= keyuse->key;
|
||||
filter= 0;
|
||||
@ -7294,6 +7293,9 @@ best_access_path(JOIN *join,
|
||||
if (!(keyuse->used_tables & ~join->const_table_map))
|
||||
const_part|= keyuse->keypart_map;
|
||||
|
||||
if (!keyuse->val->maybe_null || keyuse->null_rejecting)
|
||||
notnull_part|=keyuse->keypart_map;
|
||||
|
||||
double tmp2= prev_record_reads(join->positions, idx,
|
||||
(found_ref | keyuse->used_tables));
|
||||
if (tmp2 < best_prev_record_reads)
|
||||
@ -7347,12 +7349,19 @@ best_access_path(JOIN *join,
|
||||
loose_scan_opt.check_ref_access_part1(s, key, start_key, found_part);
|
||||
|
||||
/* Check if we found full key */
|
||||
if (found_part == PREV_BITS(uint, key_parts) &&
|
||||
!ref_or_null_part)
|
||||
const key_part_map all_key_parts= PREV_BITS(uint, key_parts);
|
||||
if (found_part == all_key_parts && !ref_or_null_part)
|
||||
{ /* use eq key */
|
||||
max_key_part= (uint) ~0;
|
||||
if ((key_flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME ||
|
||||
MY_TEST(key_flags & HA_EXT_NOSAME))
|
||||
/*
|
||||
If the index is a unique index (1), and
|
||||
- all its columns are not null (2), or
|
||||
- equalities we are using reject NULLs (3)
|
||||
then the estimate is rows=1.
|
||||
*/
|
||||
if ((key_flags & (HA_NOSAME | HA_EXT_NOSAME)) && // (1)
|
||||
(!(key_flags & HA_NULL_PART_KEY) || // (2)
|
||||
all_key_parts == notnull_part)) // (3)
|
||||
{
|
||||
trace_access_idx.add("access_type", "eq_ref")
|
||||
.add("index", keyinfo->name);
|
||||
@ -10565,8 +10574,16 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
|
||||
uint maybe_null= MY_TEST(keyinfo->key_part[i].null_bit);
|
||||
j->ref.items[i]=keyuse->val; // Save for cond removal
|
||||
j->ref.cond_guards[i]= keyuse->cond_guard;
|
||||
if (keyuse->null_rejecting)
|
||||
|
||||
/*
|
||||
Set ref.null_rejecting to true only if we are going to inject a
|
||||
"keyuse->val IS NOT NULL" predicate.
|
||||
*/
|
||||
Item *real= (keyuse->val)->real_item();
|
||||
if (keyuse->null_rejecting && (real->type() == Item::FIELD_ITEM) &&
|
||||
((Item_field*)real)->field->maybe_null())
|
||||
j->ref.null_rejecting|= (key_part_map)1 << i;
|
||||
|
||||
keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables;
|
||||
/*
|
||||
We don't want to compute heavy expressions in EXPLAIN, an example would
|
||||
@ -21163,7 +21180,6 @@ join_read_first(JOIN_TAB *tab)
|
||||
tab->table->status=0;
|
||||
tab->read_record.read_record_func= join_read_next;
|
||||
tab->read_record.table=table;
|
||||
tab->read_record.record=table->record[0];
|
||||
if (!table->file->inited)
|
||||
error= table->file->ha_index_init(tab->index, tab->sorted);
|
||||
if (likely(!error))
|
||||
@ -21183,7 +21199,7 @@ static int
|
||||
join_read_next(READ_RECORD *info)
|
||||
{
|
||||
int error;
|
||||
if (unlikely((error= info->table->file->ha_index_next(info->record))))
|
||||
if (unlikely((error= info->table->file->ha_index_next(info->record()))))
|
||||
return report_error(info->table, error);
|
||||
|
||||
return 0;
|
||||
@ -21203,7 +21219,6 @@ join_read_last(JOIN_TAB *tab)
|
||||
tab->table->status=0;
|
||||
tab->read_record.read_record_func= join_read_prev;
|
||||
tab->read_record.table=table;
|
||||
tab->read_record.record=table->record[0];
|
||||
if (!table->file->inited)
|
||||
error= table->file->ha_index_init(tab->index, 1);
|
||||
if (likely(!error))
|
||||
@ -21220,7 +21235,7 @@ static int
|
||||
join_read_prev(READ_RECORD *info)
|
||||
{
|
||||
int error;
|
||||
if (unlikely((error= info->table->file->ha_index_prev(info->record))))
|
||||
if (unlikely((error= info->table->file->ha_index_prev(info->record()))))
|
||||
return report_error(info->table, error);
|
||||
return 0;
|
||||
}
|
||||
@ -21250,7 +21265,7 @@ static int
|
||||
join_ft_read_next(READ_RECORD *info)
|
||||
{
|
||||
int error;
|
||||
if (unlikely((error= info->table->file->ha_ft_read(info->table->record[0]))))
|
||||
if (unlikely((error= info->table->file->ha_ft_read(info->record()))))
|
||||
return report_error(info->table, error);
|
||||
return 0;
|
||||
}
|
||||
@ -26505,6 +26520,7 @@ int JOIN::save_explain_data_intern(Explain_query *output,
|
||||
|
||||
xpl_sel->exec_const_cond= exec_const_cond;
|
||||
xpl_sel->outer_ref_cond= outer_ref_cond;
|
||||
xpl_sel->pseudo_bits_cond= pseudo_bits_cond;
|
||||
if (tmp_having)
|
||||
xpl_sel->having= tmp_having;
|
||||
else
|
||||
|
Reference in New Issue
Block a user