4041
4041
join->setPosInPartialPlan(idx, best_pos);
4044
We need to make best_extension_by_limited_search aware of the fact
4045
that it's not starting from top level, but from a rather specific
4046
position in the list of nested joins.
4048
check_interleaving_with_nj (best_table);
4043
4052
/* find the position of 'best_table' in 'join->best_ref' */
4045
4054
JoinTable *pos= join->best_ref[best_idx];
4201
4210
for (JoinTable **pos= join->best_ref + idx ; (s= *pos) ; pos++)
4203
4212
table_map real_table_bit= s->table->map;
4206
partial_pos= join->getPosFromPartialPlan(idx - 1);
4208
4213
if ((remaining_tables & real_table_bit) &&
4209
4214
! (remaining_tables & s->dependent) &&
4210
(! idx || ! check_interleaving_with_nj(partial_pos.getJoinTable(), s)))
4215
(! idx || ! check_interleaving_with_nj(s)))
4212
4217
double current_record_count, current_read_time;
6015
6020
Nested joins perspective: Remove the last table from the join order.
6022
The algorithm is the reciprocal of check_interleaving_with_nj(), hence
6023
parent join nest nodes are updated only when the last table in its child
6024
node is removed. The ASCII graphic below will clarify.
6026
%A table nesting such as <tt> t1 x [ ( t2 x t3 ) x ( t4 x t5 ) ] </tt>is
6027
represented by the below join nest tree.
6035
t1 x [ (t2 x t3) x (t4 x t5) ]
6038
At the point in time when check_interleaving_with_nj() adds the table t5 to
6039
the query execution plan, QEP, it also directs the node named NJ2 to mark
6040
the table as covered. NJ2 does so by incrementing its @c counter
6041
member. Since all of NJ2's tables are now covered by the QEP, the algorithm
6042
proceeds up the tree to NJ1, incrementing its counter as well. All join
6043
nests are now completely covered by the QEP.
6045
restore_prev_nj_state() does the above in reverse. As seen above, the node
6046
NJ1 contains the nodes t2, t3, and NJ2. Its counter being equal to 3 means
6047
that the plan covers t2, t3, and NJ2, @e and that the sub-plan (t4 x t5)
6048
completely covers NJ2. The removal of t5 from the partial plan will first
6049
decrement NJ2's counter to 1. It will then detect that NJ2 went from being
6050
completely to partially covered, and hence the algorithm must continue
6051
upwards to NJ1 and decrement its counter to 2. %A subsequent removal of t4
6052
will however not influence NJ1 since it did not un-cover the last table in
6056
restore_prev_nj_state()
6057
last join table to remove, it is assumed to be the last in current
6017
6062
Remove the last table from the partial join order and update the nested
6018
joins counters and join->cur_embedding_map. It is ok to call this
6019
function for the first table in join order (for which
6063
joins counters and join->cur_embedding_map. It is ok to call this
6064
function for the first table in join order (for which
6020
6065
check_interleaving_with_nj has not been called)
6022
6067
@param last join table to remove, it is assumed to be the last in current
6023
6068
partial join order.
6025
6071
static void restore_prev_nj_state(JoinTable *last)
6027
6073
TableList *last_emb= last->table->pos_in_table_list->getEmbedding();
6028
6074
Join *join= last->join;
6075
for (;last_emb != NULL; last_emb= last_emb->getEmbedding())
6031
if (last_emb->on_expr)
6033
if (!(--last_emb->getNestedJoin()->counter_))
6034
join->cur_embedding_map&= ~last_emb->getNestedJoin()->nj_map;
6035
else if (last_emb->getNestedJoin()->join_list.elements-1 ==
6036
last_emb->getNestedJoin()->counter_)
6037
join->cur_embedding_map|= last_emb->getNestedJoin()->nj_map;
6041
last_emb= last_emb->getEmbedding();
6077
nested_join_st *nest= last_emb->getNestedJoin();
6079
bool was_fully_covered= nest->is_fully_covered();
6081
if (--nest->counter_ == 0)
6082
join->cur_embedding_map&= ~nest->nj_map;
6084
if (!was_fully_covered)
6087
join->cur_embedding_map|= nest->nj_map;
6047
6092
Create a condition for a const reference and add this to the
6048
6093
currenct select for the table.