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

Commit0a27641

Browse files
committed
nodeAgg has always been willing to accept an aggregate with a finalFunc
and only one transition state, but the CREATE AGGREGATE code rejectedthis combination.
1 parent4579e68 commit0a27641

File tree

1 file changed

+56
-47
lines changed

1 file changed

+56
-47
lines changed

‎src/backend/catalog/pg_aggregate.c

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.29 2000/01/2605:56:10 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.30 2000/03/2619:43:58 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -30,7 +30,7 @@
3030
* aggregates overloading has been added. Instead of the full
3131
* overload support we have for functions, aggregate overloading only
3232
* applies to exact basetype matches. That is, we don't check the
33-
*theinheritance hierarchy
33+
* inheritance hierarchy
3434
*
3535
* OLD COMMENTS:
3636
*Currently, redefining aggregates using the same name is not
@@ -85,13 +85,28 @@ AggregateCreate(char *aggName,
8585
if (!aggtransfn1Name&& !aggtransfn2Name)
8686
elog(ERROR,"AggregateCreate: aggregate must have at least one transition function");
8787

88+
if (aggtransfn1Name&&aggtransfn2Name&& !aggfinalfnName)
89+
elog(ERROR,"AggregateCreate: Aggregate must have final function with both transition functions");
90+
91+
/* handle the aggregate's base type (input data type) */
8892
tup=SearchSysCacheTuple(TYPENAME,
8993
PointerGetDatum(aggbasetypeName),
9094
0,0,0);
9195
if (!HeapTupleIsValid(tup))
9296
elog(ERROR,"AggregateCreate: Type '%s' undefined",aggbasetypeName);
9397
xbase=tup->t_data->t_oid;
9498

99+
/* make sure there is no existing agg of same name and base type */
100+
tup=SearchSysCacheTuple(AGGNAME,
101+
PointerGetDatum(aggName),
102+
ObjectIdGetDatum(xbase),
103+
0,0);
104+
if (HeapTupleIsValid(tup))
105+
elog(ERROR,
106+
"AggregateCreate: aggregate '%s' with base type '%s' already exists",
107+
aggName,aggbasetypeName);
108+
109+
/* handle transfn1 and transtype1 */
95110
if (aggtransfn1Name)
96111
{
97112
tup=SearchSysCacheTuple(TYPENAME,
@@ -114,14 +129,14 @@ AggregateCreate(char *aggName,
114129
aggtransfn1Name,aggtransfn1typeName,aggbasetypeName);
115130
if (((Form_pg_proc)GETSTRUCT(tup))->prorettype!=xret1)
116131
elog(ERROR,"AggregateCreate: return type of '%s' is not '%s'",
117-
aggtransfn1Name,
118-
aggtransfn1typeName);
132+
aggtransfn1Name,aggtransfn1typeName);
119133
xfn1=tup->t_data->t_oid;
120134
if (!OidIsValid(xfn1)|| !OidIsValid(xret1)||
121135
!OidIsValid(xbase))
122-
elog(ERROR,"AggregateCreate: bogus function '%s'",aggfinalfnName);
136+
elog(ERROR,"AggregateCreate: bogus function '%s'",aggtransfn1Name);
123137
}
124138

139+
/* handle transfn2 and transtype2 */
125140
if (aggtransfn2Name)
126141
{
127142
tup=SearchSysCacheTuple(TYPENAME,
@@ -147,47 +162,57 @@ AggregateCreate(char *aggName,
147162
aggtransfn2Name,aggtransfn2typeName);
148163
xfn2=tup->t_data->t_oid;
149164
if (!OidIsValid(xfn2)|| !OidIsValid(xret2))
150-
elog(ERROR,"AggregateCreate: bogus function '%s'",aggfinalfnName);
165+
elog(ERROR,"AggregateCreate: bogus function '%s'",aggtransfn2Name);
151166
}
152167

153-
tup=SearchSysCacheTuple(AGGNAME,
154-
PointerGetDatum(aggName),
155-
ObjectIdGetDatum(xbase),
156-
0,0);
157-
if (HeapTupleIsValid(tup))
158-
elog(ERROR,
159-
"AggregateCreate: aggregate '%s' with base type '%s' already exists",
160-
aggName,aggbasetypeName);
161-
162-
/* more sanity checks */
163-
if (aggtransfn1Name&&aggtransfn2Name&& !aggfinalfnName)
164-
elog(ERROR,"AggregateCreate: Aggregate must have final function with both transition functions");
165-
166-
if ((!aggtransfn1Name|| !aggtransfn2Name)&&aggfinalfnName)
167-
elog(ERROR,"AggregateCreate: Aggregate cannot have final function without both transition functions");
168-
168+
/* handle finalfn */
169169
if (aggfinalfnName)
170170
{
171-
fnArgs[0]=xret1;
172-
fnArgs[1]=xret2;
171+
intnargs=0;
172+
173+
if (OidIsValid(xret1))
174+
fnArgs[nargs++]=xret1;
175+
if (OidIsValid(xret2))
176+
fnArgs[nargs++]=xret2;
177+
fnArgs[nargs]=0;/* make sure slot 2 is empty if just 1 arg */
173178
tup=SearchSysCacheTuple(PROCNAME,
174179
PointerGetDatum(aggfinalfnName),
175-
Int32GetDatum(2),
180+
Int32GetDatum(nargs),
176181
PointerGetDatum(fnArgs),
177182
0);
178183
if (!HeapTupleIsValid(tup))
179-
elog(ERROR,"AggregateCreate: '%s'('%s','%s') does not exist",
180-
aggfinalfnName,aggtransfn1typeName,aggtransfn2typeName);
184+
{
185+
if (nargs==2)
186+
elog(ERROR,"AggregateCreate: '%s'('%s','%s') does not exist",
187+
aggfinalfnName,aggtransfn1typeName,aggtransfn2typeName);
188+
elseif (OidIsValid(xret1))
189+
elog(ERROR,"AggregateCreate: '%s'('%s') does not exist",
190+
aggfinalfnName,aggtransfn1typeName);
191+
else
192+
elog(ERROR,"AggregateCreate: '%s'('%s') does not exist",
193+
aggfinalfnName,aggtransfn2typeName);
194+
}
181195
ffn=tup->t_data->t_oid;
182196
proc= (Form_pg_proc)GETSTRUCT(tup);
183197
fret=proc->prorettype;
184198
if (!OidIsValid(ffn)|| !OidIsValid(fret))
185199
elog(ERROR,"AggregateCreate: bogus function '%s'",aggfinalfnName);
186200
}
201+
else
202+
{
203+
/* If no finalfn, aggregate result type is type of the sole
204+
* state value (we already checked there is only one)
205+
*/
206+
if (OidIsValid(xret1))
207+
fret=xret1;
208+
else
209+
fret=xret2;
210+
}
211+
Assert(OidIsValid(fret));
187212

188213
/*
189214
* If transition function 2 is defined, it must have an initial value,
190-
* whereas transition function 1does not, which allowsman and min
215+
* whereas transition function 1need not, which allowsmax and min
191216
* aggregates to return NULL if they are evaluated on empty sets.
192217
*/
193218
if (OidIsValid(xfn2)&& !agginitval2)
@@ -205,26 +230,10 @@ AggregateCreate(char *aggName,
205230
values[Anum_pg_aggregate_aggtransfn1-1]=ObjectIdGetDatum(xfn1);
206231
values[Anum_pg_aggregate_aggtransfn2-1]=ObjectIdGetDatum(xfn2);
207232
values[Anum_pg_aggregate_aggfinalfn-1]=ObjectIdGetDatum(ffn);
208-
209233
values[Anum_pg_aggregate_aggbasetype-1]=ObjectIdGetDatum(xbase);
210-
if (!OidIsValid(xfn1))
211-
{
212-
values[Anum_pg_aggregate_aggtranstype1-1]=ObjectIdGetDatum(InvalidOid);
213-
values[Anum_pg_aggregate_aggtranstype2-1]=ObjectIdGetDatum(xret2);
214-
values[Anum_pg_aggregate_aggfinaltype-1]=ObjectIdGetDatum(xret2);
215-
}
216-
elseif (!OidIsValid(xfn2))
217-
{
218-
values[Anum_pg_aggregate_aggtranstype1-1]=ObjectIdGetDatum(xret1);
219-
values[Anum_pg_aggregate_aggtranstype2-1]=ObjectIdGetDatum(InvalidOid);
220-
values[Anum_pg_aggregate_aggfinaltype-1]=ObjectIdGetDatum(xret1);
221-
}
222-
else
223-
{
224-
values[Anum_pg_aggregate_aggtranstype1-1]=ObjectIdGetDatum(xret1);
225-
values[Anum_pg_aggregate_aggtranstype2-1]=ObjectIdGetDatum(xret2);
226-
values[Anum_pg_aggregate_aggfinaltype-1]=ObjectIdGetDatum(fret);
227-
}
234+
values[Anum_pg_aggregate_aggtranstype1-1]=ObjectIdGetDatum(xret1);
235+
values[Anum_pg_aggregate_aggtranstype2-1]=ObjectIdGetDatum(xret2);
236+
values[Anum_pg_aggregate_aggfinaltype-1]=ObjectIdGetDatum(fret);
228237

229238
if (agginitval1)
230239
values[Anum_pg_aggregate_agginitval1-1]=PointerGetDatum(textin(agginitval1));

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp