diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index e2c20ded90..7079b6ac3f 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -621,6 +621,10 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, { SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l); + /* ignore full joins --- their ordering is predetermined */ + if (sjinfo->jointype == JOIN_FULL) + continue; + if (bms_overlap(sjinfo->min_lefthand, join_plus_rhs) && !bms_is_subset(sjinfo->min_righthand, join_plus_rhs)) { @@ -628,15 +632,6 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, sjinfo->min_righthand); more = true; } - /* full joins constrain both sides symmetrically */ - if (sjinfo->jointype == JOIN_FULL && - bms_overlap(sjinfo->min_righthand, join_plus_rhs) && - !bms_is_subset(sjinfo->min_lefthand, join_plus_rhs)) - { - join_plus_rhs = bms_add_members(join_plus_rhs, - sjinfo->min_lefthand); - more = true; - } } } while (more); if (bms_overlap(join_plus_rhs, join_lateral_rels)) diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out index 34ca0ef890..36a5929113 100644 --- a/src/test/regress/expected/rangefuncs.out +++ b/src/test/regress/expected/rangefuncs.out @@ -1391,6 +1391,31 @@ SELECT * FROM (VALUES (1),(2),(3)) v1(r1), 3 | 3 | 30 | 8 (45 rows) +-- check handling of FULL JOIN with multiple lateral references (bug #15741) +SELECT * +FROM (VALUES (1),(2)) v1(r1) + LEFT JOIN LATERAL ( + SELECT * + FROM generate_series(1, v1.r1) AS gs1 + LEFT JOIN LATERAL ( + SELECT * + FROM generate_series(1, gs1) AS gs2 + LEFT JOIN generate_series(1, gs2) AS gs3 ON TRUE + ) AS ss1 ON TRUE + FULL JOIN generate_series(1, v1.r1) AS gs4 ON FALSE + ) AS ss0 ON TRUE; + r1 | gs1 | gs2 | gs3 | gs4 +----+-----+-----+-----+----- + 1 | | | | 1 + 1 | 1 | 1 | 1 | + 2 | | | | 1 + 2 | | | | 2 + 2 | 1 | 1 | 1 | + 2 | 2 | 1 | 1 | + 2 | 2 | 2 | 1 | + 2 | 2 | 2 | 2 | +(8 rows) + DROP FUNCTION rngfunc_sql(int,int); DROP FUNCTION rngfunc_mat(int,int); DROP SEQUENCE rngfunc_rescan_seq1; diff --git a/src/test/regress/sql/rangefuncs.sql b/src/test/regress/sql/rangefuncs.sql index fc8ad9a158..5d29d2e401 100644 --- a/src/test/regress/sql/rangefuncs.sql +++ b/src/test/regress/sql/rangefuncs.sql @@ -319,6 +319,21 @@ SELECT * FROM (VALUES (1),(2),(3)) v1(r1), LATERAL (SELECT r1, * FROM (VALUES (10),(20),(30)) v2(r2) LEFT JOIN generate_series(r1,2+r2/5) f(i) ON ((r2+i)<100) OFFSET 0) s1; +-- check handling of FULL JOIN with multiple lateral references (bug #15741) + +SELECT * +FROM (VALUES (1),(2)) v1(r1) + LEFT JOIN LATERAL ( + SELECT * + FROM generate_series(1, v1.r1) AS gs1 + LEFT JOIN LATERAL ( + SELECT * + FROM generate_series(1, gs1) AS gs2 + LEFT JOIN generate_series(1, gs2) AS gs3 ON TRUE + ) AS ss1 ON TRUE + FULL JOIN generate_series(1, v1.r1) AS gs4 ON FALSE + ) AS ss0 ON TRUE; + DROP FUNCTION rngfunc_sql(int,int); DROP FUNCTION rngfunc_mat(int,int); DROP SEQUENCE rngfunc_rescan_seq1;