aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_coerce.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_coerce.c')
-rw-r--r--src/backend/parser/parse_coerce.c101
1 files changed, 75 insertions, 26 deletions
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index eba6f5a1333..977780fecc8 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.101 2003/06/27 00:33:25 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.102 2003/07/01 19:10:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -32,8 +32,6 @@
static Node *coerce_type_typmod(Node *node,
Oid targetTypeId, int32 targetTypMod,
CoercionForm cformat, bool isExplicit);
-static Node *build_func_call(Oid funcid, Oid rettype, List *args,
- CoercionForm fformat);
/*
@@ -275,8 +273,9 @@ coerce_type(ParseState *pstate, Node *node,
*/
Oid baseTypeId = getBaseType(targetTypeId);
- result = build_func_call(funcId, baseTypeId, makeList1(node),
- cformat);
+ result = (Node *) makeFuncExpr(funcId, baseTypeId,
+ makeList1(node),
+ cformat);
/*
* If domain, coerce to the domain type and relabel with
@@ -534,7 +533,7 @@ coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
args = lappend(args, cons);
}
- node = build_func_call(funcId, targetTypeId, args, cformat);
+ node = (Node *) makeFuncExpr(funcId, targetTypeId, args, cformat);
}
return node;
@@ -935,6 +934,76 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
return rettype;
}
+/*
+ * resolve_generic_type()
+ * Deduce an individual actual datatype on the assumption that
+ * the rules for ANYARRAY/ANYELEMENT are being followed.
+ *
+ * declared_type is the declared datatype we want to resolve.
+ * context_actual_type is the actual input datatype to some argument
+ * that has declared datatype context_declared_type.
+ *
+ * If declared_type isn't polymorphic, we just return it. Otherwise,
+ * context_declared_type must be polymorphic, and we deduce the correct
+ * return type based on the relationship of the two polymorphic types.
+ */
+Oid
+resolve_generic_type(Oid declared_type,
+ Oid context_actual_type,
+ Oid context_declared_type)
+{
+ if (declared_type == ANYARRAYOID)
+ {
+ if (context_declared_type == ANYARRAYOID)
+ {
+ /* Use actual type, but it must be an array */
+ Oid array_typelem = get_element_type(context_actual_type);
+
+ if (!OidIsValid(array_typelem))
+ elog(ERROR, "Argument declared ANYARRAY is not an array: %s",
+ format_type_be(context_actual_type));
+ return context_actual_type;
+ }
+ else if (context_declared_type == ANYELEMENTOID)
+ {
+ /* Use the array type corresponding to actual type */
+ Oid array_typeid = get_array_type(context_actual_type);
+
+ if (!OidIsValid(array_typeid))
+ elog(ERROR, "Cannot find array type for datatype %s",
+ format_type_be(context_actual_type));
+ return array_typeid;
+ }
+ }
+ else if (declared_type == ANYELEMENTOID)
+ {
+ if (context_declared_type == ANYARRAYOID)
+ {
+ /* Use the element type corresponding to actual type */
+ Oid array_typelem = get_element_type(context_actual_type);
+
+ if (!OidIsValid(array_typelem))
+ elog(ERROR, "Argument declared ANYARRAY is not an array: %s",
+ format_type_be(context_actual_type));
+ return array_typelem;
+ }
+ else if (context_declared_type == ANYELEMENTOID)
+ {
+ /* Use the actual type; it doesn't matter if array or not */
+ return context_actual_type;
+ }
+ }
+ else
+ {
+ /* declared_type isn't polymorphic, so return it as-is */
+ return declared_type;
+ }
+ /* If we get here, declared_type is polymorphic and context isn't */
+ /* NB: this is a calling-code logic error, not a user error */
+ elog(ERROR, "Cannot determine ANYARRAY/ANYELEMENT type because context isn't polymorphic");
+ return InvalidOid; /* keep compiler quiet */
+}
+
/* TypeCategory()
* Assign a category to the specified type OID.
@@ -1417,23 +1486,3 @@ find_typmod_coercion_function(Oid typeId, int *nargs)
return funcid;
}
-
-/*
- * Build an expression tree representing a function call.
- *
- * The argument expressions must have been transformed already.
- */
-static Node *
-build_func_call(Oid funcid, Oid rettype, List *args, CoercionForm fformat)
-{
- FuncExpr *funcexpr;
-
- funcexpr = makeNode(FuncExpr);
- funcexpr->funcid = funcid;
- funcexpr->funcresulttype = rettype;
- funcexpr->funcretset = false; /* only possible case here */
- funcexpr->funcformat = fformat;
- funcexpr->args = args;
-
- return (Node *) funcexpr;
-}