Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb7e8feb

Browse files
committed
Allow domains over arrays to match ANYARRAY parameters again.
This use-case was broken in commit529cb26of 2010-10-21, in which I commented "For the moment, we just forbid suchmatching. We might later wish to insert an automatic downcast to theunderlying array type, but such a change should also change matching ofdomains to ANYELEMENT for consistency". We still lack consensus about whatto do with ANYELEMENT; but not matching ANYARRAY is a clear loss offunctionality compared to prior releases, so let's go ahead and make thathappen. Per complaint from Regina Obe and extensive subsequent discussion.
1 parent8f9622b commitb7e8feb

File tree

3 files changed

+110
-20
lines changed

3 files changed

+110
-20
lines changed

‎src/backend/parser/parse_coerce.c

Lines changed: 67 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,7 @@ coerce_type(ParseState *pstate, Node *node,
143143
}
144144
if (targetTypeId==ANYOID||
145145
targetTypeId==ANYELEMENTOID||
146-
targetTypeId==ANYNONARRAYOID||
147-
(targetTypeId==ANYARRAYOID&&inputTypeId!=UNKNOWNOID)||
148-
(targetTypeId==ANYENUMOID&&inputTypeId!=UNKNOWNOID))
146+
targetTypeId==ANYNONARRAYOID)
149147
{
150148
/*
151149
* Assume can_coerce_type verified that implicit coercion is okay.
@@ -154,15 +152,48 @@ coerce_type(ParseState *pstate, Node *node,
154152
* it's OK to treat an UNKNOWN constant as a valid input for a
155153
* function accepting ANY, ANYELEMENT, or ANYNONARRAY.This should be
156154
* 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.
161155
*
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.
163159
*/
164160
returnnode;
165161
}
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+
OidbaseTypeId=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+
returnnode;
195+
}
196+
}
166197
if (inputTypeId==UNKNOWNOID&&IsA(node,Const))
167198
{
168199
/*
@@ -1257,6 +1288,11 @@ coerce_to_common_type(ParseState *pstate, Node *node,
12571288
* (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
12581289
* is an extra restriction if not.)
12591290
*
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+
*
12601296
* If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
12611297
* argument, assume it is okay.
12621298
*
@@ -1309,6 +1345,7 @@ check_generic_type_consistency(Oid *actual_arg_types,
13091345
{
13101346
if (actual_type==UNKNOWNOID)
13111347
continue;
1348+
actual_type=getBaseType(actual_type);/* flatten domains */
13121349
if (OidIsValid(array_typeid)&&actual_type!=array_typeid)
13131350
return false;
13141351
array_typeid=actual_type;
@@ -1346,8 +1383,8 @@ check_generic_type_consistency(Oid *actual_arg_types,
13461383

13471384
if (have_anynonarray)
13481385
{
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 arrayor domain over array*/
1387+
if (type_is_array_domain(elem_typeid))
13511388
return false;
13521389
}
13531390

@@ -1406,6 +1443,10 @@ check_generic_type_consistency(Oid *actual_arg_types,
14061443
* (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
14071444
* is an extra restriction if not.)
14081445
*
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+
*
14091450
* When allow_poly is false, we are not expecting any of the actual_arg_types
14101451
* to be polymorphic, and we should not return a polymorphic result type
14111452
* 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,
14851526
}
14861527
if (allow_poly&&decl_type==actual_type)
14871528
continue;/* no new information here */
1529+
actual_type=getBaseType(actual_type);/* flatten domains */
14881530
if (OidIsValid(array_typeid)&&actual_type!=array_typeid)
14891531
ereport(ERROR,
14901532
(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -1557,8 +1599,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
15571599

15581600
if (have_anynonarray&&elem_typeid!=ANYELEMENTOID)
15591601
{
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 arrayor domain over array*/
1603+
if (type_is_array_domain(elem_typeid))
15621604
ereport(ERROR,
15631605
(errcode(ERRCODE_DATATYPE_MISMATCH),
15641606
errmsg("type matched to anynonarray is an array type: %s",
@@ -1655,15 +1697,19 @@ resolve_generic_type(Oid declared_type,
16551697
{
16561698
if (context_declared_type==ANYARRAYOID)
16571699
{
1658-
/* Use actual type, but it must be an array */
1659-
Oidarray_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+
Oidcontext_base_type=getBaseType(context_actual_type);
1705+
Oidarray_typelem=get_element_type(context_base_type);
16601706

16611707
if (!OidIsValid(array_typelem))
16621708
ereport(ERROR,
16631709
(errcode(ERRCODE_DATATYPE_MISMATCH),
16641710
errmsg("argument declared \"anyarray\" is not an array but type %s",
1665-
format_type_be(context_actual_type))));
1666-
returncontext_actual_type;
1711+
format_type_be(context_base_type))));
1712+
returncontext_base_type;
16671713
}
16681714
elseif (context_declared_type==ANYELEMENTOID||
16691715
context_declared_type==ANYNONARRAYOID||
@@ -1687,13 +1733,14 @@ resolve_generic_type(Oid declared_type,
16871733
if (context_declared_type==ANYARRAYOID)
16881734
{
16891735
/* Use the element type corresponding to actual type */
1690-
Oidarray_typelem=get_element_type(context_actual_type);
1736+
Oidcontext_base_type=getBaseType(context_actual_type);
1737+
Oidarray_typelem=get_element_type(context_base_type);
16911738

16921739
if (!OidIsValid(array_typelem))
16931740
ereport(ERROR,
16941741
(errcode(ERRCODE_DATATYPE_MISMATCH),
16951742
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))));
16971744
returnarray_typelem;
16981745
}
16991746
elseif (context_declared_type==ANYELEMENTOID||
@@ -1796,12 +1843,12 @@ IsBinaryCoercible(Oid srctype, Oid targettype)
17961843

17971844
/* Also accept any array type as coercible to ANYARRAY */
17981845
if (targettype==ANYARRAYOID)
1799-
if (type_is_array(srctype))
1846+
if (type_is_array_domain(srctype))
18001847
return true;
18011848

18021849
/* Also accept any non-array type as coercible to ANYNONARRAY */
18031850
if (targettype==ANYNONARRAYOID)
1804-
if (!type_is_array(srctype))
1851+
if (!type_is_array_domain(srctype))
18051852
return true;
18061853

18071854
/* Also accept any enum type as coercible to ANYENUM */

‎src/test/regress/expected/domain.out

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ select testint4arr[1], testchar4arr[2:2] from domarrtest;
127127
| {{d,e,f}}
128128
(5 rows)
129129

130+
select array_dims(testint4arr), array_dims(testchar4arr) from domarrtest;
131+
array_dims | array_dims
132+
------------+------------
133+
[1:2] | [1:2][1:2]
134+
[1:2][1:2] | [1:1][1:2]
135+
[1:2] | [1:3][1:2]
136+
[1:2] | [1:2][1:1]
137+
| [1:2][1:3]
138+
(5 rows)
139+
130140
COPY domarrtest FROM stdin;
131141
COPY domarrtest FROM stdin;-- fail
132142
ERROR: value too long for type character varying(4)
@@ -146,6 +156,32 @@ select * from domarrtest;
146156
drop table domarrtest;
147157
drop domain domainint4arr restrict;
148158
drop domain domainchar4arr restrict;
159+
create domain dia as int[];
160+
select '{1,2,3}'::dia;
161+
dia
162+
---------
163+
{1,2,3}
164+
(1 row)
165+
166+
select array_dims('{1,2,3}'::dia);
167+
array_dims
168+
------------
169+
[1:3]
170+
(1 row)
171+
172+
select pg_typeof('{1,2,3}'::dia);
173+
pg_typeof
174+
-----------
175+
dia
176+
(1 row)
177+
178+
select pg_typeof('{1,2,3}'::dia || 42); -- should be int[] not dia
179+
pg_typeof
180+
-----------
181+
integer[]
182+
(1 row)
183+
184+
drop domain dia;
149185
create domain dnotnull varchar(15) NOT NULL;
150186
create domain dnull varchar(15);
151187
create domain dcheck varchar(15) NOT NULL CHECK (VALUE = 'a' OR VALUE = 'c' OR VALUE = 'd');

‎src/test/regress/sql/domain.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ INSERT INTO domarrtest values (NULL, '{{"a","b","c"},{"d","e","f"}}');
8787
INSERT INTO domarrtestvalues (NULL,'{{"toolong","b","c"},{"d","e","f"}}');
8888
select*from domarrtest;
8989
select testint4arr[1], testchar4arr[2:2]from domarrtest;
90+
select array_dims(testint4arr), array_dims(testchar4arr)from domarrtest;
9091

9192
COPY domarrtestFROM stdin;
9293
{3,4}{q,w,e}
@@ -103,6 +104,12 @@ drop table domarrtest;
103104
dropdomain domainint4arr restrict;
104105
dropdomain domainchar4arr restrict;
105106

107+
createdomaindiaasint[];
108+
select'{1,2,3}'::dia;
109+
select array_dims('{1,2,3}'::dia);
110+
select pg_typeof('{1,2,3}'::dia);
111+
select pg_typeof('{1,2,3}'::dia||42);-- should be int[] not dia
112+
dropdomain dia;
106113

107114
createdomaindnotnullvarchar(15)NOT NULL;
108115
createdomaindnullvarchar(15);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp