From 79c2576f775b962c67cac136722c5c7cc98201aa Mon Sep 17 00:00:00 2001 From: Jan Wieck Date: Wed, 12 May 1999 15:02:39 +0000 Subject: [PATCH] Replaced targetlist entry in GroupClause by reference number in Resdom and GroupClause so changing of resno's doesn't confuse the grouping any more. Jan --- src/backend/nodes/copyfuncs.c | 5 +- src/backend/nodes/equalfuncs.c | 4 +- src/backend/nodes/freefuncs.c | 4 +- src/backend/nodes/makefuncs.c | 3 +- src/backend/nodes/outfuncs.c | 18 ++-- src/backend/nodes/readfuncs.c | 13 ++- src/backend/optimizer/plan/planner.c | 8 +- src/backend/optimizer/plan/setrefs.c | 38 +++++---- src/backend/optimizer/prep/preptlist.c | 45 +++++++++- src/backend/optimizer/util/tlist.c | 26 +++++- src/backend/parser/parse_agg.c | 23 +++--- src/backend/parser/parse_clause.c | 18 +++- src/backend/rewrite/rewriteHandler.c | 101 ++--------------------- src/backend/rewrite/rewriteManip.c | 78 ++++++++++------- src/backend/utils/adt/ruleutils.c | 27 ++++-- src/include/nodes/parsenodes.h | 4 +- src/include/nodes/primnodes.h | 4 +- src/include/nodes/relation.h | 3 +- src/include/optimizer/planmain.h | 6 +- src/include/rewrite/rewriteManip.h | 3 +- src/test/regress/expected/opr_sanity.out | 5 +- src/test/regress/sql/opr_sanity.sql | 5 +- 22 files changed, 242 insertions(+), 199 deletions(-) diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 2ff8d499e8..be70ef33fd 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.78 1999/04/27 09:49:36 ishii Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.79 1999/05/12 15:01:31 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -487,8 +487,8 @@ _copyGroupClause(GroupClause *from) { GroupClause *newnode = makeNode(GroupClause); - Node_Copy(from, newnode, entry); newnode->grpOpoid = from->grpOpoid; + newnode->tleGroupref = from->tleGroupref; return newnode; } @@ -589,6 +589,7 @@ _copyResdom(Resdom *from) newnode->resname = pstrdup(from->resname); newnode->reskey = from->reskey; newnode->reskeyop = from->reskeyop; + newnode->resgroupref = from->resgroupref; newnode->resjunk = from->resjunk; return newnode; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index a5d40ef399..45e752f502 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.35 1999/02/18 00:49:14 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.36 1999/05/12 15:01:33 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -48,6 +48,8 @@ _equalResdom(Resdom *a, Resdom *b) return false; if (a->reskey != b->reskey) return false; + if (a->resgroupref != b->resgroupref) + return false; if (a->reskeyop != b->reskeyop) return false; diff --git a/src/backend/nodes/freefuncs.c b/src/backend/nodes/freefuncs.c index c41c5fb431..3c95dcbe22 100644 --- a/src/backend/nodes/freefuncs.c +++ b/src/backend/nodes/freefuncs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.15 1999/03/01 00:10:31 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.16 1999/05/12 15:01:33 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -396,8 +396,6 @@ _freeAgg(Agg *node) static void _freeGroupClause(GroupClause *node) { - freeObject(node->entry); - pfree(node); } diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index efad14195a..fdf689a326 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.13 1999/02/13 23:15:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.14 1999/05/12 15:01:34 wieck Exp $ * * NOTES * Creator functions in POSTGRES 4.2 are generated automatically. Most of @@ -107,6 +107,7 @@ makeResdom(AttrNumber resno, resdom->resname = resname; resdom->reskey = reskey; resdom->reskeyop = reskeyop; + resdom->resgroupref = 0; resdom->resjunk = resjunk; return resdom; } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 07ea3d868a..c0df063ea0 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -5,7 +5,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: outfuncs.c,v 1.80 1999/05/10 00:45:10 momjian Exp $ + * $Id: outfuncs.c,v 1.81 1999/05/12 15:01:34 wieck Exp $ * * NOTES * Every (plan) node in POSTGRES has an associated "out" routine which @@ -255,10 +255,9 @@ _outSortClause(StringInfo str, SortClause *node) static void _outGroupClause(StringInfo str, GroupClause *node) { - appendStringInfo(str, " GROUPCLAUSE :entry "); - _outNode(str, node->entry); - - appendStringInfo(str, " :grpOpoid %u ", node->grpOpoid); + appendStringInfo(str, " GROUPCLAUSE :grpOpoid %u :tleGroupref %d", + node->grpOpoid, + node->tleGroupref); } /* @@ -556,15 +555,18 @@ _outHash(StringInfo str, Hash *node) static void _outResdom(StringInfo str, Resdom *node) { - appendStringInfo(str, " RESDOM :resno %d :restype %u :restypmod %d ", + appendStringInfo(str, " RESDOM :resno %d :restype %u :restypmod %d", node->resno, node->restype, node->restypmod); - appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u :resjunk %d", + appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u", stringStringInfo(node->resname), node->reskey, - node->reskeyop, + node->reskeyop); + + appendStringInfo(str, " :resgroupref %d :resjunk %d", + node->resgroupref, node->resjunk); } diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 3e1dca5a34..0aa0b275fa 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.60 1999/03/01 00:10:31 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.61 1999/05/12 15:01:35 wieck Exp $ * * NOTES * Most of the read functions for plan nodes are tested. (In fact, they @@ -221,13 +221,14 @@ _readGroupClause() local_node = makeNode(GroupClause); - token = lsptok(NULL, &length); /* skip the :entry */ - local_node->entry = nodeRead(true); - token = lsptok(NULL, &length); /* skip :grpOpoid */ token = lsptok(NULL, &length); /* get grpOpoid */ local_node->grpOpoid = strtoul(token, NULL, 10); + token = lsptok(NULL, &length); /* skip :tleGroupref */ + token = lsptok(NULL, &length); /* get tleGroupref */ + local_node->tleGroupref = strtoul(token, NULL, 10); + return local_node; } @@ -744,6 +745,10 @@ _readResdom() token = lsptok(NULL, &length); /* get reskeyop */ local_node->reskeyop = (Oid) atol(token); + token = lsptok(NULL, &length); /* eat :resgroupref */ + token = lsptok(NULL, &length); /* get resgroupref */ + local_node->resgroupref = strtoul(token, NULL, 10); + token = lsptok(NULL, &length); /* eat :resjunk */ token = lsptok(NULL, &length); /* get resjunk */ local_node->resjunk = atoi(token); diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 50d93942ec..a55d444a8b 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 cf3c3edfc1..ee3250080c 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 084809c9d9..5b70b368ca 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 6d25950bca..a914930cc9 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) { diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index 1b2eb21c7c..ab00040c65 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.18 1999/04/29 01:13:13 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.19 1999/05/12 15:01:48 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -32,8 +32,9 @@ #include "utils/lsyscache.h" static bool contain_agg_clause(Node *clause); -static bool exprIsAggOrGroupCol(Node *expr, List *groupClause); -static bool tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause); +static bool exprIsAggOrGroupCol(Node *expr, List *groupClause, List *tlist); +static bool tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause, + List *tlist); /* * contain_agg_clause @@ -100,7 +101,7 @@ contain_agg_clause(Node *clause) * returns true if the expression does not contain non-group columns. */ static bool -exprIsAggOrGroupCol(Node *expr, List *groupClause) +exprIsAggOrGroupCol(Node *expr, List *groupClause, List *tlist) { List *gl; @@ -113,7 +114,7 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause) { GroupClause *grpcl = lfirst(gl); - if (equal(expr, grpcl->entry->expr)) + if (equal(expr, get_groupclause_expr(grpcl, tlist))) return TRUE; } @@ -122,7 +123,7 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause) List *temp; foreach(temp, ((Expr *) expr)->args) - if (!exprIsAggOrGroupCol(lfirst(temp), groupClause)) + if (!exprIsAggOrGroupCol(lfirst(temp), groupClause, tlist)) return FALSE; return TRUE; } @@ -135,7 +136,7 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause) * returns true if the TargetEntry is Agg or GroupCol. */ static bool -tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause) +tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause, List *tlist) { Node *expr = tle->expr; List *gl; @@ -147,7 +148,7 @@ tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause) { GroupClause *grpcl = lfirst(gl); - if (tle->resdom->resno == grpcl->entry->resdom->resno) + if (tle->resdom->resgroupref == grpcl->tleGroupref) { if (contain_agg_clause((Node *) expr)) elog(ERROR, "Aggregates not allowed in GROUP BY clause"); @@ -163,7 +164,7 @@ tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause) List *temp; foreach(temp, ((Expr *) expr)->args) - if (!exprIsAggOrGroupCol(lfirst(temp), groupClause)) + if (!exprIsAggOrGroupCol(lfirst(temp), groupClause, tlist)) return FALSE; return TRUE; } @@ -200,7 +201,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry) { TargetEntry *tle = lfirst(tl); - if (!tleIsAggOrGroupCol(tle, qry->groupClause)) + if (!tleIsAggOrGroupCol(tle, qry->groupClause, qry->targetList)) elog(ERROR, "Illegal use of aggregates or non-group column in target list"); } @@ -210,7 +211,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry) * restriction as those in the target list. */ - if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause)) + if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause, qry->targetList)) elog(ERROR, "Illegal use of aggregates or non-group column in HAVING clause"); return; diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 0085a4781b..61359e3452 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.29 1999/02/23 07:46:42 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.30 1999/05/12 15:01:50 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -550,13 +550,19 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist) restarget = findTargetlistEntry(pstate, lfirst(grouplist), targetlist, GROUP_CLAUSE); - grpcl->entry = restarget; resdom = restarget->resdom; grpcl->grpOpoid = oprid(oper("<", resdom->restype, resdom->restype, false)); if (glist == NIL) + { + int groupref = length(glist) + 1; + + restarget->resdom->resgroupref = groupref; + grpcl->tleGroupref = groupref; + gl = glist = lcons(grpcl, NIL); + } else { List *i; @@ -565,11 +571,17 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist) { GroupClause *gcl = (GroupClause *) lfirst(i); - if (gcl->entry == grpcl->entry) + if (equal(get_groupclause_expr(gcl, targetlist), + restarget->expr)) break; } if (i == NIL) /* not in grouplist already */ { + int groupref = length(glist) + 1; + + restarget->resdom->resgroupref = groupref; + grpcl->tleGroupref = groupref; + lnext(gl) = lcons(grpcl, NIL); gl = lnext(gl); } diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 1ba1a5dd56..654f731080 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.38 1999/05/09 23:31:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.39 1999/05/12 15:01:53 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -170,15 +170,7 @@ rangeTableEntry_used(Node *node, int rt_index, int sublevels_up) break; case T_GroupClause: - { - GroupClause *grp = (GroupClause *)node; - - return rangeTableEntry_used( - (Node *)(grp->entry), - rt_index, - sublevels_up); - } - break; + return FALSE; case T_Expr: { @@ -348,12 +340,6 @@ rangeTableEntry_used(Node *node, int rt_index, int sublevels_up) sublevels_up)) return TRUE; - if (rangeTableEntry_used( - (Node *)(qry->groupClause), - rt_index, - sublevels_up)) - return TRUE; - return FALSE; } break; @@ -407,16 +393,7 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up) break; case T_GroupClause: - { - GroupClause *grp = (GroupClause *)node; - - return attribute_used( - (Node *)(grp->entry), - rt_index, - attno, - sublevels_up); - } - break; + return FALSE; case T_Expr: { @@ -558,13 +535,6 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up) sublevels_up)) return TRUE; - if (attribute_used( - (Node *)(qry->groupClause), - rt_index, - attno, - sublevels_up)) - return TRUE; - return FALSE; } break; @@ -697,8 +667,6 @@ modifyAggrefUplevel(Node *node) modifyAggrefUplevel( (Node *)(qry->havingQual)); - modifyAggrefUplevel( - (Node *)(qry->groupClause)); } break; @@ -752,15 +720,6 @@ modifyAggrefChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int subl break; case T_GroupClause: - { - GroupClause *grp = (GroupClause *)node; - - modifyAggrefChangeVarnodes( - (Node **)(&(grp->entry)), - rt_index, - new_index, - sublevels_up); - } break; case T_Expr: @@ -894,12 +853,6 @@ modifyAggrefChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int subl rt_index, new_index, sublevels_up); - - modifyAggrefChangeVarnodes( - (Node **)(&(qry->groupClause)), - rt_index, - new_index, - sublevels_up); } break; @@ -1186,13 +1139,6 @@ modifyAggrefQual(Node **nodePtr, Query *parsetree) break; case T_GroupClause: - { - GroupClause *grp = (GroupClause *)node; - - modifyAggrefQual( - (Node **)(&(grp->entry)), - parsetree); - } break; case T_Expr: @@ -1386,13 +1332,6 @@ apply_RIR_adjust_sublevel(Node *node, int sublevels_up) break; case T_GroupClause: - { - GroupClause *grp = (GroupClause *)node; - - apply_RIR_adjust_sublevel( - (Node *)(grp->entry), - sublevels_up); - } break; case T_Expr: @@ -1539,17 +1478,6 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in break; case T_GroupClause: - { - GroupClause *grp = (GroupClause *)node; - - apply_RIR_view( - (Node **)(&(grp->entry)), - rt_index, - rte, - tlist, - modified, - sublevels_up); - } break; case T_Expr: @@ -1724,14 +1652,6 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in tlist, modified, sublevels_up); - - apply_RIR_view( - (Node **)(&(qry->groupClause)), - rt_index, - rte, - tlist, - modified, - sublevels_up); } break; @@ -1898,10 +1818,8 @@ ApplyRetrieveRule(Query *parsetree, } if (*modified && !badsql) { AddQual(parsetree, rule_action->qual); - /* This will only work if the query made to the view defined by the following - * groupClause groups by the same attributes or does not use group at all! */ - if (parsetree->groupClause == NULL) - parsetree->groupClause=rule_action->groupClause; + AddGroupClause(parsetree, rule_action->groupClause, + rule_action->targetList); AddHavingQual(parsetree, rule_action->havingQual); parsetree->hasAggs = (rule_action->hasAggs || parsetree->hasAggs); parsetree->hasSubLinks = (rule_action->hasSubLinks || parsetree->hasSubLinks); @@ -1935,12 +1853,6 @@ fireRIRonSubselect(Node *node) break; case T_GroupClause: - { - GroupClause *grp = (GroupClause *)node; - - fireRIRonSubselect( - (Node *)(grp->entry)); - } break; case T_Expr: @@ -2048,9 +1960,6 @@ fireRIRonSubselect(Node *node) fireRIRonSubselect( (Node *)(qry->havingQual)); - - fireRIRonSubselect( - (Node *)(qry->groupClause)); } break; diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 95267241c5..057579669d 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.29 1999/02/13 23:17:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.30 1999/05/12 15:01:55 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -65,14 +65,6 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up) break; case T_GroupClause: - { - GroupClause *grp = (GroupClause *)node; - - OffsetVarNodes( - (Node *)(grp->entry), - offset, - sublevels_up); - } break; case T_Expr: @@ -199,11 +191,6 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up) (Node *)(qry->havingQual), offset, sublevels_up); - - OffsetVarNodes( - (Node *)(qry->groupClause), - offset, - sublevels_up); } break; @@ -284,15 +271,6 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up) break; case T_GroupClause: - { - GroupClause *grp = (GroupClause *)node; - - ChangeVarNodes( - (Node *)(grp->entry), - rt_index, - new_index, - sublevels_up); - } break; case T_Expr: @@ -430,12 +408,6 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up) rt_index, new_index, sublevels_up); - - ChangeVarNodes( - (Node *)(qry->groupClause), - rt_index, - new_index, - sublevels_up); } break; @@ -562,6 +534,44 @@ AddNotQual(Query *parsetree, Node *qual) AddQual(parsetree, copy); } + +void +AddGroupClause(Query *parsetree, List *group_by, List *tlist) +{ + List *l; + List *tl; + GroupClause *groupclause; + TargetEntry *tle; + int new_resno; + + new_resno = length(parsetree->targetList); + + foreach (l, group_by) + { + groupclause = (GroupClause *)copyObject(lfirst(l)); + tle = NULL; + foreach(tl, tlist) + { + if (((TargetEntry *)lfirst(tl))->resdom->resgroupref == + groupclause->tleGroupref) + { + tle = (TargetEntry *)copyObject(lfirst(tl)); + break; + } + } + if (tle == NULL) + elog(ERROR, "AddGroupClause(): GROUP BY entry not found in rules targetlist"); + + tle->resdom->resno = ++new_resno; + tle->resdom->resjunk = true; + tle->resdom->resgroupref = length(parsetree->groupClause) + 1; + groupclause->tleGroupref = tle->resdom->resgroupref; + + parsetree->targetList = lappend(parsetree->targetList, tle); + parsetree->groupClause = lappend(parsetree->groupClause, groupclause); + } +} + static Node * make_null(Oid type) { @@ -688,7 +698,10 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr, *nodePtr = make_null(((Var *) node)->vartype); } else + { *nodePtr = copyObject(n); + ((Var *) *nodePtr)->varlevelsup = this_varlevelsup; + } } break; } @@ -709,6 +722,8 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr, ResolveNew(info, targetlist, (Node **) &(query->qual), sublevels_up + 1); } break; + case T_GroupClause: + break; default: /* ignore the others */ break; @@ -720,7 +735,10 @@ FixNew(RewriteInfo *info, Query *parsetree) { ResolveNew(info, parsetree->targetList, (Node **) &(info->rule_action->targetList), 0); - ResolveNew(info, parsetree->targetList, &info->rule_action->qual, 0); + ResolveNew(info, parsetree->targetList, + (Node **) &info->rule_action->qual, 0); + ResolveNew(info, parsetree->targetList, + (Node **) &(info->rule_action->groupClause), 0); } static void diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 016d835ade..1158fdc7b5 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * out of it's tuple * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.11 1999/05/10 00:45:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.12 1999/05/12 15:01:58 wieck Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -1263,9 +1263,23 @@ get_rule_expr(QryHier *qh, int rt_index, Node *node, bool varprefix) case T_GroupClause: { GroupClause *grp = (GroupClause *) node; + List *l; + TargetEntry *tle = NULL; - return get_rule_expr(qh, rt_index, - (Node *) (grp->entry), varprefix); + foreach(l, qh->query->targetList) + { + if (((TargetEntry *)lfirst(l))->resdom->resgroupref == + grp->tleGroupref) + { + tle = (TargetEntry *)lfirst(l); + break; + } + } + + if (tle == NULL) + elog(ERROR, "GROUP BY expression not found in targetlist"); + + return get_rule_expr(qh, rt_index, (Node *)tle, varprefix); } break; @@ -1738,12 +1752,7 @@ check_if_rte_used(int rt_index, Node *node, int sup) break; case T_GroupClause: - { - GroupClause *grp = (GroupClause *) node; - - return check_if_rte_used(rt_index, - (Node *) (grp->entry), sup); - } + return FALSE; break; case T_Expr: diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index c55a8cf93b..fed516ccfb 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.71 1999/02/23 07:55:24 thomas Exp $ + * $Id: parsenodes.h,v 1.72 1999/05/12 15:02:04 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -960,8 +960,8 @@ typedef struct SortClause typedef struct GroupClause { NodeTag type; - TargetEntry *entry; /* attributes to group on */ Oid grpOpoid; /* the sort operator to use */ + Index tleGroupref; /* reference into targetlist */ } GroupClause; #define ROW_MARK_FOR_UPDATE (1 << 0) diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 981bd61f32..93eafbe72c 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: primnodes.h,v 1.25 1999/02/13 23:21:40 momjian Exp $ + * $Id: primnodes.h,v 1.26 1999/05/12 15:02:07 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -30,6 +30,7 @@ * resname - name of the resdom (could be NULL) * reskey - order of key in a sort (for those > 0) * reskeyop - sort operator Oid + * resgroupref - set to nonzero if referenced from a group by clause * resjunk - set to nonzero to eliminate the attribute * from final target list e.g., ctid for replace * and delete @@ -45,6 +46,7 @@ typedef struct Resdom char *resname; Index reskey; Oid reskeyop; + Index resgroupref; int resjunk; } Resdom; diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index d52960903e..2d47243c40 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: relation.h,v 1.29 1999/02/22 19:55:44 momjian Exp $ + * $Id: relation.h,v 1.30 1999/05/12 15:02:08 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -103,6 +103,7 @@ typedef struct RelOptInfo } RelOptInfo; extern Var *get_expr(TargetEntry *foo); +extern Var *get_groupclause_expr(GroupClause *groupClause, List *targetList); typedef struct MergeOrder { diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index 002238571c..e3848330db 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: planmain.h,v 1.24 1999/05/03 00:38:42 tgl Exp $ + * $Id: planmain.h,v 1.25 1999/05/12 15:02:22 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -62,7 +62,9 @@ extern void replace_vars_with_subplan_refs(Node *clause, List *subplanTargetList); extern bool set_agg_tlist_references(Agg *aggNode); extern void del_agg_tlist_references(List *tlist); -extern void check_having_for_ungrouped_vars(Node *clause, List *groupClause); +extern void check_having_for_ungrouped_vars(Node *clause, + List *groupClause, + List *targetList); extern void transformKeySetQuery(Query *origNode); #endif /* PLANMAIN_H */ diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h index 317dae8ea0..e41a226708 100644 --- a/src/include/rewrite/rewriteManip.h +++ b/src/include/rewrite/rewriteManip.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: rewriteManip.h,v 1.13 1999/02/13 23:22:00 momjian Exp $ + * $Id: rewriteManip.h,v 1.14 1999/05/12 15:02:28 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -26,6 +26,7 @@ void AddHavingQual(Query *parsetree, Node *havingQual); void AddNotQual(Query *parsetree, Node *qual); void AddNotHavingQual(Query *parsetree, Node *havingQual); +void AddGroupClause(Query *parsetree, List *group_by, List *tlist); void FixNew(RewriteInfo *info, Query *parsetree); diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index f626651949..f6b4bc4373 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -1,7 +1,8 @@ QUERY: SELECT p1.oid, p1.proname FROM pg_proc as p1 -WHERE p1.prolang = 0 OR p1.prorettype = 0 OR - p1.pronargs < 0 OR p1.pronargs > 9; +WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR + p1.pronargs < 0 OR p1.pronargs > 9) + AND p1.proname !~ '^pl[^_]+_call_handler$'; oid|proname ---+------- (0 rows) diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index f3d84ebe3d..d6f3b293af 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -25,8 +25,9 @@ SELECT p1.oid, p1.proname FROM pg_proc as p1 -WHERE p1.prolang = 0 OR p1.prorettype = 0 OR - p1.pronargs < 0 OR p1.pronargs > 9; +WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR + p1.pronargs < 0 OR p1.pronargs > 9) + AND p1.proname !~ '^pl[^_]+_call_handler$'; -- Look for conflicting proc definitions (same names and input datatypes). -- 2.40.0