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

Commit d14c8aa

Browse files
committed
Turns out that Mazurkiewicz's gripe about 'function inheritance' is
actually a type-coercion problem. If you have a function defined on class A, and class B inherits from A, then the function ought to work on class B as well --- but coerce_type didn't know that. Now it does.
1 parent d4a2c86 commit d14c8aa

File tree

4 files changed

+98
-49
lines changed

4 files changed

+98
-49
lines changed

src/backend/parser/parse_coerce.c

+57-45
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.35 2000/03/14 23:06:32 thomas Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.36 2000/03/16 06:35:07 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -103,6 +103,11 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
103103

104104
result = (Node *) relabel;
105105
}
106+
else if (typeInheritsFrom(inputTypeId, targetTypeId))
107+
{
108+
/* Input class type is a subclass of target, so nothing to do */
109+
result = node;
110+
}
106111
else
107112
{
108113
/*
@@ -156,62 +161,69 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
156161
bool
157162
can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
158163
{
159-
HeapTuple ftup;
160164
int i;
161-
Type tp;
165+
HeapTuple ftup;
162166
Oid oid_array[FUNC_MAX_ARGS];
163167

164168
/* run through argument list... */
165169
for (i = 0; i < nargs; i++)
166170
{
167-
if (input_typeids[i] != func_typeids[i])
168-
{
171+
Oid inputTypeId = input_typeids[i];
172+
Oid targetTypeId = func_typeids[i];
169173

170-
/*
171-
* one of the known-good transparent conversions? then drop
172-
* through...
173-
*/
174-
if (IS_BINARY_COMPATIBLE(input_typeids[i], func_typeids[i]))
175-
;
174+
/* no problem if same type */
175+
if (inputTypeId == targetTypeId)
176+
continue;
176177

177-
/* don't know what to do for the output type? then quit... */
178-
else if (func_typeids[i] == InvalidOid)
179-
return false;
180-
/* don't know what to do for the input type? then quit... */
181-
else if (input_typeids[i] == InvalidOid)
182-
return false;
178+
/*
179+
* one of the known-good transparent conversions? then drop
180+
* through...
181+
*/
182+
if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
183+
continue;
183184

184-
/*
185-
* if not unknown input type, try for explicit conversion
186-
* using functions...
187-
*/
188-
else if (input_typeids[i] != UNKNOWNOID)
189-
{
190-
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
191-
oid_array[0] = input_typeids[i];
192-
193-
/*
194-
* look for a single-argument function named with the
195-
* target type name
196-
*/
197-
ftup = SearchSysCacheTuple(PROCNAME,
198-
PointerGetDatum(typeidTypeName(func_typeids[i])),
199-
Int32GetDatum(1),
200-
PointerGetDatum(oid_array),
201-
0);
202-
203-
/*
204-
* should also check the function return type just to be
205-
* safe...
206-
*/
207-
if (!HeapTupleIsValid(ftup))
208-
return false;
209-
}
185+
/* don't know what to do for the output type? then quit... */
186+
if (targetTypeId == InvalidOid)
187+
return false;
188+
/* don't know what to do for the input type? then quit... */
189+
if (inputTypeId == InvalidOid)
190+
return false;
210191

211-
tp = typeidType(input_typeids[i]);
212-
if (typeTypeFlag(tp) == 'c')
192+
/*
193+
* If input is an untyped string constant, assume we can
194+
* convert it to anything except a class type.
195+
*/
196+
if (inputTypeId == UNKNOWNOID)
197+
{
198+
if (ISCOMPLEX(targetTypeId))
213199
return false;
200+
continue;
214201
}
202+
203+
/*
204+
* If input is a class type that inherits from target, no problem
205+
*/
206+
if (typeInheritsFrom(inputTypeId, targetTypeId))
207+
continue;
208+
209+
/*
210+
* Else, try for explicit conversion using functions:
211+
* look for a single-argument function named with the
212+
* target type name and accepting the source type.
213+
*/
214+
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
215+
oid_array[0] = inputTypeId;
216+
217+
ftup = SearchSysCacheTuple(PROCNAME,
218+
PointerGetDatum(typeidTypeName(targetTypeId)),
219+
Int32GetDatum(1),
220+
PointerGetDatum(oid_array),
221+
0);
222+
if (!HeapTupleIsValid(ftup))
223+
return false;
224+
/*
225+
* should also check the function return type just to be safe...
226+
*/
215227
}
216228

217229
return true;

src/backend/parser/parse_func.c

+35-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.74 2000/03/14 23:06:32 thomas Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.75 2000/03/16 06:35:07 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -68,7 +68,6 @@ static Oid *func_select_candidate(int nargs, Oid *input_typeids,
6868
static int agg_get_candidates(char *aggname, Oid typeId, CandidateList *candidates);
6969
static Oid agg_select_candidate(Oid typeid, CandidateList candidates);
7070

71-
#define ISCOMPLEX(type) (typeidTypeRelid(type) ? true : false)
7271

7372
/*
7473
** ParseNestedFuncOrColumn
@@ -1360,6 +1359,40 @@ gen_cross_product(InhPaths *arginh, int nargs)
13601359
}
13611360

13621361

1362+
/*
1363+
* Given two type OIDs, determine whether the first is a complex type
1364+
* (class type) that inherits from the second.
1365+
*/
1366+
bool
1367+
typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
1368+
{
1369+
Oid relid;
1370+
Oid *supervec;
1371+
int nsupers,
1372+
i;
1373+
bool result;
1374+
1375+
if (!ISCOMPLEX(subclassTypeId) || !ISCOMPLEX(superclassTypeId))
1376+
return false;
1377+
relid = typeidTypeRelid(subclassTypeId);
1378+
if (relid == InvalidOid)
1379+
return false;
1380+
nsupers = find_inheritors(relid, &supervec);
1381+
result = false;
1382+
for (i = 0; i < nsupers; i++)
1383+
{
1384+
if (supervec[i] == superclassTypeId)
1385+
{
1386+
result = true;
1387+
break;
1388+
}
1389+
}
1390+
if (supervec)
1391+
pfree(supervec);
1392+
return result;
1393+
}
1394+
1395+
13631396
/* make_arguments()
13641397
* Given the number and types of arguments to a function, and the
13651398
* actual arguments and argument types, do the necessary typecasting.

src/include/parser/parse_func.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: parse_func.h,v 1.22 2000/01/26 05:58:27 momjian Exp $
10+
* $Id: parse_func.h,v 1.23 2000/03/16 06:35:06 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -47,6 +47,8 @@ extern Node *ParseFuncOrColumn(ParseState *pstate,
4747

4848
extern List *setup_base_tlist(Oid typeid);
4949

50+
extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId);
51+
5052
extern void func_error(char *caller, char *funcname,
5153
int nargs, Oid *argtypes, char *msg);
5254

src/include/parser/parse_type.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: parse_type.h,v 1.12 2000/01/26 05:58:27 momjian Exp $
10+
* $Id: parse_type.h,v 1.13 2000/03/16 06:35:06 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -35,4 +35,6 @@ extern Oid GetArrayElementType(Oid typearray);
3535
extern Oid typeInfunc(Type typ);
3636
extern Oid typeOutfunc(Type typ);
3737

38+
#define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid)
39+
3840
#endif /* PARSE_TYPE_H */

0 commit comments

Comments
 (0)