aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-04-06 18:46:25 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-04-06 18:46:25 +0000
commit2fde46613503cb72cf2937835d8d078b16e24a16 (patch)
tree421ede4d93740658b04e2a8f1ece56ea912942cb
parent79d48449d703bbca6fa90d2857190ba4b5e46624 (diff)
downloadpostgresql-2fde46613503cb72cf2937835d8d078b16e24a16.tar.gz
postgresql-2fde46613503cb72cf2937835d8d078b16e24a16.zip
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.
-rw-r--r--src/backend/optimizer/path/costsize.c36
-rw-r--r--src/backend/optimizer/path/joinpath.c24
2 files changed, 43 insertions, 17 deletions
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 4b500bc03a5..c151ddd5f16 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -49,7 +49,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.115.2.1 2003/12/03 17:45:36 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.115.2.2 2004/04/06 18:46:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -928,23 +928,31 @@ cost_mergejoin(MergePath *path, Query *root)
* all mergejoin paths associated with the merge clause, we cache the
* results in the RestrictInfo node.
*/
- firstclause = (RestrictInfo *) lfirst(mergeclauses);
- if (firstclause->left_mergescansel < 0) /* not computed yet? */
- mergejoinscansel(root, (Node *) firstclause->clause,
- &firstclause->left_mergescansel,
- &firstclause->right_mergescansel);
-
- if (bms_is_subset(firstclause->left_relids, outer_path->parent->relids))
+ if (mergeclauses)
{
- /* left side of clause is outer */
- outerscansel = firstclause->left_mergescansel;
- innerscansel = firstclause->right_mergescansel;
+ firstclause = (RestrictInfo *) lfirst(mergeclauses);
+ if (firstclause->left_mergescansel < 0) /* not computed yet? */
+ mergejoinscansel(root, (Node *) firstclause->clause,
+ &firstclause->left_mergescansel,
+ &firstclause->right_mergescansel);
+
+ if (bms_is_subset(firstclause->left_relids, outer_path->parent->relids))
+ {
+ /* left side of clause is outer */
+ outerscansel = firstclause->left_mergescansel;
+ innerscansel = firstclause->right_mergescansel;
+ }
+ else
+ {
+ /* left side of clause is inner */
+ outerscansel = firstclause->right_mergescansel;
+ innerscansel = firstclause->left_mergescansel;
+ }
}
else
{
- /* left side of clause is inner */
- outerscansel = firstclause->right_mergescansel;
- innerscansel = firstclause->left_mergescansel;
+ /* cope with clauseless mergejoin */
+ outerscansel = innerscansel = 1.0;
}
/* convert selectivity to row count; must scan at least one row */
diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index 174c83cd211..956dd991cd6 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.82 2003/09/25 06:58:00 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.82.2.1 2004/04/06 18:46:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -489,9 +489,27 @@ match_unsorted_outer(Query *root,
outerpath->pathkeys,
mergeclause_list);
- /* Done with this outer path if no chance for a mergejoin */
+ /*
+ * Done with this outer path if no chance for a mergejoin.
+ *
+ * Special corner case: for "x FULL JOIN y ON true", there will be
+ * no join clauses at all. Ordinarily we'd generate a clauseless
+ * nestloop path, but since mergejoin is our only join type that
+ * supports FULL JOIN, it's necessary to generate a clauseless
+ * mergejoin path instead.
+ *
+ * Unfortunately this can't easily be extended to handle the case
+ * where there are joinclauses but none of them use mergejoinable
+ * operators; nodeMergejoin.c can only do a full join correctly if
+ * all the joinclauses are mergeclauses.
+ */
if (mergeclauses == NIL)
- continue;
+ {
+ if (jointype == JOIN_FULL && restrictlist == NIL)
+ /* okay to try for mergejoin */ ;
+ else
+ continue;
+ }
if (useallclauses && length(mergeclauses) != length(mergeclause_list))
continue;