*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.3 1997/04/05 06:37:37 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.4 1997/04/29 04:32:50 vadim Exp $
*
*-------------------------------------------------------------------------
*/
List *sort_tlist;
List *sl, *gl;
List *glc = listCopy (groupClause);
- List *aggvals = NIL; /* list of vars of aggregates */
- int aggvcnt;
+ List *otles = NIL; /* list of removed non-GroupBy entries */
+ List *otlvars = NIL; /* list of var in them */
+ int otlvcnt;
Sort *sortplan;
Group *grpplan;
int numCols;
/*
* Make template TL for subplan, Sort & Group:
- * 1. Take away Aggregates and re-set resno-s accordantly.
+ * 1. If there are aggregates (tuplePerGroup is true) then take
+ * away non-GroupBy entries and re-set resno-s accordantly.
* 2. Make grpColIdx
*
* Note: we assume that TLEs in *tlist are ordered in accordance
{
GroupClause *grpcl = (GroupClause*)lfirst(gl);
- if ( grpcl->resdom->resno == te->resdom->resno )
+ if ( grpcl->entry->resdom->resno == te->resdom->resno )
{
resdom = te->resdom;
break;
}
}
- if ( resdom == NULL ) /* Not GroupBy-ed entry: remove */
- { /* aggregate(s) from Group/Sort TL */
- if ( IsA (te->expr, Aggreg) )
- { /* save Aggregate' Vars */
- aggvals = nconc (aggvals, pull_var_clause (te->expr));
- sort_tlist = lremove (lfirst (sl), sort_tlist);
+ /*
+ * Non-GroupBy entry: remove it from Group/Sort TL if there are
+ * aggregates in query - it will be evaluated by Aggregate plan
+ */
+ if ( resdom == NULL )
+ {
+ if ( tuplePerGroup )
+ {
+ otlvars = nconc (otlvars, pull_var_clause (te->expr));
+ otles = lcons (te, otles);
+ sort_tlist = lremove (te, sort_tlist);
}
else
- resdom->resno = last_resno++; /* re-set */
+ te->resdom->resno = last_resno++;
}
}
}
/*
- * Aggregates were removed from TL - we are to add Vars for them
- * to the end of TL if there are no such Vars in TL already.
+ * If non-GroupBy entries were removed from TL - we are to add Vars for
+ * them to the end of TL if there are no such Vars in TL already.
*/
- aggvcnt = length (aggvals);
- foreach (gl, aggvals)
+ otlvcnt = length (otlvars);
+ foreach (gl, otlvars)
{
Var *v = (Var*)lfirst (gl);
last_resno++;
}
else /* already in TL */
- aggvcnt--;
+ otlvcnt--;
}
- /* Now aggvcnt is number of Vars added in TL for Aggregates */
+ /* Now otlvcnt is number of Vars added in TL for non-GroupBy entries */
/* Make TL for subplan: substitute Vars from subplan TL into new TL */
sl = flatten_tlist_vars (sort_tlist, subplan->targetlist);
grpColIdx, sortplan);
/*
- * Make TL for parent: "restore" Aggregates and
- * resno-s of others accordantly.
+ * Make TL for parent: "restore" non-GroupBy entries (if they
+ * were removed) and set resno-s of others accordantly.
*/
sl = sort_tlist;
sort_tlist = NIL; /* to be new parent TL */
foreach (gl, *tlist)
{
+ List *temp = NIL;
TargetEntry *te = (TargetEntry *) lfirst (gl);
-
- if ( !IsA (te->expr, Aggreg) ) /* It's "our" TLE - we're to return */
- { /* it from Sort/Group plans */
+
+ foreach (temp, otles) /* Is it removed non-GroupBy entry ? */
+ {
+ TargetEntry *ote = (TargetEntry *) lfirst (temp);
+
+ if ( ote->resdom->resno == te->resdom->resno )
+ {
+ otles = lremove (ote, otles);
+ break;
+ }
+ }
+ if ( temp == NIL ) /* It's "our" TLE - we're to return */
+ { /* it from Sort/Group plans */
TargetEntry *my = (TargetEntry *) lfirst (sl); /* get it */
sl = sl->next; /* prepare for the next "our" */
sort_tlist = lappend (sort_tlist, my);
continue;
}
- /* TLE of an aggregate */
+ /* else - it's TLE of an non-GroupBy entry */
sort_tlist = lappend (sort_tlist, copyObject(te));
}
/*
- * Pure aggregates Vars were at the end of Group' TL.
+ * Pure non-GroupBy entries Vars were at the end of Group' TL.
* They shouldn't appear in parent TL, all others shouldn't
* disappear.
*/
- Assert ( aggvcnt == length (sl) );
+ Assert ( otlvcnt == length (sl) );
+ Assert ( length (otles) == 0 );
*tlist = sort_tlist;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.26 1997/04/27 19:16:44 thomas Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.27 1997/04/29 04:32:26 vadim Exp $
*
*-------------------------------------------------------------------------
*/
if (restarget == NULL)
elog(WARN,"The field being grouped by must appear in the target list");
- grpcl->resdom = resdom = restarget->resdom;
+ grpcl->entry = restarget;
+ resdom = restarget->resdom;
grpcl->grpOpoid = oprid(oper("<",
resdom->restype,
resdom->restype,false));
return FALSE;
}
+/*
+ * exprIsAggOrGroupCol -
+ * returns true if the expression does not contain non-group columns.
+ */
+static bool
+exprIsAggOrGroupCol(Node *expr, List *groupClause)
+{
+ List *gl;
+
+ if ( expr == NULL || IsA (expr, Const) || IsA (expr, Aggreg) )
+ return TRUE;
+
+ foreach (gl, groupClause)
+ {
+ GroupClause *grpcl = lfirst(gl);
+
+ if ( equal (expr, grpcl->entry->expr) )
+ return TRUE;
+ }
+
+ if ( IsA (expr, Expr) )
+ {
+ List *temp;
+
+ foreach (temp, ((Expr*)expr)->args)
+ if (!exprIsAggOrGroupCol(lfirst(temp),groupClause))
+ return FALSE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/*
* tleIsAggOrGroupCol -
* returns true if the TargetEntry is Agg or GroupCol.
{
GroupClause *grpcl = lfirst(gl);
- if ( tle->resdom->resno == grpcl->resdom->resno )
+ if ( tle->resdom->resno == grpcl->entry->resdom->resno )
{
- if ( IsA (expr, Aggreg) )
+ if ( contain_agg_clause ((Node*) expr) )
elog (WARN, "parser: aggregates not allowed in GROUP BY clause");
return TRUE;
}
if ( IsA (expr, Aggreg) )
return TRUE;
- return FALSE;
-}
-
-#if 0 /* Now GroupBy contains resdom to enable Group By func_results */
-/*
- * exprIsAggOrGroupCol -
- * returns true if the expression does not contain non-group columns.
- */
-static bool
-exprIsAggOrGroupCol(Node *expr, List *groupClause)
-{
- if (expr==NULL)
- return TRUE;
- else if (IsA(expr,Const))
- return TRUE;
- else if (IsA(expr,Var)) {
- List *gl;
- Var *var = (Var*)expr;
- /*
- * only group columns are legal
- */
- foreach (gl, groupClause) {
- GroupClause *grpcl = lfirst(gl);
- if ((grpcl->grpAttr->varno == var->varno) &&
- (grpcl->grpAttr->varattno == var->varattno))
- return TRUE;
- }
- return FALSE;
- } else if (IsA(expr,Aggreg))
- /* aggregates can take group column or non-group column as argument,
- no further check necessary. */
- return TRUE;
- else if (IsA(expr,Expr)) {
+ if ( IsA (expr, Expr) )
+ {
List *temp;
foreach (temp, ((Expr*)expr)->args)
return FALSE;
}
-#endif
/*
* parseCheckAggregates -