* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.125 2004/02/17 00:52:53 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.126 2004/04/06 18:46:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* 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 */
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.85 2004/01/05 05:07:35 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.86 2004/04/06 18:46:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
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;