diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 8 | ||||
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 38 | ||||
-rw-r--r-- | src/backend/optimizer/prep/preptlist.c | 45 | ||||
-rw-r--r-- | src/backend/optimizer/util/tlist.c | 26 |
4 files changed, 97 insertions, 20 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 50d93942ec8..a55d444a8b3 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.50 1999/05/10 00:45:20 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.51 1999/05/12 15:01:37 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -260,7 +260,8 @@ union_planner(Query *parse) * belong to?) */ check_having_for_ungrouped_vars(parse->havingQual, - parse->groupClause); + parse->groupClause, + parse->targetList); } /* Calculate the opfids from the opnos */ @@ -426,8 +427,7 @@ make_subplanTargetList(Query *parse, GroupClause *grpcl = (GroupClause *) lfirst(gl); keyno++; /* sort key # for this GroupClause */ - /* Is it safe to use just resno to match tlist and glist items?? */ - if (grpcl->entry->resdom->resno == resdom->resno) + if (grpcl->tleGroupref == resdom->resgroupref) { /* Found a matching groupclause; record info for sorting */ foundGroupClause = true; diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index cf3c3edfc1f..ee3250080ce 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.45 1999/05/06 23:07:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.46 1999/05/12 15:01:39 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -961,7 +961,8 @@ del_agg_clause(Node *clause) */ void -check_having_for_ungrouped_vars(Node *clause, List *groupClause) +check_having_for_ungrouped_vars(Node *clause, List *groupClause, + List *targetList) { List *t; @@ -981,7 +982,7 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause) else if (IsA(clause, Iter)) { check_having_for_ungrouped_vars(((Iter *) clause)->iterexpr, - groupClause); + groupClause, targetList); } else if (is_subplan(clause)) { @@ -997,7 +998,8 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause) foreach(gl, groupClause) { if (var_equal(lfirst(t), - get_expr(((GroupClause *) lfirst(gl))->entry))) + get_groupclause_expr((GroupClause *) + lfirst(gl), targetList))) { contained_in_group_clause = true; break; @@ -1016,7 +1018,8 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause) * subplan is a kind of Expr node. */ foreach(t, ((Expr *) clause)->args) - check_having_for_ungrouped_vars(lfirst(t), groupClause); + check_having_for_ungrouped_vars(lfirst(t), groupClause, + targetList); } else if (IsA(clause, List)) { @@ -1024,12 +1027,13 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause) * Recursively scan AND subclauses (see NOTE above). */ foreach(t, ((List *) clause)) - check_having_for_ungrouped_vars(lfirst(t), groupClause); + check_having_for_ungrouped_vars(lfirst(t), groupClause, + targetList); } else if (IsA(clause, Aggref)) { check_having_for_ungrouped_vars(((Aggref *) clause)->target, - groupClause); + groupClause, targetList); } else if (IsA(clause, ArrayRef)) { @@ -1040,22 +1044,28 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause) * expression and its index expression... */ foreach(t, aref->refupperindexpr) - check_having_for_ungrouped_vars(lfirst(t), groupClause); + check_having_for_ungrouped_vars(lfirst(t), groupClause, + targetList); foreach(t, aref->reflowerindexpr) - check_having_for_ungrouped_vars(lfirst(t), groupClause); - check_having_for_ungrouped_vars(aref->refexpr, groupClause); - check_having_for_ungrouped_vars(aref->refassgnexpr, groupClause); + check_having_for_ungrouped_vars(lfirst(t), groupClause, + targetList); + check_having_for_ungrouped_vars(aref->refexpr, groupClause, + targetList); + check_having_for_ungrouped_vars(aref->refassgnexpr, groupClause, + targetList); } else if (case_clause(clause)) { foreach(t, ((CaseExpr *) clause)->args) { CaseWhen *when = (CaseWhen *) lfirst(t); - check_having_for_ungrouped_vars(when->expr, groupClause); - check_having_for_ungrouped_vars(when->result, groupClause); + check_having_for_ungrouped_vars(when->expr, groupClause, + targetList); + check_having_for_ungrouped_vars(when->result, groupClause, + targetList); } check_having_for_ungrouped_vars(((CaseExpr *) clause)->defresult, - groupClause); + groupClause, targetList); } else { diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index 084809c9d9e..5b70b368ca9 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.18 1999/02/13 23:16:38 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.19 1999/05/12 15:01:41 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -229,6 +229,49 @@ replace_matching_resname(List *new_tlist, List *old_tlist) new_tl = makeTargetEntry(newresno, old_tle->expr); t_list = lappend(t_list, new_tl); } + + /* + * Also it is possible that the parser or rewriter added + * some junk attributes to hold GROUP BY expressions which + * are not part of the result attributes. + * We can simply identify them by looking at the resgroupref + * in the TLE's resdom, which is a unique number telling which + * TLE belongs to which GroupClause. + */ + if (old_tle->resdom->resgroupref > 0) + { + bool already_there = FALSE; + TargetEntry *new_tle; + Resdom *newresno; + + /* + * Check if the tle is already in the new list + */ + foreach(i, t_list) + { + new_tle = (TargetEntry *)lfirst(i); + + if (new_tle->resdom->resgroupref == + old_tle->resdom->resgroupref) + { + already_there = TRUE; + break; + } + + } + + /* + * If not, add it and make sure it is now a junk attribute + */ + if (!already_there) + { + newresno = (Resdom *) copyObject((Node *) old_tle->resdom); + newresno->resno = length(t_list) + 1; + newresno->resjunk = 1; + new_tl = makeTargetEntry(newresno, old_tle->expr); + t_list = lappend(t_list, new_tl); + } + } } return t_list; diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index 6d25950bca0..a914930cc93 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.29 1999/05/06 23:07:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.30 1999/05/12 15:01:44 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -518,6 +518,25 @@ get_expr(TargetEntry *tle) } +Var * +get_groupclause_expr(GroupClause *groupClause, List *targetList) +{ + List *l; + TargetEntry *tle; + + foreach(l, targetList) + { + tle = (TargetEntry *)lfirst(l); + if (tle->resdom->resgroupref == groupClause->tleGroupref) + return get_expr(tle); + } + + elog(ERROR, + "get_groupclause_expr: GROUP BY expression not found in targetlist"); + return NULL; +} + + /***************************************************************************** * *****************************************************************************/ @@ -528,6 +547,11 @@ get_expr(TargetEntry *tle) * in there. */ #ifdef NOT_USED +/* + * WARNING!!! If this ever get's used again, the new reference + * mechanism from group clause to targetlist entry must be implemented + * here too. Jan + */ void AddGroupAttrToTlist(List *tlist, List *grpCl) { |