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.c350
1 files changed, 316 insertions, 34 deletions
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index da6c3ae4b5f..e33618f9744 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -190,19 +190,21 @@ coerce_type(ParseState *pstate, Node *node,
if (targetTypeId == ANYARRAYOID ||
targetTypeId == ANYENUMOID ||
targetTypeId == ANYRANGEOID ||
+ targetTypeId == ANYMULTIRANGEOID ||
targetTypeId == ANYCOMPATIBLEARRAYOID ||
- targetTypeId == ANYCOMPATIBLERANGEOID)
+ targetTypeId == ANYCOMPATIBLERANGEOID ||
+ targetTypeId == ANYCOMPATIBLEMULTIRANGEOID)
{
/*
* Assume can_coerce_type verified that implicit coercion is okay.
*
* These cases are unlike the ones above because the exposed type of
- * the argument must be an actual array, enum, or range type. In
- * particular the argument must *not* be an UNKNOWN constant. If it
- * is, we just fall through; below, we'll call the pseudotype's input
- * function, which will produce an error. Also, if what we have is a
- * domain over array, enum, or range, we have to relabel it to its
- * base type.
+ * the argument must be an actual array, enum, range, or multirange
+ * type. In particular the argument must *not* be an UNKNOWN
+ * constant. If it is, we just fall through; below, we'll call the
+ * pseudotype's input function, which will produce an error. Also, if
+ * what we have is a domain over array, enum, range, or multirange, we
+ * have to relabel it to its base type.
*
* Note: currently, we can't actually see a domain-over-enum here,
* since the other functions in this file will not match such a
@@ -1570,8 +1572,8 @@ select_common_typmod(ParseState *pstate, List *exprs, Oid common_type)
* 1) All arguments declared ANYELEMENT must have the same datatype.
* 2) All arguments declared ANYARRAY must have the same datatype,
* which must be a varlena array type.
- * 3) All arguments declared ANYRANGE must have the same datatype,
- * which must be a range type.
+ * 3) All arguments declared ANYRANGE or ANYMULTIRANGE must be a range or
+ * multirange type, all derived from the same base datatype.
* 4) If there are arguments of more than one of these polymorphic types,
* the array element type and/or range subtype must be the same as each
* other and the same as the ANYELEMENT type.
@@ -1586,8 +1588,8 @@ select_common_typmod(ParseState *pstate, List *exprs, Oid common_type)
* to a common supertype (chosen as per select_common_type's rules).
* ANYCOMPATIBLENONARRAY works like ANYCOMPATIBLE but also requires the
* common supertype to not be an array. If there are ANYCOMPATIBLEARRAY
- * or ANYCOMPATIBLERANGE arguments, their element types or subtypes are
- * included while making the choice of common supertype.
+ * or ANYCOMPATIBLERANGE or ANYCOMPATIBLEMULTIRANGE arguments, their element
+ * types or subtypes are included while making the choice of common supertype.
* 8) The resolved type of ANYCOMPATIBLEARRAY arguments will be the array
* type over the common supertype (which might not be the same array type
* as any of the original arrays).
@@ -1595,6 +1597,10 @@ select_common_typmod(ParseState *pstate, List *exprs, Oid common_type)
* (after domain flattening), since we have no preference rule that would
* let us choose one over another. Furthermore, that range's subtype
* must exactly match the common supertype chosen by rule 7.
+ * 10) All ANYCOMPATIBLEMULTIRANGE arguments must be the exact same multirange
+ * type (after domain flattening), since we have no preference rule that would
+ * let us choose one over another. Furthermore, that multirange's range's
+ * subtype must exactly match the common supertype chosen by rule 7.
*
* Domains over arrays match ANYARRAY, and are immediately flattened to their
* base type. (Thus, for example, we will consider it a match if one ANYARRAY
@@ -1603,7 +1609,9 @@ select_common_typmod(ParseState *pstate, List *exprs, Oid common_type)
* for ANYCOMPATIBLEARRAY and ANYCOMPATIBLENONARRAY.
*
* Similarly, domains over ranges match ANYRANGE or ANYCOMPATIBLERANGE,
- * and are immediately flattened to their base type.
+ * and are immediately flattened to their base type, and domains over
+ * multiranges match ANYMULTIRANGE or ANYCOMPATIBLEMULTIRANGE and are immediately
+ * flattened to their base type.
*
* Note that domains aren't currently considered to match ANYENUM,
* even if their base type would match.
@@ -1621,8 +1629,12 @@ check_generic_type_consistency(const Oid *actual_arg_types,
Oid elem_typeid = InvalidOid;
Oid array_typeid = InvalidOid;
Oid range_typeid = InvalidOid;
+ Oid multirange_typeid = InvalidOid;
Oid anycompatible_range_typeid = InvalidOid;
Oid anycompatible_range_typelem = InvalidOid;
+ Oid anycompatible_multirange_typeid = InvalidOid;
+ Oid anycompatible_multirange_typelem = InvalidOid;
+ Oid range_typelem = InvalidOid;
bool have_anynonarray = false;
bool have_anyenum = false;
bool have_anycompatible_nonarray = false;
@@ -1671,6 +1683,15 @@ check_generic_type_consistency(const Oid *actual_arg_types,
return false;
range_typeid = actual_type;
}
+ else if (decl_type == ANYMULTIRANGEOID)
+ {
+ if (actual_type == UNKNOWNOID)
+ continue;
+ actual_type = getBaseType(actual_type); /* flatten domains */
+ if (OidIsValid(multirange_typeid) && actual_type != multirange_typeid)
+ return false;
+ multirange_typeid = actual_type;
+ }
else if (decl_type == ANYCOMPATIBLEOID ||
decl_type == ANYCOMPATIBLENONARRAYOID)
{
@@ -1715,6 +1736,45 @@ check_generic_type_consistency(const Oid *actual_arg_types,
anycompatible_actual_types[n_anycompatible_args++] = anycompatible_range_typelem;
}
}
+ else if (decl_type == ANYCOMPATIBLEMULTIRANGEOID)
+ {
+ if (actual_type == UNKNOWNOID)
+ continue;
+ actual_type = getBaseType(actual_type); /* flatten domains */
+ if (OidIsValid(anycompatible_multirange_typeid))
+ {
+ /* All ANYCOMPATIBLEMULTIRANGE arguments must be the same type */
+ if (anycompatible_multirange_typeid != actual_type)
+ return false;
+ }
+ else
+ {
+ anycompatible_multirange_typeid = actual_type;
+ anycompatible_multirange_typelem = get_multirange_range(actual_type);
+ if (!OidIsValid(anycompatible_multirange_typelem))
+ return false; /* not a multirange type */
+
+ if (OidIsValid(anycompatible_range_typeid))
+ {
+ /*
+ * ANYCOMPATIBLEMULTIRANGE and ANYCOMPATIBLERANGE
+ * arguments must match
+ */
+ if (anycompatible_range_typeid != anycompatible_multirange_typelem)
+ return false;
+ }
+ else
+ {
+ anycompatible_range_typeid = anycompatible_multirange_typelem;
+ anycompatible_range_typelem = get_range_subtype(anycompatible_range_typeid);
+ if (!OidIsValid(anycompatible_range_typelem))
+ return false; /* not a range type */
+ }
+ /* collect the subtype for common-supertype choice */
+ anycompatible_actual_types[n_anycompatible_args++] =
+ anycompatible_range_typelem;
+ }
+ }
}
/* Get the element type based on the array type, if we have one */
@@ -1761,8 +1821,6 @@ check_generic_type_consistency(const Oid *actual_arg_types,
/* Get the element type based on the range type, if we have one */
if (OidIsValid(range_typeid))
{
- Oid range_typelem;
-
range_typelem = get_range_subtype(range_typeid);
if (!OidIsValid(range_typelem))
return false; /* should be a range, but isn't */
@@ -1781,6 +1839,45 @@ check_generic_type_consistency(const Oid *actual_arg_types,
}
}
+ /* Get the element type based on the multirange type, if we have one */
+ if (OidIsValid(multirange_typeid))
+ {
+ Oid multirange_typelem;
+
+ multirange_typelem = get_multirange_range(multirange_typeid);
+ if (!OidIsValid(multirange_typelem))
+ return false; /* should be a multirange, but isn't */
+
+ if (!OidIsValid(range_typeid))
+ {
+ /*
+ * If we don't have a range type yet, use the one we just got
+ */
+ range_typeid = multirange_typelem;
+ range_typelem = get_range_subtype(multirange_typelem);
+ if (!OidIsValid(range_typelem))
+ return false; /* should be a range, but isn't */
+ }
+ else if (multirange_typelem != range_typeid)
+ {
+ /* otherwise, they better match */
+ return false;
+ }
+
+ if (!OidIsValid(elem_typeid))
+ {
+ /*
+ * If we don't have an element type yet, use the one we just got
+ */
+ elem_typeid = range_typelem;
+ }
+ else if (range_typelem != elem_typeid)
+ {
+ /* otherwise, they better match */
+ return false;
+ }
+ }
+
if (have_anynonarray)
{
/* require the element type to not be an array or domain over array */
@@ -1819,8 +1916,10 @@ check_generic_type_consistency(const Oid *actual_arg_types,
}
/*
- * the anycompatible type must exactly match the range element type,
- * if we were able to identify one
+ * The anycompatible type must exactly match the range element type,
+ * if we were able to identify one. This checks compatibility for
+ * anycompatiblemultirange too since that also sets
+ * anycompatible_range_typelem above.
*/
if (OidIsValid(anycompatible_range_typelem) &&
anycompatible_range_typelem != anycompatible_typeid)
@@ -1859,21 +1958,27 @@ check_generic_type_consistency(const Oid *actual_arg_types,
* argument's actual type as the function's return type.
* 2) If return type is ANYARRAY, and any argument is ANYARRAY, use the
* argument's actual type as the function's return type.
- * 3) Similarly, if return type is ANYRANGE, and any argument is ANYRANGE,
- * use the argument's actual type as the function's return type.
- * 4) Otherwise, if return type is ANYELEMENT or ANYARRAY, and there is
+ * 3) Similarly, if return type is ANYRANGE or ANYMULTIRANGE, and any
+ * argument is ANYRANGE or ANYMULTIRANGE, use that argument's
+ * actual type, range type or multirange type as the function's return
+ * type.
+ * 4) Otherwise, if return type is ANYMULTIRANGE, and any argument is
+ * ANYMULTIRANGE, use the argument's actual type as the function's return
+ * type. Or if any argument is ANYRANGE, use its multirange type as the
+ * function's return type.
+ * 5) Otherwise, if return type is ANYELEMENT or ANYARRAY, and there is
* at least one ANYELEMENT, ANYARRAY, or ANYRANGE input, deduce the
* return type from those inputs, or throw error if we can't.
- * 5) Otherwise, if return type is ANYRANGE, throw error. (We have no way to
- * select a specific range type if the arguments don't include ANYRANGE.)
- * 6) ANYENUM is treated the same as ANYELEMENT except that if it is used
+ * 6) Otherwise, if return type is ANYRANGE or ANYMULTIRANGE, throw error.
+ * (We have no way to select a specific range type if the arguments don't
+ * include ANYRANGE.)
* (alone or in combination with plain ANYELEMENT), we add the extra
* condition that the ANYELEMENT type must be an enum.
- * 7) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
+ * 8) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
* we add the extra condition that the ANYELEMENT type must not be an array.
* (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
* is an extra restriction if not.)
- * 8) ANYCOMPATIBLE, ANYCOMPATIBLEARRAY, ANYCOMPATIBLENONARRAY, and
+ * 9) ANYCOMPATIBLE, ANYCOMPATIBLEARRAY, ANYCOMPATIBLENONARRAY, and
* ANYCOMPATIBLERANGE are handled by resolving the common supertype
* of those arguments (or their element types/subtypes, for array and range
* inputs), and then coercing all those arguments to the common supertype,
@@ -1927,10 +2032,15 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
Oid elem_typeid = InvalidOid;
Oid array_typeid = InvalidOid;
Oid range_typeid = InvalidOid;
+ Oid multirange_typeid = InvalidOid;
Oid anycompatible_typeid = InvalidOid;
Oid anycompatible_array_typeid = InvalidOid;
Oid anycompatible_range_typeid = InvalidOid;
Oid anycompatible_range_typelem = InvalidOid;
+ Oid anycompatible_multirange_typeid = InvalidOid;
+ Oid anycompatible_multirange_typelem = InvalidOid;
+ Oid range_typelem;
+ Oid multirange_typelem;
bool have_anynonarray = (rettype == ANYNONARRAYOID);
bool have_anyenum = (rettype == ANYENUMOID);
bool have_anycompatible_nonarray = (rettype == ANYCOMPATIBLENONARRAYOID);
@@ -2015,6 +2125,26 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
format_type_be(actual_type))));
range_typeid = actual_type;
}
+ else if (decl_type == ANYMULTIRANGEOID)
+ {
+ n_poly_args++;
+ if (actual_type == UNKNOWNOID)
+ {
+ have_poly_unknowns = true;
+ continue;
+ }
+ if (allow_poly && decl_type == actual_type)
+ continue; /* no new information here */
+ actual_type = getBaseType(actual_type); /* flatten domains */
+ if (OidIsValid(multirange_typeid) && actual_type != multirange_typeid)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("arguments declared \"anymultirange\" are not all alike"),
+ errdetail("%s versus %s",
+ format_type_be(multirange_typeid),
+ format_type_be(actual_type))));
+ multirange_typeid = actual_type;
+ }
else if (decl_type == ANYCOMPATIBLEOID ||
decl_type == ANYCOMPATIBLENONARRAYOID)
{
@@ -2083,6 +2213,40 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
anycompatible_actual_types[n_anycompatible_args++] = anycompatible_range_typelem;
}
}
+ else if (decl_type == ANYCOMPATIBLEMULTIRANGEOID)
+ {
+ have_poly_anycompatible = true;
+ if (actual_type == UNKNOWNOID)
+ continue;
+ if (allow_poly && decl_type == actual_type)
+ continue; /* no new information here */
+ actual_type = getBaseType(actual_type); /* flatten domains */
+ if (OidIsValid(anycompatible_multirange_typeid))
+ {
+ /* All ANYCOMPATIBLEMULTIRANGE arguments must be the same type */
+ if (anycompatible_multirange_typeid != actual_type)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("arguments declared \"anycompatiblemultirange\" are not all alike"),
+ errdetail("%s versus %s",
+ format_type_be(anycompatible_multirange_typeid),
+ format_type_be(actual_type))));
+ }
+ else
+ {
+ anycompatible_multirange_typeid = actual_type;
+ anycompatible_multirange_typelem = get_multirange_range(actual_type);
+ anycompatible_range_typelem = get_range_subtype(anycompatible_multirange_typelem);
+ if (!OidIsValid(anycompatible_multirange_typelem))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("argument declared %s is not a multirange type but type %s",
+ "anycompatiblemultirange",
+ format_type_be(actual_type))));
+ /* collect the subtype for common-supertype choice */
+ anycompatible_actual_types[n_anycompatible_args++] = anycompatible_range_typelem;
+ }
+ }
}
/*
@@ -2151,8 +2315,6 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
/* Get the element type based on the range type, if we have one */
if (OidIsValid(range_typeid))
{
- Oid range_typelem;
-
range_typelem = get_range_subtype(range_typeid);
if (!OidIsValid(range_typelem))
ereport(ERROR,
@@ -2181,6 +2343,61 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
format_type_be(elem_typeid))));
}
}
+ else
+ range_typelem = InvalidOid;
+
+ /* Get the element type based on the multirange type, if we have one */
+ if (OidIsValid(multirange_typeid))
+ {
+ multirange_typelem = get_multirange_range(multirange_typeid);
+ if (!OidIsValid(multirange_typelem))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("argument declared %s is not a multirange type but type %s",
+ "anymultirange",
+ format_type_be(multirange_typeid))));
+
+ if (!OidIsValid(range_typeid))
+ {
+ /*
+ * If we don't have a range type yet, use the one we just got
+ */
+ range_typeid = multirange_typelem;
+ range_typelem = get_range_subtype(range_typeid);
+ }
+ else if (multirange_typelem != range_typeid)
+ {
+ /* otherwise, they better match */
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("argument declared %s is not consistent with argument declared %s",
+ "anymultirange", "anyrange"),
+ errdetail("%s versus %s",
+ format_type_be(multirange_typeid),
+ format_type_be(range_typeid))));
+ }
+
+ if (!OidIsValid(elem_typeid))
+ {
+ /*
+ * if we don't have an element type yet, use the one we just got
+ */
+ elem_typeid = range_typelem;
+ }
+ else if (range_typelem != elem_typeid)
+ {
+ /* otherwise, they better match */
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("argument declared %s is not consistent with argument declared %s",
+ "anymultirange", "anyelement"),
+ errdetail("%s versus %s",
+ format_type_be(multirange_typeid),
+ format_type_be(elem_typeid))));
+ }
+ }
+ else
+ multirange_typelem = InvalidOid;
if (!OidIsValid(elem_typeid))
{
@@ -2189,6 +2406,7 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
elem_typeid = ANYELEMENTOID;
array_typeid = ANYARRAYOID;
range_typeid = ANYRANGEOID;
+ multirange_typeid = ANYMULTIRANGEOID;
}
else
{
@@ -2288,6 +2506,7 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
anycompatible_typeid = ANYCOMPATIBLEOID;
anycompatible_array_typeid = ANYCOMPATIBLEARRAYOID;
anycompatible_range_typeid = ANYCOMPATIBLERANGEOID;
+ anycompatible_multirange_typeid = ANYCOMPATIBLEMULTIRANGEOID;
}
else
{
@@ -2319,6 +2538,8 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
declared_arg_types[j] = anycompatible_array_typeid;
else if (decl_type == ANYCOMPATIBLERANGEOID)
declared_arg_types[j] = anycompatible_range_typeid;
+ else if (decl_type == ANYCOMPATIBLEMULTIRANGEOID)
+ declared_arg_types[j] = anycompatible_multirange_typeid;
}
}
@@ -2369,6 +2590,17 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
}
declared_arg_types[j] = range_typeid;
}
+ else if (decl_type == ANYMULTIRANGEOID)
+ {
+ if (!OidIsValid(multirange_typeid))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("could not find multirange type for data type %s",
+ format_type_be(elem_typeid))));
+ }
+ declared_arg_types[j] = multirange_typeid;
+ }
}
}
@@ -2405,6 +2637,22 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
return range_typeid;
}
+ /* if we return ANYMULTIRANGE use the appropriate argument type */
+ if (rettype == ANYMULTIRANGEOID)
+ {
+ if (!OidIsValid(multirange_typeid))
+ {
+ if (OidIsValid(range_typeid))
+ multirange_typeid = get_range_multirange(range_typeid);
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("could not find multirange type for data type %s",
+ format_type_be(elem_typeid))));
+ }
+ return multirange_typeid;
+ }
+
/* if we return ANYCOMPATIBLE use the appropriate type */
if (rettype == ANYCOMPATIBLEOID ||
rettype == ANYCOMPATIBLENONARRAYOID)
@@ -2439,6 +2687,17 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
return anycompatible_range_typeid;
}
+ /* if we return ANYCOMPATIBLEMULTIRANGE use the appropriate argument type */
+ if (rettype == ANYCOMPATIBLEMULTIRANGEOID)
+ {
+ /* this error is unreachable if the function signature is valid: */
+ if (!OidIsValid(anycompatible_multirange_typeid))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg_internal("could not identify anycompatiblemultirange type")));
+ return anycompatible_multirange_typeid;
+ }
+
/* we don't return a generic type; send back the original return type */
return rettype;
}
@@ -2456,20 +2715,38 @@ check_valid_polymorphic_signature(Oid ret_type,
const Oid *declared_arg_types,
int nargs)
{
- if (ret_type == ANYRANGEOID || ret_type == ANYCOMPATIBLERANGEOID)
+ if (ret_type == ANYRANGEOID || ret_type == ANYMULTIRANGEOID)
{
/*
- * ANYRANGE requires an ANYRANGE input, else we can't tell which of
- * several range types with the same element type to use. Likewise
- * for ANYCOMPATIBLERANGE.
+ * ANYRANGE and ANYMULTIRANGE require an ANYRANGE or ANYMULTIRANGE
+ * input, else we can't tell which of several range types with the
+ * same element type to use.
*/
for (int i = 0; i < nargs; i++)
{
- if (declared_arg_types[i] == ret_type)
+ if (declared_arg_types[i] == ANYRANGEOID ||
+ declared_arg_types[i] == ANYMULTIRANGEOID)
return NULL; /* OK */
}
- return psprintf(_("A result of type %s requires at least one input of type %s."),
- format_type_be(ret_type), format_type_be(ret_type));
+ return psprintf(_("A result of type %s requires at least one input of type anyrange or anymultirange."),
+ format_type_be(ret_type));
+ }
+ else if (ret_type == ANYCOMPATIBLERANGEOID || ret_type == ANYCOMPATIBLEMULTIRANGEOID)
+ {
+ /*
+ * ANYCOMPATIBLERANGE and ANYCOMPATIBLEMULTIRANGE require an
+ * ANYCOMPATIBLERANGE or ANYCOMPATIBLEMULTIRANGE input, else we can't
+ * tell which of several range types with the same element type to
+ * use.
+ */
+ for (int i = 0; i < nargs; i++)
+ {
+ if (declared_arg_types[i] == ANYCOMPATIBLERANGEOID ||
+ declared_arg_types[i] == ANYCOMPATIBLEMULTIRANGEOID)
+ return NULL; /* OK */
+ }
+ return psprintf(_("A result of type %s requires at least one input of type anycompatiblerange or anycompatiblemultirange."),
+ format_type_be(ret_type));
}
else if (IsPolymorphicTypeFamily1(ret_type))
{
@@ -2480,7 +2757,7 @@ check_valid_polymorphic_signature(Oid ret_type,
return NULL; /* OK */
}
/* Keep this list in sync with IsPolymorphicTypeFamily1! */
- return psprintf(_("A result of type %s requires at least one input of type anyelement, anyarray, anynonarray, anyenum, or anyrange."),
+ return psprintf(_("A result of type %s requires at least one input of type anyelement, anyarray, anynonarray, anyenum, anyrange, or anymultirange."),
format_type_be(ret_type));
}
else if (IsPolymorphicTypeFamily2(ret_type))
@@ -2632,6 +2909,11 @@ IsBinaryCoercible(Oid srctype, Oid targettype)
if (type_is_range(srctype))
return true;
+ /* Also accept any multirange type as coercible to ANMULTIYRANGE */
+ if (targettype == ANYMULTIRANGEOID || targettype == ANYCOMPATIBLEMULTIRANGEOID)
+ if (type_is_multirange(srctype))
+ return true;
+
/* Also accept any composite type as coercible to RECORD */
if (targettype == RECORDOID)
if (ISCOMPLEX(srctype))