Skip to content

Commit 474aee3

Browse files
committed
Fix ARRAY_SUBLINK and ARRAY[] for int2vector and oidvector input.
If the given input_type yields valid results from both get_element_type and get_array_type, initArrayResultAny believed the former and treated the input as an array type. However this is inconsistent with what get_promoted_array_type does, leading to situations where the output of an ARRAY() subquery is labeled with the wrong type: it's labeled as oidvector[] but is really a 2-D array of OID. That at least results in strange output, and can result in crashes if further processing such as unnest() is applied. AFAIK this is only possible with the int2vector and oidvector types, which are special-cased to be treated mostly as true arrays even though they aren't quite. Fix by switching the logic to match get_promoted_array_type by testing get_array_type not get_element_type, and remove an Assert thereby made pointless. (We need not introduce a symmetrical check for get_element_type in the other if-branch, because initArrayResultArr will check it.) This restores the behavior that existed before bac2739 introduced initArrayResultAny: the output really is int2vector[] or oidvector[]. Comparable confusion exists when an input of an ARRAY[] construct is int2vector or oidvector: transformArrayExpr decides it's dealing with a multidimensional array constructor, and we end up with something that's a multidimensional OID array but is alleged to be of type oidvector. I have not found a crashing case here, but it's easy to demonstrate totally-wrong results. Adjust that code so that what you get is an oidvector[] instead, for consistency with ARRAY() subqueries. (This change also makes these types work like domains-over-arrays in this context, which seems correct.) Bug: #18840 Reported-by: yang lei <ylshiyu@126.com> Author: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/18840-fbc9505f066e50d6@postgresql.org Backpatch-through: 13
1 parent b200180 commit 474aee3

File tree

4 files changed

+166
-8
lines changed

4 files changed

+166
-8
lines changed

src/backend/parser/parse_expr.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2155,10 +2155,18 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a,
21552155

21562156
/*
21572157
* Check for sub-array expressions, if we haven't already found
2158-
* one.
2158+
* one. Note we don't accept domain-over-array as a sub-array,
2159+
* nor int2vector nor oidvector; those have constraints that don't
2160+
* map well to being treated as a sub-array.
21592161
*/
2160-
if (!newa->multidims && type_is_array(exprType(newe)))
2161-
newa->multidims = true;
2162+
if (!newa->multidims)
2163+
{
2164+
Oid newetype = exprType(newe);
2165+
2166+
if (newetype != INT2VECTOROID && newetype != OIDVECTOROID &&
2167+
type_is_array(newetype))
2168+
newa->multidims = true;
2169+
}
21622170
}
21632171

21642172
newelems = lappend(newelems, newe);

src/backend/utils/adt/arrayfuncs.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5541,9 +5541,14 @@ ArrayBuildStateAny *
55415541
initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
55425542
{
55435543
ArrayBuildStateAny *astate;
5544-
Oid element_type = get_element_type(input_type);
55455544

5546-
if (OidIsValid(element_type))
5545+
/*
5546+
* int2vector and oidvector will satisfy both get_element_type and
5547+
* get_array_type. We prefer to treat them as scalars, to be consistent
5548+
* with get_promoted_array_type. Hence, check get_array_type not
5549+
* get_element_type.
5550+
*/
5551+
if (!OidIsValid(get_array_type(input_type)))
55475552
{
55485553
/* Array case */
55495554
ArrayBuildStateArr *arraystate;
@@ -5560,9 +5565,6 @@ initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
55605565
/* Scalar case */
55615566
ArrayBuildState *scalarstate;
55625567

5563-
/* Let's just check that we have a type that can be put into arrays */
5564-
Assert(OidIsValid(get_array_type(input_type)));
5565-
55665568
scalarstate = initArrayResult(input_type, rcontext, subcontext);
55675569
astate = (ArrayBuildStateAny *)
55685570
MemoryContextAlloc(scalarstate->mcontext,

src/test/regress/expected/arrays.out

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2128,6 +2128,132 @@ select array(select array['Hello', i::text] from generate_series(9,11) i);
21282128
{{Hello,9},{Hello,10},{Hello,11}}
21292129
(1 row)
21302130

2131+
-- int2vector and oidvector should be treated as scalar types for this purpose
2132+
select pg_typeof(array(select '11 22 33'::int2vector from generate_series(1,5)));
2133+
pg_typeof
2134+
--------------
2135+
int2vector[]
2136+
(1 row)
2137+
2138+
select array(select '11 22 33'::int2vector from generate_series(1,5));
2139+
array
2140+
----------------------------------------------------------
2141+
{"11 22 33","11 22 33","11 22 33","11 22 33","11 22 33"}
2142+
(1 row)
2143+
2144+
select unnest(array(select '11 22 33'::int2vector from generate_series(1,5)));
2145+
unnest
2146+
----------
2147+
11 22 33
2148+
11 22 33
2149+
11 22 33
2150+
11 22 33
2151+
11 22 33
2152+
(5 rows)
2153+
2154+
select pg_typeof(array(select '11 22 33'::oidvector from generate_series(1,5)));
2155+
pg_typeof
2156+
-------------
2157+
oidvector[]
2158+
(1 row)
2159+
2160+
select array(select '11 22 33'::oidvector from generate_series(1,5));
2161+
array
2162+
----------------------------------------------------------
2163+
{"11 22 33","11 22 33","11 22 33","11 22 33","11 22 33"}
2164+
(1 row)
2165+
2166+
select unnest(array(select '11 22 33'::oidvector from generate_series(1,5)));
2167+
unnest
2168+
----------
2169+
11 22 33
2170+
11 22 33
2171+
11 22 33
2172+
11 22 33
2173+
11 22 33
2174+
(5 rows)
2175+
2176+
-- array[] should do the same
2177+
select pg_typeof(array['11 22 33'::int2vector]);
2178+
pg_typeof
2179+
--------------
2180+
int2vector[]
2181+
(1 row)
2182+
2183+
select array['11 22 33'::int2vector];
2184+
array
2185+
--------------
2186+
{"11 22 33"}
2187+
(1 row)
2188+
2189+
select pg_typeof(unnest(array['11 22 33'::int2vector]));
2190+
pg_typeof
2191+
------------
2192+
int2vector
2193+
(1 row)
2194+
2195+
select unnest(array['11 22 33'::int2vector]);
2196+
unnest
2197+
----------
2198+
11 22 33
2199+
(1 row)
2200+
2201+
select pg_typeof(unnest('11 22 33'::int2vector));
2202+
pg_typeof
2203+
-----------
2204+
smallint
2205+
smallint
2206+
smallint
2207+
(3 rows)
2208+
2209+
select unnest('11 22 33'::int2vector);
2210+
unnest
2211+
--------
2212+
11
2213+
22
2214+
33
2215+
(3 rows)
2216+
2217+
select pg_typeof(array['11 22 33'::oidvector]);
2218+
pg_typeof
2219+
-------------
2220+
oidvector[]
2221+
(1 row)
2222+
2223+
select array['11 22 33'::oidvector];
2224+
array
2225+
--------------
2226+
{"11 22 33"}
2227+
(1 row)
2228+
2229+
select pg_typeof(unnest(array['11 22 33'::oidvector]));
2230+
pg_typeof
2231+
-----------
2232+
oidvector
2233+
(1 row)
2234+
2235+
select unnest(array['11 22 33'::oidvector]);
2236+
unnest
2237+
----------
2238+
11 22 33
2239+
(1 row)
2240+
2241+
select pg_typeof(unnest('11 22 33'::oidvector));
2242+
pg_typeof
2243+
-----------
2244+
oid
2245+
oid
2246+
oid
2247+
(3 rows)
2248+
2249+
select unnest('11 22 33'::oidvector);
2250+
unnest
2251+
--------
2252+
11
2253+
22
2254+
33
2255+
(3 rows)
2256+
21312257
-- Insert/update on a column that is array of composite
21322258
create temp table t1 (f1 int8_tbl[]);
21332259
insert into t1 (f1[5].q1) values(42);

src/test/regress/sql/arrays.sql

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,28 @@ select array_replace(array['AB',NULL,'CDE'],NULL,'12');
637637
select array(select array[i,i/2] from generate_series(1,5) i);
638638
select array(select array['Hello', i::text] from generate_series(9,11) i);
639639

640+
-- int2vector and oidvector should be treated as scalar types for this purpose
641+
select pg_typeof(array(select '11 22 33'::int2vector from generate_series(1,5)));
642+
select array(select '11 22 33'::int2vector from generate_series(1,5));
643+
select unnest(array(select '11 22 33'::int2vector from generate_series(1,5)));
644+
select pg_typeof(array(select '11 22 33'::oidvector from generate_series(1,5)));
645+
select array(select '11 22 33'::oidvector from generate_series(1,5));
646+
select unnest(array(select '11 22 33'::oidvector from generate_series(1,5)));
647+
648+
-- array[] should do the same
649+
select pg_typeof(array['11 22 33'::int2vector]);
650+
select array['11 22 33'::int2vector];
651+
select pg_typeof(unnest(array['11 22 33'::int2vector]));
652+
select unnest(array['11 22 33'::int2vector]);
653+
select pg_typeof(unnest('11 22 33'::int2vector));
654+
select unnest('11 22 33'::int2vector);
655+
select pg_typeof(array['11 22 33'::oidvector]);
656+
select array['11 22 33'::oidvector];
657+
select pg_typeof(unnest(array['11 22 33'::oidvector]));
658+
select unnest(array['11 22 33'::oidvector]);
659+
select pg_typeof(unnest('11 22 33'::oidvector));
660+
select unnest('11 22 33'::oidvector);
661+
640662
-- Insert/update on a column that is array of composite
641663

642664
create temp table t1 (f1 int8_tbl[]);

0 commit comments

Comments
 (0)