Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4b05912

Browse files
committed
Fix for count(*), aggs with views and multiple tables and sum(3).
1 parentc629d3b commit4b05912

File tree

15 files changed

+215
-97
lines changed

15 files changed

+215
-97
lines changed

‎src/backend/executor/nodeAgg.c

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ ExecAgg(Agg *node)
278278
for (i=0;i<nagg;i++)
279279
{
280280
AttrNumberattnum;
281-
int2attlen;
281+
int2attlen=0;
282282
DatumnewVal= (Datum)NULL;
283283
AggFuncInfo*aggfns=&aggFuncInfo[i];
284284
Datumargs[2];
@@ -298,18 +298,24 @@ ExecAgg(Agg *node)
298298
newVal=ExecEvalExpr(aggregates[i]->target,econtext,
299299
&isNull,&isDone);
300300
break;
301+
caseT_Const:
302+
tagnode=NULL;
303+
econtext->ecxt_scantuple=outerslot;
304+
newVal=ExecEvalExpr(aggregates[i]->target,econtext,
305+
&isNull,&isDone);
306+
break;
301307
default:
302308
elog(WARN,"ExecAgg: Bad Agg->Target for Agg %d",i);
303309
}
304310

305-
if (isNull)
311+
if (isNull&& !aggregates[i]->usenulls)
306312
continue;/* ignore this tuple for this agg */
307313

308314
if (aggfns->xfn1)
309315
{
310316
if (noInitValue[i])
311317
{
312-
intbyVal;
318+
intbyVal=0;
313319

314320
/*
315321
* value1 and value2 has not been initialized. This is
@@ -322,22 +328,34 @@ ExecAgg(Agg *node)
322328
* a copy of it since the tuple from which it came
323329
* will be freed on the next iteration of the scan
324330
*/
325-
if (tagnode!=NULL)
326-
{
327-
FunctionCachePtrfcache_ptr;
328-
329-
if (nodeTag(tagnode)==T_Func)
330-
fcache_ptr= ((Func*)tagnode)->func_fcache;
331-
else
332-
fcache_ptr= ((Oper*)tagnode)->op_fcache;
333-
attlen=fcache_ptr->typlen;
334-
byVal=fcache_ptr->typbyval;
335-
}
336-
else
331+
switch (nodeTag(aggregates[i]->target))
337332
{
338-
attnum= ((Var*)aggregates[i]->target)->varattno;
339-
attlen=outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attlen;
340-
byVal=outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attbyval;
333+
caseT_Var:
334+
attnum= ((Var*)aggregates[i]->target)->varattno;
335+
attlen=outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attlen;
336+
byVal=outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attbyval;
337+
338+
break;
339+
caseT_Expr:
340+
{
341+
FunctionCachePtrfcache_ptr;
342+
343+
if (nodeTag(tagnode)==T_Func)
344+
fcache_ptr= ((Func*)tagnode)->func_fcache;
345+
else
346+
fcache_ptr= ((Oper*)tagnode)->op_fcache;
347+
attlen=fcache_ptr->typlen;
348+
byVal=fcache_ptr->typbyval;
349+
350+
break;
351+
}
352+
caseT_Const:
353+
attlen= ((Const*)aggregates[i]->target)->constlen;
354+
byVal= ((Const*)aggregates[i]->target)->constbyval;
355+
356+
break;
357+
default:
358+
elog(WARN,"ExecAgg: Bad Agg->Target for Agg %d",i);
341359
}
342360
if (attlen==-1)
343361
{
@@ -349,7 +367,6 @@ ExecAgg(Agg *node)
349367
value1[i]=newVal;
350368
else
351369
memmove((char*) (value1[i]), (char*)newVal,attlen);
352-
/* value1[i] = newVal; */
353370
noInitValue[i]=0;
354371
nulls[i]=0;
355372
}

‎src/backend/nodes/copyfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.26 1997/12/24 06:05:52 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.27 1998/01/04 04:31:02 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -899,6 +899,7 @@ _copyAggreg(Aggreg *from)
899899
newnode->aggname=pstrdup(from->aggname);
900900
newnode->basetype=from->basetype;
901901
newnode->aggtype=from->aggtype;
902+
newnode->usenulls=from->usenulls;
902903

903904
Node_Copy(from,newnode,target);
904905

‎src/backend/parser/gram.y

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.82 1998/01/01 05:44:53 thomas Exp $
13+
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.83 1998/01/04 04:31:08 momjian Exp $
1414
*
1515
* HISTORY
1616
* AUTHORDATEMAJOR EVENT
@@ -2381,8 +2381,6 @@ OptUseOp: USING Op{ $$ = $2; }
23812381
*
23822382
*...however, recursive addattr and rename supported. make special
23832383
*cases for these.
2384-
*
2385-
*XXX i believe '*' should be the default behavior, but...
23862384
*/
23872385
opt_inh_star: '*'{ $$ = TRUE; }
23882386
| /*EMPTY*/{ $$ = FALSE; }
@@ -2978,11 +2976,12 @@ a_expr: attr opt_indirection
29782976
}
29792977
| name '(' '*' ')'
29802978
{
2979+
/* cheap hack for aggregate (eg. count) */
29812980
FuncCall *n = makeNode(FuncCall);
2982-
Ident *star = makeNode(Ident);
2981+
A_Const *star = makeNode(A_Const);
29832982

2984-
/* cheap hack for aggregate (eg. count) */
2985-
star->name = "oid";
2983+
star->val.type = T_String;
2984+
star->val.val.str = "";
29862985
n->funcname = $1;
29872986
n->args = lcons(star, NIL);
29882987
$$ = (Node *)n;

‎src/backend/parser/parse_agg.c

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.4 1997/12/22 05:42:19 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.5 1998/01/04 04:31:14 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -18,14 +18,17 @@
1818
#include"postgres.h"
1919
#include"access/heapam.h"
2020
#include"catalog/pg_aggregate.h"
21+
#include"catalog/pg_type.h"
2122
#include"nodes/nodeFuncs.h"
2223
#include"nodes/primnodes.h"
2324
#include"nodes/relation.h"
2425
#include"optimizer/clauses.h"
2526
#include"parser/parse_agg.h"
27+
#include"parser/parse_expr.h"
2628
#include"parser/parse_node.h"
2729
#include"parser/parse_target.h"
2830
#include"utils/syscache.h"
31+
#include"utils/lsyscache.h"
2932

3033
staticboolcontain_agg_clause(Node*clause);
3134
staticboolexprIsAggOrGroupCol(Node*expr,List*groupClause);
@@ -276,15 +279,17 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
276279

277280

278281
Aggreg*
279-
ParseAgg(char*aggname,Oidbasetype,Node*target)
282+
ParseAgg(ParseState*pstate,char*aggname,Oidbasetype,
283+
List*target,intprecedence)
280284
{
281285
Oidfintype;
282286
Oidvartype;
283287
Oidxfn1;
284288
Form_pg_aggregateaggform;
285289
Aggreg*aggreg;
286290
HeapTupletheAggTuple;
287-
291+
boolusenulls= false;
292+
288293
theAggTuple=SearchSysCacheTuple(AGGNAME,PointerGetDatum(aggname),
289294
ObjectIdGetDatum(basetype),
290295
0,0);
@@ -293,21 +298,78 @@ ParseAgg(char *aggname, Oid basetype, Node *target)
293298
elog(WARN,"aggregate %s does not exist",aggname);
294299
}
295300

301+
/*
302+
*We do a major hack for count(*) here.
303+
*
304+
*Count(*) poses several problems. First, we need a field that is
305+
*guaranteed to be in the range table, and unique. Using a constant
306+
*causes the optimizer to properly remove the aggragate from any
307+
*elements of the query.
308+
*Using just 'oid', which can not be null, in the parser fails on:
309+
*
310+
*select count(*) from tab1, tab2 -- oid is not unique
311+
*select count(*) from viewtable-- views don't have real oids
312+
*
313+
*So, for an aggregate with parameter '*', we use the first valid
314+
*range table entry, and pick the first column from the table.
315+
*We set a flag to count nulls, because we could have nulls in
316+
*that column.
317+
*/
318+
319+
if (nodeTag(lfirst(target))==T_Const)
320+
{
321+
Const*con= (Const*)lfirst(target);
322+
323+
if (con->consttype==UNKNOWNOID&&VARSIZE(con->constvalue)==VARHDRSZ)
324+
{
325+
Attr*attr=makeNode(Attr);
326+
List*rtable,*rlist;
327+
RangeTblEntry*first_valid_rte;
328+
329+
Assert(lnext(target)==NULL);
330+
331+
if (pstate->p_is_rule)
332+
rtable=lnext(lnext(pstate->p_rtable));
333+
else
334+
rtable=pstate->p_rtable;
335+
336+
first_valid_rte=NULL;
337+
foreach(rlist,rtable)
338+
{
339+
RangeTblEntry*rte=lfirst(rlist);
340+
341+
/* only entries on outer(non-function?) scope */
342+
if (!rte->inFromCl&&rte!=pstate->p_target_rangetblentry)
343+
continue;
344+
345+
first_valid_rte=rte;
346+
break;
347+
}
348+
if (first_valid_rte==NULL)
349+
elog(WARN,"Can't find column to do aggregate(*) on.");
350+
351+
attr->relname=first_valid_rte->refname;
352+
attr->attrs=lcons(makeString(
353+
get_attname(first_valid_rte->relid,1)),NIL);
354+
355+
lfirst(target)=transformExpr(pstate, (Node*)attr,precedence);
356+
usenulls= true;
357+
}
358+
}
359+
296360
aggform= (Form_pg_aggregate)GETSTRUCT(theAggTuple);
297361
fintype=aggform->aggfinaltype;
298362
xfn1=aggform->aggtransfn1;
299363

300-
if (nodeTag(target)!=T_Var&&nodeTag(target)!=T_Expr)
301-
elog(WARN,"parser: aggregate can only be applied on an attribute or expression");
302-
364+
303365
/* only aggregates with transfn1 need a base type */
304366
if (OidIsValid(xfn1))
305367
{
306368
basetype=aggform->aggbasetype;
307-
if (nodeTag(target)==T_Var)
308-
vartype= ((Var*)target)->vartype;
369+
if (nodeTag(lfirst(target))==T_Var)
370+
vartype= ((Var*)lfirst(target))->vartype;
309371
else
310-
vartype= ((Expr*)target)->typeOid;
372+
vartype= ((Expr*)lfirst(target))->typeOid;
311373

312374
if (basetype!=vartype)
313375
{
@@ -327,7 +389,9 @@ ParseAgg(char *aggname, Oid basetype, Node *target)
327389
aggreg->basetype=aggform->aggbasetype;
328390
aggreg->aggtype=fintype;
329391

330-
aggreg->target=target;
392+
aggreg->target=lfirst(target);
393+
if (usenulls)
394+
aggreg->usenulls= true;
331395

332396
returnaggreg;
333397
}

‎src/backend/parser/parse_func.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.3 1997/11/26 03:42:42 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.4 1998/01/04 04:31:18 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -87,7 +87,8 @@ typedef struct _SuperQE
8787
*/
8888

8989
Node*
90-
ParseFunc(ParseState*pstate,char*funcname,List*fargs,int*curr_resno)
90+
ParseFunc(ParseState*pstate,char*funcname,List*fargs,
91+
int*curr_resno,intprecedence)
9192
{
9293
Oidrettype= (Oid)0;
9394
Oidargrelid= (Oid)0;
@@ -194,9 +195,7 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
194195
*/
195196
if ((get_attnum(argrelid,funcname)==InvalidAttrNumber)
196197
&&strcmp(funcname,"*"))
197-
{
198198
elog(WARN,"Functions on sets are not yet supported");
199-
}
200199
}
201200

202201
if (retval)
@@ -223,7 +222,8 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
223222
ObjectIdGetDatum(basetype),
224223
0,0))
225224
{
226-
Aggreg*aggreg=ParseAgg(funcname,basetype,lfirst(fargs));
225+
Aggreg*aggreg=ParseAgg(pstate,funcname,basetype,
226+
fargs,precedence);
227227

228228
AddAggToParseState(pstate,aggreg);
229229
return (Node*)aggreg;
@@ -368,7 +368,7 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
368368
else
369369
{
370370
funcnode->func_tlist=setup_tlist(funcname,argrelid);
371-
rettype=attnameTypeId(argrelid,funcname);
371+
rettype=get_atttype(argrelid,get_attnum(argrelid,funcname));
372372
}
373373
}
374374

@@ -1031,7 +1031,7 @@ setup_tlist(char *attname, Oid relid)
10311031
if (attno<0)
10321032
elog(WARN,"cannot reference attribute '%s' of tuple params/return values for functions",attname);
10331033

1034-
typeid=attnameTypeId(relid,attname);
1034+
typeid=get_atttype(relid,attno);
10351035
resnode=makeResdom(1,
10361036
typeid,
10371037
typeLen(typeidType(typeid)),

‎src/backend/parser/parse_relation.c

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.3 1997/11/26 03:42:48 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.4 1998/01/04 04:31:19 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -346,34 +346,6 @@ attnumAttNelems(Relation rd, int attid)
346346
return (rd->rd_att->attrs[attid-1]->attnelems);
347347
}
348348

349-
Oid
350-
attnameTypeId(Oidrelid,char*attrname)
351-
{
352-
intattid;
353-
Oidvartype;
354-
Relationrd;
355-
356-
rd=heap_open(relid);
357-
if (!RelationIsValid(rd))
358-
{
359-
rd=heap_openr(typeidTypeName(relid));
360-
if (!RelationIsValid(rd))
361-
elog(WARN,"cannot compute type of att %s for relid %d",
362-
attrname,relid);
363-
}
364-
365-
attid=attnameAttNum(rd,attrname);/* could elog(WARN) and never return */
366-
367-
vartype=attnumTypeId(rd,attid);
368-
369-
/*
370-
* close relation we're done with it now
371-
*/
372-
heap_close(rd);
373-
374-
return (vartype);
375-
}
376-
377349
/* given attribute id, return type of that attribute */
378350
/* XXX Special case for pseudo-attributes is a hack */
379351
Oid

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp