mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
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.
This commit is contained in:
parent
473c29e6ae
commit
371a14255b
22
src/backend/utils/cache/lsyscache.c
vendored
22
src/backend/utils/cache/lsyscache.c
vendored
@ -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.138.2.2 2007/10/13 15:55:49 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.138.2.3 2010/07/09 22:58:07 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Eventually, the index information should go through here, too.
|
||||
@ -2058,6 +2058,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,
|
||||
@ -2072,6 +2076,7 @@ get_attstatsslot(HeapTuple statstuple,
|
||||
Datum val;
|
||||
bool isnull;
|
||||
ArrayType *statarray;
|
||||
Oid arrayelemtype;
|
||||
int narrayelem;
|
||||
HeapTuple typeTuple;
|
||||
Form_pg_type typeForm;
|
||||
@ -2094,17 +2099,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; NULLs not expected */
|
||||
deconstruct_array(statarray,
|
||||
atttype,
|
||||
arrayelemtype,
|
||||
typeForm->typlen,
|
||||
typeForm->typbyval,
|
||||
typeForm->typalign,
|
||||
|
Loading…
Reference in New Issue
Block a user