aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/relcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r--src/backend/utils/cache/relcache.c181
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)),