mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Corrected Evgen's fix for bug #45191.
Made sure that join buffers could be used for inner tables of any semi-join when the first match strategy is employed.
This commit is contained in:
@@ -713,9 +713,9 @@ c2 in (select 1 from t3, t2) and
|
|||||||
c1 in (select convert(c6,char(1)) from t2);
|
c1 in (select convert(c6,char(1)) from t2);
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where
|
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where
|
||||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 1
|
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using join buffer
|
||||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where
|
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; Using join buffer
|
||||||
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2)
|
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2); Using join buffer
|
||||||
drop table t2, t3;
|
drop table t2, t3;
|
||||||
set join_cache_level=default;
|
set join_cache_level=default;
|
||||||
show variables like 'join_cache_level';
|
show variables like 'join_cache_level';
|
||||||
|
@@ -374,8 +374,8 @@ WHERE PNUM IN
|
|||||||
(SELECT PNUM FROM PROJ));
|
(SELECT PNUM FROM PROJ));
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 PRIMARY STAFF ALL NULL NULL NULL NULL 5
|
1 PRIMARY STAFF ALL NULL NULL NULL NULL 5
|
||||||
1 PRIMARY PROJ ALL NULL NULL NULL NULL 6
|
1 PRIMARY PROJ ALL NULL NULL NULL NULL 6 Using join buffer
|
||||||
1 PRIMARY WORKS ALL NULL NULL NULL NULL 12 Using where; FirstMatch(STAFF)
|
1 PRIMARY WORKS ALL NULL NULL NULL NULL 12 Using where; FirstMatch(STAFF); Using join buffer
|
||||||
SELECT EMPNUM, EMPNAME
|
SELECT EMPNUM, EMPNAME
|
||||||
FROM STAFF
|
FROM STAFF
|
||||||
WHERE EMPNUM IN
|
WHERE EMPNUM IN
|
||||||
|
@@ -407,8 +407,10 @@ void JOIN_CACHE::set_constants()
|
|||||||
However at this moment we don't know whether we have referenced fields for
|
However at this moment we don't know whether we have referenced fields for
|
||||||
the cache or not. Later when a referenced field is registered for the cache
|
the cache or not. Later when a referenced field is registered for the cache
|
||||||
we adjust the value of the flag 'with_length'.
|
we adjust the value of the flag 'with_length'.
|
||||||
*/
|
*/
|
||||||
with_length= is_key_access() || with_match_flag;
|
with_length= is_key_access() ||
|
||||||
|
join_tab->is_inner_table_of_semi_join_with_first_match() ||
|
||||||
|
join_tab->is_inner_table_of_outer_join();
|
||||||
/*
|
/*
|
||||||
At this moment we don't know yet the value of 'referenced_fields',
|
At this moment we don't know yet the value of 'referenced_fields',
|
||||||
but in any case it can't be greater than the value of 'fields'.
|
but in any case it can't be greater than the value of 'fields'.
|
||||||
@@ -1304,7 +1306,7 @@ bool JOIN_CACHE::get_match_flag_by_pos(uchar *rec_ptr)
|
|||||||
uchar *prev_rec_ptr= prev_cache->get_rec_ref(rec_ptr);
|
uchar *prev_rec_ptr= prev_cache->get_rec_ref(rec_ptr);
|
||||||
return prev_cache->get_match_flag_by_pos(prev_rec_ptr);
|
return prev_cache->get_match_flag_by_pos(prev_rec_ptr);
|
||||||
}
|
}
|
||||||
DBUG_ASSERT(1);
|
DBUG_ASSERT(0);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1538,12 +1540,12 @@ bool JOIN_CACHE::read_referenced_field(CACHE_FIELD *copy,
|
|||||||
|
|
||||||
bool JOIN_CACHE::skip_record_if_match()
|
bool JOIN_CACHE::skip_record_if_match()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(with_match_flag && with_length);
|
DBUG_ASSERT(with_length);
|
||||||
uint offset= size_of_rec_len;
|
uint offset= size_of_rec_len;
|
||||||
if (prev_cache)
|
if (prev_cache)
|
||||||
offset+= prev_cache->get_size_of_rec_offset();
|
offset+= prev_cache->get_size_of_rec_offset();
|
||||||
/* Check whether the match flag is on */
|
/* Check whether the match flag is on */
|
||||||
if (test(*(pos+offset)))
|
if (get_match_flag_by_pos(pos+offset))
|
||||||
{
|
{
|
||||||
pos+= size_of_rec_len + get_rec_length(pos);
|
pos+= size_of_rec_len + get_rec_length(pos);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@@ -6352,10 +6352,17 @@ make_outerjoin_info(JOIN *join)
|
|||||||
}
|
}
|
||||||
if (!tab->first_inner)
|
if (!tab->first_inner)
|
||||||
tab->first_inner= nested_join->first_nested;
|
tab->first_inner= nested_join->first_nested;
|
||||||
|
if (tab->table->reginfo.not_exists_optimize)
|
||||||
|
tab->first_inner->table->reginfo.not_exists_optimize= 1;
|
||||||
if (++nested_join->counter < nested_join->n_tables)
|
if (++nested_join->counter < nested_join->n_tables)
|
||||||
break;
|
break;
|
||||||
/* Table tab is the last inner table for nested join. */
|
/* Table tab is the last inner table for nested join. */
|
||||||
nested_join->first_nested->last_inner= tab;
|
nested_join->first_nested->last_inner= tab;
|
||||||
|
if (tab->first_inner->table->reginfo.not_exists_optimize)
|
||||||
|
{
|
||||||
|
for (JOIN_TAB *join_tab= tab->first_inner; join_tab <= tab; join_tab++)
|
||||||
|
join_tab->table->reginfo.not_exists_optimize= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@@ -7108,19 +7115,15 @@ uint check_join_cache_usage(JOIN_TAB *tab,
|
|||||||
*/
|
*/
|
||||||
if (tab->use_quick == 2)
|
if (tab->use_quick == 2)
|
||||||
goto no_join_cache;
|
goto no_join_cache;
|
||||||
/*
|
|
||||||
Use join cache with FirstMatch semi-join strategy only when semi-join
|
|
||||||
contains only one table.
|
|
||||||
*/
|
|
||||||
if (tab->is_inner_table_of_semi_join_with_first_match() &&
|
|
||||||
!tab->is_single_inner_of_semi_join_with_first_match())
|
|
||||||
goto no_join_cache;
|
|
||||||
/*
|
/*
|
||||||
Non-linked join buffers can't guarantee one match
|
Non-linked join buffers can't guarantee one match
|
||||||
*/
|
*/
|
||||||
if (force_unlinked_cache &&
|
if (force_unlinked_cache &&
|
||||||
(tab->is_inner_table_of_outer_join() &&
|
(!tab->type == JT_ALL || cache_level <= 4) &&
|
||||||
!tab->is_single_inner_of_outer_join()))
|
((tab->is_inner_table_of_semi_join_with_first_match() &&
|
||||||
|
!tab->is_single_inner_of_semi_join_with_first_match()) ||
|
||||||
|
(tab->is_inner_table_of_outer_join() &&
|
||||||
|
!tab->is_single_inner_of_outer_join())))
|
||||||
goto no_join_cache;
|
goto no_join_cache;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -321,8 +321,8 @@ typedef struct st_join_table {
|
|||||||
}
|
}
|
||||||
bool check_only_first_match()
|
bool check_only_first_match()
|
||||||
{
|
{
|
||||||
return last_sj_inner_tab == this ||
|
return is_inner_table_of_semi_join_with_first_match() ||
|
||||||
(first_inner && first_inner->last_inner == this &&
|
(is_inner_table_of_outer_join() &&
|
||||||
table->reginfo.not_exists_optimize);
|
table->reginfo.not_exists_optimize);
|
||||||
}
|
}
|
||||||
bool is_last_inner_table()
|
bool is_last_inner_table()
|
||||||
|
Reference in New Issue
Block a user