aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/parser/parse_coerce.c102
-rw-r--r--src/backend/parser/parse_func.c37
-rw-r--r--src/include/parser/parse_func.h4
-rw-r--r--src/include/parser/parse_type.h4
4 files changed, 98 insertions, 49 deletions
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index ce06da2669e..f37082a87f5 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -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];
- /*
- * one of the known-good transparent conversions? then drop
- * through...
- */
- if (IS_BINARY_COMPATIBLE(input_typeids[i], func_typeids[i]))
- ;
+ /* no problem if same type */
+ if (inputTypeId == targetTypeId)
+ continue;
- /* 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;
+ /*
+ * one of the known-good transparent conversions? then drop
+ * through...
+ */
+ if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
+ continue;
- /*
- * 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;
- }
+ /* 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;
- tp = typeidType(input_typeids[i]);
- if (typeTypeFlag(tp) == 'c')
+ /*
+ * If input is an untyped string constant, assume we can
+ * convert it to anything except a class type.
+ */
+ if (inputTypeId == UNKNOWNOID)
+ {
+ 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;
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index eb4884accbb..e24007a4393 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -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.
diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h
index 9ee17203708..b191944ee2f 100644
--- a/src/include/parser/parse_func.h
+++ b/src/include/parser/parse_func.h
@@ -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);
diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h
index 034c47b8b0b..190d65db4d8 100644
--- a/src/include/parser/parse_type.h
+++ b/src/include/parser/parse_type.h
@@ -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 */