mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-15 08:20:16 +08:00
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.
This commit is contained in:
parent
d4a2c86eaf
commit
d14c8aab99
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.35 2000/03/14 23:06:32 thomas Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.36 2000/03/16 06:35:07 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -103,6 +103,11 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
||||
|
||||
result = (Node *) relabel;
|
||||
}
|
||||
else if (typeInheritsFrom(inputTypeId, targetTypeId))
|
||||
{
|
||||
/* Input class type is a subclass of target, so nothing to do */
|
||||
result = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
@ -156,62 +161,69 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
|
||||
bool
|
||||
can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
|
||||
{
|
||||
HeapTuple ftup;
|
||||
int i;
|
||||
Type tp;
|
||||
HeapTuple ftup;
|
||||
Oid oid_array[FUNC_MAX_ARGS];
|
||||
|
||||
/* run through argument list... */
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
if (input_typeids[i] != func_typeids[i])
|
||||
Oid inputTypeId = input_typeids[i];
|
||||
Oid targetTypeId = func_typeids[i];
|
||||
|
||||
/* no problem if same type */
|
||||
if (inputTypeId == targetTypeId)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* one of the known-good transparent conversions? then drop
|
||||
* through...
|
||||
*/
|
||||
if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
|
||||
continue;
|
||||
|
||||
/* don't know what to do for the output type? then quit... */
|
||||
if (targetTypeId == InvalidOid)
|
||||
return false;
|
||||
/* don't know what to do for the input type? then quit... */
|
||||
if (inputTypeId == InvalidOid)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If input is an untyped string constant, assume we can
|
||||
* convert it to anything except a class type.
|
||||
*/
|
||||
if (inputTypeId == UNKNOWNOID)
|
||||
{
|
||||
|
||||
/*
|
||||
* one of the known-good transparent conversions? then drop
|
||||
* through...
|
||||
*/
|
||||
if (IS_BINARY_COMPATIBLE(input_typeids[i], func_typeids[i]))
|
||||
;
|
||||
|
||||
/* don't know what to do for the output type? then quit... */
|
||||
else if (func_typeids[i] == InvalidOid)
|
||||
return false;
|
||||
/* don't know what to do for the input type? then quit... */
|
||||
else if (input_typeids[i] == InvalidOid)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* if not unknown input type, try for explicit conversion
|
||||
* using functions...
|
||||
*/
|
||||
else if (input_typeids[i] != UNKNOWNOID)
|
||||
{
|
||||
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
|
||||
oid_array[0] = input_typeids[i];
|
||||
|
||||
/*
|
||||
* look for a single-argument function named with the
|
||||
* target type name
|
||||
*/
|
||||
ftup = SearchSysCacheTuple(PROCNAME,
|
||||
PointerGetDatum(typeidTypeName(func_typeids[i])),
|
||||
Int32GetDatum(1),
|
||||
PointerGetDatum(oid_array),
|
||||
0);
|
||||
|
||||
/*
|
||||
* should also check the function return type just to be
|
||||
* safe...
|
||||
*/
|
||||
if (!HeapTupleIsValid(ftup))
|
||||
return false;
|
||||
}
|
||||
|
||||
tp = typeidType(input_typeids[i]);
|
||||
if (typeTypeFlag(tp) == 'c')
|
||||
if (ISCOMPLEX(targetTypeId))
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If input is a class type that inherits from target, no problem
|
||||
*/
|
||||
if (typeInheritsFrom(inputTypeId, targetTypeId))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Else, try for explicit conversion using functions:
|
||||
* look for a single-argument function named with the
|
||||
* target type name and accepting the source type.
|
||||
*/
|
||||
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
|
||||
oid_array[0] = inputTypeId;
|
||||
|
||||
ftup = SearchSysCacheTuple(PROCNAME,
|
||||
PointerGetDatum(typeidTypeName(targetTypeId)),
|
||||
Int32GetDatum(1),
|
||||
PointerGetDatum(oid_array),
|
||||
0);
|
||||
if (!HeapTupleIsValid(ftup))
|
||||
return false;
|
||||
/*
|
||||
* should also check the function return type just to be safe...
|
||||
*/
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.74 2000/03/14 23:06:32 thomas Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.75 2000/03/16 06:35:07 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -68,7 +68,6 @@ static Oid *func_select_candidate(int nargs, Oid *input_typeids,
|
||||
static int agg_get_candidates(char *aggname, Oid typeId, CandidateList *candidates);
|
||||
static Oid agg_select_candidate(Oid typeid, CandidateList candidates);
|
||||
|
||||
#define ISCOMPLEX(type) (typeidTypeRelid(type) ? true : false)
|
||||
|
||||
/*
|
||||
** ParseNestedFuncOrColumn
|
||||
@ -1360,6 +1359,40 @@ gen_cross_product(InhPaths *arginh, int nargs)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Given two type OIDs, determine whether the first is a complex type
|
||||
* (class type) that inherits from the second.
|
||||
*/
|
||||
bool
|
||||
typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
|
||||
{
|
||||
Oid relid;
|
||||
Oid *supervec;
|
||||
int nsupers,
|
||||
i;
|
||||
bool result;
|
||||
|
||||
if (!ISCOMPLEX(subclassTypeId) || !ISCOMPLEX(superclassTypeId))
|
||||
return false;
|
||||
relid = typeidTypeRelid(subclassTypeId);
|
||||
if (relid == InvalidOid)
|
||||
return false;
|
||||
nsupers = find_inheritors(relid, &supervec);
|
||||
result = false;
|
||||
for (i = 0; i < nsupers; i++)
|
||||
{
|
||||
if (supervec[i] == superclassTypeId)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (supervec)
|
||||
pfree(supervec);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* make_arguments()
|
||||
* Given the number and types of arguments to a function, and the
|
||||
* actual arguments and argument types, do the necessary typecasting.
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parse_func.h,v 1.22 2000/01/26 05:58:27 momjian Exp $
|
||||
* $Id: parse_func.h,v 1.23 2000/03/16 06:35:06 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -47,6 +47,8 @@ extern Node *ParseFuncOrColumn(ParseState *pstate,
|
||||
|
||||
extern List *setup_base_tlist(Oid typeid);
|
||||
|
||||
extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId);
|
||||
|
||||
extern void func_error(char *caller, char *funcname,
|
||||
int nargs, Oid *argtypes, char *msg);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parse_type.h,v 1.12 2000/01/26 05:58:27 momjian Exp $
|
||||
* $Id: parse_type.h,v 1.13 2000/03/16 06:35:06 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -35,4 +35,6 @@ extern Oid GetArrayElementType(Oid typearray);
|
||||
extern Oid typeInfunc(Type typ);
|
||||
extern Oid typeOutfunc(Type typ);
|
||||
|
||||
#define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid)
|
||||
|
||||
#endif /* PARSE_TYPE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user