88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.62 2001/03/22 03:59:35 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.63 2001/04/15 00:48:17 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -290,20 +290,34 @@ match_unsorted_outer(Query *root,
290290JoinType jointype )
291291{
292292bool nestjoinOK ;
293+ bool useallclauses ;
293294Path * bestinnerjoin ;
294295List * i ;
295296
296297/*
297- * Nestloop only supports inner and left joins.
298+ * Nestloop only supports inner and left joins. Also, if we are doing
299+ * a right or full join, we must use *all* the mergeclauses as join
300+ * clauses, else we will not have a valid plan. (Although these two flags
301+ * are currently inverses, keep them separate for clarity and possible
302+ * future changes.)
298303 */
299304switch (jointype )
300305{
301306case JOIN_INNER :
302307case JOIN_LEFT :
303308nestjoinOK = true;
309+ useallclauses = false;
304310break ;
305- default :
311+ case JOIN_RIGHT :
312+ case JOIN_FULL :
306313nestjoinOK = false;
314+ useallclauses = true;
315+ break ;
316+ default :
317+ elog (ERROR ,"match_unsorted_outer: unexpected join type %d" ,
318+ (int )jointype );
319+ nestjoinOK = false;/* keep compiler quiet */
320+ useallclauses = false;
307321break ;
308322}
309323
@@ -339,8 +353,8 @@ match_unsorted_outer(Query *root,
339353
340354/*
341355 * Always consider a nestloop join with this outer and
342- * cheapest- total-cost inner.Consider nestloops using the
343- * cheapest- startup-cost inner as well, and the best
356+ * cheapest-total-cost inner.Consider nestloops using the
357+ * cheapest-startup-cost inner as well, and the best
344358 * innerjoin indexpath.
345359 */
346360add_path (joinrel , (Path * )
@@ -377,6 +391,8 @@ match_unsorted_outer(Query *root,
377391/* Done with this outer path if no chance for a mergejoin */
378392if (mergeclauses == NIL )
379393continue ;
394+ if (useallclauses && length (mergeclauses )!= length (mergeclause_list ))
395+ continue ;
380396
381397/* Compute the required ordering of the inner path */
382398innersortkeys = make_pathkeys_for_mergeclauses (root ,
@@ -402,13 +418,14 @@ match_unsorted_outer(Query *root,
402418
403419/*
404420 * Look for presorted inner paths that satisfy the innersortkey
405- * list or any truncation thereof.Here, we consider both cheap
406- * startup cost and cheap total cost. Ignore
421+ * list --- or any truncation thereof, if we are allowed to build
422+ * a mergejoin using a subset of the merge clauses. Here, we
423+ * consider both cheap startup cost and cheap total cost. Ignore
407424 * innerrel->cheapest_total_path, since we already made a path
408425 * with it.
409426 */
410427num_sortkeys = length (innersortkeys );
411- if (num_sortkeys > 1 )
428+ if (num_sortkeys > 1 && ! useallclauses )
412429trialsortkeys = listCopy (innersortkeys );/* need modifiable copy */
413430else
414431trialsortkeys = innersortkeys ;/* won't really truncate */
@@ -503,6 +520,11 @@ match_unsorted_outer(Query *root,
503520}
504521cheapest_startup_inner = innerpath ;
505522}
523+ /*
524+ * Don't consider truncated sortkeys if we need all clauses.
525+ */
526+ if (useallclauses )
527+ break ;
506528}
507529}
508530}
@@ -532,8 +554,26 @@ match_unsorted_inner(Query *root,
532554List * mergeclause_list ,
533555JoinType jointype )
534556{
557+ bool useallclauses ;
535558List * i ;
536559
560+ switch (jointype )
561+ {
562+ case JOIN_INNER :
563+ case JOIN_LEFT :
564+ useallclauses = false;
565+ break ;
566+ case JOIN_RIGHT :
567+ case JOIN_FULL :
568+ useallclauses = true;
569+ break ;
570+ default :
571+ elog (ERROR ,"match_unsorted_inner: unexpected join type %d" ,
572+ (int )jointype );
573+ useallclauses = false;/* keep compiler quiet */
574+ break ;
575+ }
576+
537577foreach (i ,innerrel -> pathlist )
538578{
539579Path * innerpath = (Path * )lfirst (i );
@@ -547,8 +587,12 @@ match_unsorted_inner(Query *root,
547587mergeclauses = find_mergeclauses_for_pathkeys (root ,
548588innerpath -> pathkeys ,
549589mergeclause_list );
590+
591+ /* Done with this inner path if no chance for a mergejoin */
550592if (mergeclauses == NIL )
551593continue ;
594+ if (useallclauses && length (mergeclauses )!= length (mergeclause_list ))
595+ continue ;
552596
553597/* Compute the required ordering of the outer path */
554598outersortkeys = make_pathkeys_for_mergeclauses (root ,