aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/relcache.c
diff options
context:
space:
mode:
authorPeter Eisentraut <peter_e@gmx.net>2012-01-27 20:08:34 +0200
committerPeter Eisentraut <peter_e@gmx.net>2012-01-27 20:08:34 +0200
commit8a3f745f160d8334ad978676828d3926ac949f43 (patch)
treecccdd60563e196b388dab9b915f25f7548a11614 /src/backend/utils/cache/relcache.c
parenteb6af016fc04392c41106ac866072914bf66ecd0 (diff)
downloadpostgresql-8a3f745f160d8334ad978676828d3926ac949f43.tar.gz
postgresql-8a3f745f160d8334ad978676828d3926ac949f43.zip
Do not access indclass through Form_pg_index
Normally, accessing variable-length members of catalog structures past the first one doesn't work at all. Here, it happened to work because indnatts was checked to be 1, and so the defined FormData_pg_index layout, using int2vector[1] and oidvector[1] for variable-length arrays, happened to match the actual memory layout. But it's a very fragile assumption, and it's not in a performance-critical path, so code it properly using heap_getattr() instead. bug analysis by Tom Lane
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r--src/backend/utils/cache/relcache.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index d0138fc7e84..a59950e45a0 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -3351,15 +3351,30 @@ RelationGetIndexList(Relation relation)
while (HeapTupleIsValid(htup = systable_getnext(indscan)))
{
Form_pg_index index = (Form_pg_index) GETSTRUCT(htup);
+ Datum indclassDatum;
+ oidvector *indclass;
+ bool isnull;
/* Add index's OID to result list in the proper order */
result = insert_ordered_oid(result, index->indexrelid);
+ /*
+ * indclass cannot be referenced directly through the C struct, because
+ * it comes after the variable-width indkey field. Must extract the
+ * datum the hard way...
+ */
+ indclassDatum = heap_getattr(htup,
+ Anum_pg_index_indclass,
+ GetPgIndexDescriptor(),
+ &isnull);
+ Assert(!isnull);
+ indclass = (oidvector *) DatumGetPointer(indclassDatum);
+
/* Check to see if it is a unique, non-partial btree index on OID */
if (index->indnatts == 1 &&
index->indisunique && index->indimmediate &&
index->indkey.values[0] == ObjectIdAttributeNumber &&
- index->indclass.values[0] == OID_BTREE_OPS_OID &&
+ indclass->values[0] == OID_BTREE_OPS_OID &&
heap_attisnull(htup, Anum_pg_index_indpred))
oidIndex = index->indexrelid;
}