mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-01 22:01:22 +02:00
Make reduce_outer_joins() smarter about semijoins.
reduce_outer_joins() mistakenly treated a semijoin like a left join for purposes of deciding whether not-null constraints created by the join's quals could be passed down into the join's left-hand side (possibly resulting in outer-join simplification there). Actually, semijoin works like inner join for this purpose, ie, we do not need to see any rows that can't possibly satisfy the quals. Hence, two-line fix to treat semi and inner joins alike. Per observation by Andres Freund about a performance gripe from Yazan Suleiman. Back-patch to 8.4, since this oversight has been there since the current handling of semijoins was implemented.
This commit is contained in:
parent
507069de6d
commit
9688c4e6f1
@ -1840,6 +1840,11 @@ reduce_outer_joins_pass2(Node *jtnode,
|
|||||||
* is that we pass either the local or the upper constraints,
|
* is that we pass either the local or the upper constraints,
|
||||||
* never both, to the children of an outer join.
|
* never both, to the children of an outer join.
|
||||||
*
|
*
|
||||||
|
* Note that a SEMI join works like an inner join here: it's okay
|
||||||
|
* to pass down both local and upper constraints. (There can't
|
||||||
|
* be any upper constraints affecting its inner side, but it's
|
||||||
|
* not worth having a separate code path to avoid passing them.)
|
||||||
|
*
|
||||||
* At a FULL join we just punt and pass nothing down --- is it
|
* At a FULL join we just punt and pass nothing down --- is it
|
||||||
* possible to be smarter?
|
* possible to be smarter?
|
||||||
*/
|
*/
|
||||||
@ -1849,7 +1854,7 @@ reduce_outer_joins_pass2(Node *jtnode,
|
|||||||
if (!computed_local_nonnullable_vars)
|
if (!computed_local_nonnullable_vars)
|
||||||
local_nonnullable_vars = find_nonnullable_vars(j->quals);
|
local_nonnullable_vars = find_nonnullable_vars(j->quals);
|
||||||
local_forced_null_vars = find_forced_null_vars(j->quals);
|
local_forced_null_vars = find_forced_null_vars(j->quals);
|
||||||
if (jointype == JOIN_INNER)
|
if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
|
||||||
{
|
{
|
||||||
/* OK to merge upper and local constraints */
|
/* OK to merge upper and local constraints */
|
||||||
local_nonnullable_rels = bms_add_members(local_nonnullable_rels,
|
local_nonnullable_rels = bms_add_members(local_nonnullable_rels,
|
||||||
@ -1869,14 +1874,14 @@ reduce_outer_joins_pass2(Node *jtnode,
|
|||||||
|
|
||||||
if (left_state->contains_outer)
|
if (left_state->contains_outer)
|
||||||
{
|
{
|
||||||
if (jointype == JOIN_INNER)
|
if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
|
||||||
{
|
{
|
||||||
/* pass union of local and upper constraints */
|
/* pass union of local and upper constraints */
|
||||||
pass_nonnullable_rels = local_nonnullable_rels;
|
pass_nonnullable_rels = local_nonnullable_rels;
|
||||||
pass_nonnullable_vars = local_nonnullable_vars;
|
pass_nonnullable_vars = local_nonnullable_vars;
|
||||||
pass_forced_null_vars = local_forced_null_vars;
|
pass_forced_null_vars = local_forced_null_vars;
|
||||||
}
|
}
|
||||||
else if (jointype != JOIN_FULL) /* ie, LEFT/SEMI/ANTI */
|
else if (jointype != JOIN_FULL) /* ie, LEFT or ANTI */
|
||||||
{
|
{
|
||||||
/* can't pass local constraints to non-nullable side */
|
/* can't pass local constraints to non-nullable side */
|
||||||
pass_nonnullable_rels = nonnullable_rels;
|
pass_nonnullable_rels = nonnullable_rels;
|
||||||
|
Loading…
Reference in New Issue
Block a user