Skip to content

Commit f7ae513

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 1a20bc9 commit f7ae513

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
@@ -1969,10 +1969,18 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a,
19691969

19701970
/*
19711971
* Check for sub-array expressions, if we haven't already found
1972-
* one.
1972+
* one. Note we don't accept domain-over-array as a sub-array,
1973+
* nor int2vector nor oidvector; those have constraints that don't
1974+
* map well to being treated as a sub-array.
19731975
*/
1974-
if (!newa->multidims && type_is_array(exprType(newe)))
1975-
newa->multidims = true;
1976+
if (!newa->multidims)
1977+
{
1978+
Oid newetype = exprType(newe);
1979+
1980+
if (newetype != INT2VECTOROID && newetype != OIDVECTOROID &&
1981+
type_is_array(newetype))
1982+
newa->multidims = true;
1983+
}
19761984
}
19771985

19781986
newelems = lappend(newelems, newe);

src/backend/utils/adt/arrayfuncs.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5602,9 +5602,14 @@ ArrayBuildStateAny *
56025602
initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
56035603
{
56045604
ArrayBuildStateAny *astate;
5605-
Oid element_type = get_element_type(input_type);
56065605

5607-
if (OidIsValid(element_type))
5606+
/*
5607+
* int2vector and oidvector will satisfy both get_element_type and
5608+
* get_array_type. We prefer to treat them as scalars, to be consistent
5609+
* with get_promoted_array_type. Hence, check get_array_type not
5610+
* get_element_type.
5611+
*/
5612+
if (!OidIsValid(get_array_type(input_type)))
56085613
{
56095614
/* Array case */
56105615
ArrayBuildStateArr *arraystate;
@@ -5621,9 +5626,6 @@ initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
56215626
/* Scalar case */
56225627
ArrayBuildState *scalarstate;
56235628

5624-
/* Let's just check that we have a type that can be put into arrays */
5625-
Assert(OidIsValid(get_array_type(input_type)));
5626-
56275629
scalarstate = initArrayResult(input_type, rcontext, subcontext);
56285630
astate = (ArrayBuildStateAny *)
56295631
MemoryContextAlloc(scalarstate->mcontext,

src/test/regress/expected/arrays.out

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

2266+
-- int2vector and oidvector should be treated as scalar types for this purpose
2267+
select pg_typeof(array(select '11 22 33'::int2vector from generate_series(1,5)));
2268+
pg_typeof
2269+
--------------
2270+
int2vector[]
2271+
(1 row)
2272+
2273+
select array(select '11 22 33'::int2vector from generate_series(1,5));
2274+
array
2275+
----------------------------------------------------------
2276+
{"11 22 33","11 22 33","11 22 33","11 22 33","11 22 33"}
2277+
(1 row)
2278+
2279+
select unnest(array(select '11 22 33'::int2vector from generate_series(1,5)));
2280+
unnest
2281+
----------
2282+
11 22 33
2283+
11 22 33
2284+
11 22 33
2285+
11 22 33
2286+
11 22 33
2287+
(5 rows)
2288+
2289+
select pg_typeof(array(select '11 22 33'::oidvector from generate_series(1,5)));
2290+
pg_typeof
2291+
-------------
2292+
oidvector[]
2293+
(1 row)
2294+
2295+
select array(select '11 22 33'::oidvector from generate_series(1,5));
2296+
array
2297+
----------------------------------------------------------
2298+
{"11 22 33","11 22 33","11 22 33","11 22 33","11 22 33"}
2299+
(1 row)
2300+
2301+
select unnest(array(select '11 22 33'::oidvector from generate_series(1,5)));
2302+
unnest
2303+
----------
2304+
11 22 33
2305+
11 22 33
2306+
11 22 33
2307+
11 22 33
2308+
11 22 33
2309+
(5 rows)
2310+
2311+
-- array[] should do the same
2312+
select pg_typeof(array['11 22 33'::int2vector]);
2313+
pg_typeof
2314+
--------------
2315+
int2vector[]
2316+
(1 row)
2317+
2318+
select array['11 22 33'::int2vector];
2319+
array
2320+
--------------
2321+
{"11 22 33"}
2322+
(1 row)
2323+
2324+
select pg_typeof(unnest(array['11 22 33'::int2vector]));
2325+
pg_typeof
2326+
------------
2327+
int2vector
2328+
(1 row)
2329+
2330+
select unnest(array['11 22 33'::int2vector]);
2331+
unnest
2332+
----------
2333+
11 22 33
2334+
(1 row)
2335+
2336+
select pg_typeof(unnest('11 22 33'::int2vector));
2337+
pg_typeof
2338+
-----------
2339+
smallint
2340+
smallint
2341+
smallint
2342+
(3 rows)
2343+
2344+
select unnest('11 22 33'::int2vector);
2345+
unnest
2346+
--------
2347+
11
2348+
22
2349+
33
2350+
(3 rows)
2351+
2352+
select pg_typeof(array['11 22 33'::oidvector]);
2353+
pg_typeof
2354+
-------------
2355+
oidvector[]
2356+
(1 row)
2357+
2358+
select array['11 22 33'::oidvector];
2359+
array
2360+
--------------
2361+
{"11 22 33"}
2362+
(1 row)
2363+
2364+
select pg_typeof(unnest(array['11 22 33'::oidvector]));
2365+
pg_typeof
2366+
-----------
2367+
oidvector
2368+
(1 row)
2369+
2370+
select unnest(array['11 22 33'::oidvector]);
2371+
unnest
2372+
----------
2373+
11 22 33
2374+
(1 row)
2375+
2376+
select pg_typeof(unnest('11 22 33'::oidvector));
2377+
pg_typeof
2378+
-----------
2379+
oid
2380+
oid
2381+
oid
2382+
(3 rows)
2383+
2384+
select unnest('11 22 33'::oidvector);
2385+
unnest
2386+
--------
2387+
11
2388+
22
2389+
33
2390+
(3 rows)
2391+
22662392
-- Insert/update on a column that is array of composite
22672393
create temp table t1 (f1 int8_tbl[]);
22682394
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
@@ -659,6 +659,28 @@ select array_replace(array['AB',NULL,'CDE'],NULL,'12');
659659
select array(select array[i,i/2] from generate_series(1,5) i);
660660
select array(select array['Hello', i::text] from generate_series(9,11) i);
661661

662+
-- int2vector and oidvector should be treated as scalar types for this purpose
663+
select pg_typeof(array(select '11 22 33'::int2vector from generate_series(1,5)));
664+
select array(select '11 22 33'::int2vector from generate_series(1,5));
665+
select unnest(array(select '11 22 33'::int2vector from generate_series(1,5)));
666+
select pg_typeof(array(select '11 22 33'::oidvector from generate_series(1,5)));
667+
select array(select '11 22 33'::oidvector from generate_series(1,5));
668+
select unnest(array(select '11 22 33'::oidvector from generate_series(1,5)));
669+
670+
-- array[] should do the same
671+
select pg_typeof(array['11 22 33'::int2vector]);
672+
select array['11 22 33'::int2vector];
673+
select pg_typeof(unnest(array['11 22 33'::int2vector]));
674+
select unnest(array['11 22 33'::int2vector]);
675+
select pg_typeof(unnest('11 22 33'::int2vector));
676+
select unnest('11 22 33'::int2vector);
677+
select pg_typeof(array['11 22 33'::oidvector]);
678+
select array['11 22 33'::oidvector];
679+
select pg_typeof(unnest(array['11 22 33'::oidvector]));
680+
select unnest(array['11 22 33'::oidvector]);
681+
select pg_typeof(unnest('11 22 33'::oidvector));
682+
select unnest('11 22 33'::oidvector);
683+
662684
-- Insert/update on a column that is array of composite
663685

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

0 commit comments

Comments
 (0)