aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/lsyscache.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2010-07-09 22:57:39 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2010-07-09 22:57:39 +0000
commit5ce63f480b9b9e77d4f5ab70cf59e8e31d40a8e0 (patch)
treec97113e8e622625ae0ae889a4196c159f2aeddb6 /src/backend/utils/cache/lsyscache.c
parent2b8a624596179efc3605cef4c80ba9fcea75c21c (diff)
downloadpostgresql-5ce63f480b9b9e77d4f5ab70cf59e8e31d40a8e0.tar.gz
postgresql-5ce63f480b9b9e77d4f5ab70cf59e8e31d40a8e0.zip
Avoid an Assert failure in deconstruct_array() by making get_attstatsslot()
use the actual element type of the array it's disassembling, rather than trusting the type OID passed in by its caller. This is needed because sometimes the planner passes in a type OID that's only binary-compatible with the target column's type, rather than being an exact match. Per an example from Bernd Helmle. Possibly we should refactor get_attstatsslot/free_attstatsslot to not expect the caller to supply type ID data at all, but for now I'll just do the minimum-change fix. Back-patch to 7.4. Bernd's test case only crashes back to 8.0, but since these subroutines are the same in 7.4, I suspect there may be variant cases that would crash 7.4 as well.
Diffstat (limited to 'src/backend/utils/cache/lsyscache.c')
-rw-r--r--src/backend/utils/cache/lsyscache.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index cc33c459a25..f49656eda22 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.170 2010/04/24 16:20:32 sriggs Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.171 2010/07/09 22:57:39 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -2463,6 +2463,10 @@ get_attavgwidth(Oid relid, AttrNumber attnum)
* If the attribute type is pass-by-reference, the values referenced by
* the values array are themselves palloc'd. The palloc'd stuff can be
* freed by calling free_attstatsslot.
+ *
+ * Note: at present, atttype/atttypmod aren't actually used here at all.
+ * But the caller must have the correct (or at least binary-compatible)
+ * type ID to pass to free_attstatsslot later.
*/
bool
get_attstatsslot(HeapTuple statstuple,
@@ -2478,6 +2482,7 @@ get_attstatsslot(HeapTuple statstuple,
Datum val;
bool isnull;
ArrayType *statarray;
+ Oid arrayelemtype;
int narrayelem;
HeapTuple typeTuple;
Form_pg_type typeForm;
@@ -2503,15 +2508,22 @@ get_attstatsslot(HeapTuple statstuple,
elog(ERROR, "stavalues is null");
statarray = DatumGetArrayTypeP(val);
- /* Need to get info about the array element type */
- typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(atttype));
+ /*
+ * Need to get info about the array element type. We look at the
+ * actual element type embedded in the array, which might be only
+ * binary-compatible with the passed-in atttype. The info we
+ * extract here should be the same either way, but deconstruct_array
+ * is picky about having an exact type OID match.
+ */
+ arrayelemtype = ARR_ELEMTYPE(statarray);
+ typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
if (!HeapTupleIsValid(typeTuple))
- elog(ERROR, "cache lookup failed for type %u", atttype);
+ elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
/* Deconstruct array into Datum elements; NULLs not expected */
deconstruct_array(statarray,
- atttype,
+ arrayelemtype,
typeForm->typlen,
typeForm->typbyval,
typeForm->typalign,