mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +03:00
Fix some oversights in commit 2455ab488
.
The idea was to generate all the junk in a destroyable subcontext rather than leaking it in the caller's context, but partition_bounds_create was still being called in the caller's context, allowing plenty of scope for leakage. Also, get_rel_relkind() was still being called in the rel's rd_pdcxt, creating a risk of session-lifespan memory wastage. Simplify the logic a bit while at it. Also, reduce rd_pdcxt to ALLOCSET_SMALL_SIZES, since it seems likely to not usually be big. Probably something like this needs to be back-patched into v11, but for now let's get some buildfarm testing on this. Discussion: https://postgr.es/m/15943.1552601288@sss.pgh.pa.us
This commit is contained in:
@ -67,8 +67,8 @@ RelationBuildPartitionDesc(Relation rel)
|
|||||||
nparts;
|
nparts;
|
||||||
PartitionKey key = RelationGetPartitionKey(rel);
|
PartitionKey key = RelationGetPartitionKey(rel);
|
||||||
MemoryContext oldcxt;
|
MemoryContext oldcxt;
|
||||||
|
MemoryContext rbcontext;
|
||||||
int *mapping;
|
int *mapping;
|
||||||
MemoryContext rbcontext = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* While building the partition descriptor, we create various temporary
|
* While building the partition descriptor, we create various temporary
|
||||||
@ -187,56 +187,50 @@ RelationBuildPartitionDesc(Relation rel)
|
|||||||
/* Now build the actual relcache partition descriptor */
|
/* Now build the actual relcache partition descriptor */
|
||||||
rel->rd_pdcxt = AllocSetContextCreate(CacheMemoryContext,
|
rel->rd_pdcxt = AllocSetContextCreate(CacheMemoryContext,
|
||||||
"partition descriptor",
|
"partition descriptor",
|
||||||
ALLOCSET_DEFAULT_SIZES);
|
ALLOCSET_SMALL_SIZES);
|
||||||
MemoryContextCopyAndSetIdentifier(rel->rd_pdcxt,
|
MemoryContextCopyAndSetIdentifier(rel->rd_pdcxt,
|
||||||
RelationGetRelationName(rel));
|
RelationGetRelationName(rel));
|
||||||
|
|
||||||
MemoryContextSwitchTo(rel->rd_pdcxt);
|
partdesc = (PartitionDescData *)
|
||||||
partdesc = (PartitionDescData *) palloc0(sizeof(PartitionDescData));
|
MemoryContextAllocZero(rel->rd_pdcxt, sizeof(PartitionDescData));
|
||||||
partdesc->nparts = nparts;
|
partdesc->nparts = nparts;
|
||||||
/* oids and boundinfo are allocated below. */
|
/* If there are no partitions, the rest of the partdesc can stay zero */
|
||||||
|
if (nparts > 0)
|
||||||
MemoryContextSwitchTo(oldcxt);
|
|
||||||
|
|
||||||
if (nparts == 0)
|
|
||||||
{
|
{
|
||||||
/* We can exit early in this case. */
|
/* Create PartitionBoundInfo, using the temporary context. */
|
||||||
rel->rd_partdesc = partdesc;
|
|
||||||
|
|
||||||
/* Blow away the temporary context. */
|
|
||||||
MemoryContextDelete(rbcontext);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First create PartitionBoundInfo */
|
|
||||||
boundinfo = partition_bounds_create(boundspecs, nparts, key, &mapping);
|
boundinfo = partition_bounds_create(boundspecs, nparts, key, &mapping);
|
||||||
|
|
||||||
/* Now copy boundinfo and oids into partdesc. */
|
/* Now copy all info into relcache's partdesc. */
|
||||||
oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
|
MemoryContextSwitchTo(rel->rd_pdcxt);
|
||||||
partdesc->boundinfo = partition_bounds_copy(boundinfo, key);
|
partdesc->boundinfo = partition_bounds_copy(boundinfo, key);
|
||||||
partdesc->oids = (Oid *) palloc(partdesc->nparts * sizeof(Oid));
|
partdesc->oids = (Oid *) palloc(nparts * sizeof(Oid));
|
||||||
partdesc->is_leaf = (bool *) palloc(partdesc->nparts * sizeof(bool));
|
partdesc->is_leaf = (bool *) palloc(nparts * sizeof(bool));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now assign OIDs from the original array into mapped indexes of the
|
* Assign OIDs from the original array into mapped indexes of the
|
||||||
* result array. The order of OIDs in the former is defined by the
|
* result array. The order of OIDs in the former is defined by the
|
||||||
* catalog scan that retrieved them, whereas that in the latter is defined
|
* catalog scan that retrieved them, whereas that in the latter is
|
||||||
* by canonicalized representation of the partition bounds.
|
* defined by canonicalized representation of the partition bounds.
|
||||||
|
*
|
||||||
|
* Also record leaf-ness of each partition. For this we use
|
||||||
|
* get_rel_relkind() which may leak memory, so be sure to run it in
|
||||||
|
* the temporary context.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < partdesc->nparts; i++)
|
MemoryContextSwitchTo(rbcontext);
|
||||||
|
for (i = 0; i < nparts; i++)
|
||||||
{
|
{
|
||||||
int index = mapping[i];
|
int index = mapping[i];
|
||||||
|
|
||||||
partdesc->oids[index] = oids[i];
|
partdesc->oids[index] = oids[i];
|
||||||
/* Record if the partition is a leaf partition */
|
|
||||||
partdesc->is_leaf[index] =
|
partdesc->is_leaf[index] =
|
||||||
(get_rel_relkind(oids[i]) != RELKIND_PARTITIONED_TABLE);
|
(get_rel_relkind(oids[i]) != RELKIND_PARTITIONED_TABLE);
|
||||||
}
|
}
|
||||||
MemoryContextSwitchTo(oldcxt);
|
}
|
||||||
|
|
||||||
rel->rd_partdesc = partdesc;
|
rel->rd_partdesc = partdesc;
|
||||||
|
|
||||||
/* Blow away the temporary context. */
|
/* Return to caller's context, and blow away the temporary context. */
|
||||||
|
MemoryContextSwitchTo(oldcxt);
|
||||||
MemoryContextDelete(rbcontext);
|
MemoryContextDelete(rbcontext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user