diff options
Diffstat (limited to 'src/backend/optimizer/plan/setrefs.c')
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 96 |
1 files changed, 95 insertions, 1 deletions
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index b6afa5fcb92..1d0f0963c5a 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.8 1997/09/08 21:45:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.9 1997/12/20 07:59:28 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -47,6 +47,7 @@ static List *tlist_temp_references(Oid tempid, List *tlist); static void replace_result_clause(List *clause, List *subplanTargetList); static bool OperandIsInner(Node *opnd, int inner_relid); static void replace_agg_clause(Node *expr, List *targetlist); +static Node *del_agg_clause(Node *clause); /***************************************************************************** * @@ -803,3 +804,96 @@ replace_agg_clause(Node *clause, List *subplanTargetList) } } + +/* + * del_agg_tlist_references + * Remove the Agg nodes from the target list + * We do this so inheritance only does aggregates in the upper node + */ +void del_agg_tlist_references(List *tlist) +{ + List *tl; + + foreach(tl, tlist) + { + TargetEntry *tle = lfirst(tl); + + tle->expr = del_agg_clause(tle->expr); + } +} + +static Node * +del_agg_clause(Node *clause) +{ + List *t; + + if (IsA(clause, Var)) + { + return clause; + } + else if (is_funcclause(clause)) + { + /* + * This is a function. Recursively call this routine for its + * arguments... + */ + foreach(t, ((Expr *) clause)->args) + { + lfirst(t) = del_agg_clause(lfirst(t)); + } + } + else if (IsA(clause, Aggreg)) + { + + /* here is the real action, to remove the Agg node */ + return del_agg_clause(((Aggreg *) clause)->target); + + } + else if (IsA(clause, ArrayRef)) + { + ArrayRef *aref = (ArrayRef *) clause; + + /* + * This is an arrayref. Recursively call this routine for its + * expression and its index expression... + */ + foreach(t, aref->refupperindexpr) + { + lfirst(t) = del_agg_clause(lfirst(t)); + } + foreach(t, aref->reflowerindexpr) + { + lfirst(t) = del_agg_clause(lfirst(t)); + } + aref->refexpr = del_agg_clause(aref->refexpr); + aref->refassgnexpr = del_agg_clause(aref->refassgnexpr); + } + else if (is_opclause(clause)) + { + + /* + * This is an operator. Recursively call this routine for both its + * left and right operands + */ + Node *left = (Node *) get_leftop((Expr *) clause); + Node *right = (Node *) get_rightop((Expr *) clause); + + if (left != (Node *) NULL) + left = del_agg_clause(left); + if (right != (Node *) NULL) + right = del_agg_clause(right); + } + else if (IsA(clause, Param) ||IsA(clause, Const)) + { + return clause; + } + else + { + + /* + * Ooops! we can not handle that! + */ + elog(WARN, "del_agg_clause: Can not handle this tlist!\n"); + } + return NULL; +} |