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

Commit53b4767

Browse files
author
Thomas G. Lockhart
committed
Define routines and catalog entries for string min()/max() functions.
Extend new type coersion techniques to aggregates.Clean up a few elog() messages.
1 parent9470ab0 commit53b4767

File tree

4 files changed

+194
-16
lines changed

4 files changed

+194
-16
lines changed

‎src/backend/parser/parse_agg.c

Lines changed: 12 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.14 1998/09/09 03:48:17 vadim Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.15 1998/12/08 06:18:56 thomas Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -27,6 +27,7 @@
2727
#include"parser/parse_expr.h"
2828
#include"parser/parse_node.h"
2929
#include"parser/parse_target.h"
30+
#include"parser/parse_coerce.h"
3031
#include"utils/syscache.h"
3132
#include"utils/lsyscache.h"
3233

@@ -149,7 +150,7 @@ tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
149150
if (tle->resdom->resno==grpcl->entry->resdom->resno)
150151
{
151152
if (contain_agg_clause((Node*)expr))
152-
elog(ERROR,"parser: aggregates not allowed in GROUP BY clause");
153+
elog(ERROR,"Aggregates not allowed in GROUP BY clause");
153154
return TRUE;
154155
}
155156
}
@@ -189,7 +190,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
189190
* non-group column in target list may fail.)
190191
*/
191192
if (contain_agg_clause(qry->qual))
192-
elog(ERROR,"parser: aggregates not allowed in WHERE clause");
193+
elog(ERROR,"Aggregates not allowed in WHERE clause");
193194

194195
/*
195196
* the target list can only contain aggregates, group columns and
@@ -201,7 +202,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
201202

202203
if (!tleIsAggOrGroupCol(tle,qry->groupClause))
203204
elog(ERROR,
204-
"parser: illegal use of aggregates or non-group column in target list");
205+
"Illegal use of aggregates or non-group column in target list");
205206
}
206207

207208
/*
@@ -211,7 +212,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
211212

212213
if (!exprIsAggOrGroupCol(qry->havingQual,qry->groupClause))
213214
elog(ERROR,
214-
"parser: illegal use of aggregates or non-group column in HAVING clause");
215+
"Illegal use of aggregates or non-group column in HAVING clause");
215216
return;
216217
}
217218

@@ -233,7 +234,7 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
233234
ObjectIdGetDatum(basetype),
234235
0,0);
235236
if (!HeapTupleIsValid(theAggTuple))
236-
elog(ERROR,"aggregate %s does not exist",aggname);
237+
elog(ERROR,"Aggregate %s does not exist",aggname);
237238

238239
/*
239240
* We do a major hack for count(*) here.
@@ -309,16 +310,17 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
309310
else
310311
vartype= ((Expr*)lfirst(target))->typeOid;
311312

312-
if (basetype!=vartype)
313+
if ((basetype!=vartype)
314+
&& (!IS_BINARY_COMPATIBLE(basetype,vartype)))
313315
{
314316
Typetp1,
315317
tp2;
316318

317319
tp1=typeidType(basetype);
318320
tp2=typeidType(vartype);
319-
elog(NOTICE,"Aggregate type mismatch:");
320-
elog(ERROR,"%s works on %s, not %s",aggname,
321-
typeTypeName(tp1),typeTypeName(tp2));
321+
elog(ERROR,"Aggregate type mismatch"
322+
"\n\t%s() works on %s, noton%s",
323+
aggname,typeTypeName(tp1),typeTypeName(tp2));
322324
}
323325
}
324326

‎src/backend/parser/parse_func.c

Lines changed: 145 additions & 4 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.31 1998/11/27 19:52:13 vadim Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.32 1998/12/08 06:18:56 thomas Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -25,6 +25,7 @@
2525
#include"catalog/pg_inherits.h"
2626
#include"catalog/pg_proc.h"
2727
#include"catalog/pg_type.h"
28+
#include"catalog/pg_aggregate.h"
2829
#include"fmgr.h"
2930
#include"lib/dllist.h"
3031
#include"miscadmin.h"
@@ -76,6 +77,8 @@ static List *setup_tlist(char *attname, Oid relid);
7677
staticList*setup_base_tlist(Oidtypeid);
7778
staticOid*func_select_candidate(intnargs,Oid*input_typeids,
7879
CandidateListcandidates);
80+
staticintagg_get_candidates(char*aggname,OidtypeId,CandidateList*candidates);
81+
staticOidagg_select_candidate(Oidtypeid,CandidateListcandidates);
7982

8083
#defineISCOMPLEX(type) (typeidTypeRelid(type) ? true : false)
8184

@@ -130,6 +133,108 @@ ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, int *curr_resno, int pre
130133
returnretval;
131134
}
132135

136+
staticint
137+
agg_get_candidates(char*aggname,
138+
OidtypeId,
139+
CandidateList*candidates)
140+
{
141+
CandidateListcurrent_candidate;
142+
Relationpg_aggregate_desc;
143+
HeapScanDescpg_aggregate_scan;
144+
HeapTupletup;
145+
Form_pg_aggregateagg;
146+
intncandidates=0;
147+
148+
staticScanKeyDataaggKey[1]= {
149+
{0,Anum_pg_aggregate_aggname,F_NAMEEQ}};
150+
151+
*candidates=NULL;
152+
153+
fmgr_info(F_NAMEEQ, (FmgrInfo*)&aggKey[0].sk_func);
154+
aggKey[0].sk_argument=NameGetDatum(aggname);
155+
156+
pg_aggregate_desc=heap_openr(AggregateRelationName);
157+
pg_aggregate_scan=heap_beginscan(pg_aggregate_desc,
158+
0,
159+
SnapshotSelf,/* ??? */
160+
1,
161+
aggKey);
162+
163+
while (HeapTupleIsValid(tup=heap_getnext(pg_aggregate_scan,0)))
164+
{
165+
current_candidate= (CandidateList)palloc(sizeof(struct_CandidateList));
166+
current_candidate->args= (Oid*)palloc(sizeof(Oid));
167+
168+
agg= (Form_pg_aggregate)GETSTRUCT(tup);
169+
current_candidate->args[0]=agg->aggbasetype;
170+
current_candidate->next=*candidates;
171+
*candidates=current_candidate;
172+
ncandidates++;
173+
}
174+
175+
heap_endscan(pg_aggregate_scan);
176+
heap_close(pg_aggregate_desc);
177+
178+
returnncandidates;
179+
}/* agg_get_candidates() */
180+
181+
/* agg_select_candidate()
182+
* Try to choose only one candidate aggregate function from a list of possibles.
183+
*/
184+
staticOid
185+
agg_select_candidate(Oidtypeid,CandidateListcandidates)
186+
{
187+
CandidateListcurrent_candidate;
188+
CandidateListlast_candidate;
189+
Oidcurrent_typeid;
190+
intncandidates;
191+
CATEGORYcategory,
192+
current_category;
193+
194+
/*
195+
* Look for candidates which allow coersion and have a preferred type.
196+
* Keep all candidates if none match.
197+
*/
198+
category=TypeCategory(typeid);
199+
ncandidates=0;
200+
last_candidate=NULL;
201+
for (current_candidate=candidates;
202+
current_candidate!=NULL;
203+
current_candidate=current_candidate->next)
204+
{
205+
current_typeid=current_candidate->args[0];
206+
current_category=TypeCategory(current_typeid);
207+
208+
if ((current_category==category)
209+
&&IsPreferredType(current_category,current_typeid)
210+
&&can_coerce_type(1,&typeid,&current_typeid))
211+
{
212+
/* only one so far? then keep it... */
213+
if (last_candidate==NULL)
214+
{
215+
candidates=current_candidate;
216+
last_candidate=current_candidate;
217+
ncandidates=1;
218+
}
219+
/* otherwise, keep this one too... */
220+
else
221+
{
222+
last_candidate->next=current_candidate;
223+
last_candidate=current_candidate;
224+
ncandidates++;
225+
}
226+
}
227+
/* otherwise, don't bother keeping this one around... */
228+
else
229+
{
230+
last_candidate->next=NULL;
231+
}
232+
}
233+
234+
return ((ncandidates==1) ?candidates->args[0] :0);
235+
}/* agg_select_candidate() */
236+
237+
133238
/*
134239
* parse function
135240
*/
@@ -250,8 +355,11 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
250355
/*
251356
* Parsing aggregates.
252357
*/
253-
Typetp;
254-
Oidbasetype;
358+
Typetp;
359+
Oidbasetype;
360+
intncandidates;
361+
CandidateListcandidates;
362+
255363

256364
/*
257365
* the aggregate COUNT is a special case, ignore its base
@@ -261,23 +369,56 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
261369
basetype=0;
262370
else
263371
basetype=exprType(lfirst(fargs));
372+
373+
/* try for exact match first... */
264374
if (SearchSysCacheTuple(AGGNAME,
265375
PointerGetDatum(funcname),
266376
ObjectIdGetDatum(basetype),
267377
0,0))
268378
return (Node*)ParseAgg(pstate,funcname,basetype,
269379
fargs,precedence);
270380

381+
/*
382+
* No exact match yet, so see if there is another entry
383+
* in the aggregate table which is compatible.
384+
* - thomas 1998-12-05
385+
*/
386+
ncandidates=agg_get_candidates(funcname,basetype,&candidates);
387+
if (ncandidates>0)
388+
{
389+
Oidtype;
390+
391+
type=agg_select_candidate(basetype,candidates);
392+
if (OidIsValid(type))
393+
{
394+
lfirst(fargs)=coerce_type(pstate,lfirst(fargs),basetype,type);
395+
basetype=type;
396+
397+
return (Node*)ParseAgg(pstate,funcname,basetype,
398+
fargs,precedence);
399+
}
400+
else
401+
{
402+
elog(ERROR,"Unable to select an aggregate function for type %s",
403+
typeidTypeName(basetype));
404+
}
405+
}
406+
271407
/*
272408
* See if this is a single argument function with the function
273409
* name also a type name and the input argument and type name
274410
* binary compatible...
411+
* This means that you are trying for a type conversion which does not
412+
* need to take place, so we'll just pass through the argument itself.
413+
* (make this clearer with some extra brackets - thomas 1998-12-05)
275414
*/
276415
if ((HeapTupleIsValid(tp=SearchSysCacheTuple(TYPNAME,
277-
PointerGetDatum(funcname),
416+
PointerGetDatum(funcname),
278417
0,0,0)))
279418
&&IS_BINARY_COMPATIBLE(typeTypeId(tp),basetype))
419+
{
280420
return ((Node*)lfirst(fargs));
421+
}
281422
}
282423
}
283424

‎src/backend/parser/parse_oper.c

Lines changed: 4 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/parser/parse_oper.c,v 1.21 1998/11/27 19:52:14 vadim Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.22 1998/12/08 06:18:57 thomas Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -210,19 +210,22 @@ oper_select_candidate(int nargs,
210210
nmatch++;
211211
}
212212

213+
/* take this one as the best choice so far? */
213214
if ((nmatch>nbestMatch)|| (last_candidate==NULL))
214215
{
215216
nbestMatch=nmatch;
216217
candidates=current_candidate;
217218
last_candidate=current_candidate;
218219
ncandidates=1;
219220
}
221+
/* no worse than the last choice, so keep this one too? */
220222
elseif (nmatch==nbestMatch)
221223
{
222224
last_candidate->next=current_candidate;
223225
last_candidate=current_candidate;
224226
ncandidates++;
225227
}
228+
/* otherwise, don't bother keeping this one... */
226229
else
227230
{
228231
last_candidate->next=NULL;

‎src/backend/utils/adt/varlena.c

Lines changed: 33 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/utils/adt/varlena.c,v 1.44 1998/10/0818:30:12 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.45 1998/12/0806:19:15 thomas Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -577,6 +577,38 @@ text_ge(text *arg1, text *arg2)
577577
return (bool) !text_lt(arg1,arg2);
578578
}
579579

580+
text*
581+
text_larger(text*arg1,text*arg2)
582+
{
583+
text*result;
584+
text*temp;
585+
586+
temp= ((text_cmp(arg1,arg2) <=0)?arg2:arg1);
587+
588+
/* Make a copy */
589+
590+
result= (text*)palloc(VARSIZE(temp));
591+
memmove((char*)result, (char*)temp,VARSIZE(temp));
592+
593+
return (result);
594+
}
595+
596+
text*
597+
text_smaller(text*arg1,text*arg2)
598+
{
599+
text*result;
600+
text*temp;
601+
602+
temp= ((text_cmp(arg1,arg2)>0)?arg2:arg1);
603+
604+
/* Make a copy */
605+
606+
result= (text*)palloc(VARSIZE(temp));
607+
memmove((char*)result, (char*)temp,VARSIZE(temp));
608+
609+
return (result);
610+
}
611+
580612
/*-------------------------------------------------------------
581613
* byteaGetSize
582614
*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp