pdoldcxt-v1.patch
application/octet-stream
Filename: pdoldcxt-v1.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| src/backend/utils/cache/relcache.c | 24 | 6 |
| src/include/utils/rel.h | 1 | 0 |
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 2b992d7832..4fb6ec60d4 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -1179,6 +1179,7 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
relation->rd_partkeycxt = NULL;
relation->rd_partdesc = NULL;
relation->rd_pdcxt = NULL;
+ relation->rd_pdoldcxt = NULL;
}
/* ... but partcheck is not loaded till asked for */
relation->rd_partcheck = NIL;
@@ -2073,6 +2074,11 @@ RelationDecrementReferenceCount(Relation rel)
rel->rd_refcnt -= 1;
if (!IsBootstrapProcessingMode())
ResourceOwnerForgetRelationRef(CurrentResourceOwner, rel);
+ if (rel->rd_refcnt == 0 && rel->rd_pdoldcxt != NULL)
+ {
+ MemoryContextDelete(rel->rd_pdoldcxt);
+ rel->rd_pdoldcxt = NULL;
+ }
}
/*
@@ -2368,6 +2374,8 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc)
MemoryContextDelete(relation->rd_partkeycxt);
if (relation->rd_pdcxt)
MemoryContextDelete(relation->rd_pdcxt);
+ if (relation->rd_pdoldcxt)
+ MemoryContextDelete(relation->rd_pdoldcxt);
if (relation->rd_partcheckcxt)
MemoryContextDelete(relation->rd_partcheckcxt);
if (relation->rd_fdwroutine)
@@ -2622,6 +2630,7 @@ RelationClearRelation(Relation relation, bool rebuild)
{
SWAPFIELD(PartitionDesc, rd_partdesc);
SWAPFIELD(MemoryContext, rd_pdcxt);
+ SWAPFIELD(MemoryContext, rd_pdoldcxt);
}
else if (rebuild && newrel->rd_pdcxt != NULL)
{
@@ -2629,17 +2638,25 @@ RelationClearRelation(Relation relation, bool rebuild)
* We are rebuilding a partitioned relation with a non-zero
* reference count, so keep the old partition descriptor around,
* in case there's a PartitionDirectory with a pointer to it.
- * Attach it to the new rd_pdcxt so that it gets cleaned up
- * eventually. In the case where the reference count is 0, this
- * code is not reached, which should be OK because in that case
- * there should be no PartitionDirectory with a pointer to the old
- * entry.
+ * In the case where the reference count is 0, this code is not
+ * reached, which should be OK because in that case there should be
+ * no PartitionDirectory with a pointer to the old entry.
+ *
+ * To avoid leaking memory, we've got to make sure that the next
+ * time rd_pdoldcxt is destroyed, the old context will be freed.
+ * If rd_pdoldcxt is NULL, we can just make it point to the
+ * old descriptor's context; otherwise, we make this context of
+ * the previous one.
*
* Note that newrel and relation have already been swapped, so the
* "old" partition descriptor is actually the one hanging off of
* newrel.
*/
- MemoryContextSetParent(newrel->rd_pdcxt, relation->rd_pdcxt);
+ if (relation->rd_pdoldcxt == NULL)
+ relation->rd_pdoldcxt = newrel->rd_pdcxt;
+ else
+ MemoryContextSetParent(newrel->rd_pdcxt,
+ relation->rd_pdoldcxt);
newrel->rd_partdesc = NULL;
newrel->rd_pdcxt = NULL;
}
@@ -5580,6 +5597,7 @@ load_relcache_init_file(bool shared)
rel->rd_partkeycxt = NULL;
rel->rd_partdesc = NULL;
rel->rd_pdcxt = NULL;
+ rel->rd_pdoldcxt = NULL;
rel->rd_partcheck = NIL;
rel->rd_partcheckvalid = false;
rel->rd_partcheckcxt = NULL;
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index d7f33abce3..09abcdf030 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -99,6 +99,7 @@ typedef struct RelationData
MemoryContext rd_partkeycxt; /* private context for rd_partkey, if any */
struct PartitionDescData *rd_partdesc; /* partitions, or NULL */
MemoryContext rd_pdcxt; /* private context for rd_partdesc, if any */
+ MemoryContext rd_pdoldcxt; /* context for older PartitionDescs, if any */
List *rd_partcheck; /* partition CHECK quals */
bool rd_partcheckvalid; /* true if list has been computed */
MemoryContext rd_partcheckcxt; /* private cxt for rd_partcheck, if any */