*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
GroupClause *newnode = makeNode(GroupClause);
- Node_Copy(from, newnode, entry);
newnode->grpOpoid = from->grpOpoid;
+ newnode->tleGroupref = from->tleGroupref;
return newnode;
}
newnode->resname = pstrdup(from->resname);
newnode->reskey = from->reskey;
newnode->reskeyop = from->reskeyop;
+ newnode->resgroupref = from->resgroupref;
newnode->resjunk = from->resjunk;
return newnode;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
return false;
if (a->reskey != b->reskey)
return false;
+ if (a->resgroupref != b->resgroupref)
+ return false;
if (a->reskeyop != b->reskeyop)
return false;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
static void
_freeGroupClause(GroupClause *node)
{
- freeObject(node->entry);
-
pfree(node);
}
*
*
* 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
resdom->resname = resname;
resdom->reskey = reskey;
resdom->reskeyop = reskeyop;
+ resdom->resgroupref = 0;
resdom->resjunk = resjunk;
return resdom;
}
*
* 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
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);
}
/*
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);
}
*
*
* 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
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;
}
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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* belong to?)
*/
check_having_for_ungrouped_vars(parse->havingQual,
- parse->groupClause);
+ parse->groupClause,
+ parse->targetList);
}
/* Calculate the opfids from the opnos */
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
void
-check_having_for_ungrouped_vars(Node *clause, List *groupClause)
+check_having_for_ungrouped_vars(Node *clause, List *groupClause,
+ List *targetList)
{
List *t;
else if (IsA(clause, Iter))
{
check_having_for_ungrouped_vars(((Iter *) clause)->iterexpr,
- groupClause);
+ groupClause, targetList);
}
else if (is_subplan(clause))
{
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;
* 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))
{
* 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))
{
* 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
{
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
}
+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;
+}
+
+
/*****************************************************************************
*
*****************************************************************************/
* 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)
{
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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
* 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;
{
GroupClause *grpcl = lfirst(gl);
- if (equal(expr, grpcl->entry->expr))
+ if (equal(expr, get_groupclause_expr(grpcl, tlist)))
return TRUE;
}
List *temp;
foreach(temp, ((Expr *) expr)->args)
- if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
+ if (!exprIsAggOrGroupCol(lfirst(temp), groupClause, tlist))
return FALSE;
return TRUE;
}
* 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;
{
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");
List *temp;
foreach(temp, ((Expr *) expr)->args)
- if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
+ if (!exprIsAggOrGroupCol(lfirst(temp), groupClause, tlist))
return FALSE;
return TRUE;
}
{
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");
}
* 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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
{
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);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
break;
case T_GroupClause:
- {
- GroupClause *grp = (GroupClause *)node;
-
- return rangeTableEntry_used(
- (Node *)(grp->entry),
- rt_index,
- sublevels_up);
- }
- break;
+ return FALSE;
case T_Expr:
{
sublevels_up))
return TRUE;
- if (rangeTableEntry_used(
- (Node *)(qry->groupClause),
- rt_index,
- sublevels_up))
- return TRUE;
-
return FALSE;
}
break;
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:
{
sublevels_up))
return TRUE;
- if (attribute_used(
- (Node *)(qry->groupClause),
- rt_index,
- attno,
- sublevels_up))
- return TRUE;
-
return FALSE;
}
break;
modifyAggrefUplevel(
(Node *)(qry->havingQual));
- modifyAggrefUplevel(
- (Node *)(qry->groupClause));
}
break;
break;
case T_GroupClause:
- {
- GroupClause *grp = (GroupClause *)node;
-
- modifyAggrefChangeVarnodes(
- (Node **)(&(grp->entry)),
- rt_index,
- new_index,
- sublevels_up);
- }
break;
case T_Expr:
rt_index,
new_index,
sublevels_up);
-
- modifyAggrefChangeVarnodes(
- (Node **)(&(qry->groupClause)),
- rt_index,
- new_index,
- sublevels_up);
}
break;
break;
case T_GroupClause:
- {
- GroupClause *grp = (GroupClause *)node;
-
- modifyAggrefQual(
- (Node **)(&(grp->entry)),
- parsetree);
- }
break;
case T_Expr:
break;
case T_GroupClause:
- {
- GroupClause *grp = (GroupClause *)node;
-
- apply_RIR_adjust_sublevel(
- (Node *)(grp->entry),
- sublevels_up);
- }
break;
case T_Expr:
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:
tlist,
modified,
sublevels_up);
-
- apply_RIR_view(
- (Node **)(&(qry->groupClause)),
- rt_index,
- rte,
- tlist,
- modified,
- sublevels_up);
}
break;
}
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);
break;
case T_GroupClause:
- {
- GroupClause *grp = (GroupClause *)node;
-
- fireRIRonSubselect(
- (Node *)(grp->entry));
- }
break;
case T_Expr:
fireRIRonSubselect(
(Node *)(qry->havingQual));
-
- fireRIRonSubselect(
- (Node *)(qry->groupClause));
}
break;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
break;
case T_GroupClause:
- {
- GroupClause *grp = (GroupClause *)node;
-
- OffsetVarNodes(
- (Node *)(grp->entry),
- offset,
- sublevels_up);
- }
break;
case T_Expr:
(Node *)(qry->havingQual),
offset,
sublevels_up);
-
- OffsetVarNodes(
- (Node *)(qry->groupClause),
- offset,
- sublevels_up);
}
break;
break;
case T_GroupClause:
- {
- GroupClause *grp = (GroupClause *)node;
-
- ChangeVarNodes(
- (Node *)(grp->entry),
- rt_index,
- new_index,
- sublevels_up);
- }
break;
case T_Expr:
rt_index,
new_index,
sublevels_up);
-
- ChangeVarNodes(
- (Node *)(qry->groupClause),
- rt_index,
- new_index,
- sublevels_up);
}
break;
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)
{
*nodePtr = make_null(((Var *) node)->vartype);
}
else
+ {
*nodePtr = copyObject(n);
+ ((Var *) *nodePtr)->varlevelsup = this_varlevelsup;
+ }
}
break;
}
ResolveNew(info, targetlist, (Node **) &(query->qual), sublevels_up + 1);
}
break;
+ case T_GroupClause:
+ break;
default:
/* ignore the others */
break;
{
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
* 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.
*
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;
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:
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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)
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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
char *resname;
Index reskey;
Oid reskeyop;
+ Index resgroupref;
int resjunk;
} Resdom;
*
* 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 $
*
*-------------------------------------------------------------------------
*/
} RelOptInfo;
extern Var *get_expr(TargetEntry *foo);
+extern Var *get_groupclause_expr(GroupClause *groupClause, List *targetList);
typedef struct MergeOrder
{
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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 */
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
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)
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).