diff options
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r-- | src/backend/utils/cache/relcache.c | 181 |
1 files changed, 125 insertions, 56 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 65cd1e72907..be5fb60dc8e 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.250 2006/11/05 23:40:30 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.251 2006/12/23 00:43:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -69,7 +69,7 @@ */ #define RELCACHE_INIT_FILENAME "pg_internal.init" -#define RELCACHE_INIT_FILEMAGIC 0x573263 /* version ID value */ +#define RELCACHE_INIT_FILEMAGIC 0x573264 /* version ID value */ /* * hardcoded tuple descriptors. see include/catalog/pg_attribute.h @@ -159,7 +159,8 @@ do { \ /* * Special cache for opclass-related information * - * Note: only default-subtype operators and support procs get cached + * Note: only default operators and support procs get cached, ie, those with + * lefttype = righttype = opcintype. */ typedef struct opclasscacheent { @@ -167,6 +168,8 @@ typedef struct opclasscacheent bool valid; /* set TRUE after successful fill-in */ StrategyNumber numStrats; /* max # of strategies (from pg_am) */ StrategyNumber numSupport; /* max # of support procs (from pg_am) */ + Oid opcfamily; /* OID of opclass's family */ + Oid opcintype; /* OID of opclass's declared input type */ Oid *operatorOids; /* strategy operators' OIDs */ RegProcedure *supportProcs; /* support procs */ } OpClassCacheEnt; @@ -201,6 +204,8 @@ static List *insert_ordered_oid(List *list, Oid datum); static void IndexSupportInitialize(oidvector *indclass, Oid *indexOperator, RegProcedure *indexSupport, + Oid *opFamily, + Oid *opcInType, StrategyNumber maxStrategyNumber, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber); @@ -921,11 +926,9 @@ RelationInitIndexAccessInfo(Relation relation) Form_pg_am aform; Datum indclassDatum; bool isnull; + oidvector *indclass; MemoryContext indexcxt; MemoryContext oldcontext; - Oid *operator; - RegProcedure *support; - FmgrInfo *supportinfo; int natts; uint16 amstrategies; uint16 amsupport; @@ -948,18 +951,6 @@ RelationInitIndexAccessInfo(Relation relation) ReleaseSysCache(tuple); /* - * indclass cannot be referenced directly through the C struct, because it - * is after the variable-width indkey field. Therefore we extract the - * datum the hard way and provide a direct link in the relcache. - */ - indclassDatum = fastgetattr(relation->rd_indextuple, - Anum_pg_index_indclass, - GetPgIndexDescriptor(), - &isnull); - Assert(!isnull); - relation->rd_indclass = (oidvector *) DatumGetPointer(indclassDatum); - - /* * Make a copy of the pg_am entry for the index's access method */ tuple = SearchSysCache(AMOID, @@ -1001,38 +992,53 @@ RelationInitIndexAccessInfo(Relation relation) relation->rd_aminfo = (RelationAmInfo *) MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo)); + relation->rd_opfamily = (Oid *) + MemoryContextAllocZero(indexcxt, natts * sizeof(Oid)); + relation->rd_opcintype = (Oid *) + MemoryContextAllocZero(indexcxt, natts * sizeof(Oid)); + if (amstrategies > 0) - operator = (Oid *) + relation->rd_operator = (Oid *) MemoryContextAllocZero(indexcxt, natts * amstrategies * sizeof(Oid)); else - operator = NULL; + relation->rd_operator = NULL; if (amsupport > 0) { int nsupport = natts * amsupport; - support = (RegProcedure *) + relation->rd_support = (RegProcedure *) MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure)); - supportinfo = (FmgrInfo *) + relation->rd_supportinfo = (FmgrInfo *) MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo)); } else { - support = NULL; - supportinfo = NULL; + relation->rd_support = NULL; + relation->rd_supportinfo = NULL; } - relation->rd_operator = operator; - relation->rd_support = support; - relation->rd_supportinfo = supportinfo; + /* + * 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 = fastgetattr(relation->rd_indextuple, + Anum_pg_index_indclass, + GetPgIndexDescriptor(), + &isnull); + Assert(!isnull); + indclass = (oidvector *) DatumGetPointer(indclassDatum); /* - * Fill the operator and support procedure OID arrays. (aminfo and + * Fill the operator and support procedure OID arrays, as well as the + * info about opfamilies and opclass input types. (aminfo and * supportinfo are left as zeroes, and are filled on-the-fly when used) */ - IndexSupportInitialize(relation->rd_indclass, - operator, support, + IndexSupportInitialize(indclass, + relation->rd_operator, relation->rd_support, + relation->rd_opfamily, relation->rd_opcintype, amstrategies, amsupport, natts); /* @@ -1048,8 +1054,8 @@ RelationInitIndexAccessInfo(Relation relation) * Initializes an index's cached opclass information, * given the index's pg_index.indclass entry. * - * Data is returned into *indexOperator and *indexSupport, which are arrays - * allocated by the caller. + * Data is returned into *indexOperator, *indexSupport, *opFamily, and + * *opcInType, which are arrays allocated by the caller. * * The caller also passes maxStrategyNumber, maxSupportNumber, and * maxAttributeNumber, since these indicate the size of the arrays @@ -1061,6 +1067,8 @@ static void IndexSupportInitialize(oidvector *indclass, Oid *indexOperator, RegProcedure *indexSupport, + Oid *opFamily, + Oid *opcInType, StrategyNumber maxStrategyNumber, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber) @@ -1080,6 +1088,8 @@ IndexSupportInitialize(oidvector *indclass, maxSupportNumber); /* copy cached data into relcache entry */ + opFamily[attIndex] = opcentry->opcfamily; + opcInType[attIndex] = opcentry->opcintype; if (maxStrategyNumber > 0) memcpy(&indexOperator[attIndex * maxStrategyNumber], opcentry->operatorOids, @@ -1116,7 +1126,7 @@ LookupOpclassInfo(Oid operatorClassOid, bool found; Relation rel; SysScanDesc scan; - ScanKeyData skey[2]; + ScanKeyData skey[3]; HeapTuple htup; bool indexOK; @@ -1177,22 +1187,54 @@ LookupOpclassInfo(Oid operatorClassOid, operatorClassOid != INT2_BTREE_OPS_OID); /* + * We have to fetch the pg_opclass row to determine its opfamily and + * opcintype, which are needed to look up the operators and functions. + * It'd be convenient to use the syscache here, but that probably doesn't + * work while bootstrapping. + */ + ScanKeyInit(&skey[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(operatorClassOid)); + rel = heap_open(OperatorClassRelationId, AccessShareLock); + scan = systable_beginscan(rel, OpclassOidIndexId, indexOK, + SnapshotNow, 1, skey); + + if (HeapTupleIsValid(htup = systable_getnext(scan))) + { + Form_pg_opclass opclassform = (Form_pg_opclass) GETSTRUCT(htup); + + opcentry->opcfamily = opclassform->opcfamily; + opcentry->opcintype = opclassform->opcintype; + } + else + elog(ERROR, "could not find tuple for opclass %u", operatorClassOid); + + systable_endscan(scan); + heap_close(rel, AccessShareLock); + + + /* * Scan pg_amop to obtain operators for the opclass. We only fetch the - * default ones (those with subtype zero). + * default ones (those with lefttype = righttype = opcintype). */ if (numStrats > 0) { ScanKeyInit(&skey[0], - Anum_pg_amop_amopclaid, + Anum_pg_amop_amopfamily, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(operatorClassOid)); + ObjectIdGetDatum(opcentry->opcfamily)); ScanKeyInit(&skey[1], - Anum_pg_amop_amopsubtype, + Anum_pg_amop_amoplefttype, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(opcentry->opcintype)); + ScanKeyInit(&skey[2], + Anum_pg_amop_amoprighttype, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(InvalidOid)); + ObjectIdGetDatum(opcentry->opcintype)); rel = heap_open(AccessMethodOperatorRelationId, AccessShareLock); scan = systable_beginscan(rel, AccessMethodStrategyIndexId, indexOK, - SnapshotNow, 2, skey); + SnapshotNow, 3, skey); while (HeapTupleIsValid(htup = systable_getnext(scan))) { @@ -1212,21 +1254,25 @@ LookupOpclassInfo(Oid operatorClassOid, /* * Scan pg_amproc to obtain support procs for the opclass. We only fetch - * the default ones (those with subtype zero). + * the default ones (those with lefttype = righttype = opcintype). */ if (numSupport > 0) { ScanKeyInit(&skey[0], - Anum_pg_amproc_amopclaid, + Anum_pg_amproc_amprocfamily, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(operatorClassOid)); + ObjectIdGetDatum(opcentry->opcfamily)); ScanKeyInit(&skey[1], - Anum_pg_amproc_amprocsubtype, + Anum_pg_amproc_amproclefttype, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(InvalidOid)); + ObjectIdGetDatum(opcentry->opcintype)); + ScanKeyInit(&skey[2], + Anum_pg_amproc_amprocrighttype, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(opcentry->opcintype)); rel = heap_open(AccessMethodProcedureRelationId, AccessShareLock); scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK, - SnapshotNow, 2, skey); + SnapshotNow, 3, skey); while (HeapTupleIsValid(htup = systable_getnext(scan))) { @@ -3097,8 +3143,6 @@ load_relcache_init_file(void) Relation rel; Form_pg_class relform; bool has_not_null; - Datum indclassDatum; - bool isnull; /* first read the relation descriptor length */ if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len)) @@ -3187,6 +3231,8 @@ load_relcache_init_file(void) { Form_pg_am am; MemoryContext indexcxt; + Oid *opfamily; + Oid *opcintype; Oid *operator; RegProcedure *support; int nsupport; @@ -3207,14 +3253,6 @@ load_relcache_init_file(void) rel->rd_indextuple->t_data = (HeapTupleHeader) ((char *) rel->rd_indextuple + HEAPTUPLESIZE); rel->rd_index = (Form_pg_index) GETSTRUCT(rel->rd_indextuple); - /* fix up indclass pointer too */ - indclassDatum = fastgetattr(rel->rd_indextuple, - Anum_pg_index_indclass, - GetPgIndexDescriptor(), - &isnull); - Assert(!isnull); - rel->rd_indclass = (oidvector *) DatumGetPointer(indclassDatum); - /* next, read the access method tuple form */ if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len)) goto read_failed; @@ -3235,6 +3273,26 @@ load_relcache_init_file(void) ALLOCSET_SMALL_MAXSIZE); rel->rd_indexcxt = indexcxt; + /* next, read the vector of opfamily OIDs */ + if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len)) + goto read_failed; + + opfamily = (Oid *) MemoryContextAlloc(indexcxt, len); + if ((nread = fread(opfamily, 1, len, fp)) != len) + goto read_failed; + + rel->rd_opfamily = opfamily; + + /* next, read the vector of opcintype OIDs */ + if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len)) + goto read_failed; + + opcintype = (Oid *) MemoryContextAlloc(indexcxt, len); + if ((nread = fread(opcintype, 1, len, fp)) != len) + goto read_failed; + + rel->rd_opcintype = opcintype; + /* next, read the vector of operator OIDs */ if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len)) goto read_failed; @@ -3269,10 +3327,11 @@ load_relcache_init_file(void) Assert(rel->rd_index == NULL); Assert(rel->rd_indextuple == NULL); - Assert(rel->rd_indclass == NULL); Assert(rel->rd_am == NULL); Assert(rel->rd_indexcxt == NULL); Assert(rel->rd_aminfo == NULL); + Assert(rel->rd_opfamily == NULL); + Assert(rel->rd_opcintype == NULL); Assert(rel->rd_operator == NULL); Assert(rel->rd_support == NULL); Assert(rel->rd_supportinfo == NULL); @@ -3450,6 +3509,16 @@ write_relcache_init_file(void) /* next, write the access method tuple form */ write_item(am, sizeof(FormData_pg_am), fp); + /* next, write the vector of opfamily OIDs */ + write_item(rel->rd_opfamily, + relform->relnatts * sizeof(Oid), + fp); + + /* next, write the vector of opcintype OIDs */ + write_item(rel->rd_opcintype, + relform->relnatts * sizeof(Oid), + fp); + /* next, write the vector of operator OIDs */ write_item(rel->rd_operator, relform->relnatts * (am->amstrategies * sizeof(Oid)), |