From c81c71d8846fa1667e67b45559ce4c72a8e076d9 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 18 Aug 2016 14:48:51 -0400 Subject: [PATCH] In plpgsql, don't try to convert int2vector or oidvector to expanded array. These types are storage-compatible with real arrays, but they don't support toasting, so of course they can't support expansion either. Per bug #14289 from Michael Overmeyer. Back-patch to 9.5 where expanded arrays were introduced. Report: <20160818174414.1529.37913@wrigleys.postgresql.org> --- src/include/utils/array.h | 2 +- src/pl/plpgsql/src/pl_comp.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/include/utils/array.h b/src/include/utils/array.h index b62b08c482..6164f119ba 100644 --- a/src/include/utils/array.h +++ b/src/include/utils/array.h @@ -36,7 +36,7 @@ * * The OIDVECTOR and INT2VECTOR datatypes are storage-compatible with * generic arrays, but they support only one-dimensional arrays with no - * nulls (and no null bitmap). + * nulls (and no null bitmap). They don't support being toasted, either. * * There are also some "fixed-length array" datatypes, such as NAME and * POINT. These are simply a sequence of a fixed number of items each diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index b628c2811b..38aa030303 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -2192,14 +2192,19 @@ build_datatype(HeapTuple typeTup, int32 typmod, Oid collation) /* NB: this is only used to decide whether to apply expand_array */ if (typeStruct->typtype == TYPTYPE_BASE) { - /* this test should match what get_element_type() checks */ + /* + * This test should include what get_element_type() checks. We also + * disallow non-toastable array types (i.e. oidvector and int2vector). + */ typ->typisarray = (typeStruct->typlen == -1 && - OidIsValid(typeStruct->typelem)); + OidIsValid(typeStruct->typelem) && + typeStruct->typstorage != 'p'); } else if (typeStruct->typtype == TYPTYPE_DOMAIN) { /* we can short-circuit looking up base types if it's not varlena */ typ->typisarray = (typeStruct->typlen == -1 && + typeStruct->typstorage != 'p' && OidIsValid(get_base_element_type(typeStruct->typbasetype))); } else