8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -290,20 +290,34 @@ match_unsorted_outer(Query *root,
290
290
JoinType jointype )
291
291
{
292
292
bool nestjoinOK ;
293
+ bool useallclauses ;
293
294
Path * bestinnerjoin ;
294
295
List * i ;
295
296
296
297
/*
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.)
298
303
*/
299
304
switch (jointype )
300
305
{
301
306
case JOIN_INNER :
302
307
case JOIN_LEFT :
303
308
nestjoinOK = true;
309
+ useallclauses = false;
304
310
break ;
305
- default :
311
+ case JOIN_RIGHT :
312
+ case JOIN_FULL :
306
313
nestjoinOK = 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;
307
321
break ;
308
322
}
309
323
@@ -339,8 +353,8 @@ match_unsorted_outer(Query *root,
339
353
340
354
/*
341
355
* 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
344
358
* innerjoin indexpath.
345
359
*/
346
360
add_path (joinrel , (Path * )
@@ -377,6 +391,8 @@ match_unsorted_outer(Query *root,
377
391
/* Done with this outer path if no chance for a mergejoin */
378
392
if (mergeclauses == NIL )
379
393
continue ;
394
+ if (useallclauses && length (mergeclauses ) != length (mergeclause_list ))
395
+ continue ;
380
396
381
397
/* Compute the required ordering of the inner path */
382
398
innersortkeys = make_pathkeys_for_mergeclauses (root ,
@@ -402,13 +418,14 @@ match_unsorted_outer(Query *root,
402
418
403
419
/*
404
420
* 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
407
424
* innerrel->cheapest_total_path, since we already made a path
408
425
* with it.
409
426
*/
410
427
num_sortkeys = length (innersortkeys );
411
- if (num_sortkeys > 1 )
428
+ if (num_sortkeys > 1 && ! useallclauses )
412
429
trialsortkeys = listCopy (innersortkeys ); /* need modifiable copy */
413
430
else
414
431
trialsortkeys = innersortkeys ; /* won't really truncate */
@@ -503,6 +520,11 @@ match_unsorted_outer(Query *root,
503
520
}
504
521
cheapest_startup_inner = innerpath ;
505
522
}
523
+ /*
524
+ * Don't consider truncated sortkeys if we need all clauses.
525
+ */
526
+ if (useallclauses )
527
+ break ;
506
528
}
507
529
}
508
530
}
@@ -532,8 +554,26 @@ match_unsorted_inner(Query *root,
532
554
List * mergeclause_list ,
533
555
JoinType jointype )
534
556
{
557
+ bool useallclauses ;
535
558
List * i ;
536
559
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
+
537
577
foreach (i , innerrel -> pathlist )
538
578
{
539
579
Path * innerpath = (Path * ) lfirst (i );
@@ -547,8 +587,12 @@ match_unsorted_inner(Query *root,
547
587
mergeclauses = find_mergeclauses_for_pathkeys (root ,
548
588
innerpath -> pathkeys ,
549
589
mergeclause_list );
590
+
591
+ /* Done with this inner path if no chance for a mergejoin */
550
592
if (mergeclauses == NIL )
551
593
continue ;
594
+ if (useallclauses && length (mergeclauses ) != length (mergeclause_list ))
595
+ continue ;
552
596
553
597
/* Compute the required ordering of the outer path */
554
598
outersortkeys = make_pathkeys_for_mergeclauses (root ,
0 commit comments