mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Manual merge of mysql-5.1-bugteam to mysql-trunk-merge.
Conflicts: Text conflict in mysql-test/r/grant.result Text conflict in mysql-test/t/grant.test Text conflict in mysys/mf_loadpath.c Text conflict in sql/slave.cc Text conflict in sql/sql_priv.h
This commit is contained in:
@ -3005,8 +3005,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
|
||||
s->quick=select->quick;
|
||||
s->needed_reg=select->needed_reg;
|
||||
select->quick=0;
|
||||
if (records == 0 && s->table->reginfo.impossible_range &&
|
||||
(s->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT))
|
||||
if (records == 0 && s->table->reginfo.impossible_range)
|
||||
{
|
||||
/*
|
||||
Impossible WHERE or ON expression
|
||||
@ -9209,6 +9208,46 @@ static bool check_interleaving_with_nj(JOIN_TAB *next_tab)
|
||||
/**
|
||||
Nested joins perspective: Remove the last table from the join order.
|
||||
|
||||
The algorithm is the reciprocal of check_interleaving_with_nj(), hence
|
||||
parent join nest nodes are updated only when the last table in its child
|
||||
node is removed. The ASCII graphic below will clarify.
|
||||
|
||||
%A table nesting such as <tt> t1 x [ ( t2 x t3 ) x ( t4 x t5 ) ] </tt>is
|
||||
represented by the below join nest tree.
|
||||
|
||||
@verbatim
|
||||
NJ1
|
||||
_/ / \
|
||||
_/ / NJ2
|
||||
_/ / / \
|
||||
/ / / \
|
||||
t1 x [ (t2 x t3) x (t4 x t5) ]
|
||||
@endverbatim
|
||||
|
||||
At the point in time when check_interleaving_with_nj() adds the table t5 to
|
||||
the query execution plan, QEP, it also directs the node named NJ2 to mark
|
||||
the table as covered. NJ2 does so by incrementing its @c counter
|
||||
member. Since all of NJ2's tables are now covered by the QEP, the algorithm
|
||||
proceeds up the tree to NJ1, incrementing its counter as well. All join
|
||||
nests are now completely covered by the QEP.
|
||||
|
||||
restore_prev_nj_state() does the above in reverse. As seen above, the node
|
||||
NJ1 contains the nodes t2, t3, and NJ2. Its counter being equal to 3 means
|
||||
that the plan covers t2, t3, and NJ2, @e and that the sub-plan (t4 x t5)
|
||||
completely covers NJ2. The removal of t5 from the partial plan will first
|
||||
decrement NJ2's counter to 1. It will then detect that NJ2 went from being
|
||||
completely to partially covered, and hence the algorithm must continue
|
||||
upwards to NJ1 and decrement its counter to 2. %A subsequent removal of t4
|
||||
will however not influence NJ1 since it did not un-cover the last table in
|
||||
NJ2.
|
||||
|
||||
SYNOPSIS
|
||||
restore_prev_nj_state()
|
||||
last join table to remove, it is assumed to be the last in current
|
||||
partial join order.
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Remove the last table from the partial join order and update the nested
|
||||
joins counters and join->cur_embedding_map. It is ok to call this
|
||||
function for the first table in join order (for which
|
||||
@ -9222,19 +9261,20 @@ static void restore_prev_nj_state(JOIN_TAB *last)
|
||||
{
|
||||
TABLE_LIST *last_emb= last->table->pos_in_table_list->embedding;
|
||||
JOIN *join= last->join;
|
||||
while (last_emb)
|
||||
for (;last_emb != NULL; last_emb= last_emb->embedding)
|
||||
{
|
||||
if (!(--last_emb->nested_join->counter))
|
||||
join->cur_embedding_map&= ~last_emb->nested_join->nj_map;
|
||||
else if (last_emb->nested_join->join_list.elements-1 ==
|
||||
last_emb->nested_join->counter)
|
||||
{
|
||||
join->cur_embedding_map|= last_emb->nested_join->nj_map;
|
||||
NESTED_JOIN *nest= last_emb->nested_join;
|
||||
DBUG_ASSERT(nest->counter > 0);
|
||||
|
||||
bool was_fully_covered= nest->is_fully_covered();
|
||||
|
||||
if (--nest->counter == 0)
|
||||
join->cur_embedding_map&= ~nest->nj_map;
|
||||
|
||||
if (!was_fully_covered)
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
last_emb= last_emb->embedding;
|
||||
|
||||
join->cur_embedding_map|= nest->nj_map;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user