From 5697522d8411135d26a5d807f9e4afa182502f64 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
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 b62b08c4824..6164f119ba7 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 b628c2811be..38aa030303a 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
-- 
GitLab