Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 53b4767

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 parent 9470ab0 commit 53b4767

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
Type tp1,
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, not on %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
static List *setup_base_tlist(Oid typeid);
7778
static Oid *func_select_candidate(int nargs, Oid *input_typeids,
7879
CandidateList candidates);
80+
static int agg_get_candidates(char *aggname, Oid typeId, CandidateList *candidates);
81+
static Oid agg_select_candidate(Oid typeid, CandidateList candidates);
7982

8083
#define ISCOMPLEX(type) (typeidTypeRelid(type) ? true : false)
8184

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

136+
static int
137+
agg_get_candidates(char *aggname,
138+
Oid typeId,
139+
CandidateList *candidates)
140+
{
141+
CandidateList current_candidate;
142+
Relation pg_aggregate_desc;
143+
HeapScanDesc pg_aggregate_scan;
144+
HeapTuple tup;
145+
Form_pg_aggregate agg;
146+
int ncandidates = 0;
147+
148+
static ScanKeyData aggKey[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+
return ncandidates;
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+
static Oid
185+
agg_select_candidate(Oid typeid, CandidateList candidates)
186+
{
187+
CandidateList current_candidate;
188+
CandidateList last_candidate;
189+
Oid current_typeid;
190+
int ncandidates;
191+
CATEGORY category,
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-
Type tp;
254-
Oid basetype;
358+
Type tp;
359+
Oid basetype;
360+
int ncandidates;
361+
CandidateList candidates;
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+
Oid type;
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
else if (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/08 18:30:12 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.45 1998/12/08 06: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)