Skip to content

Commit e517086

Browse files
committed
Support FULL JOIN with no join clauses, such as X FULL JOIN Y ON TRUE.
That particular corner case is not exactly compelling, but given 7.4's ability to discard redundant join clauses, it is possible for the situation to arise from queries that are not so obviously silly. Per bug report of 6-Apr-04.
1 parent 2098ec6 commit e517086

File tree

2 files changed

+43
-17
lines changed

2 files changed

+43
-17
lines changed

src/backend/optimizer/path/costsize.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
* Portions Copyright (c) 1994, Regents of the University of California
5050
*
5151
* IDENTIFICATION
52-
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.125 2004/02/17 00:52:53 tgl Exp $
52+
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.126 2004/04/06 18:46:03 tgl Exp $
5353
*
5454
*-------------------------------------------------------------------------
5555
*/
@@ -918,23 +918,31 @@ cost_mergejoin(MergePath *path, Query *root)
918918
* all mergejoin paths associated with the merge clause, we cache the
919919
* results in the RestrictInfo node.
920920
*/
921-
firstclause = (RestrictInfo *) lfirst(mergeclauses);
922-
if (firstclause->left_mergescansel < 0) /* not computed yet? */
923-
mergejoinscansel(root, (Node *) firstclause->clause,
924-
&firstclause->left_mergescansel,
925-
&firstclause->right_mergescansel);
926-
927-
if (bms_is_subset(firstclause->left_relids, outer_path->parent->relids))
921+
if (mergeclauses)
928922
{
929-
/* left side of clause is outer */
930-
outerscansel = firstclause->left_mergescansel;
931-
innerscansel = firstclause->right_mergescansel;
923+
firstclause = (RestrictInfo *) lfirst(mergeclauses);
924+
if (firstclause->left_mergescansel < 0) /* not computed yet? */
925+
mergejoinscansel(root, (Node *) firstclause->clause,
926+
&firstclause->left_mergescansel,
927+
&firstclause->right_mergescansel);
928+
929+
if (bms_is_subset(firstclause->left_relids, outer_path->parent->relids))
930+
{
931+
/* left side of clause is outer */
932+
outerscansel = firstclause->left_mergescansel;
933+
innerscansel = firstclause->right_mergescansel;
934+
}
935+
else
936+
{
937+
/* left side of clause is inner */
938+
outerscansel = firstclause->right_mergescansel;
939+
innerscansel = firstclause->left_mergescansel;
940+
}
932941
}
933942
else
934943
{
935-
/* left side of clause is inner */
936-
outerscansel = firstclause->right_mergescansel;
937-
innerscansel = firstclause->left_mergescansel;
944+
/* cope with clauseless mergejoin */
945+
outerscansel = innerscansel = 1.0;
938946
}
939947

940948
/* convert selectivity to row count; must scan at least one row */

src/backend/optimizer/path/joinpath.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.85 2004/01/05 05:07:35 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.86 2004/04/06 18:46:03 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -489,9 +489,27 @@ match_unsorted_outer(Query *root,
489489
outerpath->pathkeys,
490490
mergeclause_list);
491491

492-
/* Done with this outer path if no chance for a mergejoin */
492+
/*
493+
* Done with this outer path if no chance for a mergejoin.
494+
*
495+
* Special corner case: for "x FULL JOIN y ON true", there will be
496+
* no join clauses at all. Ordinarily we'd generate a clauseless
497+
* nestloop path, but since mergejoin is our only join type that
498+
* supports FULL JOIN, it's necessary to generate a clauseless
499+
* mergejoin path instead.
500+
*
501+
* Unfortunately this can't easily be extended to handle the case
502+
* where there are joinclauses but none of them use mergejoinable
503+
* operators; nodeMergejoin.c can only do a full join correctly if
504+
* all the joinclauses are mergeclauses.
505+
*/
493506
if (mergeclauses == NIL)
494-
continue;
507+
{
508+
if (jointype == JOIN_FULL && restrictlist == NIL)
509+
/* okay to try for mergejoin */ ;
510+
else
511+
continue;
512+
}
495513
if (useallclauses && length(mergeclauses) != length(mergeclause_list))
496514
continue;
497515

0 commit comments

Comments
 (0)