1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +03:00

Move code for managing PartitionDescs into a new file, partdesc.c

This is similar in spirit to the existing partbounds.c file in the
same directory, except that there's a lot less code in the new file
created by this commit.  Pending work in this area proposes to add a
bunch more code related to PartitionDescs, though, and this will give
us a good place to put it.

Discussion: http://postgr.es/m/CA+TgmoZUwPf_uanjF==gTGBMJrn8uCq52XYvAEorNkLrUdoawg@mail.gmail.com
This commit is contained in:
Robert Haas
2019-02-21 11:38:54 -05:00
parent 9eefba181f
commit 1bb5e78218
17 changed files with 273 additions and 218 deletions

View File

@ -243,130 +243,6 @@ RelationBuildPartitionKey(Relation relation)
relation->rd_partkey = key;
}
/*
* RelationBuildPartitionDesc
* Form rel's partition descriptor
*
* Not flushed from the cache by RelationClearRelation() unless changed because
* of addition or removal of partition.
*/
void
RelationBuildPartitionDesc(Relation rel)
{
PartitionDesc partdesc;
PartitionBoundInfo boundinfo = NULL;
List *inhoids;
PartitionBoundSpec **boundspecs = NULL;
Oid *oids = NULL;
ListCell *cell;
int i,
nparts;
PartitionKey key = RelationGetPartitionKey(rel);
MemoryContext oldcxt;
int *mapping;
/* Get partition oids from pg_inherits */
inhoids = find_inheritance_children(RelationGetRelid(rel), NoLock);
nparts = list_length(inhoids);
if (nparts > 0)
{
oids = palloc(nparts * sizeof(Oid));
boundspecs = palloc(nparts * sizeof(PartitionBoundSpec *));
}
/* Collect bound spec nodes for each partition */
i = 0;
foreach(cell, inhoids)
{
Oid inhrelid = lfirst_oid(cell);
HeapTuple tuple;
Datum datum;
bool isnull;
PartitionBoundSpec *boundspec;
tuple = SearchSysCache1(RELOID, inhrelid);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for relation %u", inhrelid);
datum = SysCacheGetAttr(RELOID, tuple,
Anum_pg_class_relpartbound,
&isnull);
if (isnull)
elog(ERROR, "null relpartbound for relation %u", inhrelid);
boundspec = stringToNode(TextDatumGetCString(datum));
if (!IsA(boundspec, PartitionBoundSpec))
elog(ERROR, "invalid relpartbound for relation %u", inhrelid);
/*
* Sanity check: If the PartitionBoundSpec says this is the default
* partition, its OID should correspond to whatever's stored in
* pg_partitioned_table.partdefid; if not, the catalog is corrupt.
*/
if (boundspec->is_default)
{
Oid partdefid;
partdefid = get_default_partition_oid(RelationGetRelid(rel));
if (partdefid != inhrelid)
elog(ERROR, "expected partdefid %u, but got %u",
inhrelid, partdefid);
}
oids[i] = inhrelid;
boundspecs[i] = boundspec;
++i;
ReleaseSysCache(tuple);
}
/* Now build the actual relcache partition descriptor */
rel->rd_pdcxt = AllocSetContextCreate(CacheMemoryContext,
"partition descriptor",
ALLOCSET_DEFAULT_SIZES);
MemoryContextCopyAndSetIdentifier(rel->rd_pdcxt, RelationGetRelationName(rel));
oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
partdesc = (PartitionDescData *) palloc0(sizeof(PartitionDescData));
partdesc->nparts = nparts;
/* oids and boundinfo are allocated below. */
MemoryContextSwitchTo(oldcxt);
if (nparts == 0)
{
rel->rd_partdesc = partdesc;
return;
}
/* First create PartitionBoundInfo */
boundinfo = partition_bounds_create(boundspecs, nparts, key, &mapping);
/* Now copy boundinfo and oids into partdesc. */
oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
partdesc->boundinfo = partition_bounds_copy(boundinfo, key);
partdesc->oids = (Oid *) palloc(partdesc->nparts * sizeof(Oid));
partdesc->is_leaf = (bool *) palloc(partdesc->nparts * sizeof(bool));
/*
* Now assign OIDs from the original array into mapped indexes of 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
* by canonicalized representation of the partition bounds.
*/
for (i = 0; i < partdesc->nparts; i++)
{
int index = mapping[i];
partdesc->oids[index] = oids[i];
/* Record if the partition is a leaf partition */
partdesc->is_leaf[index] =
(get_rel_relkind(oids[i]) != RELKIND_PARTITIONED_TABLE);
}
MemoryContextSwitchTo(oldcxt);
rel->rd_partdesc = partdesc;
}
/*
* RelationGetPartitionQual
*

View File

@ -72,6 +72,7 @@
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "partitioning/partbounds.h"
#include "partitioning/partdesc.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rowsecurity.h"
#include "storage/lmgr.h"
@ -283,8 +284,6 @@ static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid,
StrategyNumber numSupport);
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath);
static void unlink_initfile(const char *initfilename, int elevel);
static bool equalPartitionDescs(PartitionKey key, PartitionDesc partdesc1,
PartitionDesc partdesc2);
/*
@ -995,60 +994,6 @@ equalRSDesc(RowSecurityDesc *rsdesc1, RowSecurityDesc *rsdesc2)
return true;
}
/*
* equalPartitionDescs
* Compare two partition descriptors for logical equality
*/
static bool
equalPartitionDescs(PartitionKey key, PartitionDesc partdesc1,
PartitionDesc partdesc2)
{
int i;
if (partdesc1 != NULL)
{
if (partdesc2 == NULL)
return false;
if (partdesc1->nparts != partdesc2->nparts)
return false;
Assert(key != NULL || partdesc1->nparts == 0);
/*
* Same oids? If the partitioning structure did not change, that is,
* no partitions were added or removed to the relation, the oids array
* should still match element-by-element.
*/
for (i = 0; i < partdesc1->nparts; i++)
{
if (partdesc1->oids[i] != partdesc2->oids[i])
return false;
}
/*
* Now compare partition bound collections. The logic to iterate over
* the collections is private to partition.c.
*/
if (partdesc1->boundinfo != NULL)
{
if (partdesc2->boundinfo == NULL)
return false;
if (!partition_bounds_equal(key->partnatts, key->parttyplen,
key->parttypbyval,
partdesc1->boundinfo,
partdesc2->boundinfo))
return false;
}
else if (partdesc2->boundinfo != NULL)
return false;
}
else if (partdesc2 != NULL)
return false;
return true;
}
/*
* RelationBuildDesc
*