Commit 4b05912f authored by Bruce Momjian's avatar Bruce Momjian

Fix for count(*), aggs with views and multiple tables and sum(3).

parent c629d3b9
...@@ -278,7 +278,7 @@ ExecAgg(Agg *node) ...@@ -278,7 +278,7 @@ ExecAgg(Agg *node)
for (i = 0; i < nagg; i++) for (i = 0; i < nagg; i++)
{ {
AttrNumber attnum; AttrNumber attnum;
int2 attlen; int2 attlen = 0;
Datum newVal = (Datum) NULL; Datum newVal = (Datum) NULL;
AggFuncInfo *aggfns = &aggFuncInfo[i]; AggFuncInfo *aggfns = &aggFuncInfo[i];
Datum args[2]; Datum args[2];
...@@ -298,18 +298,24 @@ ExecAgg(Agg *node) ...@@ -298,18 +298,24 @@ ExecAgg(Agg *node)
newVal = ExecEvalExpr(aggregates[i]->target, econtext, newVal = ExecEvalExpr(aggregates[i]->target, econtext,
&isNull, &isDone); &isNull, &isDone);
break; break;
case T_Const:
tagnode = NULL;
econtext->ecxt_scantuple = outerslot;
newVal = ExecEvalExpr(aggregates[i]->target, econtext,
&isNull, &isDone);
break;
default: default:
elog(WARN, "ExecAgg: Bad Agg->Target for Agg %d", i); elog(WARN, "ExecAgg: Bad Agg->Target for Agg %d", i);
} }
if (isNull) if (isNull && !aggregates[i]->usenulls)
continue; /* ignore this tuple for this agg */ continue; /* ignore this tuple for this agg */
if (aggfns->xfn1) if (aggfns->xfn1)
{ {
if (noInitValue[i]) if (noInitValue[i])
{ {
int byVal; int byVal = 0;
/* /*
* value1 and value2 has not been initialized. This is * value1 and value2 has not been initialized. This is
...@@ -322,22 +328,34 @@ ExecAgg(Agg *node) ...@@ -322,22 +328,34 @@ ExecAgg(Agg *node)
* a copy of it since the tuple from which it came * a copy of it since the tuple from which it came
* will be freed on the next iteration of the scan * will be freed on the next iteration of the scan
*/ */
if (tagnode != NULL) switch (nodeTag(aggregates[i]->target))
{
FunctionCachePtr fcache_ptr;
if (nodeTag(tagnode) == T_Func)
fcache_ptr = ((Func *) tagnode)->func_fcache;
else
fcache_ptr = ((Oper *) tagnode)->op_fcache;
attlen = fcache_ptr->typlen;
byVal = fcache_ptr->typbyval;
}
else
{ {
attnum = ((Var *) aggregates[i]->target)->varattno; case T_Var:
attlen = outerslot->ttc_tupleDescriptor->attrs[attnum - 1]->attlen; attnum = ((Var *) aggregates[i]->target)->varattno;
byVal = outerslot->ttc_tupleDescriptor->attrs[attnum - 1]->attbyval; attlen = outerslot->ttc_tupleDescriptor->attrs[attnum - 1]->attlen;
byVal = outerslot->ttc_tupleDescriptor->attrs[attnum - 1]->attbyval;
break;
case T_Expr:
{
FunctionCachePtr fcache_ptr;
if (nodeTag(tagnode) == T_Func)
fcache_ptr = ((Func *) tagnode)->func_fcache;
else
fcache_ptr = ((Oper *) tagnode)->op_fcache;
attlen = fcache_ptr->typlen;
byVal = fcache_ptr->typbyval;
break;
}
case T_Const:
attlen = ((Const *) aggregates[i]->target)->constlen;
byVal = ((Const *) aggregates[i]->target)->constbyval;
break;
default:
elog(WARN, "ExecAgg: Bad Agg->Target for Agg %d", i);
} }
if (attlen == -1) if (attlen == -1)
{ {
...@@ -349,7 +367,6 @@ ExecAgg(Agg *node) ...@@ -349,7 +367,6 @@ ExecAgg(Agg *node)
value1[i] = newVal; value1[i] = newVal;
else else
memmove((char *) (value1[i]), (char *) newVal, attlen); memmove((char *) (value1[i]), (char *) newVal, attlen);
/* value1[i] = newVal; */
noInitValue[i] = 0; noInitValue[i] = 0;
nulls[i] = 0; nulls[i] = 0;
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.26 1997/12/24 06:05:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.27 1998/01/04 04:31:02 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -899,6 +899,7 @@ _copyAggreg(Aggreg *from) ...@@ -899,6 +899,7 @@ _copyAggreg(Aggreg *from)
newnode->aggname = pstrdup(from->aggname); newnode->aggname = pstrdup(from->aggname);
newnode->basetype = from->basetype; newnode->basetype = from->basetype;
newnode->aggtype = from->aggtype; newnode->aggtype = from->aggtype;
newnode->usenulls = from->usenulls;
Node_Copy(from, newnode, target); Node_Copy(from, newnode, target);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.82 1998/01/01 05:44:53 thomas Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.83 1998/01/04 04:31:08 momjian Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -2381,8 +2381,6 @@ OptUseOp: USING Op { $$ = $2; } ...@@ -2381,8 +2381,6 @@ OptUseOp: USING Op { $$ = $2; }
* *
* ...however, recursive addattr and rename supported. make special * ...however, recursive addattr and rename supported. make special
* cases for these. * cases for these.
*
* XXX i believe '*' should be the default behavior, but...
*/ */
opt_inh_star: '*' { $$ = TRUE; } opt_inh_star: '*' { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; } | /*EMPTY*/ { $$ = FALSE; }
...@@ -2978,11 +2976,12 @@ a_expr: attr opt_indirection ...@@ -2978,11 +2976,12 @@ a_expr: attr opt_indirection
} }
| name '(' '*' ')' | name '(' '*' ')'
{ {
/* cheap hack for aggregate (eg. count) */
FuncCall *n = makeNode(FuncCall); FuncCall *n = makeNode(FuncCall);
Ident *star = makeNode(Ident); A_Const *star = makeNode(A_Const);
/* cheap hack for aggregate (eg. count) */ star->val.type = T_String;
star->name = "oid"; star->val.val.str = "";
n->funcname = $1; n->funcname = $1;
n->args = lcons(star, NIL); n->args = lcons(star, NIL);
$$ = (Node *)n; $$ = (Node *)n;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.4 1997/12/22 05:42:19 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.5 1998/01/04 04:31:14 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -18,14 +18,17 @@ ...@@ -18,14 +18,17 @@
#include "postgres.h" #include "postgres.h"
#include "access/heapam.h" #include "access/heapam.h"
#include "catalog/pg_aggregate.h" #include "catalog/pg_aggregate.h"
#include "catalog/pg_type.h"
#include "nodes/nodeFuncs.h" #include "nodes/nodeFuncs.h"
#include "nodes/primnodes.h" #include "nodes/primnodes.h"
#include "nodes/relation.h" #include "nodes/relation.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "parser/parse_agg.h" #include "parser/parse_agg.h"
#include "parser/parse_expr.h"
#include "parser/parse_node.h" #include "parser/parse_node.h"
#include "parser/parse_target.h" #include "parser/parse_target.h"
#include "utils/syscache.h" #include "utils/syscache.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);
...@@ -276,7 +279,8 @@ parseCheckAggregates(ParseState *pstate, Query *qry) ...@@ -276,7 +279,8 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
Aggreg * Aggreg *
ParseAgg(char *aggname, Oid basetype, Node *target) ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
List *target, int precedence)
{ {
Oid fintype; Oid fintype;
Oid vartype; Oid vartype;
...@@ -284,7 +288,8 @@ ParseAgg(char *aggname, Oid basetype, Node *target) ...@@ -284,7 +288,8 @@ ParseAgg(char *aggname, Oid basetype, Node *target)
Form_pg_aggregate aggform; Form_pg_aggregate aggform;
Aggreg *aggreg; Aggreg *aggreg;
HeapTuple theAggTuple; HeapTuple theAggTuple;
bool usenulls = false;
theAggTuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggname), theAggTuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggname),
ObjectIdGetDatum(basetype), ObjectIdGetDatum(basetype),
0, 0); 0, 0);
...@@ -293,21 +298,78 @@ ParseAgg(char *aggname, Oid basetype, Node *target) ...@@ -293,21 +298,78 @@ ParseAgg(char *aggname, Oid basetype, Node *target)
elog(WARN, "aggregate %s does not exist", aggname); elog(WARN, "aggregate %s does not exist", aggname);
} }
/*
* We do a major hack for count(*) here.
*
* Count(*) poses several problems. First, we need a field that is
* guaranteed to be in the range table, and unique. Using a constant
* causes the optimizer to properly remove the aggragate from any
* elements of the query.
* Using just 'oid', which can not be null, in the parser fails on:
*
* select count(*) from tab1, tab2 -- oid is not unique
* select count(*) from viewtable -- views don't have real oids
*
* So, for an aggregate with parameter '*', we use the first valid
* range table entry, and pick the first column from the table.
* We set a flag to count nulls, because we could have nulls in
* that column.
*/
if (nodeTag(lfirst(target)) == T_Const)
{
Const *con = (Const *)lfirst(target);
if (con->consttype == UNKNOWNOID && VARSIZE(con->constvalue) == VARHDRSZ)
{
Attr *attr = makeNode(Attr);
List *rtable, *rlist;
RangeTblEntry *first_valid_rte;
Assert(lnext(target) == NULL);
if (pstate->p_is_rule)
rtable = lnext(lnext(pstate->p_rtable));
else
rtable = pstate->p_rtable;
first_valid_rte = NULL;
foreach(rlist, rtable)
{
RangeTblEntry *rte = lfirst(rlist);
/* only entries on outer(non-function?) scope */
if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
continue;
first_valid_rte =rte;
break;
}
if (first_valid_rte == NULL)
elog(WARN, "Can't find column to do aggregate(*) on.");
attr->relname = first_valid_rte->refname;
attr->attrs = lcons(makeString(
get_attname(first_valid_rte->relid,1)),NIL);
lfirst(target) = transformExpr(pstate, (Node *) attr, precedence);
usenulls = true;
}
}
aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple); aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
fintype = aggform->aggfinaltype; fintype = aggform->aggfinaltype;
xfn1 = aggform->aggtransfn1; xfn1 = aggform->aggtransfn1;
if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
/* only aggregates with transfn1 need a base type */ /* only aggregates with transfn1 need a base type */
if (OidIsValid(xfn1)) if (OidIsValid(xfn1))
{ {
basetype = aggform->aggbasetype; basetype = aggform->aggbasetype;
if (nodeTag(target) == T_Var) if (nodeTag(lfirst(target)) == T_Var)
vartype = ((Var *) target)->vartype; vartype = ((Var *) lfirst(target))->vartype;
else else
vartype = ((Expr *) target)->typeOid; vartype = ((Expr *) lfirst(target))->typeOid;
if (basetype != vartype) if (basetype != vartype)
{ {
...@@ -327,7 +389,9 @@ ParseAgg(char *aggname, Oid basetype, Node *target) ...@@ -327,7 +389,9 @@ ParseAgg(char *aggname, Oid basetype, Node *target)
aggreg->basetype = aggform->aggbasetype; aggreg->basetype = aggform->aggbasetype;
aggreg->aggtype = fintype; aggreg->aggtype = fintype;
aggreg->target = target; aggreg->target = lfirst(target);
if (usenulls)
aggreg->usenulls = true;
return aggreg; return aggreg;
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.3 1997/11/26 03:42:42 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.4 1998/01/04 04:31:18 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -87,7 +87,8 @@ typedef struct _SuperQE ...@@ -87,7 +87,8 @@ typedef struct _SuperQE
*/ */
Node * Node *
ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno) ParseFunc(ParseState *pstate, char *funcname, List *fargs,
int *curr_resno, int precedence)
{ {
Oid rettype = (Oid) 0; Oid rettype = (Oid) 0;
Oid argrelid = (Oid) 0; Oid argrelid = (Oid) 0;
...@@ -194,9 +195,7 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno) ...@@ -194,9 +195,7 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
*/ */
if ((get_attnum(argrelid, funcname) == InvalidAttrNumber) if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
&& strcmp(funcname, "*")) && strcmp(funcname, "*"))
{
elog(WARN, "Functions on sets are not yet supported"); elog(WARN, "Functions on sets are not yet supported");
}
} }
if (retval) if (retval)
...@@ -223,7 +222,8 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno) ...@@ -223,7 +222,8 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
ObjectIdGetDatum(basetype), ObjectIdGetDatum(basetype),
0, 0)) 0, 0))
{ {
Aggreg *aggreg = ParseAgg(funcname, basetype, lfirst(fargs)); Aggreg *aggreg = ParseAgg(pstate, funcname, basetype,
fargs, precedence);
AddAggToParseState(pstate, aggreg); AddAggToParseState(pstate, aggreg);
return (Node *) aggreg; return (Node *) aggreg;
...@@ -368,7 +368,7 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno) ...@@ -368,7 +368,7 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
else else
{ {
funcnode->func_tlist = setup_tlist(funcname, argrelid); funcnode->func_tlist = setup_tlist(funcname, argrelid);
rettype = attnameTypeId(argrelid, funcname); rettype = get_atttype(argrelid, get_attnum(argrelid, funcname));
} }
} }
...@@ -1031,7 +1031,7 @@ setup_tlist(char *attname, Oid relid) ...@@ -1031,7 +1031,7 @@ setup_tlist(char *attname, Oid relid)
if (attno < 0) if (attno < 0)
elog(WARN, "cannot reference attribute '%s' of tuple params/return values for functions", attname); elog(WARN, "cannot reference attribute '%s' of tuple params/return values for functions", attname);
typeid = attnameTypeId(relid, attname); typeid = get_atttype(relid, attno);
resnode = makeResdom(1, resnode = makeResdom(1,
typeid, typeid,
typeLen(typeidType(typeid)), typeLen(typeidType(typeid)),
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.3 1997/11/26 03:42:48 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.4 1998/01/04 04:31:19 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -346,34 +346,6 @@ attnumAttNelems(Relation rd, int attid) ...@@ -346,34 +346,6 @@ attnumAttNelems(Relation rd, int attid)
return (rd->rd_att->attrs[attid - 1]->attnelems); return (rd->rd_att->attrs[attid - 1]->attnelems);
} }
Oid
attnameTypeId(Oid relid, char *attrname)
{
int attid;
Oid vartype;
Relation rd;
rd = heap_open(relid);
if (!RelationIsValid(rd))
{
rd = heap_openr(typeidTypeName(relid));
if (!RelationIsValid(rd))
elog(WARN, "cannot compute type of att %s for relid %d",
attrname, relid);
}
attid = attnameAttNum(rd, attrname); /* could elog(WARN) and never return */
vartype = attnumTypeId(rd, attid);
/*
* close relation we're done with it now
*/
heap_close(rd);
return (vartype);
}
/* given attribute id, return type of that attribute */ /* given attribute id, return type of that attribute */
/* XXX Special case for pseudo-attributes is a hack */ /* XXX Special case for pseudo-attributes is a hack */
Oid Oid
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.3 1997/11/26 03:42:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.4 1998/01/04 04:31:22 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -255,7 +255,7 @@ transformTargetList(ParseState *pstate, List *targetlist) ...@@ -255,7 +255,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
* Target item is fully specified: ie. * Target item is fully specified: ie.
* relation.attribute * relation.attribute
*/ */
result = handleNestedDots(pstate, att, &pstate->p_last_resno); result = handleNestedDots(pstate, att, &pstate->p_last_resno,EXPR_COLUMN_FIRST);
handleTargetColname(pstate, &res->name, att->relname, attrname); handleTargetColname(pstate, &res->name, att->relname, attrname);
if (att->indirection != NIL) if (att->indirection != NIL)
{ {
...@@ -467,7 +467,8 @@ make_targetlist_expr(ParseState *pstate, ...@@ -467,7 +467,8 @@ make_targetlist_expr(ParseState *pstate,
att->relname = pstrdup(RelationGetRelationName(rd)->data); att->relname = pstrdup(RelationGetRelationName(rd)->data);
att->attrs = lcons(makeString(colname), NIL); att->attrs = lcons(makeString(colname), NIL);
target_expr = (Expr *) handleNestedDots(pstate, att, target_expr = (Expr *) handleNestedDots(pstate, att,
&pstate->p_last_resno); &pstate->p_last_resno,
EXPR_COLUMN_FIRST);
while (ar != NIL) while (ar != NIL)
{ {
A_Indices *ind = lfirst(ar); A_Indices *ind = lfirst(ar);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.5 1997/09/08 21:46:33 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.6 1998/01/04 04:31:27 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -58,6 +58,14 @@ nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum) ...@@ -58,6 +58,14 @@ nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum)
nodeThisLockWasTriggered(tle->expr, varno, attnum); nodeThisLockWasTriggered(tle->expr, varno, attnum);
} }
break; break;
case T_Aggreg:
{
Aggreg *agg = (Aggreg *) node;
return
nodeThisLockWasTriggered(agg->target, varno, attnum);
}
break;
case T_List: case T_List:
{ {
List *l; List *l;
...@@ -87,10 +95,20 @@ thisLockWasTriggered(int varno, ...@@ -87,10 +95,20 @@ thisLockWasTriggered(int varno,
AttrNumber attnum, AttrNumber attnum,
Query *parsetree) Query *parsetree)
{ {
return int i;
(nodeThisLockWasTriggered(parsetree->qual, varno, attnum) ||
nodeThisLockWasTriggered((Node *) parsetree->targetList, if (nodeThisLockWasTriggered(parsetree->qual, varno, attnum))
varno, attnum)); return true;
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 @@ ...@@ -6,7 +6,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.6 1997/09/08 21:46:38 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.7 1998/01/04 04:31:28 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -225,6 +225,7 @@ FireRetrieveRulesAtQuery(Query *parsetree, ...@@ -225,6 +225,7 @@ FireRetrieveRulesAtQuery(Query *parsetree,
{ {
*instead_flag = TRUE; *instead_flag = TRUE;
FixResdomTypes(parsetree->targetList); FixResdomTypes(parsetree->targetList);
return lcons(parsetree, NIL); return lcons(parsetree, NIL);
} }
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.8 1997/09/18 20:21:11 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.9 1998/01/04 04:31:29 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -46,6 +46,13 @@ OffsetVarNodes(Node *node, int offset) ...@@ -46,6 +46,13 @@ OffsetVarNodes(Node *node, int offset)
OffsetVarNodes(tle->expr, offset); OffsetVarNodes(tle->expr, offset);
} }
break; break;
case T_Aggreg:
{
Aggreg *agg = (Aggreg *) node;
OffsetVarNodes(agg->target, offset);
}
break;
case T_Expr: case T_Expr:
{ {
Expr *expr = (Expr *) node; Expr *expr = (Expr *) node;
...@@ -91,6 +98,13 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno) ...@@ -91,6 +98,13 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno)
ChangeVarNodes(tle->expr, old_varno, new_varno); ChangeVarNodes(tle->expr, old_varno, new_varno);
} }
break; break;
case T_Aggreg:
{
Aggreg *agg = (Aggreg *) node;
ChangeVarNodes(agg->target, old_varno, new_varno);
}
break;
case T_Expr: case T_Expr:
{ {
Expr *expr = (Expr *) node; Expr *expr = (Expr *) node;
...@@ -235,6 +249,9 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr) ...@@ -235,6 +249,9 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr)
case T_TargetEntry: case T_TargetEntry:
ResolveNew(info, targetlist, &((TargetEntry *) node)->expr); ResolveNew(info, targetlist, &((TargetEntry *) node)->expr);
break; break;
case T_Aggreg:
ResolveNew(info, targetlist, &((Aggreg *) node)->target);
break;
case T_Expr: case T_Expr:
ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args))); ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)));
break; break;
...@@ -325,6 +342,14 @@ nodeHandleRIRAttributeRule(Node **nodePtr, ...@@ -325,6 +342,14 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
rt_index, attr_num, modified, badsql); rt_index, attr_num, modified, badsql);
} }
break; break;
case T_Aggreg:
{
Aggreg *agg = (Aggreg *) node;
nodeHandleRIRAttributeRule(&agg->target, rtable, targetlist,
rt_index, attr_num, modified, badsql);
}
break;
case T_Expr: case T_Expr:
{ {
Expr *expr = (Expr *) node; Expr *expr = (Expr *) node;
...@@ -395,11 +420,16 @@ HandleRIRAttributeRule(Query *parsetree, ...@@ -395,11 +420,16 @@ HandleRIRAttributeRule(Query *parsetree,
int *modified, int *modified,
int *badsql) int *badsql)
{ {
int i;
nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable, nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable,
targetlist, rt_index, attr_num, targetlist, rt_index, attr_num,
modified, badsql); modified, badsql);
nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist, nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist,
rt_index, attr_num, modified, badsql); 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);
} }
...@@ -437,6 +467,14 @@ nodeHandleViewRule(Node **nodePtr, ...@@ -437,6 +467,14 @@ nodeHandleViewRule(Node **nodePtr,
rt_index, modified); rt_index, modified);
} }
break; break;
case T_Aggreg:
{
Aggreg *agg = (Aggreg *) node;
nodeHandleViewRule(&(agg->target), rtable, targetlist,
rt_index, modified);
}
break;
case T_Expr: case T_Expr:
{ {
Expr *expr = (Expr *) node; Expr *expr = (Expr *) node;
...@@ -483,8 +521,13 @@ HandleViewRule(Query *parsetree, ...@@ -483,8 +521,13 @@ HandleViewRule(Query *parsetree,
int rt_index, int rt_index,
int *modified) int *modified)
{ {
int i;
nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index, nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
modified); modified);
nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist, nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist,
rt_index, modified); 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 @@ ...@@ -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.11 1997/09/08 21:52:58 momjian Exp $ * $Id: primnodes.h,v 1.12 1998/01/04 04:31:37 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -255,18 +255,19 @@ typedef struct Func ...@@ -255,18 +255,19 @@ typedef struct Func
* aggname - name of the aggregate * aggname - name of the aggregate
* basetype - base type Oid of the aggregate * basetype - base type Oid of the aggregate
* aggtype - type Oid of final result of the aggregate * aggtype - type Oid of final result of the aggregate
* query - XXX comment me * target - attribute or expression we are aggregating on
* target - XXX comment me * aggno - index to ecxt_values
* ---------------- * ----------------
*/ */
typedef struct Aggreg typedef struct Aggreg
{ {
NodeTag type; NodeTag type;
char *aggname; char *aggname;
Oid basetype; /* base type of the aggregate */ Oid basetype;
Oid aggtype; /* type of final result */ Oid aggtype;
Node *target; /* attribute to aggreg on */ Node *target;
int aggno; /* index to ecxt_values */ int aggno;
bool usenulls;
} Aggreg; } Aggreg;
/* ---------------- /* ----------------
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_agg.h,v 1.3 1997/11/26 03:43:08 momjian Exp $ * $Id: parse_agg.h,v 1.4 1998/01/04 04:31:39 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
extern void AddAggToParseState(ParseState *pstate, Aggreg *aggreg); extern void AddAggToParseState(ParseState *pstate, Aggreg *aggreg);
extern void finalizeAggregates(ParseState *pstate, Query *qry); extern void finalizeAggregates(ParseState *pstate, Query *qry);
extern void parseCheckAggregates(ParseState *pstate, Query *qry); extern void parseCheckAggregates(ParseState *pstate, Query *qry);
extern Aggreg *ParseAgg(char *aggname, Oid basetype, Node *target); extern Aggreg *ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
List *target, int precedence);
extern void agg_error(char *caller, char *aggname, Oid basetypeID); extern void agg_error(char *caller, char *aggname, Oid basetypeID);
#endif /* PARSE_AGG_H */ #endif /* PARSE_AGG_H */
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_expr.h,v 1.3 1997/11/26 03:43:11 momjian Exp $ * $Id: parse_expr.h,v 1.4 1998/01/04 04:31:41 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
extern Node *transformExpr(ParseState *pstate, Node *expr, int precedence); extern Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
extern Node *transformIdent(ParseState *pstate, Node *expr, int precedence); extern Node *transformIdent(ParseState *pstate, Node *expr, int precedence);
extern Oid exprType(Node *expr); extern Oid exprType(Node *expr);
extern Node *handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno); extern Node *handleNestedDots(ParseState *pstate, Attr *attr,
int *curr_resno, int precedence);
extern Node *parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen); extern Node *parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen);
#endif /* PARSE_EXPR_H */ #endif /* PARSE_EXPR_H */
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_func.h,v 1.3 1997/11/26 03:43:12 momjian Exp $ * $Id: parse_func.h,v 1.4 1998/01/04 04:31:42 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -43,7 +43,7 @@ typedef struct _CandidateList ...@@ -43,7 +43,7 @@ typedef struct _CandidateList
} *CandidateList; } *CandidateList;
extern Node *ParseFunc(ParseState *pstate, char *funcname, List *fargs, extern Node *ParseFunc(ParseState *pstate, char *funcname, List *fargs,
int *curr_resno); int *curr_resno, int precedence);
extern void func_error(char *caller, char *funcname, int nargs, Oid *argtypes); extern void func_error(char *caller, char *funcname, int nargs, Oid *argtypes);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_relation.h,v 1.3 1997/11/26 03:43:16 momjian Exp $ * $Id: parse_relation.h,v 1.4 1998/01/04 04:31:43 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -34,7 +34,6 @@ extern int attnameAttNum(Relation rd, char *a); ...@@ -34,7 +34,6 @@ extern int attnameAttNum(Relation rd, char *a);
extern bool attnameIsSet(Relation rd, char *name); extern bool attnameIsSet(Relation rd, char *name);
extern char *attnumAttName(Relation rd, int attrno); extern char *attnumAttName(Relation rd, int attrno);
extern int attnumAttNelems(Relation rd, int attid); extern int attnumAttNelems(Relation rd, int attid);
extern Oid attnameTypeId(Oid relid, char *attrname);
extern Oid attnumTypeId(Relation rd, int attid); extern Oid attnumTypeId(Relation rd, int attid);
extern void handleTargetColname(ParseState *pstate, char **resname, extern void handleTargetColname(ParseState *pstate, char **resname,
char *refname, char *colname); char *refname, char *colname);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment