@@ -143,9 +143,7 @@ coerce_type(ParseState *pstate, Node *node,
143
143
}
144
144
if (targetTypeId == ANYOID ||
145
145
targetTypeId == ANYELEMENTOID ||
146
- targetTypeId == ANYNONARRAYOID ||
147
- (targetTypeId == ANYARRAYOID && inputTypeId != UNKNOWNOID ) ||
148
- (targetTypeId == ANYENUMOID && inputTypeId != UNKNOWNOID ))
146
+ targetTypeId == ANYNONARRAYOID )
149
147
{
150
148
/*
151
149
* Assume can_coerce_type verified that implicit coercion is okay.
@@ -154,15 +152,48 @@ coerce_type(ParseState *pstate, Node *node,
154
152
* it's OK to treat an UNKNOWN constant as a valid input for a
155
153
* function accepting ANY, ANYELEMENT, or ANYNONARRAY. This should be
156
154
* all right, since an UNKNOWN value is still a perfectly valid Datum.
157
- * However an UNKNOWN value is definitely *not* an array, and so we
158
- * mustn't accept it for ANYARRAY. (Instead, we will call anyarray_in
159
- * below, which will produce an error.) Likewise, UNKNOWN input is no
160
- * good for ANYENUM.
161
155
*
162
- * NB: we do NOT want a RelabelType here.
156
+ * NB: we do NOT want a RelabelType here: the exposed type of the
157
+ * function argument must be its actual type, not the polymorphic
158
+ * pseudotype.
163
159
*/
164
160
return node ;
165
161
}
162
+ if (targetTypeId == ANYARRAYOID ||
163
+ targetTypeId == ANYENUMOID )
164
+ {
165
+ /*
166
+ * Assume can_coerce_type verified that implicit coercion is okay.
167
+ *
168
+ * These cases are unlike the ones above because the exposed type of
169
+ * the argument must be an actual array or enum type. In particular
170
+ * the argument must *not* be an UNKNOWN constant. If it is, we just
171
+ * fall through; below, we'll call anyarray_in or anyenum_in, which
172
+ * will produce an error. Also, if what we have is a domain over
173
+ * array or enum, we have to relabel it to its base type.
174
+ *
175
+ * Note: currently, we can't actually see a domain-over-enum here,
176
+ * since the other functions in this file will not match such a
177
+ * parameter to ANYENUM. But that should get changed eventually.
178
+ */
179
+ if (inputTypeId != UNKNOWNOID )
180
+ {
181
+ Oid baseTypeId = getBaseType (inputTypeId );
182
+
183
+ if (baseTypeId != inputTypeId )
184
+ {
185
+ RelabelType * r = makeRelabelType ((Expr * ) node ,
186
+ baseTypeId , -1 ,
187
+ InvalidOid ,
188
+ cformat );
189
+
190
+ r -> location = location ;
191
+ return (Node * ) r ;
192
+ }
193
+ /* Not a domain type, so return it as-is */
194
+ return node ;
195
+ }
196
+ }
166
197
if (inputTypeId == UNKNOWNOID && IsA (node , Const ))
167
198
{
168
199
/*
@@ -1257,6 +1288,11 @@ coerce_to_common_type(ParseState *pstate, Node *node,
1257
1288
* (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
1258
1289
* is an extra restriction if not.)
1259
1290
*
1291
+ * Domains over arrays match ANYARRAY, and are immediately flattened to their
1292
+ * base type. (Thus, for example, we will consider it a match if one ANYARRAY
1293
+ * argument is a domain over int4[] while another one is just int4[].) Also
1294
+ * notice that such a domain does *not* match ANYNONARRAY.
1295
+ *
1260
1296
* If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
1261
1297
* argument, assume it is okay.
1262
1298
*
@@ -1309,6 +1345,7 @@ check_generic_type_consistency(Oid *actual_arg_types,
1309
1345
{
1310
1346
if (actual_type == UNKNOWNOID )
1311
1347
continue ;
1348
+ actual_type = getBaseType (actual_type ); /* flatten domains */
1312
1349
if (OidIsValid (array_typeid ) && actual_type != array_typeid )
1313
1350
return false;
1314
1351
array_typeid = actual_type ;
@@ -1346,8 +1383,8 @@ check_generic_type_consistency(Oid *actual_arg_types,
1346
1383
1347
1384
if (have_anynonarray )
1348
1385
{
1349
- /* require the element type to not be an array */
1350
- if (type_is_array (elem_typeid ))
1386
+ /* require the element type to not be an array or domain over array */
1387
+ if (type_is_array_domain (elem_typeid ))
1351
1388
return false;
1352
1389
}
1353
1390
@@ -1406,6 +1443,10 @@ check_generic_type_consistency(Oid *actual_arg_types,
1406
1443
* (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
1407
1444
* is an extra restriction if not.)
1408
1445
*
1446
+ * Domains over arrays match ANYARRAY arguments, and are immediately flattened
1447
+ * to their base type. (In particular, if the return type is also ANYARRAY,
1448
+ * we'll set it to the base type not the domain type.)
1449
+ *
1409
1450
* When allow_poly is false, we are not expecting any of the actual_arg_types
1410
1451
* to be polymorphic, and we should not return a polymorphic result type
1411
1452
* either. When allow_poly is true, it is okay to have polymorphic "actual"
@@ -1485,6 +1526,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
1485
1526
}
1486
1527
if (allow_poly && decl_type == actual_type )
1487
1528
continue ; /* no new information here */
1529
+ actual_type = getBaseType (actual_type ); /* flatten domains */
1488
1530
if (OidIsValid (array_typeid ) && actual_type != array_typeid )
1489
1531
ereport (ERROR ,
1490
1532
(errcode (ERRCODE_DATATYPE_MISMATCH ),
@@ -1557,8 +1599,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
1557
1599
1558
1600
if (have_anynonarray && elem_typeid != ANYELEMENTOID )
1559
1601
{
1560
- /* require the element type to not be an array */
1561
- if (type_is_array (elem_typeid ))
1602
+ /* require the element type to not be an array or domain over array */
1603
+ if (type_is_array_domain (elem_typeid ))
1562
1604
ereport (ERROR ,
1563
1605
(errcode (ERRCODE_DATATYPE_MISMATCH ),
1564
1606
errmsg ("type matched to anynonarray is an array type: %s" ,
@@ -1655,15 +1697,19 @@ resolve_generic_type(Oid declared_type,
1655
1697
{
1656
1698
if (context_declared_type == ANYARRAYOID )
1657
1699
{
1658
- /* Use actual type, but it must be an array */
1659
- Oid array_typelem = get_element_type (context_actual_type );
1700
+ /*
1701
+ * Use actual type, but it must be an array; or if it's a domain
1702
+ * over array, use the base array type.
1703
+ */
1704
+ Oid context_base_type = getBaseType (context_actual_type );
1705
+ Oid array_typelem = get_element_type (context_base_type );
1660
1706
1661
1707
if (!OidIsValid (array_typelem ))
1662
1708
ereport (ERROR ,
1663
1709
(errcode (ERRCODE_DATATYPE_MISMATCH ),
1664
1710
errmsg ("argument declared \"anyarray\" is not an array but type %s" ,
1665
- format_type_be (context_actual_type ))));
1666
- return context_actual_type ;
1711
+ format_type_be (context_base_type ))));
1712
+ return context_base_type ;
1667
1713
}
1668
1714
else if (context_declared_type == ANYELEMENTOID ||
1669
1715
context_declared_type == ANYNONARRAYOID ||
@@ -1687,13 +1733,14 @@ resolve_generic_type(Oid declared_type,
1687
1733
if (context_declared_type == ANYARRAYOID )
1688
1734
{
1689
1735
/* Use the element type corresponding to actual type */
1690
- Oid array_typelem = get_element_type (context_actual_type );
1736
+ Oid context_base_type = getBaseType (context_actual_type );
1737
+ Oid array_typelem = get_element_type (context_base_type );
1691
1738
1692
1739
if (!OidIsValid (array_typelem ))
1693
1740
ereport (ERROR ,
1694
1741
(errcode (ERRCODE_DATATYPE_MISMATCH ),
1695
1742
errmsg ("argument declared \"anyarray\" is not an array but type %s" ,
1696
- format_type_be (context_actual_type ))));
1743
+ format_type_be (context_base_type ))));
1697
1744
return array_typelem ;
1698
1745
}
1699
1746
else if (context_declared_type == ANYELEMENTOID ||
@@ -1796,12 +1843,12 @@ IsBinaryCoercible(Oid srctype, Oid targettype)
1796
1843
1797
1844
/* Also accept any array type as coercible to ANYARRAY */
1798
1845
if (targettype == ANYARRAYOID )
1799
- if (type_is_array (srctype ))
1846
+ if (type_is_array_domain (srctype ))
1800
1847
return true;
1801
1848
1802
1849
/* Also accept any non-array type as coercible to ANYNONARRAY */
1803
1850
if (targettype == ANYNONARRAYOID )
1804
- if (!type_is_array (srctype ))
1851
+ if (!type_is_array_domain (srctype ))
1805
1852
return true;
1806
1853
1807
1854
/* Also accept any enum type as coercible to ANYENUM */
0 commit comments