diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2010-07-09 22:58:25 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2010-07-09 22:58:25 +0000 |
commit | 678e0d92c2d7e3b9648e07fea8d288571091d699 (patch) | |
tree | 673dd1b6711ef66831d4f64062da40339bd07b65 | |
parent | 1cf269cf99b59da9693d95f1c66bccdce11fac4c (diff) | |
download | postgresql-678e0d92c2d7e3b9648e07fea8d288571091d699.tar.gz |
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.
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 3543ac0edc..95ed355d0b 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 - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.108.2.1 2003/12/03 17:45:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.108.2.2 2010/07/09 22:58:25 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -1796,6 +1796,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, @@ -1810,6 +1814,7 @@ get_attstatsslot(HeapTuple statstuple, Datum val; bool isnull; ArrayType *statarray; + Oid arrayelemtype; int narrayelem; HeapTuple typeTuple; Form_pg_type typeForm; @@ -1832,17 +1837,24 @@ get_attstatsslot(HeapTuple statstuple, elog(ERROR, "stavalues is null"); statarray = DatumGetArrayTypeP(val); - /* Need to get info about the array element type */ + /* + * 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 = SearchSysCache(TYPEOID, - ObjectIdGetDatum(atttype), + ObjectIdGetDatum(arrayelemtype), 0, 0, 0); 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 */ deconstruct_array(statarray, - atttype, + arrayelemtype, typeForm->typlen, typeForm->typbyval, typeForm->typalign, |