Remove Query->qry_aggs and qry_numaggs and replace with Query->hasAggs.
Pass List* of Aggregs into executor, and create needed array there. No longer need to double-processs Aggregs with second copy in Query. Fix crash when doing: select sum(x+1) from test where 1 > 0;
This commit is contained in:
parent
f22d8e6668
commit
763ff8aef8
|
@ -105,6 +105,7 @@ ExecAgg(Agg *node)
|
|||
ProjectionInfo *projInfo;
|
||||
TupleTableSlot *resultSlot;
|
||||
HeapTuple oneTuple;
|
||||
List *alist;
|
||||
char *nulls;
|
||||
bool isDone;
|
||||
bool isNull = FALSE,
|
||||
|
@ -121,8 +122,17 @@ ExecAgg(Agg *node)
|
|||
|
||||
estate = node->plan.state;
|
||||
econtext = aggstate->csstate.cstate.cs_ExprContext;
|
||||
aggregates = node->aggs;
|
||||
nagg = node->numAgg;
|
||||
nagg = length(node->aggs);
|
||||
|
||||
aggregates = (Aggreg **)palloc(sizeof(Aggreg *) * nagg);
|
||||
|
||||
/* take List* and make it an array that can be quickly indexed */
|
||||
alist = node->aggs;
|
||||
for (i = 0; i < nagg; i++)
|
||||
{
|
||||
aggregates[i] = lfirst(alist);
|
||||
alist = lnext(alist);
|
||||
}
|
||||
|
||||
value1 = node->aggstate->csstate.cstate.cs_ExprContext->ecxt_values;
|
||||
nulls = node->aggstate->csstate.cstate.cs_ExprContext->ecxt_nulls;
|
||||
|
@ -540,10 +550,10 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
|
|||
|
||||
econtext = aggstate->csstate.cstate.cs_ExprContext;
|
||||
econtext->ecxt_values =
|
||||
(Datum *) palloc(sizeof(Datum) * node->numAgg);
|
||||
MemSet(econtext->ecxt_values, 0, sizeof(Datum) * node->numAgg);
|
||||
econtext->ecxt_nulls = (char *) palloc(node->numAgg);
|
||||
MemSet(econtext->ecxt_nulls, 0, node->numAgg);
|
||||
(Datum *) palloc(sizeof(Datum) * length(node->aggs));
|
||||
MemSet(econtext->ecxt_values, 0, sizeof(Datum) * length(node->aggs));
|
||||
econtext->ecxt_nulls = (char *) palloc(length(node->aggs));
|
||||
MemSet(econtext->ecxt_nulls, 0, length(node->aggs));
|
||||
|
||||
/*
|
||||
* initializes child nodes
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.29 1998/01/11 20:01:53 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.30 1998/01/15 18:59:20 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -493,15 +493,10 @@ static Agg *
|
|||
_copyAgg(Agg *from)
|
||||
{
|
||||
Agg *newnode = makeNode(Agg);
|
||||
int i;
|
||||
|
||||
CopyPlanFields((Plan *) from, (Plan *) newnode);
|
||||
|
||||
newnode->numAgg = from->numAgg;
|
||||
newnode->aggs = palloc(sizeof(Aggreg *));
|
||||
for (i = 0; i < from->numAgg; i++)
|
||||
newnode->aggs[i] = copyObject(from->aggs[i]);
|
||||
|
||||
Node_Copy(from, newnode, aggs);
|
||||
Node_Copy(from, newnode, aggstate);
|
||||
|
||||
return newnode;
|
||||
|
@ -1495,7 +1490,6 @@ static Query *
|
|||
_copyQuery(Query *from)
|
||||
{
|
||||
Query *newnode = makeNode(Query);
|
||||
int i;
|
||||
|
||||
newnode->commandType = from->commandType;
|
||||
if (from->utilityStmt && nodeTag(from->utilityStmt) == T_NotifyStmt)
|
||||
|
@ -1522,14 +1516,7 @@ _copyQuery(Query *from)
|
|||
Node_Copy(from, newnode, groupClause);
|
||||
Node_Copy(from, newnode, havingQual);
|
||||
|
||||
newnode->qry_numAgg = from->qry_numAgg;
|
||||
if (from->qry_numAgg > 0)
|
||||
{
|
||||
newnode->qry_aggs =
|
||||
(Aggreg **) palloc(sizeof(Aggreg *) * from->qry_numAgg);
|
||||
for (i=0; i < from->qry_numAgg; i++)
|
||||
newnode->qry_aggs[i] = _copyAggreg(from->qry_aggs[i]);
|
||||
}
|
||||
newnode->hasAggs = from->hasAggs;
|
||||
|
||||
if (from->unionClause)
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.10 1998/01/07 21:03:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.11 1998/01/15 18:59:23 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* XXX a few of the following functions are duplicated to handle
|
||||
|
@ -89,6 +89,48 @@ lappendi(List *list, int datum)
|
|||
return nconc(list, lconsi(datum, NIL));
|
||||
}
|
||||
|
||||
List *
|
||||
nconc(List *l1, List *l2)
|
||||
{
|
||||
List *temp;
|
||||
|
||||
if (l1 == NIL)
|
||||
return l2;
|
||||
if (l2 == NIL)
|
||||
return l1;
|
||||
if (l1 == l2)
|
||||
elog(ERROR, "tryout to nconc a list to itself");
|
||||
|
||||
for (temp = l1; lnext(temp) != NULL; temp = lnext(temp))
|
||||
;
|
||||
|
||||
lnext(temp) = l2;
|
||||
return (l1); /* list1 is now list1[]list2 */
|
||||
}
|
||||
|
||||
|
||||
List *
|
||||
nreverse(List *list)
|
||||
{
|
||||
List *rlist = NIL;
|
||||
List *p = NIL;
|
||||
|
||||
if (list == NULL)
|
||||
return (NIL);
|
||||
|
||||
if (length(list) == 1)
|
||||
return (list);
|
||||
|
||||
for (p = list; p != NULL; p = lnext(p))
|
||||
{
|
||||
rlist = lcons(lfirst(p), rlist);
|
||||
}
|
||||
|
||||
lfirst(list) = lfirst(rlist);
|
||||
lnext(list) = lnext(rlist);
|
||||
return (list);
|
||||
}
|
||||
|
||||
Value *
|
||||
makeInteger(long i)
|
||||
{
|
||||
|
@ -227,48 +269,6 @@ intAppend(List *l1, List *l2)
|
|||
return newlist;
|
||||
}
|
||||
|
||||
List *
|
||||
nconc(List *l1, List *l2)
|
||||
{
|
||||
List *temp;
|
||||
|
||||
if (l1 == NIL)
|
||||
return l2;
|
||||
if (l2 == NIL)
|
||||
return l1;
|
||||
if (l1 == l2)
|
||||
elog(ERROR, "tryout to nconc a list to itself");
|
||||
|
||||
for (temp = l1; lnext(temp) != NULL; temp = lnext(temp))
|
||||
;
|
||||
|
||||
lnext(temp) = l2;
|
||||
return (l1); /* list1 is now list1[]list2 */
|
||||
}
|
||||
|
||||
|
||||
List *
|
||||
nreverse(List *list)
|
||||
{
|
||||
List *rlist = NIL;
|
||||
List *p = NIL;
|
||||
|
||||
if (list == NULL)
|
||||
return (NIL);
|
||||
|
||||
if (length(list) == 1)
|
||||
return (list);
|
||||
|
||||
for (p = list; p != NULL; p = lnext(p))
|
||||
{
|
||||
rlist = lcons(lfirst(p), rlist);
|
||||
}
|
||||
|
||||
lfirst(list) = lfirst(rlist);
|
||||
lnext(list) = lnext(rlist);
|
||||
return (list);
|
||||
}
|
||||
|
||||
/*
|
||||
* same
|
||||
*
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.20 1998/01/07 15:32:25 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.21 1998/01/15 18:59:26 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||
|
@ -163,7 +163,6 @@ static void
|
|||
_outQuery(StringInfo str, Query *node)
|
||||
{
|
||||
char buf[500];
|
||||
int i;
|
||||
|
||||
appendStringInfo(str, "QUERY");
|
||||
|
||||
|
@ -229,12 +228,8 @@ _outQuery(StringInfo str, Query *node)
|
|||
_outNode(str, node->groupClause);
|
||||
appendStringInfo(str, " :havingQual ");
|
||||
_outNode(str, node->havingQual);
|
||||
appendStringInfo(str, " :qry_numAgg ");
|
||||
sprintf(buf, " %d ", node->qry_numAgg);
|
||||
appendStringInfo(str, buf);
|
||||
appendStringInfo(str, " :qry_aggs ");
|
||||
for (i=0; i < node->qry_numAgg; i++)
|
||||
_outNode(str, node->qry_aggs[i]);
|
||||
appendStringInfo(str, " :hasAggs ");
|
||||
appendStringInfo(str, (node->hasAggs ? "true" : "false"));
|
||||
appendStringInfo(str, " :unionClause ");
|
||||
_outNode(str, node->unionClause);
|
||||
}
|
||||
|
@ -505,14 +500,12 @@ _outSort(StringInfo str, Sort *node)
|
|||
static void
|
||||
_outAgg(StringInfo str, Agg *node)
|
||||
{
|
||||
char buf[500];
|
||||
|
||||
appendStringInfo(str, "AGG");
|
||||
_outPlanInfo(str, (Plan *) node);
|
||||
|
||||
/* the actual Agg fields */
|
||||
sprintf(buf, " :numagg %d ", node->numAgg);
|
||||
appendStringInfo(str, buf);
|
||||
appendStringInfo(str, " :aggs ");
|
||||
_outNode(str, node->aggs);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.17 1998/01/07 21:03:37 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.18 1998/01/15 18:59:31 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Most of the read functions for plan nodes are tested. (In fact, they
|
||||
|
@ -76,7 +76,6 @@ _readQuery()
|
|||
Query *local_node;
|
||||
char *token;
|
||||
int length;
|
||||
int i;
|
||||
|
||||
local_node = makeNode(Query);
|
||||
|
||||
|
@ -153,19 +152,9 @@ _readQuery()
|
|||
token = lsptok(NULL, &length); /* skip :havingQual */
|
||||
local_node->havingQual = nodeRead(true);
|
||||
|
||||
token = lsptok(NULL, &length); /* skip the :qry_numAgg */
|
||||
token = lsptok(NULL, &length); /* get qry_numAgg */
|
||||
local_node->qry_numAgg = atoi(token);
|
||||
|
||||
token = lsptok(NULL, &length); /* skip the :qry_Aggs */
|
||||
if (local_node->qry_numAgg == 0)
|
||||
local_node->qry_aggs = NULL;
|
||||
else
|
||||
{
|
||||
local_node->qry_aggs = palloc(sizeof(Aggreg *) * local_node->qry_numAgg);
|
||||
for (i=0; i < local_node->qry_numAgg; i++)
|
||||
local_node->qry_aggs[i] = nodeRead(true);
|
||||
}
|
||||
token = lsptok(NULL, &length); /* skip the :hasAggs */
|
||||
token = lsptok(NULL, &length); /* get hasAggs */
|
||||
local_node->hasAggs = (token[0] == 't') ? true : false;
|
||||
|
||||
token = lsptok(NULL, &length); /* skip :unionClause */
|
||||
local_node->unionClause = nodeRead(true);
|
||||
|
@ -618,9 +607,8 @@ _readAgg()
|
|||
local_node = makeNode(Agg);
|
||||
_getPlan((Plan *) local_node);
|
||||
|
||||
token = lsptok(NULL, &length); /* eat :numagg */
|
||||
token = lsptok(NULL, &length); /* get numagg */
|
||||
local_node->numAgg = atoi(token);
|
||||
token = lsptok(NULL, &length); /* eat :agg */
|
||||
local_node->aggs = nodeRead(true); /* now read it */
|
||||
|
||||
return (local_node);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.22 1998/01/07 21:04:01 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.23 1998/01/15 18:59:37 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -1106,7 +1106,7 @@ make_material(List *tlist,
|
|||
}
|
||||
|
||||
Agg *
|
||||
make_agg(List *tlist, int nagg, Aggreg **aggs, Plan *lefttree)
|
||||
make_agg(List *tlist, Plan *lefttree)
|
||||
{
|
||||
Agg *node = makeNode(Agg);
|
||||
|
||||
|
@ -1116,8 +1116,7 @@ make_agg(List *tlist, int nagg, Aggreg **aggs, Plan *lefttree)
|
|||
node->plan.targetlist = tlist;
|
||||
node->plan.lefttree = lefttree;
|
||||
node->plan.righttree = (Plan *) NULL;
|
||||
node->numAgg = nagg;
|
||||
node->aggs = aggs;
|
||||
node->aggs = NIL;
|
||||
|
||||
return (node);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.15 1998/01/07 21:04:04 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.16 1998/01/15 18:59:44 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -71,7 +71,7 @@ query_planner(Query *root,
|
|||
List *constant_qual = NIL;
|
||||
List *var_only_tlist = NIL;
|
||||
List *level_tlist = NIL;
|
||||
Plan *subplan = (Plan *) NULL;
|
||||
Plan *subplan = NULL;
|
||||
|
||||
/*
|
||||
* A command without a target list or qualification is an error,
|
||||
|
@ -174,20 +174,19 @@ query_planner(Query *root,
|
|||
*/
|
||||
if (constant_qual)
|
||||
{
|
||||
Plan *plan;
|
||||
|
||||
plan = (Plan *) make_result(tlist,
|
||||
(Node *) constant_qual,
|
||||
subplan);
|
||||
subplan = (Plan *)make_result((!root->hasAggs && !root->groupClause)
|
||||
? tlist : subplan->targetlist,
|
||||
(Node *) constant_qual,
|
||||
subplan);
|
||||
|
||||
/*
|
||||
* Change all varno's of the Result's node target list.
|
||||
*/
|
||||
set_result_tlist_references((Result *) plan);
|
||||
if (!root->hasAggs && !root->groupClause)
|
||||
set_tlist_references(subplan);
|
||||
|
||||
return (plan);
|
||||
return subplan;
|
||||
}
|
||||
|
||||
/*
|
||||
* fix up the flattened target list of the plan root node so that
|
||||
* expressions are evaluated. this forces expression evaluations that
|
||||
|
@ -201,12 +200,14 @@ query_planner(Query *root,
|
|||
* aggregates fixing only other entries (i.e. - GroupBy-ed and so
|
||||
* fixed by make_groupPlan). - vadim 04/05/97
|
||||
*/
|
||||
if (root->groupClause == NULL && root->qry_aggs == NULL)
|
||||
{
|
||||
subplan->targetlist = flatten_tlist_vars(tlist,
|
||||
else
|
||||
{
|
||||
if (!root->hasAggs && !root->groupClause)
|
||||
subplan->targetlist = flatten_tlist_vars(tlist,
|
||||
subplan->targetlist);
|
||||
}
|
||||
|
||||
return subplan;
|
||||
}
|
||||
|
||||
#ifdef NOT_USED
|
||||
/*
|
||||
* Destructively modify the query plan's targetlist to add fjoin lists
|
||||
|
@ -215,7 +216,6 @@ query_planner(Query *root,
|
|||
subplan->targetlist = generate_fjoin(subplan->targetlist);
|
||||
#endif
|
||||
|
||||
return (subplan);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.20 1998/01/07 21:04:05 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.21 1998/01/15 18:59:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -117,7 +117,7 @@ planner(Query *parse)
|
|||
* If we have a GROUP BY clause, insert a group node (with the
|
||||
* appropriate sort node.)
|
||||
*/
|
||||
if (parse->groupClause != NULL)
|
||||
if (parse->groupClause)
|
||||
{
|
||||
bool tuplePerGroup;
|
||||
|
||||
|
@ -127,7 +127,7 @@ planner(Query *parse)
|
|||
* present. Otherwise, need every tuple from the group to do the
|
||||
* aggregation.)
|
||||
*/
|
||||
tuplePerGroup = (parse->qry_aggs) ? TRUE : FALSE;
|
||||
tuplePerGroup = parse->hasAggs;
|
||||
|
||||
result_plan =
|
||||
make_groupPlan( &tlist,
|
||||
|
@ -140,22 +140,16 @@ planner(Query *parse)
|
|||
/*
|
||||
* If aggregate is present, insert the agg node
|
||||
*/
|
||||
if (parse->qry_aggs)
|
||||
if (parse->hasAggs)
|
||||
{
|
||||
result_plan = (Plan *)make_agg(tlist,
|
||||
parse->qry_numAgg,
|
||||
parse->qry_aggs,
|
||||
result_plan);
|
||||
result_plan = (Plan *)make_agg(tlist, result_plan);
|
||||
|
||||
/*
|
||||
* set the varno/attno entries to the appropriate references to
|
||||
* the result tuple of the subplans. (We need to set those in the
|
||||
* array of aggreg's in the Agg node also. Even though they're
|
||||
* pointers, after a few dozen's of copying, they're not the same
|
||||
* as those in the target list.)
|
||||
* the result tuple of the subplans.
|
||||
*/
|
||||
set_agg_tlist_references((Agg *)result_plan);
|
||||
set_agg_agglist_references((Agg *)result_plan);
|
||||
((Agg *)result_plan)->aggs =
|
||||
set_agg_tlist_references((Agg *)result_plan);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.14 1998/01/14 19:55:53 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.15 1998/01/15 18:59:50 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -44,7 +44,7 @@ static Var *replace_joinvar_refs(Var *var, List *outer_tlist, List *inner_tlist)
|
|||
static List *tlist_temp_references(Oid tempid, List *tlist);
|
||||
static void replace_result_clause(Node *clause, List *subplanTargetList);
|
||||
static bool OperandIsInner(Node *opnd, int inner_relid);
|
||||
static void replace_agg_clause(Node *expr, List *targetlist);
|
||||
static List *replace_agg_clause(Node *expr, List *targetlist);
|
||||
static Node *del_agg_clause(Node *clause);
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -536,13 +536,9 @@ set_result_tlist_references(Result *resultNode)
|
|||
*/
|
||||
subplan = ((Plan *) resultNode)->lefttree;
|
||||
if (subplan != NULL)
|
||||
{
|
||||
subplanTargetList = subplan->targetlist;
|
||||
}
|
||||
else
|
||||
{
|
||||
subplanTargetList = NIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* now for traverse all the entris of the target list. These should be
|
||||
|
@ -695,13 +691,16 @@ OperandIsInner(Node *opnd, int inner_relid)
|
|||
* changes the target list of an Agg node so that it points to
|
||||
* the tuples returned by its left tree subplan.
|
||||
*
|
||||
* We now also generate a linked list of Aggreg pointers for Agg.
|
||||
*
|
||||
*/
|
||||
void
|
||||
List *
|
||||
set_agg_tlist_references(Agg *aggNode)
|
||||
{
|
||||
List *aggTargetList;
|
||||
List *subplanTargetList;
|
||||
List *tl;
|
||||
List *aggreg_list = NIL;
|
||||
|
||||
aggTargetList = aggNode->plan.targetlist;
|
||||
subplanTargetList = aggNode->plan.lefttree->targetlist;
|
||||
|
@ -710,30 +709,18 @@ set_agg_tlist_references(Agg *aggNode)
|
|||
{
|
||||
TargetEntry *tle = lfirst(tl);
|
||||
|
||||
replace_agg_clause(tle->expr, subplanTargetList);
|
||||
aggreg_list = nconc(
|
||||
replace_agg_clause(tle->expr, subplanTargetList),aggreg_list);
|
||||
}
|
||||
return aggreg_list;
|
||||
}
|
||||
|
||||
void
|
||||
set_agg_agglist_references(Agg *aggNode)
|
||||
{
|
||||
List *subplanTargetList;
|
||||
Aggreg **aggs;
|
||||
int i;
|
||||
|
||||
aggs = aggNode->aggs;
|
||||
subplanTargetList = aggNode->plan.lefttree->targetlist;
|
||||
|
||||
for (i = 0; i < aggNode->numAgg; i++)
|
||||
{
|
||||
replace_agg_clause(aggs[i]->target, subplanTargetList);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static List *
|
||||
replace_agg_clause(Node *clause, List *subplanTargetList)
|
||||
{
|
||||
List *t;
|
||||
List *agg_list = NIL;
|
||||
|
||||
if (IsA(clause, Var))
|
||||
{
|
||||
TargetEntry *subplanVar;
|
||||
|
@ -748,41 +735,51 @@ replace_agg_clause(Node *clause, List *subplanTargetList)
|
|||
*
|
||||
*/
|
||||
((Var *) clause)->varattno = subplanVar->resdom->resno;
|
||||
|
||||
return NIL;
|
||||
}
|
||||
else if (is_funcclause(clause))
|
||||
{
|
||||
|
||||
/*
|
||||
* This is a function. Recursively call this routine for its
|
||||
* arguments...
|
||||
*/
|
||||
foreach(t, ((Expr *) clause)->args)
|
||||
{
|
||||
replace_agg_clause(lfirst(t), subplanTargetList);
|
||||
agg_list = nconc(agg_list,
|
||||
replace_agg_clause(lfirst(t), subplanTargetList));
|
||||
}
|
||||
return agg_list;
|
||||
}
|
||||
else if (IsA(clause, Aggreg))
|
||||
{
|
||||
replace_agg_clause(((Aggreg *) clause)->target, subplanTargetList);
|
||||
return lcons(clause,
|
||||
replace_agg_clause(((Aggreg *) clause)->target, subplanTargetList));
|
||||
}
|
||||
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)
|
||||
{
|
||||
replace_agg_clause(lfirst(t), subplanTargetList);
|
||||
agg_list = nconc(agg_list,
|
||||
replace_agg_clause(lfirst(t), subplanTargetList));
|
||||
}
|
||||
foreach(t, aref->reflowerindexpr)
|
||||
{
|
||||
replace_agg_clause(lfirst(t), subplanTargetList);
|
||||
agg_list = nconc(agg_list,
|
||||
replace_agg_clause(lfirst(t), subplanTargetList));
|
||||
}
|
||||
replace_agg_clause(aref->refexpr, subplanTargetList);
|
||||
replace_agg_clause(aref->refassgnexpr, subplanTargetList);
|
||||
agg_list = nconc(agg_list,
|
||||
replace_agg_clause(aref->refexpr, subplanTargetList));
|
||||
agg_list = nconc(agg_list,
|
||||
replace_agg_clause(aref->refassgnexpr, subplanTargetList));
|
||||
|
||||
return agg_list;
|
||||
}
|
||||
else if (is_opclause(clause))
|
||||
{
|
||||
|
@ -792,15 +789,20 @@ replace_agg_clause(Node *clause, List *subplanTargetList)
|
|||
*/
|
||||
Node *left = (Node *) get_leftop((Expr *) clause);
|
||||
Node *right = (Node *) get_rightop((Expr *) clause);
|
||||
|
||||
|
||||
if (left != (Node *) NULL)
|
||||
replace_agg_clause(left, subplanTargetList);
|
||||
agg_list = nconc(agg_list,
|
||||
replace_agg_clause(left, subplanTargetList));
|
||||
if (right != (Node *) NULL)
|
||||
replace_agg_clause(right, subplanTargetList);
|
||||
agg_list = nconc(agg_list,
|
||||
replace_agg_clause(right, subplanTargetList));
|
||||
|
||||
return agg_list;
|
||||
}
|
||||
else if (IsA(clause, Param) ||IsA(clause, Const))
|
||||
{
|
||||
/* do nothing! */
|
||||
return NIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -809,8 +811,8 @@ replace_agg_clause(Node *clause, List *subplanTargetList)
|
|||
* Ooops! we can not handle that!
|
||||
*/
|
||||
elog(ERROR, "replace_agg_clause: Can not handle this tlist!\n");
|
||||
return NIL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.17 1997/12/29 04:31:23 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.18 1998/01/15 18:59:53 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -185,8 +185,7 @@ plan_union_queries(Query *parse)
|
|||
parse->uniqueFlag = NULL;
|
||||
|
||||
parse->havingQual = NULL;
|
||||
parse->qry_numAgg = 0;
|
||||
parse->qry_aggs = NULL;
|
||||
parse->hasAggs = false;
|
||||
|
||||
return (make_append(union_plans,
|
||||
union_rts,
|
||||
|
@ -267,11 +266,9 @@ plan_inherit_query(List *relids,
|
|||
new_root->uniqueFlag = NULL;
|
||||
new_root->sortClause = NULL;
|
||||
new_root->groupClause = NULL;
|
||||
if (new_root->qry_numAgg != 0)
|
||||
if (new_root->hasAggs)
|
||||
{
|
||||
new_root->qry_numAgg = 0;
|
||||
pfree(new_root->qry_aggs);
|
||||
new_root->qry_aggs = NULL;
|
||||
new_root->hasAggs = false;
|
||||
del_agg_tlist_references(new_root->targetList);
|
||||
}
|
||||
fix_parsetree_attnums(rt_index,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.64 1998/01/11 03:41:35 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.65 1998/01/15 18:59:56 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -219,7 +219,7 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
|
|||
qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
|
||||
|
||||
/* make sure we don't have aggregates in the where clause */
|
||||
if (pstate->p_numAgg > 0)
|
||||
if (pstate->p_hasAggs)
|
||||
parseCheckAggregates(pstate, qry);
|
||||
|
||||
return (Query *) qry;
|
||||
|
@ -334,7 +334,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
|
|||
qry->targetList,
|
||||
qry->uniqueFlag);
|
||||
|
||||
if (pstate->p_numAgg > 0)
|
||||
if (pstate->p_hasAggs)
|
||||
finalizeAggregates(pstate, qry);
|
||||
|
||||
qry->unionall = stmt->unionall; /* in child, so unionClause may be false */
|
||||
|
@ -796,8 +796,7 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
|
|||
|
||||
pstate->p_last_resno = 1;
|
||||
pstate->p_is_rule = true; /* for expand all */
|
||||
pstate->p_numAgg = 0;
|
||||
pstate->p_aggs = NULL;
|
||||
pstate->p_hasAggs = false;
|
||||
|
||||
lfirst(actions) = transformStmt(pstate, lfirst(actions));
|
||||
actions = lnext(actions);
|
||||
|
@ -853,7 +852,7 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
|
|||
qry->targetList);
|
||||
qry->rtable = pstate->p_rtable;
|
||||
|
||||
if (pstate->p_numAgg > 0)
|
||||
if (pstate->p_hasAggs)
|
||||
finalizeAggregates(pstate, qry);
|
||||
|
||||
qry->unionall = stmt->unionall; /* in child, so unionClause may be false */
|
||||
|
@ -890,11 +889,11 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
|||
qry->rtable = pstate->p_rtable;
|
||||
qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
|
||||
|
||||
if (pstate->p_numAgg > 0)
|
||||
if (pstate->p_hasAggs)
|
||||
finalizeAggregates(pstate, qry);
|
||||
|
||||
/* make sure we don't have aggregates in the where clause */
|
||||
if (pstate->p_numAgg > 0)
|
||||
if (pstate->p_hasAggs)
|
||||
parseCheckAggregates(pstate, qry);
|
||||
|
||||
return (Query *) qry;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.6 1998/01/05 03:32:25 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.7 1998/01/15 18:59:59 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -34,64 +34,17 @@ static bool contain_agg_clause(Node *clause);
|
|||
static bool exprIsAggOrGroupCol(Node *expr, List *groupClause);
|
||||
static bool tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause);
|
||||
|
||||
/*
|
||||
* AddAggToParseState -
|
||||
* add the aggregate to the list of unique aggregates in pstate.
|
||||
*
|
||||
* SIDE EFFECT: aggno in target list entry will be modified
|
||||
*/
|
||||
void
|
||||
AddAggToParseState(ParseState *pstate, Aggreg *aggreg)
|
||||
{
|
||||
List *ag;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* see if we have the aggregate already (we only need to record the
|
||||
* aggregate once)
|
||||
*/
|
||||
i = 0;
|
||||
foreach(ag, pstate->p_aggs)
|
||||
{
|
||||
Aggreg *a = lfirst(ag);
|
||||
|
||||
if (!strcmp(a->aggname, aggreg->aggname) &&
|
||||
equal(a->target, aggreg->target))
|
||||
{
|
||||
|
||||
/* fill in the aggno and we're done */
|
||||
aggreg->aggno = i;
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
/* not found, new aggregate */
|
||||
aggreg->aggno = i;
|
||||
pstate->p_numAgg++;
|
||||
pstate->p_aggs = lappend(pstate->p_aggs, aggreg);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* finalizeAggregates -
|
||||
* fill in qry_aggs from pstate. Also checks to make sure that aggregates
|
||||
* fill in hasAggs from pstate. Also checks to make sure that aggregates
|
||||
* are used in the proper place.
|
||||
*/
|
||||
void
|
||||
finalizeAggregates(ParseState *pstate, Query *qry)
|
||||
{
|
||||
List *l;
|
||||
int i;
|
||||
|
||||
parseCheckAggregates(pstate, qry);
|
||||
|
||||
qry->qry_numAgg = pstate->p_numAgg;
|
||||
qry->qry_aggs =
|
||||
(Aggreg **) palloc(sizeof(Aggreg *) * qry->qry_numAgg);
|
||||
i = 0;
|
||||
foreach(l, pstate->p_aggs)
|
||||
qry->qry_aggs[i++] = (Aggreg *) lfirst(l);
|
||||
qry->hasAggs = pstate->p_hasAggs;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -240,7 +193,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
|
|||
{
|
||||
List *tl;
|
||||
|
||||
Assert(pstate->p_numAgg > 0);
|
||||
Assert(pstate->p_hasAggs);
|
||||
|
||||
/*
|
||||
* aggregates never appear in WHERE clauses. (we have to check where
|
||||
|
@ -393,6 +346,8 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
|
|||
if (usenulls)
|
||||
aggreg->usenulls = true;
|
||||
|
||||
pstate->p_hasAggs = true;
|
||||
|
||||
return aggreg;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.5 1998/01/05 03:32:28 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.6 1998/01/15 19:00:02 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -221,13 +221,8 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs,
|
|||
PointerGetDatum(funcname),
|
||||
ObjectIdGetDatum(basetype),
|
||||
0, 0))
|
||||
{
|
||||
Aggreg *aggreg = ParseAgg(pstate, funcname, basetype,
|
||||
return (Node *)ParseAgg(pstate, funcname, basetype,
|
||||
fargs, precedence);
|
||||
|
||||
AddAggToParseState(pstate, aggreg);
|
||||
return (Node *) aggreg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.5 1998/01/05 03:32:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.6 1998/01/15 19:00:04 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -49,8 +49,7 @@ make_parsestate(void)
|
|||
pstate = palloc(sizeof(ParseState));
|
||||
pstate->p_last_resno = 1;
|
||||
pstate->p_rtable = NIL;
|
||||
pstate->p_numAgg = 0;
|
||||
pstate->p_aggs = NIL;
|
||||
pstate->p_hasAggs = false;
|
||||
pstate->p_is_insert = false;
|
||||
pstate->p_insert_columns = NIL;
|
||||
pstate->p_is_update = false;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.6 1998/01/04 04:31:27 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.7 1998/01/15 19:00:06 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -95,7 +95,6 @@ thisLockWasTriggered(int varno,
|
|||
AttrNumber attnum,
|
||||
Query *parsetree)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (nodeThisLockWasTriggered(parsetree->qual, varno, attnum))
|
||||
return true;
|
||||
|
@ -103,10 +102,6 @@ thisLockWasTriggered(int varno,
|
|||
if (nodeThisLockWasTriggered((Node *) parsetree->targetList, varno, attnum))
|
||||
return true;
|
||||
|
||||
for(i=0; i < parsetree->qry_numAgg; i++)
|
||||
if (nodeThisLockWasTriggered(parsetree->qry_aggs[i]->target,
|
||||
varno, attnum))
|
||||
return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.9 1998/01/04 04:31:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.10 1998/01/15 19:00:07 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -420,16 +420,12 @@ HandleRIRAttributeRule(Query *parsetree,
|
|||
int *modified,
|
||||
int *badsql)
|
||||
{
|
||||
int i;
|
||||
|
||||
nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable,
|
||||
targetlist, rt_index, attr_num,
|
||||
modified, badsql);
|
||||
nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist,
|
||||
rt_index, attr_num, modified, badsql);
|
||||
for(i=0; i < parsetree->qry_numAgg; i++)
|
||||
nodeHandleRIRAttributeRule(&parsetree->qry_aggs[i]->target, rtable,
|
||||
targetlist, rt_index, attr_num, modified, badsql);
|
||||
}
|
||||
|
||||
|
||||
|
@ -521,13 +517,9 @@ HandleViewRule(Query *parsetree,
|
|||
int rt_index,
|
||||
int *modified)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
|
||||
modified);
|
||||
nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist,
|
||||
rt_index, modified);
|
||||
for(i=0; i < parsetree->qry_numAgg; i++)
|
||||
nodeHandleViewRule(&parsetree->qry_aggs[i]->target, rtable, targetlist, rt_index,
|
||||
modified);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parsenodes.h,v 1.43 1998/01/11 03:41:49 momjian Exp $
|
||||
* $Id: parsenodes.h,v 1.44 1998/01/15 19:00:11 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -44,6 +44,7 @@ typedef struct Query
|
|||
bool isPortal; /* is this a retrieve into portal? */
|
||||
bool isBinary; /* binary portal? */
|
||||
bool unionall; /* union without unique sort */
|
||||
bool hasAggs; /* has aggregates in target list */
|
||||
|
||||
char *uniqueFlag; /* NULL, '*', or Unique attribute name */
|
||||
List *sortClause; /* a list of SortClause's */
|
||||
|
@ -56,9 +57,6 @@ typedef struct Query
|
|||
* BY */
|
||||
Node *havingQual; /* qualification of each group */
|
||||
|
||||
int qry_numAgg; /* number of aggregates in the target list */
|
||||
Aggreg **qry_aggs; /* the aggregates */
|
||||
|
||||
List *unionClause; /* unions are linked under the previous query */
|
||||
|
||||
/* internal to planner */
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: plannodes.h,v 1.12 1997/12/27 06:41:41 momjian Exp $
|
||||
* $Id: plannodes.h,v 1.13 1998/01/15 19:00:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -214,8 +214,7 @@ typedef struct HashJoin
|
|||
typedef struct Agg
|
||||
{
|
||||
Plan plan;
|
||||
int numAgg;
|
||||
Aggreg **aggs;
|
||||
List *aggs;
|
||||
AggState *aggstate;
|
||||
} Agg;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: planmain.h,v 1.9 1997/12/20 07:59:43 momjian Exp $
|
||||
* $Id: planmain.h,v 1.10 1998/01/15 19:00:15 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -33,7 +33,7 @@ extern SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid,
|
|||
Plan *lefttree);
|
||||
extern Sort *make_sort(List *tlist, Oid tempid, Plan *lefttree,
|
||||
int keycount);
|
||||
extern Agg *make_agg(List *tlist, int nagg, Aggreg **aggs, Plan *lefttree);
|
||||
extern Agg *make_agg(List *tlist, Plan *lefttree);
|
||||
extern Group *make_group(List *tlist, bool tuplePerGroup, int ngrp,
|
||||
AttrNumber *grpColIdx, Sort *lefttree);
|
||||
extern Unique *make_unique(List *tlist, Plan *lefttree, char *uniqueAttr);
|
||||
|
@ -55,7 +55,7 @@ extern List *join_references(List *clauses, List *outer_tlist,
|
|||
extern List *index_outerjoin_references(List *inner_indxqual,
|
||||
List *outer_tlist, Index inner_relid);
|
||||
extern void set_result_tlist_references(Result *resultNode);
|
||||
extern void set_agg_tlist_references(Agg *aggNode);
|
||||
extern List *set_agg_tlist_references(Agg *aggNode);
|
||||
extern void set_agg_agglist_references(Agg *aggNode);
|
||||
extern void del_agg_tlist_references(List *tlist);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parse_node.h,v 1.3 1997/11/26 03:43:13 momjian Exp $
|
||||
* $Id: parse_node.h,v 1.4 1998/01/15 19:00:16 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -30,10 +30,9 @@ typedef struct ParseState
|
|||
{
|
||||
int p_last_resno;
|
||||
List *p_rtable;
|
||||
int p_numAgg;
|
||||
List *p_aggs;
|
||||
bool p_is_insert;
|
||||
List *p_insert_columns;
|
||||
bool p_hasAggs;
|
||||
bool p_is_insert;
|
||||
bool p_is_update;
|
||||
bool p_is_rule;
|
||||
bool p_in_where_clause;
|
||||
|
|
Loading…
Reference in New Issue