diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-03-29 00:17:27 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-03-29 00:17:27 +0000 |
| commit | 70c9763d4815ac847f0f7694f43eb6a59a236868 (patch) | |
| tree | 7d8aa05f668f1ef7809ff521b6c1e12d31125fd7 /src/backend/utils/cache/relcache.c | |
| parent | 119191609c507528b20d74c59be69f2129127575 (diff) | |
Convert oidvector and int2vector into variable-length arrays. This
change saves a great deal of space in pg_proc and its primary index,
and it eliminates the former requirement that INDEX_MAX_KEYS and
FUNC_MAX_ARGS have the same value. INDEX_MAX_KEYS is still embedded
in the on-disk representation (because it affects index tuple header
size), but FUNC_MAX_ARGS is not. I believe it would now be possible
to increase FUNC_MAX_ARGS at little cost, but haven't experimented yet.
There are still a lot of vestigial references to FUNC_MAX_ARGS, which
I will clean up in a separate pass. However, getting rid of it
altogether would require changing the FunctionCallInfoData struct,
and I'm not sure I want to buy into that.
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
| -rw-r--r-- | src/backend/utils/cache/relcache.c | 121 |
1 files changed, 91 insertions, 30 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index a6660fc4d32..109a6e811aa 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.217 2005/03/28 00:58:26 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.218 2005/03/29 00:17:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,7 +27,6 @@ */ #include "postgres.h" -#include <errno.h> #include <sys/file.h> #include <fcntl.h> #include <unistd.h> @@ -81,6 +80,7 @@ static FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class}; static FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute}; static FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = {Schema_pg_proc}; static FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type}; +static FormData_pg_attribute Desc_pg_index[Natts_pg_index] = {Schema_pg_index}; /* * Hash tables that index the relation cache @@ -267,10 +267,11 @@ static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo, Relation oldrelation); static void RelationInitPhysicalAddr(Relation relation); +static TupleDesc GetPgIndexDescriptor(void); static void AttrDefaultFetch(Relation relation); static void CheckConstraintFetch(Relation relation); static List *insert_ordered_oid(List *list, Oid datum); -static void IndexSupportInitialize(Form_pg_index iform, +static void IndexSupportInitialize(oidvector *indclass, Oid *indexOperator, RegProcedure *indexSupport, StrategyNumber maxStrategyNumber, @@ -918,6 +919,8 @@ RelationInitIndexAccessInfo(Relation relation) { HeapTuple tuple; Form_pg_am aform; + Datum indclassDatum; + bool isnull; MemoryContext indexcxt; MemoryContext oldcontext; Oid *operator; @@ -946,6 +949,18 @@ 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, @@ -1014,7 +1029,7 @@ RelationInitIndexAccessInfo(Relation relation) * Fill the operator and support procedure OID arrays. (supportinfo is * left as zeroes, and is filled on-the-fly when used) */ - IndexSupportInitialize(relation->rd_index, + IndexSupportInitialize(relation->rd_indclass, operator, support, amstrategies, amsupport, natts); @@ -1028,7 +1043,7 @@ RelationInitIndexAccessInfo(Relation relation) /* * IndexSupportInitialize * Initializes an index's cached opclass information, - * given the index's pg_index tuple. + * given the index's pg_index.indclass entry. * * Data is returned into *indexOperator and *indexSupport, which are arrays * allocated by the caller. @@ -1040,7 +1055,7 @@ RelationInitIndexAccessInfo(Relation relation) * access method. */ static void -IndexSupportInitialize(Form_pg_index iform, +IndexSupportInitialize(oidvector *indclass, Oid *indexOperator, RegProcedure *indexSupport, StrategyNumber maxStrategyNumber, @@ -1049,19 +1064,15 @@ IndexSupportInitialize(Form_pg_index iform, { int attIndex; - /* - * XXX note that the following assumes the INDEX tuple is well formed - * and that the *key and *class are 0 terminated. - */ for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++) { OpClassCacheEnt *opcentry; - if (!OidIsValid(iform->indclass[attIndex])) + if (!OidIsValid(indclass->values[attIndex])) elog(ERROR, "bogus pg_index tuple"); /* look up the info for this opclass, using a cache */ - opcentry = LookupOpclassInfo(iform->indclass[attIndex], + opcentry = LookupOpclassInfo(indclass->values[attIndex], maxStrategyNumber, maxSupportNumber); @@ -2479,6 +2490,53 @@ RelationCacheInitializePhase3(void) } } +/* + * GetPgIndexDescriptor -- get a predefined tuple descriptor for pg_index + * + * We need this kluge because we have to be able to access non-fixed-width + * fields of pg_index before we have the standard catalog caches available. + * We use predefined data that's set up in just the same way as the + * bootstrapped reldescs used by formrdesc(). The resulting tupdesc is + * not 100% kosher: it does not have the correct relation OID in attrelid, + * nor does it have a TupleConstr field. But it's good enough for the + * purpose of extracting fields. + */ +static TupleDesc +GetPgIndexDescriptor(void) +{ + static TupleDesc pgindexdesc = NULL; + MemoryContext oldcxt; + int i; + + /* Already done? */ + if (pgindexdesc) + return pgindexdesc; + + oldcxt = MemoryContextSwitchTo(CacheMemoryContext); + + pgindexdesc = CreateTemplateTupleDesc(Natts_pg_index, false); + pgindexdesc->tdtypeid = RECORDOID; /* not right, but we don't care */ + pgindexdesc->tdtypmod = -1; + + for (i = 0; i < Natts_pg_index; i++) + { + memcpy(pgindexdesc->attrs[i], + &Desc_pg_index[i], + ATTRIBUTE_TUPLE_SIZE); + /* make sure attcacheoff is valid */ + pgindexdesc->attrs[i]->attcacheoff = -1; + } + + /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */ + pgindexdesc->attrs[0]->attcacheoff = 0; + + /* Note: we don't bother to set up a TupleConstr entry */ + + MemoryContextSwitchTo(oldcxt); + + return pgindexdesc; +} + static void AttrDefaultFetch(Relation relation) { @@ -2773,15 +2831,11 @@ RelationGetIndexExpressions(Relation relation) * After successfully completing the work, we copy it into the * relcache entry. This avoids problems if we get some sort of error * partway through. - * - * We make use of the syscache's copy of pg_index's tupledesc to access - * the non-fixed fields of the tuple. We assume that the syscache - * will be initialized before any access of a partial index could - * occur. (This would probably fail if we were to allow partial - * indexes on system catalogs.) - */ - exprsDatum = SysCacheGetAttr(INDEXRELID, relation->rd_indextuple, - Anum_pg_index_indexprs, &isnull); + */ + exprsDatum = heap_getattr(relation->rd_indextuple, + Anum_pg_index_indexprs, + GetPgIndexDescriptor(), + &isnull); Assert(!isnull); exprsString = DatumGetCString(DirectFunctionCall1(textout, exprsDatum)); result = (List *) stringToNode(exprsString); @@ -2845,15 +2899,11 @@ RelationGetIndexPredicate(Relation relation) * After successfully completing the work, we copy it into the * relcache entry. This avoids problems if we get some sort of error * partway through. - * - * We make use of the syscache's copy of pg_index's tupledesc to access - * the non-fixed fields of the tuple. We assume that the syscache - * will be initialized before any access of a partial index could - * occur. (This would probably fail if we were to allow partial - * indexes on system catalogs.) - */ - predDatum = SysCacheGetAttr(INDEXRELID, relation->rd_indextuple, - Anum_pg_index_indpred, &isnull); + */ + predDatum = heap_getattr(relation->rd_indextuple, + Anum_pg_index_indpred, + GetPgIndexDescriptor(), + &isnull); Assert(!isnull); predString = DatumGetCString(DirectFunctionCall1(textout, predDatum)); result = (List *) stringToNode(predString); @@ -2990,6 +3040,8 @@ 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)) @@ -3081,6 +3133,14 @@ 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; @@ -3133,6 +3193,7 @@ 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_operator == NULL); |
