nparts;
PartitionKey key = RelationGetPartitionKey(rel);
MemoryContext oldcxt;
- MemoryContext rbcontext;
int *mapping;
- /*
- * While building the partition descriptor, we create various temporary
- * data structures; in CLOBBER_CACHE_ALWAYS mode, at least, it's important
- * not to them, since this can get called a lot.
- */
- rbcontext = AllocSetContextCreate(CurrentMemoryContext,
- "RelationBuildPartitionDesc",
- ALLOCSET_DEFAULT_SIZES);
- oldcxt = MemoryContextSwitchTo(rbcontext);
-
/*
* Get partition oids from pg_inherits. This uses a single snapshot to
* fetch the list of children, so while more children may be getting
/* If there are no partitions, the rest of the partdesc can stay zero */
if (nparts > 0)
{
- /* Create PartitionBoundInfo, using the temporary context. */
+ /* Create PartitionBoundInfo, using the caller's context. */
boundinfo = partition_bounds_create(boundspecs, nparts, key, &mapping);
/* Now copy all info into relcache's partdesc. */
- MemoryContextSwitchTo(rel->rd_pdcxt);
+ oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
partdesc->boundinfo = partition_bounds_copy(boundinfo, key);
partdesc->oids = (Oid *) palloc(nparts * sizeof(Oid));
partdesc->is_leaf = (bool *) palloc(nparts * sizeof(bool));
+ MemoryContextSwitchTo(oldcxt);
/*
* Assign OIDs from the original array into mapped indexes of the
*
* Also record leaf-ness of each partition. For this we use
* get_rel_relkind() which may memory, so be sure to run it in
- * the temporary context.
+ * the caller's context.
*/
- MemoryContextSwitchTo(rbcontext);
for (i = 0; i < nparts; i++)
{
int index = mapping[i];
}
rel->rd_partdesc = partdesc;
-
- /* Return to caller's context, and blow away the temporary context. */
- MemoryContextSwitchTo(oldcxt);
- MemoryContextDelete(rbcontext);
}
/*
#define RELCACHE_INIT_FILEMAGIC 0x573266 /* version ID value */
+/*
+ * Default policy for whether to apply RECOVER_RELATION_BUILD_MEMORY:
+ * do so in clobber-cache builds but not otherwise. This choice can be
+ * overridden at compile time with -DRECOVER_RELATION_BUILD_MEMORY=1 or =0.
+ */
+#ifndef RECOVER_RELATION_BUILD_MEMORY
+#if defined(CLOBBER_CACHE_ALWAYS) || defined(CLOBBER_CACHE_RECURSIVELY)
+#define RECOVER_RELATION_BUILD_MEMORY 1
+#else
+#define RECOVER_RELATION_BUILD_MEMORY 0
+#endif
+#endif
+
/*
* hardcoded tuple descriptors, contents generated by genbki.pl
*/
HeapTuple pg_class_tuple;
Form_pg_class relp;
+ /*
+ * This function and its subroutines can allocate a good deal of transient
+ * data in CurrentMemoryContext. Traditionally we've just that
+ * data, reasoning that the caller's context is at worst of transaction
+ * scope, and relcache loads shouldn't happen so often that it's essential
+ * to recover transient data before end of statement/transaction. However
+ * that's definitely not true in clobber-cache test builds, and perhaps
+ * it's not true in other cases. If RECOVER_RELATION_BUILD_MEMORY is not
+ * zero, arrange to allocate the junk in a temporary context that we'll
+ * free before returning. Make it a child of caller's context so that it
+ * will get cleaned up appropriately if we error out partway through.
+ */
+#if RECOVER_RELATION_BUILD_MEMORY
+ MemoryContext tmpcxt;
+ MemoryContext oldcxt;
+
+ tmpcxt = AllocSetContextCreate(CurrentMemoryContext,
+ "RelationBuildDesc workspace",
+ ALLOCSET_DEFAULT_SIZES);
+ oldcxt = MemoryContextSwitchTo(tmpcxt);
+#endif
+
/*
* find the tuple in pg_class corresponding to the given relation id
*/
* if no such tuple exists, return NULL
*/
if (!HeapTupleIsValid(pg_class_tuple))
+ {
+#if RECOVER_RELATION_BUILD_MEMORY
+ /* Return to caller's context, and blow away the temporary context */
+ MemoryContextSwitchTo(oldcxt);
+ MemoryContextDelete(tmpcxt);
+#endif
return NULL;
+ }
/*
* get information from the pg_class_tuple
/* It's fully valid */
relation->rd_isvalid = true;
+#if RECOVER_RELATION_BUILD_MEMORY
+ /* Return to caller's context, and blow away the temporary context */
+ MemoryContextSwitchTo(oldcxt);
+ MemoryContextDelete(tmpcxt);
+#endif
+
return relation;
}