mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
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
This commit is contained in:
parent
1a87c14c9c
commit
79c2576f77
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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);
|
GroupClause *newnode = makeNode(GroupClause);
|
||||||
|
|
||||||
Node_Copy(from, newnode, entry);
|
|
||||||
newnode->grpOpoid = from->grpOpoid;
|
newnode->grpOpoid = from->grpOpoid;
|
||||||
|
newnode->tleGroupref = from->tleGroupref;
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
}
|
}
|
||||||
@ -589,6 +589,7 @@ _copyResdom(Resdom *from)
|
|||||||
newnode->resname = pstrdup(from->resname);
|
newnode->resname = pstrdup(from->resname);
|
||||||
newnode->reskey = from->reskey;
|
newnode->reskey = from->reskey;
|
||||||
newnode->reskeyop = from->reskeyop;
|
newnode->reskeyop = from->reskeyop;
|
||||||
|
newnode->resgroupref = from->resgroupref;
|
||||||
newnode->resjunk = from->resjunk;
|
newnode->resjunk = from->resjunk;
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
return false;
|
||||||
if (a->reskey != b->reskey)
|
if (a->reskey != b->reskey)
|
||||||
return false;
|
return false;
|
||||||
|
if (a->resgroupref != b->resgroupref)
|
||||||
|
return false;
|
||||||
if (a->reskeyop != b->reskeyop)
|
if (a->reskeyop != b->reskeyop)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
static void
|
||||||
_freeGroupClause(GroupClause *node)
|
_freeGroupClause(GroupClause *node)
|
||||||
{
|
{
|
||||||
freeObject(node->entry);
|
|
||||||
|
|
||||||
pfree(node);
|
pfree(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Creator functions in POSTGRES 4.2 are generated automatically. Most of
|
* Creator functions in POSTGRES 4.2 are generated automatically. Most of
|
||||||
@ -107,6 +107,7 @@ makeResdom(AttrNumber resno,
|
|||||||
resdom->resname = resname;
|
resdom->resname = resname;
|
||||||
resdom->reskey = reskey;
|
resdom->reskey = reskey;
|
||||||
resdom->reskeyop = reskeyop;
|
resdom->reskeyop = reskeyop;
|
||||||
|
resdom->resgroupref = 0;
|
||||||
resdom->resjunk = resjunk;
|
resdom->resjunk = resjunk;
|
||||||
return resdom;
|
return resdom;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
* NOTES
|
||||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||||
@ -255,10 +255,9 @@ _outSortClause(StringInfo str, SortClause *node)
|
|||||||
static void
|
static void
|
||||||
_outGroupClause(StringInfo str, GroupClause *node)
|
_outGroupClause(StringInfo str, GroupClause *node)
|
||||||
{
|
{
|
||||||
appendStringInfo(str, " GROUPCLAUSE :entry ");
|
appendStringInfo(str, " GROUPCLAUSE :grpOpoid %u :tleGroupref %d",
|
||||||
_outNode(str, node->entry);
|
node->grpOpoid,
|
||||||
|
node->tleGroupref);
|
||||||
appendStringInfo(str, " :grpOpoid %u ", node->grpOpoid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -556,15 +555,18 @@ _outHash(StringInfo str, Hash *node)
|
|||||||
static void
|
static void
|
||||||
_outResdom(StringInfo str, Resdom *node)
|
_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->resno,
|
||||||
node->restype,
|
node->restype,
|
||||||
node->restypmod);
|
node->restypmod);
|
||||||
|
|
||||||
appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u :resjunk %d",
|
appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u",
|
||||||
stringStringInfo(node->resname),
|
stringStringInfo(node->resname),
|
||||||
node->reskey,
|
node->reskey,
|
||||||
node->reskeyop,
|
node->reskeyop);
|
||||||
|
|
||||||
|
appendStringInfo(str, " :resgroupref %d :resjunk %d",
|
||||||
|
node->resgroupref,
|
||||||
node->resjunk);
|
node->resjunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Most of the read functions for plan nodes are tested. (In fact, they
|
* Most of the read functions for plan nodes are tested. (In fact, they
|
||||||
@ -221,13 +221,14 @@ _readGroupClause()
|
|||||||
|
|
||||||
local_node = makeNode(GroupClause);
|
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); /* skip :grpOpoid */
|
||||||
token = lsptok(NULL, &length); /* get grpOpoid */
|
token = lsptok(NULL, &length); /* get grpOpoid */
|
||||||
local_node->grpOpoid = strtoul(token, NULL, 10);
|
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;
|
return local_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,6 +745,10 @@ _readResdom()
|
|||||||
token = lsptok(NULL, &length); /* get reskeyop */
|
token = lsptok(NULL, &length); /* get reskeyop */
|
||||||
local_node->reskeyop = (Oid) atol(token);
|
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); /* eat :resjunk */
|
||||||
token = lsptok(NULL, &length); /* get resjunk */
|
token = lsptok(NULL, &length); /* get resjunk */
|
||||||
local_node->resjunk = atoi(token);
|
local_node->resjunk = atoi(token);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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?)
|
* belong to?)
|
||||||
*/
|
*/
|
||||||
check_having_for_ungrouped_vars(parse->havingQual,
|
check_having_for_ungrouped_vars(parse->havingQual,
|
||||||
parse->groupClause);
|
parse->groupClause,
|
||||||
|
parse->targetList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the opfids from the opnos */
|
/* Calculate the opfids from the opnos */
|
||||||
@ -426,8 +427,7 @@ make_subplanTargetList(Query *parse,
|
|||||||
GroupClause *grpcl = (GroupClause *) lfirst(gl);
|
GroupClause *grpcl = (GroupClause *) lfirst(gl);
|
||||||
|
|
||||||
keyno++; /* sort key # for this GroupClause */
|
keyno++; /* sort key # for this GroupClause */
|
||||||
/* Is it safe to use just resno to match tlist and glist items?? */
|
if (grpcl->tleGroupref == resdom->resgroupref)
|
||||||
if (grpcl->entry->resdom->resno == resdom->resno)
|
|
||||||
{
|
{
|
||||||
/* Found a matching groupclause; record info for sorting */
|
/* Found a matching groupclause; record info for sorting */
|
||||||
foundGroupClause = true;
|
foundGroupClause = true;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
void
|
||||||
check_having_for_ungrouped_vars(Node *clause, List *groupClause)
|
check_having_for_ungrouped_vars(Node *clause, List *groupClause,
|
||||||
|
List *targetList)
|
||||||
{
|
{
|
||||||
List *t;
|
List *t;
|
||||||
|
|
||||||
@ -981,7 +982,7 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause)
|
|||||||
else if (IsA(clause, Iter))
|
else if (IsA(clause, Iter))
|
||||||
{
|
{
|
||||||
check_having_for_ungrouped_vars(((Iter *) clause)->iterexpr,
|
check_having_for_ungrouped_vars(((Iter *) clause)->iterexpr,
|
||||||
groupClause);
|
groupClause, targetList);
|
||||||
}
|
}
|
||||||
else if (is_subplan(clause))
|
else if (is_subplan(clause))
|
||||||
{
|
{
|
||||||
@ -997,7 +998,8 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause)
|
|||||||
foreach(gl, groupClause)
|
foreach(gl, groupClause)
|
||||||
{
|
{
|
||||||
if (var_equal(lfirst(t),
|
if (var_equal(lfirst(t),
|
||||||
get_expr(((GroupClause *) lfirst(gl))->entry)))
|
get_groupclause_expr((GroupClause *)
|
||||||
|
lfirst(gl), targetList)))
|
||||||
{
|
{
|
||||||
contained_in_group_clause = true;
|
contained_in_group_clause = true;
|
||||||
break;
|
break;
|
||||||
@ -1016,7 +1018,8 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause)
|
|||||||
* subplan is a kind of Expr node.
|
* subplan is a kind of Expr node.
|
||||||
*/
|
*/
|
||||||
foreach(t, ((Expr *) clause)->args)
|
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))
|
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).
|
* Recursively scan AND subclauses (see NOTE above).
|
||||||
*/
|
*/
|
||||||
foreach(t, ((List *) clause))
|
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))
|
else if (IsA(clause, Aggref))
|
||||||
{
|
{
|
||||||
check_having_for_ungrouped_vars(((Aggref *) clause)->target,
|
check_having_for_ungrouped_vars(((Aggref *) clause)->target,
|
||||||
groupClause);
|
groupClause, targetList);
|
||||||
}
|
}
|
||||||
else if (IsA(clause, ArrayRef))
|
else if (IsA(clause, ArrayRef))
|
||||||
{
|
{
|
||||||
@ -1040,22 +1044,28 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause)
|
|||||||
* expression and its index expression...
|
* expression and its index expression...
|
||||||
*/
|
*/
|
||||||
foreach(t, aref->refupperindexpr)
|
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)
|
foreach(t, aref->reflowerindexpr)
|
||||||
check_having_for_ungrouped_vars(lfirst(t), groupClause);
|
check_having_for_ungrouped_vars(lfirst(t), groupClause,
|
||||||
check_having_for_ungrouped_vars(aref->refexpr, groupClause);
|
targetList);
|
||||||
check_having_for_ungrouped_vars(aref->refassgnexpr, groupClause);
|
check_having_for_ungrouped_vars(aref->refexpr, groupClause,
|
||||||
|
targetList);
|
||||||
|
check_having_for_ungrouped_vars(aref->refassgnexpr, groupClause,
|
||||||
|
targetList);
|
||||||
}
|
}
|
||||||
else if (case_clause(clause))
|
else if (case_clause(clause))
|
||||||
{
|
{
|
||||||
foreach(t, ((CaseExpr *) clause)->args)
|
foreach(t, ((CaseExpr *) clause)->args)
|
||||||
{
|
{
|
||||||
CaseWhen *when = (CaseWhen *) lfirst(t);
|
CaseWhen *when = (CaseWhen *) lfirst(t);
|
||||||
check_having_for_ungrouped_vars(when->expr, groupClause);
|
check_having_for_ungrouped_vars(when->expr, groupClause,
|
||||||
check_having_for_ungrouped_vars(when->result, groupClause);
|
targetList);
|
||||||
|
check_having_for_ungrouped_vars(when->result, groupClause,
|
||||||
|
targetList);
|
||||||
}
|
}
|
||||||
check_having_for_ungrouped_vars(((CaseExpr *) clause)->defresult,
|
check_having_for_ungrouped_vars(((CaseExpr *) clause)->defresult,
|
||||||
groupClause);
|
groupClause, targetList);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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);
|
new_tl = makeTargetEntry(newresno, old_tle->expr);
|
||||||
t_list = lappend(t_list, new_tl);
|
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;
|
return t_list;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* in there.
|
||||||
*/
|
*/
|
||||||
#ifdef NOT_USED
|
#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
|
void
|
||||||
AddGroupAttrToTlist(List *tlist, List *grpCl)
|
AddGroupAttrToTlist(List *tlist, List *grpCl)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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"
|
#include "utils/lsyscache.h"
|
||||||
|
|
||||||
static bool contain_agg_clause(Node *clause);
|
static bool contain_agg_clause(Node *clause);
|
||||||
static bool exprIsAggOrGroupCol(Node *expr, List *groupClause);
|
static bool exprIsAggOrGroupCol(Node *expr, List *groupClause, List *tlist);
|
||||||
static bool tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause);
|
static bool tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause,
|
||||||
|
List *tlist);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* contain_agg_clause
|
* contain_agg_clause
|
||||||
@ -100,7 +101,7 @@ contain_agg_clause(Node *clause)
|
|||||||
* returns true if the expression does not contain non-group columns.
|
* returns true if the expression does not contain non-group columns.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
exprIsAggOrGroupCol(Node *expr, List *groupClause)
|
exprIsAggOrGroupCol(Node *expr, List *groupClause, List *tlist)
|
||||||
{
|
{
|
||||||
List *gl;
|
List *gl;
|
||||||
|
|
||||||
@ -113,7 +114,7 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause)
|
|||||||
{
|
{
|
||||||
GroupClause *grpcl = lfirst(gl);
|
GroupClause *grpcl = lfirst(gl);
|
||||||
|
|
||||||
if (equal(expr, grpcl->entry->expr))
|
if (equal(expr, get_groupclause_expr(grpcl, tlist)))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +123,7 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause)
|
|||||||
List *temp;
|
List *temp;
|
||||||
|
|
||||||
foreach(temp, ((Expr *) expr)->args)
|
foreach(temp, ((Expr *) expr)->args)
|
||||||
if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
|
if (!exprIsAggOrGroupCol(lfirst(temp), groupClause, tlist))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -135,7 +136,7 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause)
|
|||||||
* returns true if the TargetEntry is Agg or GroupCol.
|
* returns true if the TargetEntry is Agg or GroupCol.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
|
tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause, List *tlist)
|
||||||
{
|
{
|
||||||
Node *expr = tle->expr;
|
Node *expr = tle->expr;
|
||||||
List *gl;
|
List *gl;
|
||||||
@ -147,7 +148,7 @@ tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
|
|||||||
{
|
{
|
||||||
GroupClause *grpcl = lfirst(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))
|
if (contain_agg_clause((Node *) expr))
|
||||||
elog(ERROR, "Aggregates not allowed in GROUP BY clause");
|
elog(ERROR, "Aggregates not allowed in GROUP BY clause");
|
||||||
@ -163,7 +164,7 @@ tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
|
|||||||
List *temp;
|
List *temp;
|
||||||
|
|
||||||
foreach(temp, ((Expr *) expr)->args)
|
foreach(temp, ((Expr *) expr)->args)
|
||||||
if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
|
if (!exprIsAggOrGroupCol(lfirst(temp), groupClause, tlist))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -200,7 +201,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
|
|||||||
{
|
{
|
||||||
TargetEntry *tle = lfirst(tl);
|
TargetEntry *tle = lfirst(tl);
|
||||||
|
|
||||||
if (!tleIsAggOrGroupCol(tle, qry->groupClause))
|
if (!tleIsAggOrGroupCol(tle, qry->groupClause, qry->targetList))
|
||||||
elog(ERROR,
|
elog(ERROR,
|
||||||
"Illegal use of aggregates or non-group column in target list");
|
"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.
|
* restriction as those in the target list.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause))
|
if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause, qry->targetList))
|
||||||
elog(ERROR,
|
elog(ERROR,
|
||||||
"Illegal use of aggregates or non-group column in HAVING clause");
|
"Illegal use of aggregates or non-group column in HAVING clause");
|
||||||
return;
|
return;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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);
|
restarget = findTargetlistEntry(pstate, lfirst(grouplist), targetlist, GROUP_CLAUSE);
|
||||||
|
|
||||||
grpcl->entry = restarget;
|
|
||||||
resdom = restarget->resdom;
|
resdom = restarget->resdom;
|
||||||
grpcl->grpOpoid = oprid(oper("<",
|
grpcl->grpOpoid = oprid(oper("<",
|
||||||
resdom->restype,
|
resdom->restype,
|
||||||
resdom->restype, false));
|
resdom->restype, false));
|
||||||
if (glist == NIL)
|
if (glist == NIL)
|
||||||
|
{
|
||||||
|
int groupref = length(glist) + 1;
|
||||||
|
|
||||||
|
restarget->resdom->resgroupref = groupref;
|
||||||
|
grpcl->tleGroupref = groupref;
|
||||||
|
|
||||||
gl = glist = lcons(grpcl, NIL);
|
gl = glist = lcons(grpcl, NIL);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
List *i;
|
List *i;
|
||||||
@ -565,11 +571,17 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
|
|||||||
{
|
{
|
||||||
GroupClause *gcl = (GroupClause *) lfirst(i);
|
GroupClause *gcl = (GroupClause *) lfirst(i);
|
||||||
|
|
||||||
if (gcl->entry == grpcl->entry)
|
if (equal(get_groupclause_expr(gcl, targetlist),
|
||||||
|
restarget->expr))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i == NIL) /* not in grouplist already */
|
if (i == NIL) /* not in grouplist already */
|
||||||
{
|
{
|
||||||
|
int groupref = length(glist) + 1;
|
||||||
|
|
||||||
|
restarget->resdom->resgroupref = groupref;
|
||||||
|
grpcl->tleGroupref = groupref;
|
||||||
|
|
||||||
lnext(gl) = lcons(grpcl, NIL);
|
lnext(gl) = lcons(grpcl, NIL);
|
||||||
gl = lnext(gl);
|
gl = lnext(gl);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
break;
|
||||||
|
|
||||||
case T_GroupClause:
|
case T_GroupClause:
|
||||||
{
|
return FALSE;
|
||||||
GroupClause *grp = (GroupClause *)node;
|
|
||||||
|
|
||||||
return rangeTableEntry_used(
|
|
||||||
(Node *)(grp->entry),
|
|
||||||
rt_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Expr:
|
case T_Expr:
|
||||||
{
|
{
|
||||||
@ -348,12 +340,6 @@ rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
|
|||||||
sublevels_up))
|
sublevels_up))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (rangeTableEntry_used(
|
|
||||||
(Node *)(qry->groupClause),
|
|
||||||
rt_index,
|
|
||||||
sublevels_up))
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -407,16 +393,7 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case T_GroupClause:
|
case T_GroupClause:
|
||||||
{
|
return FALSE;
|
||||||
GroupClause *grp = (GroupClause *)node;
|
|
||||||
|
|
||||||
return attribute_used(
|
|
||||||
(Node *)(grp->entry),
|
|
||||||
rt_index,
|
|
||||||
attno,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Expr:
|
case T_Expr:
|
||||||
{
|
{
|
||||||
@ -558,13 +535,6 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
|
|||||||
sublevels_up))
|
sublevels_up))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (attribute_used(
|
|
||||||
(Node *)(qry->groupClause),
|
|
||||||
rt_index,
|
|
||||||
attno,
|
|
||||||
sublevels_up))
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -697,8 +667,6 @@ modifyAggrefUplevel(Node *node)
|
|||||||
modifyAggrefUplevel(
|
modifyAggrefUplevel(
|
||||||
(Node *)(qry->havingQual));
|
(Node *)(qry->havingQual));
|
||||||
|
|
||||||
modifyAggrefUplevel(
|
|
||||||
(Node *)(qry->groupClause));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -752,15 +720,6 @@ modifyAggrefChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int subl
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case T_GroupClause:
|
case T_GroupClause:
|
||||||
{
|
|
||||||
GroupClause *grp = (GroupClause *)node;
|
|
||||||
|
|
||||||
modifyAggrefChangeVarnodes(
|
|
||||||
(Node **)(&(grp->entry)),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Expr:
|
case T_Expr:
|
||||||
@ -894,12 +853,6 @@ modifyAggrefChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int subl
|
|||||||
rt_index,
|
rt_index,
|
||||||
new_index,
|
new_index,
|
||||||
sublevels_up);
|
sublevels_up);
|
||||||
|
|
||||||
modifyAggrefChangeVarnodes(
|
|
||||||
(Node **)(&(qry->groupClause)),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1186,13 +1139,6 @@ modifyAggrefQual(Node **nodePtr, Query *parsetree)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case T_GroupClause:
|
case T_GroupClause:
|
||||||
{
|
|
||||||
GroupClause *grp = (GroupClause *)node;
|
|
||||||
|
|
||||||
modifyAggrefQual(
|
|
||||||
(Node **)(&(grp->entry)),
|
|
||||||
parsetree);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Expr:
|
case T_Expr:
|
||||||
@ -1386,13 +1332,6 @@ apply_RIR_adjust_sublevel(Node *node, int sublevels_up)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case T_GroupClause:
|
case T_GroupClause:
|
||||||
{
|
|
||||||
GroupClause *grp = (GroupClause *)node;
|
|
||||||
|
|
||||||
apply_RIR_adjust_sublevel(
|
|
||||||
(Node *)(grp->entry),
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Expr:
|
case T_Expr:
|
||||||
@ -1539,17 +1478,6 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case T_GroupClause:
|
case T_GroupClause:
|
||||||
{
|
|
||||||
GroupClause *grp = (GroupClause *)node;
|
|
||||||
|
|
||||||
apply_RIR_view(
|
|
||||||
(Node **)(&(grp->entry)),
|
|
||||||
rt_index,
|
|
||||||
rte,
|
|
||||||
tlist,
|
|
||||||
modified,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Expr:
|
case T_Expr:
|
||||||
@ -1724,14 +1652,6 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in
|
|||||||
tlist,
|
tlist,
|
||||||
modified,
|
modified,
|
||||||
sublevels_up);
|
sublevels_up);
|
||||||
|
|
||||||
apply_RIR_view(
|
|
||||||
(Node **)(&(qry->groupClause)),
|
|
||||||
rt_index,
|
|
||||||
rte,
|
|
||||||
tlist,
|
|
||||||
modified,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1898,10 +1818,8 @@ ApplyRetrieveRule(Query *parsetree,
|
|||||||
}
|
}
|
||||||
if (*modified && !badsql) {
|
if (*modified && !badsql) {
|
||||||
AddQual(parsetree, rule_action->qual);
|
AddQual(parsetree, rule_action->qual);
|
||||||
/* This will only work if the query made to the view defined by the following
|
AddGroupClause(parsetree, rule_action->groupClause,
|
||||||
* groupClause groups by the same attributes or does not use group at all! */
|
rule_action->targetList);
|
||||||
if (parsetree->groupClause == NULL)
|
|
||||||
parsetree->groupClause=rule_action->groupClause;
|
|
||||||
AddHavingQual(parsetree, rule_action->havingQual);
|
AddHavingQual(parsetree, rule_action->havingQual);
|
||||||
parsetree->hasAggs = (rule_action->hasAggs || parsetree->hasAggs);
|
parsetree->hasAggs = (rule_action->hasAggs || parsetree->hasAggs);
|
||||||
parsetree->hasSubLinks = (rule_action->hasSubLinks || parsetree->hasSubLinks);
|
parsetree->hasSubLinks = (rule_action->hasSubLinks || parsetree->hasSubLinks);
|
||||||
@ -1935,12 +1853,6 @@ fireRIRonSubselect(Node *node)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case T_GroupClause:
|
case T_GroupClause:
|
||||||
{
|
|
||||||
GroupClause *grp = (GroupClause *)node;
|
|
||||||
|
|
||||||
fireRIRonSubselect(
|
|
||||||
(Node *)(grp->entry));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Expr:
|
case T_Expr:
|
||||||
@ -2048,9 +1960,6 @@ fireRIRonSubselect(Node *node)
|
|||||||
|
|
||||||
fireRIRonSubselect(
|
fireRIRonSubselect(
|
||||||
(Node *)(qry->havingQual));
|
(Node *)(qry->havingQual));
|
||||||
|
|
||||||
fireRIRonSubselect(
|
|
||||||
(Node *)(qry->groupClause));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
break;
|
||||||
|
|
||||||
case T_GroupClause:
|
case T_GroupClause:
|
||||||
{
|
|
||||||
GroupClause *grp = (GroupClause *)node;
|
|
||||||
|
|
||||||
OffsetVarNodes(
|
|
||||||
(Node *)(grp->entry),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Expr:
|
case T_Expr:
|
||||||
@ -199,11 +191,6 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up)
|
|||||||
(Node *)(qry->havingQual),
|
(Node *)(qry->havingQual),
|
||||||
offset,
|
offset,
|
||||||
sublevels_up);
|
sublevels_up);
|
||||||
|
|
||||||
OffsetVarNodes(
|
|
||||||
(Node *)(qry->groupClause),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -284,15 +271,6 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case T_GroupClause:
|
case T_GroupClause:
|
||||||
{
|
|
||||||
GroupClause *grp = (GroupClause *)node;
|
|
||||||
|
|
||||||
ChangeVarNodes(
|
|
||||||
(Node *)(grp->entry),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Expr:
|
case T_Expr:
|
||||||
@ -430,12 +408,6 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
|
|||||||
rt_index,
|
rt_index,
|
||||||
new_index,
|
new_index,
|
||||||
sublevels_up);
|
sublevels_up);
|
||||||
|
|
||||||
ChangeVarNodes(
|
|
||||||
(Node *)(qry->groupClause),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -562,6 +534,44 @@ AddNotQual(Query *parsetree, Node *qual)
|
|||||||
AddQual(parsetree, copy);
|
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 *
|
static Node *
|
||||||
make_null(Oid type)
|
make_null(Oid type)
|
||||||
{
|
{
|
||||||
@ -688,7 +698,10 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr,
|
|||||||
*nodePtr = make_null(((Var *) node)->vartype);
|
*nodePtr = make_null(((Var *) node)->vartype);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
*nodePtr = copyObject(n);
|
*nodePtr = copyObject(n);
|
||||||
|
((Var *) *nodePtr)->varlevelsup = this_varlevelsup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -709,6 +722,8 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr,
|
|||||||
ResolveNew(info, targetlist, (Node **) &(query->qual), sublevels_up + 1);
|
ResolveNew(info, targetlist, (Node **) &(query->qual), sublevels_up + 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case T_GroupClause:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* ignore the others */
|
/* ignore the others */
|
||||||
break;
|
break;
|
||||||
@ -720,7 +735,10 @@ FixNew(RewriteInfo *info, Query *parsetree)
|
|||||||
{
|
{
|
||||||
ResolveNew(info, parsetree->targetList,
|
ResolveNew(info, parsetree->targetList,
|
||||||
(Node **) &(info->rule_action->targetList), 0);
|
(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
|
static void
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* out of it's tuple
|
* out of it's tuple
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* 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:
|
case T_GroupClause:
|
||||||
{
|
{
|
||||||
GroupClause *grp = (GroupClause *) node;
|
GroupClause *grp = (GroupClause *) node;
|
||||||
|
List *l;
|
||||||
|
TargetEntry *tle = NULL;
|
||||||
|
|
||||||
return get_rule_expr(qh, rt_index,
|
foreach(l, qh->query->targetList)
|
||||||
(Node *) (grp->entry), varprefix);
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
@ -1738,12 +1752,7 @@ check_if_rte_used(int rt_index, Node *node, int sup)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case T_GroupClause:
|
case T_GroupClause:
|
||||||
{
|
return FALSE;
|
||||||
GroupClause *grp = (GroupClause *) node;
|
|
||||||
|
|
||||||
return check_if_rte_used(rt_index,
|
|
||||||
(Node *) (grp->entry), sup);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Expr:
|
case T_Expr:
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
typedef struct GroupClause
|
||||||
{
|
{
|
||||||
NodeTag type;
|
NodeTag type;
|
||||||
TargetEntry *entry; /* attributes to group on */
|
|
||||||
Oid grpOpoid; /* the sort operator to use */
|
Oid grpOpoid; /* the sort operator to use */
|
||||||
|
Index tleGroupref; /* reference into targetlist */
|
||||||
} GroupClause;
|
} GroupClause;
|
||||||
|
|
||||||
#define ROW_MARK_FOR_UPDATE (1 << 0)
|
#define ROW_MARK_FOR_UPDATE (1 << 0)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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)
|
* resname - name of the resdom (could be NULL)
|
||||||
* reskey - order of key in a sort (for those > 0)
|
* reskey - order of key in a sort (for those > 0)
|
||||||
* reskeyop - sort operator Oid
|
* reskeyop - sort operator Oid
|
||||||
|
* resgroupref - set to nonzero if referenced from a group by clause
|
||||||
* resjunk - set to nonzero to eliminate the attribute
|
* resjunk - set to nonzero to eliminate the attribute
|
||||||
* from final target list e.g., ctid for replace
|
* from final target list e.g., ctid for replace
|
||||||
* and delete
|
* and delete
|
||||||
@ -45,6 +46,7 @@ typedef struct Resdom
|
|||||||
char *resname;
|
char *resname;
|
||||||
Index reskey;
|
Index reskey;
|
||||||
Oid reskeyop;
|
Oid reskeyop;
|
||||||
|
Index resgroupref;
|
||||||
int resjunk;
|
int resjunk;
|
||||||
} Resdom;
|
} Resdom;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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;
|
} RelOptInfo;
|
||||||
|
|
||||||
extern Var *get_expr(TargetEntry *foo);
|
extern Var *get_expr(TargetEntry *foo);
|
||||||
|
extern Var *get_groupclause_expr(GroupClause *groupClause, List *targetList);
|
||||||
|
|
||||||
typedef struct MergeOrder
|
typedef struct MergeOrder
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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);
|
List *subplanTargetList);
|
||||||
extern bool set_agg_tlist_references(Agg *aggNode);
|
extern bool set_agg_tlist_references(Agg *aggNode);
|
||||||
extern void del_agg_tlist_references(List *tlist);
|
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);
|
extern void transformKeySetQuery(Query *origNode);
|
||||||
|
|
||||||
#endif /* PLANMAIN_H */
|
#endif /* PLANMAIN_H */
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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 AddNotQual(Query *parsetree, Node *qual);
|
||||||
void AddNotHavingQual(Query *parsetree, Node *havingQual);
|
void AddNotHavingQual(Query *parsetree, Node *havingQual);
|
||||||
|
void AddGroupClause(Query *parsetree, List *group_by, List *tlist);
|
||||||
|
|
||||||
void FixNew(RewriteInfo *info, Query *parsetree);
|
void FixNew(RewriteInfo *info, Query *parsetree);
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
QUERY: SELECT p1.oid, p1.proname
|
QUERY: SELECT p1.oid, p1.proname
|
||||||
FROM pg_proc as p1
|
FROM pg_proc as p1
|
||||||
WHERE p1.prolang = 0 OR p1.prorettype = 0 OR
|
WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR
|
||||||
p1.pronargs < 0 OR p1.pronargs > 9;
|
p1.pronargs < 0 OR p1.pronargs > 9)
|
||||||
|
AND p1.proname !~ '^pl[^_]+_call_handler$';
|
||||||
oid|proname
|
oid|proname
|
||||||
---+-------
|
---+-------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
@ -25,8 +25,9 @@
|
|||||||
|
|
||||||
SELECT p1.oid, p1.proname
|
SELECT p1.oid, p1.proname
|
||||||
FROM pg_proc as p1
|
FROM pg_proc as p1
|
||||||
WHERE p1.prolang = 0 OR p1.prorettype = 0 OR
|
WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR
|
||||||
p1.pronargs < 0 OR p1.pronargs > 9;
|
p1.pronargs < 0 OR p1.pronargs > 9)
|
||||||
|
AND p1.proname !~ '^pl[^_]+_call_handler$';
|
||||||
|
|
||||||
-- Look for conflicting proc definitions (same names and input datatypes).
|
-- Look for conflicting proc definitions (same names and input datatypes).
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user