OSDN Git Service

Generalize concept of temporary relations to "relation persistence".
[pg-rex/syncrep.git] / src / backend / utils / cache / relcache.c
index 2a44303..1509686 100644 (file)
@@ -39,7 +39,6 @@
 #include "catalog/index.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
-#include "catalog/pg_amop.h"
 #include "catalog/pg_amproc.h"
 #include "catalog/pg_attrdef.h"
 #include "catalog/pg_authid.h"
@@ -48,7 +47,6 @@
 #include "catalog/pg_database.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
-#include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_tablespace.h"
  */
 #define RELCACHE_INIT_FILENAME "pg_internal.init"
 
-#define RELCACHE_INIT_FILEMAGIC                0x573265        /* version ID value */
+#define RELCACHE_INIT_FILEMAGIC                0x573266        /* version ID value */
 
 /*
- *             hardcoded tuple descriptors, generated by genbki.pl
+ *             hardcoded tuple descriptors, contents generated by genbki.pl
  */
 static const FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class};
 static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute};
@@ -185,19 +183,17 @@ do { \
 /*
  * Special cache for opclass-related information
  *
- * Note: only default operators and support procs get cached, ie, those with
+ * Note: only default support procs get cached, ie, those with
  * lefttype = righttype = opcintype.
  */
 typedef struct opclasscacheent
 {
        Oid                     opclassoid;             /* lookup key: OID of opclass */
        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 */
+       RegProcedure *supportProcs; /* OIDs of support procedures */
 } OpClassCacheEnt;
 
 static HTAB *OpClassCache = NULL;
@@ -231,15 +227,12 @@ static void AttrDefaultFetch(Relation relation);
 static void CheckConstraintFetch(Relation relation);
 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);
 static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid,
-                                 StrategyNumber numStrats,
                                  StrategyNumber numSupport);
 static void RelationCacheInitFileRemoveInDir(const char *tblspcpath);
 static void unlink_initfile(const char *initfilename);
@@ -856,20 +849,30 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
        relation->rd_isnailed = false;
        relation->rd_createSubid = InvalidSubTransactionId;
        relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
-       relation->rd_istemp = relation->rd_rel->relistemp;
-       if (!relation->rd_istemp)
-               relation->rd_backend = InvalidBackendId;
-       else if (isTempOrToastNamespace(relation->rd_rel->relnamespace))
-               relation->rd_backend = MyBackendId;
-       else
+       switch (relation->rd_rel->relpersistence)
        {
-               /*
-                * If it's a temporary table, but not one of ours, we have to use
-                * the slow, grotty method to figure out the owning backend.
-                */
-               relation->rd_backend =
-                       GetTempNamespaceBackendId(relation->rd_rel->relnamespace);
-               Assert(relation->rd_backend != InvalidBackendId);
+               case RELPERSISTENCE_PERMANENT:
+                       relation->rd_backend = InvalidBackendId;
+                       break;
+               case RELPERSISTENCE_TEMP:
+                       if (isTempOrToastNamespace(relation->rd_rel->relnamespace))
+                               relation->rd_backend = MyBackendId;
+                       else
+                       {
+                               /*
+                                * If it's a local temp table, but not one of ours, we have to
+                                * use the slow, grotty method to figure out the owning
+                                * backend.
+                                */
+                               relation->rd_backend =
+                                       GetTempNamespaceBackendId(relation->rd_rel->relnamespace);
+                               Assert(relation->rd_backend != InvalidBackendId);
+                       }
+                       break;
+               default:
+                       elog(ERROR, "invalid relpersistence: %c",
+                                relation->rd_rel->relpersistence);
+                       break;
        }
 
        /*
@@ -980,7 +983,6 @@ RelationInitIndexAccessInfo(Relation relation)
        MemoryContext indexcxt;
        MemoryContext oldcontext;
        int                     natts;
-       uint16          amstrategies;
        uint16          amsupport;
 
        /*
@@ -1015,7 +1017,6 @@ RelationInitIndexAccessInfo(Relation relation)
        if (natts != relation->rd_index->indnatts)
                elog(ERROR, "relnatts disagrees with indnatts for index %u",
                         RelationGetRelid(relation));
-       amstrategies = aform->amstrategies;
        amsupport = aform->amsupport;
 
        /*
@@ -1044,13 +1045,6 @@ RelationInitIndexAccessInfo(Relation relation)
        relation->rd_opcintype = (Oid *)
                MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
 
-       if (amstrategies > 0)
-               relation->rd_operator = (Oid *)
-                       MemoryContextAllocZero(indexcxt,
-                                                                  natts * amstrategies * sizeof(Oid));
-       else
-               relation->rd_operator = NULL;
-
        if (amsupport > 0)
        {
                int                     nsupport = natts * amsupport;
@@ -1082,14 +1076,13 @@ RelationInitIndexAccessInfo(Relation relation)
        indclass = (oidvector *) DatumGetPointer(indclassDatum);
 
        /*
-        * 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)
+        * Fill the support procedure OID array, 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(indclass,
-                                                  relation->rd_operator, relation->rd_support,
+       IndexSupportInitialize(indclass, relation->rd_support,
                                                   relation->rd_opfamily, relation->rd_opcintype,
-                                                  amstrategies, amsupport, natts);
+                                                  amsupport, natts);
 
        /*
         * Similarly extract indoption and copy it to the cache entry
@@ -1118,22 +1111,19 @@ RelationInitIndexAccessInfo(Relation relation)
  *             Initializes an index's cached opclass information,
  *             given the index's pg_index.indclass entry.
  *
- * Data is returned into *indexOperator, *indexSupport, *opFamily, and
- * *opcInType, which are arrays allocated by the caller.
+ * Data is returned into *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
- * it has allocated --- but in practice these numbers must always match
- * those obtainable from the system catalog entries for the index and
- * access method.
+ * The caller also passes maxSupportNumber and maxAttributeNumber, since these
+ * indicate the size of the arrays it has allocated --- but in practice these
+ * numbers must always match those obtainable from the system catalog entries
+ * for the index and access method.
  */
 static void
 IndexSupportInitialize(oidvector *indclass,
-                                          Oid *indexOperator,
                                           RegProcedure *indexSupport,
                                           Oid *opFamily,
                                           Oid *opcInType,
-                                          StrategyNumber maxStrategyNumber,
                                           StrategyNumber maxSupportNumber,
                                           AttrNumber maxAttributeNumber)
 {
@@ -1148,16 +1138,11 @@ IndexSupportInitialize(oidvector *indclass,
 
                /* look up the info for this opclass, using a cache */
                opcentry = LookupOpclassInfo(indclass->values[attIndex],
-                                                                        maxStrategyNumber,
                                                                         maxSupportNumber);
 
                /* copy cached data into relcache entry */
                opFamily[attIndex] = opcentry->opcfamily;
                opcInType[attIndex] = opcentry->opcintype;
-               if (maxStrategyNumber > 0)
-                       memcpy(&indexOperator[attIndex * maxStrategyNumber],
-                                  opcentry->operatorOids,
-                                  maxStrategyNumber * sizeof(Oid));
                if (maxSupportNumber > 0)
                        memcpy(&indexSupport[attIndex * maxSupportNumber],
                                   opcentry->supportProcs,
@@ -1171,9 +1156,9 @@ IndexSupportInitialize(oidvector *indclass,
  * This routine maintains a per-opclass cache of the information needed
  * by IndexSupportInitialize().  This is more efficient than relying on
  * the catalog cache, because we can load all the info about a particular
- * opclass in a single indexscan of pg_amproc or pg_amop.
+ * opclass in a single indexscan of pg_amproc.
  *
- * The information from pg_am about expected range of strategy and support
+ * The information from pg_am about expected range of support function
  * numbers is passed in, rather than being looked up, mainly because the
  * caller will have it already.
  *
@@ -1187,7 +1172,6 @@ IndexSupportInitialize(oidvector *indclass,
  */
 static OpClassCacheEnt *
 LookupOpclassInfo(Oid operatorClassOid,
-                                 StrategyNumber numStrats,
                                  StrategyNumber numSupport)
 {
        OpClassCacheEnt *opcentry;
@@ -1223,16 +1207,8 @@ LookupOpclassInfo(Oid operatorClassOid,
        {
                /* Need to allocate memory for new entry */
                opcentry->valid = false;        /* until known OK */
-               opcentry->numStrats = numStrats;
                opcentry->numSupport = numSupport;
 
-               if (numStrats > 0)
-                       opcentry->operatorOids = (Oid *)
-                               MemoryContextAllocZero(CacheMemoryContext,
-                                                                          numStrats * sizeof(Oid));
-               else
-                       opcentry->operatorOids = NULL;
-
                if (numSupport > 0)
                        opcentry->supportProcs = (RegProcedure *)
                                MemoryContextAllocZero(CacheMemoryContext,
@@ -1242,7 +1218,6 @@ LookupOpclassInfo(Oid operatorClassOid,
        }
        else
        {
-               Assert(numStrats == opcentry->numStrats);
                Assert(numSupport == opcentry->numSupport);
        }
 
@@ -1273,7 +1248,7 @@ LookupOpclassInfo(Oid operatorClassOid,
 
        /*
         * We have to fetch the pg_opclass row to determine its opfamily and
-        * opcintype, which are needed to look up the operators and functions.
+        * opcintype, which are needed to look up related operators and functions.
         * It'd be convenient to use the syscache here, but that probably doesn't
         * work while bootstrapping.
         */
@@ -1298,45 +1273,6 @@ LookupOpclassInfo(Oid 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 lefttype = righttype = opcintype).
-        */
-       if (numStrats > 0)
-       {
-               ScanKeyInit(&skey[0],
-                                       Anum_pg_amop_amopfamily,
-                                       BTEqualStrategyNumber, F_OIDEQ,
-                                       ObjectIdGetDatum(opcentry->opcfamily));
-               ScanKeyInit(&skey[1],
-                                       Anum_pg_amop_amoplefttype,
-                                       BTEqualStrategyNumber, F_OIDEQ,
-                                       ObjectIdGetDatum(opcentry->opcintype));
-               ScanKeyInit(&skey[2],
-                                       Anum_pg_amop_amoprighttype,
-                                       BTEqualStrategyNumber, F_OIDEQ,
-                                       ObjectIdGetDatum(opcentry->opcintype));
-               rel = heap_open(AccessMethodOperatorRelationId, AccessShareLock);
-               scan = systable_beginscan(rel, AccessMethodStrategyIndexId, indexOK,
-                                                                 SnapshotNow, 3, skey);
-
-               while (HeapTupleIsValid(htup = systable_getnext(scan)))
-               {
-                       Form_pg_amop amopform = (Form_pg_amop) GETSTRUCT(htup);
-
-                       if (amopform->amopstrategy <= 0 ||
-                               (StrategyNumber) amopform->amopstrategy > numStrats)
-                               elog(ERROR, "invalid amopstrategy number %d for opclass %u",
-                                        amopform->amopstrategy, operatorClassOid);
-                       opcentry->operatorOids[amopform->amopstrategy - 1] =
-                               amopform->amopopr;
-               }
-
-               systable_endscan(scan);
-               heap_close(rel, AccessShareLock);
-       }
-
        /*
         * Scan pg_amproc to obtain support procs for the opclass.      We only fetch
         * the default ones (those with lefttype = righttype = opcintype).
@@ -1432,7 +1368,6 @@ formrdesc(const char *relationName, Oid relationReltype,
        relation->rd_isnailed = true;
        relation->rd_createSubid = InvalidSubTransactionId;
        relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
-       relation->rd_istemp = false;
        relation->rd_backend = InvalidBackendId;
 
        /*
@@ -1458,11 +1393,8 @@ formrdesc(const char *relationName, Oid relationReltype,
        if (isshared)
                relation->rd_rel->reltablespace = GLOBALTABLESPACE_OID;
 
-       /*
-        * Likewise, we must know if a relation is temp ... but formrdesc is not
-        * used for any temp relations.
-        */
-       relation->rd_rel->relistemp = false;
+       /* formrdesc is used only for permanent relations */
+       relation->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
 
        relation->rd_rel->relpages = 1;
        relation->rd_rel->reltuples = 1;
@@ -2440,7 +2372,8 @@ RelationBuildLocalRelation(const char *relname,
                                                   Oid relid,
                                                   Oid reltablespace,
                                                   bool shared_relation,
-                                                  bool mapped_relation)
+                                                  bool mapped_relation,
+                                                  char relpersistence)
 {
        Relation        rel;
        MemoryContext oldcxt;
@@ -2514,10 +2447,6 @@ RelationBuildLocalRelation(const char *relname,
        /* must flag that we have rels created in this transaction */
        need_eoxact_work = true;
 
-       /* it is temporary if and only if it is in my temp-table namespace */
-       rel->rd_istemp = isTempOrToastNamespace(relnamespace);
-       rel->rd_backend = rel->rd_istemp ? MyBackendId : InvalidBackendId;
-
        /*
         * create a new tuple descriptor from the one passed in.  We do this
         * partly to copy it into the cache context, and partly because the new
@@ -2557,6 +2486,21 @@ RelationBuildLocalRelation(const char *relname,
        /* needed when bootstrapping: */
        rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
 
+       /* set up persistence; rd_backend is a function of persistence type */
+       rel->rd_rel->relpersistence = relpersistence;
+       switch (relpersistence)
+       {
+               case RELPERSISTENCE_PERMANENT:
+                       rel->rd_backend = InvalidBackendId;
+                       break;
+               case RELPERSISTENCE_TEMP:
+                       rel->rd_backend = MyBackendId;
+                       break;
+               default:
+                       elog(ERROR, "invalid relpersistence: %c", relpersistence);
+                       break;
+       }
+
        /*
         * Insert relation physical and logical identifiers (OIDs) into the right
         * places.      Note that the physical ID (relfilenode) is initially the same
@@ -2565,7 +2509,6 @@ RelationBuildLocalRelation(const char *relname,
         * map.
         */
        rel->rd_rel->relisshared = shared_relation;
-       rel->rd_rel->relistemp = rel->rd_istemp;
 
        RelationGetRelid(rel) = relid;
 
@@ -2623,8 +2566,8 @@ RelationBuildLocalRelation(const char *relname,
  * Caller must already hold exclusive lock on the relation.
  *
  * The relation is marked with relfrozenxid = freezeXid (InvalidTransactionId
- * must be passed for indexes).  This should be a lower bound on the XIDs
- * that will be put into the new relation contents.
+ * must be passed for indexes and sequences).  This should be a lower bound on
+ * the XIDs that will be put into the new relation contents.
  */
 void
 RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid)
@@ -2635,14 +2578,15 @@ RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid)
        HeapTuple       tuple;
        Form_pg_class classform;
 
-       /* Indexes must have Invalid frozenxid; other relations must not */
-       Assert((relation->rd_rel->relkind == RELKIND_INDEX &&
-                       freezeXid == InvalidTransactionId) ||
+       /* Indexes, sequences must have Invalid frozenxid; other rels must not */
+       Assert((relation->rd_rel->relkind == RELKIND_INDEX ||
+                       relation->rd_rel->relkind == RELKIND_SEQUENCE) ?
+                  freezeXid == InvalidTransactionId :
                   TransactionIdIsNormal(freezeXid));
 
        /* Allocate a new relfilenode */
        newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
-                                                                          relation->rd_backend);
+                                                                          relation->rd_rel->relpersistence);
 
        /*
         * Get a writable copy of the pg_class tuple for the given relation.
@@ -2665,7 +2609,7 @@ RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid)
        newrnode.node = relation->rd_node;
        newrnode.node.relNode = newrelfilenode;
        newrnode.backend = relation->rd_backend;
-       RelationCreateStorage(newrnode.node, relation->rd_istemp);
+       RelationCreateStorage(newrnode.node, relation->rd_rel->relpersistence);
        smgrclosenode(newrnode);
 
        /*
@@ -2687,8 +2631,11 @@ RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid)
                classform->relfilenode = newrelfilenode;
 
        /* These changes are safe even for a mapped relation */
-       classform->relpages = 0;        /* it's empty until further notice */
-       classform->reltuples = 0;
+       if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
+       {
+               classform->relpages = 0;        /* it's empty until further notice */
+               classform->reltuples = 0;
+       }
        classform->relfrozenxid = freezeXid;
 
        simple_heap_update(pg_class, &tuple->t_self, tuple);
@@ -2751,7 +2698,7 @@ RelationCacheInitialize(void)
                                                                  &ctl, HASH_ELEM | HASH_FUNCTION);
 
        /*
-        * relation mapper needs initialized too
+        * relation mapper needs to be initialized too
         */
        RelationMapInitialize();
 }
@@ -2903,18 +2850,14 @@ RelationCacheInitializePhase3(void)
                                                        IndexRelationId);
                load_critical_index(OpclassOidIndexId,
                                                        OperatorClassRelationId);
-               load_critical_index(AccessMethodStrategyIndexId,
-                                                       AccessMethodOperatorRelationId);
                load_critical_index(AccessMethodProcedureIndexId,
                                                        AccessMethodProcedureRelationId);
-               load_critical_index(OperatorOidIndexId,
-                                                       OperatorRelationId);
                load_critical_index(RewriteRelRulenameIndexId,
                                                        RewriteRelationId);
                load_critical_index(TriggerRelidNameIndexId,
                                                        TriggerRelationId);
 
-#define NUM_CRITICAL_LOCAL_INDEXES     9       /* fix if you change list above */
+#define NUM_CRITICAL_LOCAL_INDEXES     7       /* fix if you change list above */
 
                criticalRelcachesBuilt = true;
        }
@@ -4040,7 +3983,6 @@ load_relcache_init_file(bool shared)
                        MemoryContext indexcxt;
                        Oid                *opfamily;
                        Oid                *opcintype;
-                       Oid                *operator;
                        RegProcedure *support;
                        int                     nsupport;
                        int16      *indoption;
@@ -4101,17 +4043,7 @@ load_relcache_init_file(bool shared)
 
                        rel->rd_opcintype = opcintype;
 
-                       /* next, read the vector of operator OIDs */
-                       if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
-                               goto read_failed;
-
-                       operator = (Oid *) MemoryContextAlloc(indexcxt, len);
-                       if (fread(operator, 1, len, fp) != len)
-                               goto read_failed;
-
-                       rel->rd_operator = operator;
-
-                       /* next, read the vector of support procedures */
+                       /* next, read the vector of support procedure OIDs */
                        if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
                                goto read_failed;
                        support = (RegProcedure *) MemoryContextAlloc(indexcxt, len);
@@ -4150,7 +4082,6 @@ load_relcache_init_file(bool shared)
                        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);
                        Assert(rel->rd_indoption == NULL);
@@ -4367,12 +4298,7 @@ write_relcache_init_file(bool shared)
                                           relform->relnatts * sizeof(Oid),
                                           fp);
 
-                       /* next, write the vector of operator OIDs */
-                       write_item(rel->rd_operator,
-                                          relform->relnatts * (am->amstrategies * sizeof(Oid)),
-                                          fp);
-
-                       /* next, write the vector of support procedures */
+                       /* next, write the vector of support procedure OIDs */
                        write_item(rel->rd_support,
                                  relform->relnatts * (am->amsupport * sizeof(RegProcedure)),
                                           fp);