10
10
*
11
11
*
12
12
* IDENTIFICATION
13
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.193 2005/07/02 23:00:41 tgl Exp $
13
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.194 2005/07/15 22:02:51 tgl Exp $
14
14
*
15
15
*-------------------------------------------------------------------------
16
16
*/
@@ -525,34 +525,33 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path)
525
525
Plan * plan ;
526
526
Plan * subplan ;
527
527
List * uniq_exprs ;
528
- int numGroupCols ;
529
- AttrNumber * groupColIdx ;
530
- int groupColPos ;
531
528
List * newtlist ;
532
529
int nextresno ;
533
530
bool newitems ;
531
+ int numGroupCols ;
532
+ AttrNumber * groupColIdx ;
533
+ int groupColPos ;
534
534
ListCell * l ;
535
535
536
536
subplan = create_plan (root , best_path -> subpath );
537
537
538
+ /* Done if we don't need to do any actual unique-ifying */
539
+ if (best_path -> umethod == UNIQUE_PATH_NOOP )
540
+ return subplan ;
541
+
538
542
/*----------
539
543
* As constructed, the subplan has a "flat" tlist containing just the
540
544
* Vars needed here and at upper levels. The values we are supposed
541
545
* to unique-ify may be expressions in these variables. We have to
542
- * add any such expressions to the subplan's tlist. We then build
543
- * control information showing which subplan output columns are to be
544
- * examined by the grouping step. (Since we do not remove any
545
- * existing subplan outputs, not all the output columns may be used
546
- * for grouping.)
546
+ * add any such expressions to the subplan's tlist.
547
547
*
548
- * Note: the reason we don't remove any subplan outputs is that there
549
- * are scenarios where a Var is needed at higher levels even though
550
- * it is not one of the nominal outputs of an IN clause. Consider
551
- * WHERE x IN (SELECT y FROM t1,t2 WHERE y = z)
552
- * Implied equality deduction will generate an "x = z" clause, which may
553
- * get used instead of "x = y" in the upper join step. Therefore the
554
- * sub-select had better deliver both y and z in its targetlist.
555
- * It is sufficient to unique-ify on y, however.
548
+ * The subplan may have a "physical" tlist if it is a simple scan plan.
549
+ * This should be left as-is if we don't need to add any expressions;
550
+ * but if we do have to add expressions, then a projection step will be
551
+ * needed at runtime anyway, and so we may as well remove unneeded items.
552
+ * Therefore newtlist starts from build_relation_tlist() not just a
553
+ * copy of the subplan's tlist; and we don't install it into the subplan
554
+ * unless stuff has to be added.
556
555
*
557
556
* To find the correct list of values to unique-ify, we look in the
558
557
* information saved for IN expressions. If this code is ever used in
@@ -574,12 +573,8 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path)
574
573
if (l == NULL ) /* fell out of loop? */
575
574
elog (ERROR , "could not find UniquePath in in_info_list" );
576
575
577
- /* set up to record positions of unique columns */
578
- numGroupCols = list_length (uniq_exprs );
579
- groupColIdx = (AttrNumber * ) palloc (numGroupCols * sizeof (AttrNumber ));
580
- groupColPos = 0 ;
581
- /* not sure if tlist might be shared with other nodes, so copy */
582
- newtlist = copyObject (subplan -> targetlist );
576
+ /* initialize modified subplan tlist as just the "required" vars */
577
+ newtlist = build_relation_tlist (best_path -> path .parent );
583
578
nextresno = list_length (newtlist ) + 1 ;
584
579
newitems = false;
585
580
@@ -599,7 +594,6 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path)
599
594
nextresno ++ ;
600
595
newitems = true;
601
596
}
602
- groupColIdx [groupColPos ++ ] = tle -> resno ;
603
597
}
604
598
605
599
if (newitems )
@@ -614,18 +608,41 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path)
614
608
subplan -> targetlist = newtlist ;
615
609
}
616
610
617
- /* Done if we don't need to do any actual unique-ifying */
618
- if (best_path -> umethod == UNIQUE_PATH_NOOP )
619
- return subplan ;
611
+ /*
612
+ * Build control information showing which subplan output columns are
613
+ * to be examined by the grouping step. Unfortunately we can't merge this
614
+ * with the previous loop, since we didn't then know which version of the
615
+ * subplan tlist we'd end up using.
616
+ */
617
+ newtlist = subplan -> targetlist ;
618
+ numGroupCols = list_length (uniq_exprs );
619
+ groupColIdx = (AttrNumber * ) palloc (numGroupCols * sizeof (AttrNumber ));
620
+ groupColPos = 0 ;
621
+
622
+ foreach (l , uniq_exprs )
623
+ {
624
+ Node * uniqexpr = lfirst (l );
625
+ TargetEntry * tle ;
626
+
627
+ tle = tlist_member (uniqexpr , newtlist );
628
+ if (!tle ) /* shouldn't happen */
629
+ elog (ERROR , "failed to find unique expression in subplan tlist" );
630
+ groupColIdx [groupColPos ++ ] = tle -> resno ;
631
+ }
620
632
621
633
if (best_path -> umethod == UNIQUE_PATH_HASH )
622
634
{
623
635
long numGroups ;
624
636
625
637
numGroups = (long ) Min (best_path -> rows , (double ) LONG_MAX );
626
638
639
+ /*
640
+ * Since the Agg node is going to project anyway, we can give it
641
+ * the minimum output tlist, without any stuff we might have added
642
+ * to the subplan tlist.
643
+ */
627
644
plan = (Plan * ) make_agg (root ,
628
- copyObject ( subplan -> targetlist ),
645
+ build_relation_tlist ( best_path -> path . parent ),
629
646
NIL ,
630
647
AGG_HASHED ,
631
648
numGroupCols ,
0 commit comments