diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 959c17206c0..589bebef697 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.193 2005/07/02 23:00:41 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.194 2005/07/15 22:02:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -525,34 +525,33 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path) Plan *plan; Plan *subplan; List *uniq_exprs; - int numGroupCols; - AttrNumber *groupColIdx; - int groupColPos; List *newtlist; int nextresno; bool newitems; + int numGroupCols; + AttrNumber *groupColIdx; + int groupColPos; ListCell *l; subplan = create_plan(root, best_path->subpath); + /* Done if we don't need to do any actual unique-ifying */ + if (best_path->umethod == UNIQUE_PATH_NOOP) + return subplan; + /*---------- * As constructed, the subplan has a "flat" tlist containing just the * Vars needed here and at upper levels. The values we are supposed * to unique-ify may be expressions in these variables. We have to - * add any such expressions to the subplan's tlist. We then build - * control information showing which subplan output columns are to be - * examined by the grouping step. (Since we do not remove any - * existing subplan outputs, not all the output columns may be used - * for grouping.) + * add any such expressions to the subplan's tlist. * - * Note: the reason we don't remove any subplan outputs is that there - * are scenarios where a Var is needed at higher levels even though - * it is not one of the nominal outputs of an IN clause. Consider - * WHERE x IN (SELECT y FROM t1,t2 WHERE y = z) - * Implied equality deduction will generate an "x = z" clause, which may - * get used instead of "x = y" in the upper join step. Therefore the - * sub-select had better deliver both y and z in its targetlist. - * It is sufficient to unique-ify on y, however. + * The subplan may have a "physical" tlist if it is a simple scan plan. + * This should be left as-is if we don't need to add any expressions; + * but if we do have to add expressions, then a projection step will be + * needed at runtime anyway, and so we may as well remove unneeded items. + * Therefore newtlist starts from build_relation_tlist() not just a + * copy of the subplan's tlist; and we don't install it into the subplan + * unless stuff has to be added. * * To find the correct list of values to unique-ify, we look in the * information saved for IN expressions. If this code is ever used in @@ -574,12 +573,8 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path) if (l == NULL) /* fell out of loop? */ elog(ERROR, "could not find UniquePath in in_info_list"); - /* set up to record positions of unique columns */ - numGroupCols = list_length(uniq_exprs); - groupColIdx = (AttrNumber *) palloc(numGroupCols * sizeof(AttrNumber)); - groupColPos = 0; - /* not sure if tlist might be shared with other nodes, so copy */ - newtlist = copyObject(subplan->targetlist); + /* initialize modified subplan tlist as just the "required" vars */ + newtlist = build_relation_tlist(best_path->path.parent); nextresno = list_length(newtlist) + 1; newitems = false; @@ -599,7 +594,6 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path) nextresno++; newitems = true; } - groupColIdx[groupColPos++] = tle->resno; } if (newitems) @@ -614,9 +608,27 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path) subplan->targetlist = newtlist; } - /* Done if we don't need to do any actual unique-ifying */ - if (best_path->umethod == UNIQUE_PATH_NOOP) - return subplan; + /* + * Build control information showing which subplan output columns are + * to be examined by the grouping step. Unfortunately we can't merge this + * with the previous loop, since we didn't then know which version of the + * subplan tlist we'd end up using. + */ + newtlist = subplan->targetlist; + numGroupCols = list_length(uniq_exprs); + groupColIdx = (AttrNumber *) palloc(numGroupCols * sizeof(AttrNumber)); + groupColPos = 0; + + foreach(l, uniq_exprs) + { + Node *uniqexpr = lfirst(l); + TargetEntry *tle; + + tle = tlist_member(uniqexpr, newtlist); + if (!tle) /* shouldn't happen */ + elog(ERROR, "failed to find unique expression in subplan tlist"); + groupColIdx[groupColPos++] = tle->resno; + } if (best_path->umethod == UNIQUE_PATH_HASH) { @@ -624,8 +636,13 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path) numGroups = (long) Min(best_path->rows, (double) LONG_MAX); + /* + * Since the Agg node is going to project anyway, we can give it + * the minimum output tlist, without any stuff we might have added + * to the subplan tlist. + */ plan = (Plan *) make_agg(root, - copyObject(subplan->targetlist), + build_relation_tlist(best_path->path.parent), NIL, AGG_HASHED, numGroupCols,