1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00
This commit is contained in:
Igor Babaev
2010-10-30 06:07:45 -07:00
108 changed files with 7091 additions and 3170 deletions

View File

@ -100,6 +100,7 @@ static void make_outerjoin_info(JOIN *join);
static Item*
make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables, table_map sjm_tables);
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
static void revise_cache_usage(JOIN_TAB *join_tab);
static bool make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after);
static bool only_eq_ref_tables(JOIN *join, ORDER *order, table_map tables);
static void update_depend_map(JOIN *join);
@ -1631,6 +1632,62 @@ void JOIN::restore_tmp()
}
/*
Shrink join buffers used for preceding tables to reduce the occupied space
SYNOPSIS
shrink_join_buffers()
jt table up to which the buffers are to be shrunk
curr_space the size of the space used by the buffers for tables 1..jt
needed_space the size of the space that has to be used by these buffers
DESCRIPTION
The function makes an attempt to shrink all join buffers used for the
tables starting from the first up to jt to reduce the total size of the
space occupied by the buffers used for tables 1,...,jt from curr_space
to needed_space.
The function assumes that the buffer for the table jt has not been
allocated yet.
RETURN
FALSE if all buffer have been successfully shrunk
TRUE otherwise
*/
bool JOIN::shrink_join_buffers(JOIN_TAB *jt,
ulonglong curr_space,
ulonglong needed_space)
{
JOIN_CACHE *cache;
for (JOIN_TAB *tab= join_tab+const_tables; tab < jt; tab++)
{
cache= tab->cache;
if (cache)
{
ulong buff_size;
if (needed_space < cache->get_min_join_buffer_size())
return TRUE;
if (cache->shrink_join_buffer_in_ratio(curr_space, needed_space))
{
revise_cache_usage(tab);
return TRUE;
}
buff_size= cache->get_join_buffer_size();
curr_space-= buff_size;
needed_space-= buff_size;
}
}
cache= jt->cache;
DBUG_ASSERT(cache);
if (needed_space < cache->get_min_join_buffer_size())
return TRUE;
cache->set_join_buffer_size(needed_space);
return FALSE;
}
int
JOIN::reinit()
{
@ -5836,15 +5893,15 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
Find how much space the prevous read not const tables takes in cache.
*/
void calc_used_field_length(THD *thd, JOIN_TAB *join_tab)
void JOIN_TAB::calc_used_field_length(bool max_fl)
{
uint null_fields,blobs,fields,rec_length;
Field **f_ptr,*field;
uint uneven_bit_fields;
MY_BITMAP *read_set= join_tab->table->read_set;
MY_BITMAP *read_set= table->read_set;
uneven_bit_fields= null_fields= blobs= fields= rec_length=0;
for (f_ptr=join_tab->table->field ; (field= *f_ptr) ; f_ptr++)
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
{
if (bitmap_is_set(read_set, field->field_index))
{
@ -5861,24 +5918,31 @@ void calc_used_field_length(THD *thd, JOIN_TAB *join_tab)
}
}
if (null_fields || uneven_bit_fields)
rec_length+=(join_tab->table->s->null_fields+7)/8;
if (join_tab->table->maybe_null)
rec_length+=(table->s->null_fields+7)/8;
if (table->maybe_null)
rec_length+=sizeof(my_bool);
if (blobs)
if (max_fl)
{
uint blob_length=(uint) (join_tab->table->file->stats.mean_rec_length-
(join_tab->table->s->reclength-rec_length));
rec_length+=(uint) max(4,blob_length);
}
// TODO: to improve this estimate for max expected length if the record
if (blobs)
{
uint blob_length=(uint) (table->file->stats.mean_rec_length-
(table->s->reclength-rec_length));
rec_length+=(uint) max(4,blob_length);
}
}
else
rec_length= table->file->stats.mean_rec_length;
/*
psergey-todo: why we don't count here rowid that we might need to store
when using DuplicateElimination?
*/
join_tab->used_fields=fields;
join_tab->used_fieldlength=rec_length;
join_tab->used_blobs=blobs;
join_tab->used_null_fields= null_fields;
join_tab->used_uneven_bit_fields= uneven_bit_fields;
used_fields=fields;
used_fieldlength=rec_length;
used_blobs=blobs;
used_null_fields= null_fields;
used_uneven_bit_fields= uneven_bit_fields;
}
@ -5887,16 +5951,13 @@ cache_record_length(JOIN *join,uint idx)
{
uint length=0;
JOIN_TAB **pos,**end;
THD *thd=join->thd;
for (pos=join->best_ref+join->const_tables,end=join->best_ref+idx ;
pos != end ;
pos++)
{
JOIN_TAB *join_tab= *pos;
if (!join_tab->used_fieldlength) /* Not calced yet */
calc_used_field_length(thd, join_tab);
length+=join_tab->used_fieldlength;
length+= join_tab->get_used_fieldlength();
}
return length;
}
@ -6366,6 +6427,8 @@ inline void add_cond_and_fix(Item **e1, Item *e2)
{
if (*e1)
{
if (!e2)
return;
Item *res;
if ((res= new Item_cond_and(*e1, e2)))
{
@ -6436,9 +6499,8 @@ static void add_not_null_conds(JOIN *join)
for (uint i=join->const_tables ; i < join->tables ; i++)
{
JOIN_TAB *tab=join->join_tab+i;
if ((tab->type == JT_REF || tab->type == JT_EQ_REF ||
tab->type == JT_REF_OR_NULL) &&
!tab->table->maybe_null)
if (tab->type == JT_REF || tab->type == JT_EQ_REF ||
tab->type == JT_REF_OR_NULL)
{
for (uint keypart= 0; keypart < tab->ref.key_parts; keypart++)
{
@ -6470,9 +6532,14 @@ static void add_not_null_conds(JOIN *join)
DBUG_EXECUTE("where",print_where(notnull,
referred_tab->table->alias,
QT_ORDINARY););
COND *new_cond= referred_tab->select_cond;
add_cond_and_fix(&new_cond, notnull);
referred_tab->set_select_cond(new_cond, __LINE__);
if (!tab->first_inner)
{
COND *new_cond= referred_tab->select_cond;
add_cond_and_fix(&new_cond, notnull);
referred_tab->set_select_cond(new_cond, __LINE__);
}
else
add_cond_and_fix(tab->first_inner->on_expr_ref, notnull);
}
}
}
@ -6652,6 +6719,10 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
make_cond_for_table(cond,
join->const_table_map,
(table_map) 0, TRUE);
/* Add conditions added by add_not_null_conds(). */
for (uint i= 0 ; i < join->const_tables ; i++)
add_cond_and_fix(&const_cond, join->join_tab[i].select_cond);
DBUG_EXECUTE("where",print_where(const_cond,"constants", QT_ORDINARY););
for (JOIN_TAB *tab= join->join_tab+join->const_tables;
tab < join->join_tab+join->tables ; tab++)
@ -6750,6 +6821,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
tmp= NULL;
if (cond)
tmp= make_cond_for_table(cond, used_tables, current_map, FALSE);
/* Add conditions added by add_not_null_conds(). */
if (tab->select_cond)
add_cond_and_fix(&tmp, tab->select_cond);
if (cond && !tmp && tab->quick)
{ // Outer join
if (tab->type != JT_ALL)
@ -7000,9 +7074,13 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
used_tables2|= current_map;
COND *tmp_cond= make_cond_for_table(on_expr, used_tables2,
current_map, FALSE);
add_cond_and_fix(&tmp_cond, tab->on_precond);
if (tmp_cond)
{
JOIN_TAB *cond_tab= tab < first_inner_tab ? first_inner_tab : tab;
Item **sel_cond_ref= tab < first_inner_tab ?
&first_inner_tab->on_precond :
&tab->select_cond;
/*
First add the guards for match variables of
all embedding outer join operations.
@ -7025,15 +7103,15 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
tmp_cond->quick_fix_field();
/* Add the predicate to other pushed down predicates */
DBUG_PRINT("info", ("Item_cond_and"));
cond_tab->select_cond= !cond_tab->select_cond ? tmp_cond :
new Item_cond_and(cond_tab->select_cond,
tmp_cond);
*sel_cond_ref= !(*sel_cond_ref) ?
tmp_cond :
new Item_cond_and(*sel_cond_ref, tmp_cond);
DBUG_PRINT("info", ("Item_cond_and 0x%lx",
(ulong)cond_tab->select_cond));
if (!cond_tab->select_cond)
DBUG_RETURN(1);
cond_tab->select_cond->quick_fix_field();
cond_tab->select_cond->update_used_tables();
(ulong)(*sel_cond_ref)));
if (!(*sel_cond_ref))
DBUG_RETURN(1);
(*sel_cond_ref)->quick_fix_field();
(*sel_cond_ref)->update_used_tables();
if (cond_tab->select)
cond_tab->select->cond= cond_tab->select_cond;
}
@ -7125,6 +7203,19 @@ void set_join_cache_denial(JOIN_TAB *join_tab)
{
if (join_tab->cache)
{
/*
If there is a previous cache linked to this cache through the
next_cache pointer: remove the link.
*/
if (join_tab->cache->prev_cache)
join_tab->cache->prev_cache->next_cache= 0;
/*
No need to do the same for next_cache since cache denial is done
backwards starting from the latest cache in the linked list (see
revise_cache_usage()).
*/
DBUG_ASSERT(!join_tab->cache->next_cache);
join_tab->cache->free();
join_tab->cache= 0;
}
@ -7319,6 +7410,8 @@ end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
no_jbuf_after don't use join buffering after table with this number
icp_other_tables_ok OUT TRUE if condition pushdown supports
other tables presence
idx_cond_fact_out OUT TRUE if condition pushed to the index is factored
out of the condition pushed to the table
DESCRIPTION
The function finds out whether the table 'tab' can be joined using a join
@ -7330,24 +7423,66 @@ end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
depend on:
- the access method to access rows of the joined table
- whether the join table is an inner table of an outer join or semi-join
- whether the optimizer switches
outer_join_with_cache, semijoin_with_cache, join_cache_incremental,
join_cache_hashed, join_cache_bka,
are set on or off
- the join cache level set for the query
- the join 'options'.
In any case join buffer is not used if the number of the joined table is
greater than 'no_jbuf_after'. It's also never used if the value of
join_cache_level is equal to 0.
The other valid settings of join_cache_level lay in the interval 1..8.
If join_cache_level==1|2 then join buffer is used only for inner joins
with 'JT_ALL' access method.
If join_cache_level==3|4 then join buffer is used for any join operation
(inner join, outer join, semi-join) with 'JT_ALL' access method.
If 'JT_ALL' access method is used to read rows of the joined table then
always a JOIN_CACHE_BNL object is employed.
If the optimizer switch outer_join_with_cache is off no join buffer is
used for outer join operations.
If the optimizer switch semijoin_with_cache is off no join buffer is used
for semi-join operations.
If the optimizer switch join_cache_incremental is off no incremental join
buffers are used.
If the optimizer switch join_cache_hashed is off then the optimizer does
not use neither BNLH algorithm, nor BKAH algorithm to perform join
operations.
If the optimizer switch join_cache_bka is off then the optimizer does not
use neither BKA algprithm, nor BKAH algorithm to perform join operation.
The valid settings for join_cache_level lay in the interval 0..8.
If it set to 0 no join buffers are used to perform join operations.
Currently we differentiate between join caches of 8 levels:
1 : non-incremental join cache used for BNL join algorithm
2 : incremental join cache used for BNL join algorithm
3 : non-incremental join cache used for BNLH join algorithm
4 : incremental join cache used for BNLH join algorithm
5 : non-incremental join cache used for BKA join algorithm
6 : incremental join cache used for BKA join algorithm
7 : non-incremental join cache used for BKAH join algorithm
8 : incremental join cache used for BKAH join algorithm
If the value of join_cache_level is set to n then no join caches of
levels higher than n can be employed.
If the optimizer switches outer_join_with_cache, semijoin_with_cache,
join_cache_incremental, join_cache_hashed, join_cache_bka are all on
the following rules are applied.
If join_cache_level==1|2 then join buffer is used for inner joins, outer
joins and semi-joins with 'JT_ALL' access method. In this case a
JOIN_CACHE_BNL object is employed.
If join_cache_level==3|4 and then join buffer is used for a join operation
(inner join, outer join, semi-join) with 'JT_REF'/'JT_EQREF' access method
then a JOIN_CACHE_BNLH object is employed.
If an index is used to access rows of the joined table and the value of
join_cache_level==5|6 then a JOIN_CACHE_BKA object is employed.
If an index is used to access rows of the joined table and the value of
join_cache_level==7|8 then a JOIN_CACHE_BKA_UNIQUE object is employed.
join_cache_level==7|8 then a JOIN_CACHE_BKAH object is employed.
If the value of join_cache_level is odd then creation of a non-linked
join cache is forced.
Currently for any join operation a join cache of the level of the
highest allowed and applicable level is used.
For example, if join_cache_level is set to 6 and the optimizer switch
join_cache_bka is off, while the optimizer switch join_cache_hashed is
on then for any inner join operation with JT_REF/JT_EQREF access method
to the joined table the BNLH join algorithm will be used, while for
the table accessed by the JT_ALL methods the BNL algorithm will be used.
If the function decides that a join buffer can be used to join the table
'tab' then it sets the value of tab->use_join_buffer to TRUE and assigns
the selected join cache object to the field 'cache' of the previous
@ -7364,10 +7499,13 @@ end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
For a nested outer join/semi-join, currently, we either use join buffers for
all inner tables or for none of them.
Some engines (e.g. Falcon) currently allow to use only a join cache
of the type JOIN_CACHE_BKA_UNIQUE when the joined table is accessed through
of the type JOIN_CACHE_BKAH when the joined table is accessed through
an index. For these engines setting the value of join_cache_level to 5 or 6
results in that no join buffer is used to join the table.
RETURN VALUE
cache level if cache is used, otherwise returns 0
TODO
Support BKA inside SJ-Materialization nests. When doing this, we'll need
to only store sj-inner tables in the join buffer.
@ -7391,17 +7529,14 @@ end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
first_tab= join->join_tab + first_sjm_table;
}
#endif
RETURN
cache level if cache is used, otherwise returns 0
*/
static
uint check_join_cache_usage(JOIN_TAB *tab,
JOIN *join, ulonglong options,
uint no_jbuf_after,
bool *icp_other_tables_ok)
bool *icp_other_tables_ok,
bool *idx_cond_fact_out)
{
uint flags;
COST_VECT cost;
@ -7409,10 +7544,16 @@ uint check_join_cache_usage(JOIN_TAB *tab,
uint bufsz= 4096;
JOIN_CACHE *prev_cache=0;
uint cache_level= join->thd->variables.join_cache_level;
bool force_unlinked_cache= test(cache_level & 1);
bool force_unlinked_cache=
!optimizer_flag(join->thd, OPTIMIZER_SWITCH_JOIN_CACHE_INCREMENTAL);
bool no_hashed_cache=
!optimizer_flag(join->thd, OPTIMIZER_SWITCH_JOIN_CACHE_HASHED);
bool no_bka_cache=
!optimizer_flag(join->thd, OPTIMIZER_SWITCH_JOIN_CACHE_BKA);
uint i= tab - join->join_tab;
*icp_other_tables_ok= TRUE;
*idx_cond_fact_out= TRUE;
if (cache_level == 0 || i == join->const_tables)
return 0;
@ -7424,16 +7565,23 @@ uint check_join_cache_usage(JOIN_TAB *tab,
*/
if (tab->use_quick == 2)
goto no_join_cache;
if (tab->is_inner_table_of_semi_join_with_first_match() &&
!optimizer_flag(join->thd, OPTIMIZER_SWITCH_SEMIJOIN_WITH_CACHE))
goto no_join_cache;
if (tab->is_inner_table_of_outer_join() &&
!optimizer_flag(join->thd, OPTIMIZER_SWITCH_OUTER_JOIN_WITH_CACHE))
goto no_join_cache;
/*
Non-linked join buffers can't guarantee one match
*/
if (force_unlinked_cache &&
(!tab->type == JT_ALL || cache_level <= 4) &&
((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;
if (force_unlinked_cache &&
((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;
/*
Don't use join buffering if we're dictated not to by no_jbuf_after (this
@ -7478,43 +7626,78 @@ uint check_join_cache_usage(JOIN_TAB *tab,
switch (tab->type) {
case JT_ALL:
if (cache_level <= 2 && (tab->first_inner || tab->first_sj_inner_tab))
goto no_join_cache;
if ((options & SELECT_DESCRIBE) ||
(((tab->cache= new JOIN_CACHE_BNL(join, tab, prev_cache))) &&
!tab->cache->init()))
if (cache_level == 1)
prev_cache= 0;
if ((tab->cache= new JOIN_CACHE_BNL(join, tab, prev_cache)) &&
((options & SELECT_DESCRIBE) || !tab->cache->init()))
{
*icp_other_tables_ok= FALSE;
return cache_level;
return (2-test(!prev_cache));
}
goto no_join_cache;
case JT_SYSTEM:
case JT_CONST:
case JT_REF:
case JT_EQ_REF:
if (cache_level <= 4)
return 0;
if (cache_level <=2 || (no_hashed_cache && no_bka_cache))
goto no_join_cache;
flags= HA_MRR_NO_NULL_ENDPOINTS;
if (tab->table->covering_keys.is_set(tab->ref.key))
flags|= HA_MRR_INDEX_ONLY;
rows= tab->table->file->multi_range_read_info(tab->ref.key, 10, 20,
&bufsz, &flags, &cost);
if ((rows != HA_POS_ERROR) && !(flags & HA_MRR_USE_DEFAULT_IMPL) &&
(!(flags & HA_MRR_NO_ASSOCIATION) || cache_level > 6) &&
((options & SELECT_DESCRIBE) ||
(((cache_level <= 6 &&
(tab->cache= new JOIN_CACHE_BKA(join, tab, flags, prev_cache))) ||
(cache_level > 6 &&
(tab->cache= new JOIN_CACHE_BKA_UNIQUE(join, tab, flags, prev_cache)))
) && !tab->cache->init())))
return cache_level;
if ((cache_level <=4 && !no_hashed_cache) || no_bka_cache ||
(flags & HA_MRR_NO_ASSOCIATION) && cache_level <=6)
{
if (cache_level == 3)
prev_cache= 0;
if ((tab->cache= new JOIN_CACHE_BNLH(join, tab, prev_cache)) &&
((options & SELECT_DESCRIBE) || !tab->cache->init()))
{
*icp_other_tables_ok= FALSE;
return (4-test(!prev_cache));
}
goto no_join_cache;
}
if (cache_level > 4 && no_bka_cache)
goto no_join_cache;
if ((flags & HA_MRR_NO_ASSOCIATION) &&
(cache_level <= 6 || no_hashed_cache))
goto no_join_cache;
if ((rows != HA_POS_ERROR) && !(flags & HA_MRR_USE_DEFAULT_IMPL))
{
if (cache_level <= 6 || no_hashed_cache)
{
if (cache_level == 5)
prev_cache= 0;
if ((tab->cache= new JOIN_CACHE_BKA(join, tab, flags, prev_cache)) &&
((options & SELECT_DESCRIBE) || !tab->cache->init()))
return (6-test(!prev_cache));
goto no_join_cache;
}
else
{
if (cache_level == 7)
prev_cache= 0;
if ((tab->cache= new JOIN_CACHE_BKAH(join, tab, flags, prev_cache)) &&
((options & SELECT_DESCRIBE) || !tab->cache->init()))
{
*idx_cond_fact_out= FALSE;
return (8-test(!prev_cache));
}
goto no_join_cache;
}
}
goto no_join_cache;
default : ;
}
no_join_cache:
if (cache_level>2)
revise_cache_usage(tab);
revise_cache_usage(tab);
return 0;
}
@ -7545,6 +7728,7 @@ static bool
make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
{
uint i;
uint jcl;
bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
bool sorted= 1;
uint first_sjm_table= MAX_TABLES;
@ -7556,17 +7740,31 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
setup_semijoin_dups_elimination(join, options, no_jbuf_after))
DBUG_RETURN(TRUE); /* purecov: inspected */
for (i= 0; i < join->const_tables; i++)
join->join_tab[i].partial_join_cardinality= 1;
for (i=join->const_tables ; i < join->tables ; i++)
{
JOIN_TAB *tab=join->join_tab+i;
TABLE *table=tab->table;
bool icp_other_tables_ok;
bool idx_cond_fact_out;
tab->read_record.table= table;
tab->read_record.file=table->file;
tab->read_record.unlock_row= rr_unlock_row;
tab->next_select=sub_select; /* normal select */
tab->sorted= sorted;
sorted= 0; // only first must be sorted
/*
The approximation below for partial join cardinality is not good because
- it does not take into account some pushdown predicates
- it does not differentiate between inner joins, outer joins and semi-joins.
Later it should be improved.
*/
tab->partial_join_cardinality= join->best_positions[i].records_read *
(i ? (tab-1)->partial_join_cardinality : 1);
if (tab->loosescan_match_tab)
{
if (!(tab->loosescan_buf= (uchar*)join->thd->alloc(tab->
@ -7596,27 +7794,29 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
/* Only happens with outer joins */
tab->read_first_record= tab->type == JT_SYSTEM ?
join_read_system :join_read_const;
if (check_join_cache_usage(tab, join, options, no_jbuf_after,
&icp_other_tables_ok))
if ((jcl= check_join_cache_usage(tab, join, options,
no_jbuf_after, &icp_other_tables_ok,
&idx_cond_fact_out)))
{
tab->use_join_cache= TRUE;
tab[-1].next_select=sub_select_cache;
}
else
if (table->covering_keys.is_set(tab->ref.key) &&
!table->no_keyread)
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
}
else
push_index_cond(tab, tab->ref.key, icp_other_tables_ok);
else if (!jcl || jcl > 4)
push_index_cond(tab, tab->ref.key,
icp_other_tables_ok, idx_cond_fact_out);
break;
case JT_EQ_REF:
tab->read_record.unlock_row= join_read_key_unlock_row;
/* fall through */
if (check_join_cache_usage(tab, join, options, no_jbuf_after,
&icp_other_tables_ok))
if ((jcl= check_join_cache_usage(tab, join, options,
no_jbuf_after, &icp_other_tables_ok,
&idx_cond_fact_out)))
{
tab->use_join_cache= TRUE;
tab[-1].next_select=sub_select_cache;
@ -7627,8 +7827,9 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
}
else
push_index_cond(tab, tab->ref.key, icp_other_tables_ok );
else if (!jcl || jcl > 4)
push_index_cond(tab, tab->ref.key,
icp_other_tables_ok, idx_cond_fact_out);
break;
case JT_REF_OR_NULL:
case JT_REF:
@ -7639,8 +7840,9 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
}
delete tab->quick;
tab->quick=0;
if (check_join_cache_usage(tab, join, options, no_jbuf_after,
&icp_other_tables_ok))
if ((jcl= check_join_cache_usage(tab, join, options,
no_jbuf_after, &icp_other_tables_ok,
&idx_cond_fact_out)))
{
tab->use_join_cache= TRUE;
tab[-1].next_select=sub_select_cache;
@ -7648,8 +7850,9 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
if (table->covering_keys.is_set(tab->ref.key) &&
!table->no_keyread)
table->enable_keyread();
else
push_index_cond(tab, tab->ref.key, icp_other_tables_ok);
else if (!jcl || jcl > 4)
push_index_cond(tab, tab->ref.key,
icp_other_tables_ok, idx_cond_fact_out);
break;
case JT_ALL:
/*
@ -7659,7 +7862,7 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
materialization nest.
*/
if (check_join_cache_usage(tab, join, options, no_jbuf_after,
&icp_other_tables_ok))
&icp_other_tables_ok, &idx_cond_fact_out))
{
tab->use_join_cache= TRUE;
tab[-1].next_select=sub_select_cache;
@ -7736,7 +7939,8 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
}
if (tab->select && tab->select->quick &&
tab->select->quick->index != MAX_KEY && ! tab->table->key_read)
push_index_cond(tab, tab->select->quick->index, icp_other_tables_ok);
push_index_cond(tab, tab->select->quick->index,
icp_other_tables_ok, idx_cond_fact_out);
}
break;
case JT_FT:
@ -7760,8 +7964,11 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
JOIN_TAB *tab=join->join_tab+i;
if (tab->use_join_cache)
{
JOIN_TAB *sort_by_tab= join->get_sort_by_join_tab();
if (sort_by_tab && !join->need_tmp)
JOIN_TAB *sort_by_tab= join->group && join->simple_group &&
join->group_list ?
join->join_tab+join->const_tables :
join->get_sort_by_join_tab();
if (sort_by_tab)
{
join->need_tmp= 1;
join->simple_order= join->simple_group= 0;
@ -13079,7 +13286,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
DBUG_RETURN(nls);
}
int error;
enum_nested_loop_state rc;
enum_nested_loop_state rc= NESTED_LOOP_OK;
READ_RECORD *info= &join_tab->read_record;
if (join_tab->flush_weedout_table)
@ -13112,18 +13319,21 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
/* Set first_unmatched for the last inner table of this group */
join_tab->last_inner->first_unmatched= join_tab;
}
if (join_tab->on_precond && !join_tab->on_precond->val_int())
rc= NESTED_LOOP_NO_MORE_ROWS;
}
join->thd->row_count= 0;
if (join_tab->loosescan_match_tab)
join_tab->loosescan_match_tab->found_match= FALSE;
error= (*join_tab->read_first_record)(join_tab);
if (join_tab->keep_current_rowid)
join_tab->table->file->position(join_tab->table->record[0]);
rc= evaluate_join_record(join, join_tab, error);
if (rc != NESTED_LOOP_NO_MORE_ROWS)
{
error= (*join_tab->read_first_record)(join_tab);
if (join_tab->keep_current_rowid)
join_tab->table->file->position(join_tab->table->record[0]);
rc= evaluate_join_record(join, join_tab, error);
}
}
/*
@ -13415,27 +13625,6 @@ evaluate_null_complemented_join_record(JOIN *join, JOIN_TAB *join_tab)
return (*join_tab->next_select)(join, join_tab+1, 0);
}
#ifdef MERGE_JUNK
//psergey3-merge: remove:
SQL_SELECT *select;
select= join_tab->select;
int err= 0;
(err= join_tab->cache.select->skip_record(join->thd)) != 0 ))
{
reset_cache_write(&join_tab->cache);
return NESTED_LOOP_ERROR;
}
if (!select || (err= select->skip_record(join->thd)) != 0)
if (err < 0)
{
reset_cache_write(&join_tab->cache);
return NESTED_LOOP_ERROR;
}
rc= NESTED_LOOP_OK;
#endif
/*****************************************************************************
The different ways to read a record
Returns -1 if row was not found, 0 if row was found and 1 on errors
@ -13774,13 +13963,6 @@ join_read_always_key(JOIN_TAB *tab)
}
}
/* Perform "Late NULLs Filtering" (see internals manual for explanations) */
for (uint i= 0 ; i < tab->ref.key_parts ; i++)
{
if ((tab->ref.null_rejecting & 1 << i) && tab->ref.items[i]->is_null())
return -1;
}
if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref))
return -1;
if ((error= table->file->ha_index_read_map(table->record[0],
@ -18418,8 +18600,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(new Item_string("func", strlen("func"), cs));
}
/* rows */
ha_rows rows= (sj_strategy == SJ_OPT_MATERIALIZE_SCAN)?
tab->emb_sj_nest->sj_mat_info->rows : 1;
ha_rows rows= (ha_rows) ((sj_strategy == SJ_OPT_MATERIALIZE_SCAN)?
tab->emb_sj_nest->sj_mat_info->rows : 1);
item_list.push_back(new Item_int((longlong)rows,
MY_INT64_NUM_DECIMAL_DIGITS));
/* filtered */
@ -18827,8 +19009,11 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
}
}
if (i > 0 && tab[-1].next_select == sub_select_cache)
if (tab->cache)
{
extra.append(STRING_WITH_LEN("; Using join buffer"));
tab->cache->print_explain_comment(&extra);
}
/* Skip initial "; "*/
const char *str= extra.ptr();