mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
Reorganize partitioning code
There's been a massive addition of partitioning code in PostgreSQL 11, with little oversight on its placement, resulting in a catalog/partition.c with poorly defined boundaries and responsibilities. This commit tries to set a couple of distinct modules to separate things a little bit. There are no code changes here, only code movement. There are three new files: src/backend/utils/cache/partcache.c src/include/partitioning/partdefs.h src/include/utils/partcache.h The previous arrangement of #including catalog/partition.h almost everywhere is no more. Authors: Amit Langote and Álvaro Herrera Discussion: https://postgr.es/m/98e8d509-790a-128c-be7f-e48a5b2d8d97@lab.ntt.co.jp https://postgr.es/m/11aa0c50-316b-18bb-722d-c23814f39059@lab.ntt.co.jp https://postgr.es/m/143ed9a4-6038-76d4-9a55-502035815e68@lab.ntt.co.jp https://postgr.es/m/20180413193503.nynq7bnmgh6vs5vm@alvherre.pgsql
This commit is contained in:
208
src/backend/utils/cache/relcache.c
vendored
208
src/backend/utils/cache/relcache.c
vendored
@ -73,6 +73,7 @@
|
||||
#include "optimizer/cost.h"
|
||||
#include "optimizer/prep.h"
|
||||
#include "optimizer/var.h"
|
||||
#include "partitioning/partbounds.h"
|
||||
#include "pgstat.h"
|
||||
#include "rewrite/rewriteDefine.h"
|
||||
#include "rewrite/rowsecurity.h"
|
||||
@ -85,6 +86,7 @@
|
||||
#include "utils/inval.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/partcache.h"
|
||||
#include "utils/relmapper.h"
|
||||
#include "utils/resowner_private.h"
|
||||
#include "utils/snapmgr.h"
|
||||
@ -265,7 +267,6 @@ static HeapTuple ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_hi
|
||||
static Relation AllocateRelationDesc(Form_pg_class relp);
|
||||
static void RelationParseRelOptions(Relation relation, HeapTuple tuple);
|
||||
static void RelationBuildTupleDesc(Relation relation);
|
||||
static void RelationBuildPartitionKey(Relation relation);
|
||||
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt);
|
||||
static void RelationInitPhysicalAddr(Relation relation);
|
||||
static void load_critical_index(Oid indexoid, Oid heapoid);
|
||||
@ -873,211 +874,6 @@ RelationBuildRuleLock(Relation relation)
|
||||
relation->rd_rules = rulelock;
|
||||
}
|
||||
|
||||
/*
|
||||
* RelationBuildPartitionKey
|
||||
* Build and attach to relcache partition key data of relation
|
||||
*
|
||||
* Partitioning key data is a complex structure; to avoid complicated logic to
|
||||
* free individual elements whenever the relcache entry is flushed, we give it
|
||||
* its own memory context, child of CacheMemoryContext, which can easily be
|
||||
* deleted on its own. To avoid leaking memory in that context in case of an
|
||||
* error partway through this function, the context is initially created as a
|
||||
* child of CurTransactionContext and only re-parented to CacheMemoryContext
|
||||
* at the end, when no further errors are possible. Also, we don't make this
|
||||
* context the current context except in very brief code sections, out of fear
|
||||
* that some of our callees allocate memory on their own which would be leaked
|
||||
* permanently.
|
||||
*/
|
||||
static void
|
||||
RelationBuildPartitionKey(Relation relation)
|
||||
{
|
||||
Form_pg_partitioned_table form;
|
||||
HeapTuple tuple;
|
||||
bool isnull;
|
||||
int i;
|
||||
PartitionKey key;
|
||||
AttrNumber *attrs;
|
||||
oidvector *opclass;
|
||||
oidvector *collation;
|
||||
ListCell *partexprs_item;
|
||||
Datum datum;
|
||||
MemoryContext partkeycxt,
|
||||
oldcxt;
|
||||
int16 procnum;
|
||||
|
||||
tuple = SearchSysCache1(PARTRELID,
|
||||
ObjectIdGetDatum(RelationGetRelid(relation)));
|
||||
|
||||
/*
|
||||
* The following happens when we have created our pg_class entry but not
|
||||
* the pg_partitioned_table entry yet.
|
||||
*/
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
return;
|
||||
|
||||
partkeycxt = AllocSetContextCreate(CurTransactionContext,
|
||||
"partition key",
|
||||
ALLOCSET_SMALL_SIZES);
|
||||
MemoryContextCopyAndSetIdentifier(partkeycxt,
|
||||
RelationGetRelationName(relation));
|
||||
|
||||
key = (PartitionKey) MemoryContextAllocZero(partkeycxt,
|
||||
sizeof(PartitionKeyData));
|
||||
|
||||
/* Fixed-length attributes */
|
||||
form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
|
||||
key->strategy = form->partstrat;
|
||||
key->partnatts = form->partnatts;
|
||||
|
||||
/*
|
||||
* We can rely on the first variable-length attribute being mapped to the
|
||||
* relevant field of the catalog's C struct, because all previous
|
||||
* attributes are non-nullable and fixed-length.
|
||||
*/
|
||||
attrs = form->partattrs.values;
|
||||
|
||||
/* But use the hard way to retrieve further variable-length attributes */
|
||||
/* Operator class */
|
||||
datum = SysCacheGetAttr(PARTRELID, tuple,
|
||||
Anum_pg_partitioned_table_partclass, &isnull);
|
||||
Assert(!isnull);
|
||||
opclass = (oidvector *) DatumGetPointer(datum);
|
||||
|
||||
/* Collation */
|
||||
datum = SysCacheGetAttr(PARTRELID, tuple,
|
||||
Anum_pg_partitioned_table_partcollation, &isnull);
|
||||
Assert(!isnull);
|
||||
collation = (oidvector *) DatumGetPointer(datum);
|
||||
|
||||
/* Expressions */
|
||||
datum = SysCacheGetAttr(PARTRELID, tuple,
|
||||
Anum_pg_partitioned_table_partexprs, &isnull);
|
||||
if (!isnull)
|
||||
{
|
||||
char *exprString;
|
||||
Node *expr;
|
||||
|
||||
exprString = TextDatumGetCString(datum);
|
||||
expr = stringToNode(exprString);
|
||||
pfree(exprString);
|
||||
|
||||
/*
|
||||
* Run the expressions through const-simplification since the planner
|
||||
* will be comparing them to similarly-processed qual clause operands,
|
||||
* and may fail to detect valid matches without this step; fix
|
||||
* opfuncids while at it. We don't need to bother with
|
||||
* canonicalize_qual() though, because partition expressions should be
|
||||
* in canonical form already (ie, no need for OR-merging or constant
|
||||
* elimination).
|
||||
*/
|
||||
expr = eval_const_expressions(NULL, expr);
|
||||
fix_opfuncids(expr);
|
||||
|
||||
oldcxt = MemoryContextSwitchTo(partkeycxt);
|
||||
key->partexprs = (List *) copyObject(expr);
|
||||
MemoryContextSwitchTo(oldcxt);
|
||||
}
|
||||
|
||||
oldcxt = MemoryContextSwitchTo(partkeycxt);
|
||||
key->partattrs = (AttrNumber *) palloc0(key->partnatts * sizeof(AttrNumber));
|
||||
key->partopfamily = (Oid *) palloc0(key->partnatts * sizeof(Oid));
|
||||
key->partopcintype = (Oid *) palloc0(key->partnatts * sizeof(Oid));
|
||||
key->partsupfunc = (FmgrInfo *) palloc0(key->partnatts * sizeof(FmgrInfo));
|
||||
|
||||
key->partcollation = (Oid *) palloc0(key->partnatts * sizeof(Oid));
|
||||
|
||||
/* Gather type and collation info as well */
|
||||
key->parttypid = (Oid *) palloc0(key->partnatts * sizeof(Oid));
|
||||
key->parttypmod = (int32 *) palloc0(key->partnatts * sizeof(int32));
|
||||
key->parttyplen = (int16 *) palloc0(key->partnatts * sizeof(int16));
|
||||
key->parttypbyval = (bool *) palloc0(key->partnatts * sizeof(bool));
|
||||
key->parttypalign = (char *) palloc0(key->partnatts * sizeof(char));
|
||||
key->parttypcoll = (Oid *) palloc0(key->partnatts * sizeof(Oid));
|
||||
MemoryContextSwitchTo(oldcxt);
|
||||
|
||||
/* determine support function number to search for */
|
||||
procnum = (key->strategy == PARTITION_STRATEGY_HASH) ?
|
||||
HASHEXTENDED_PROC : BTORDER_PROC;
|
||||
|
||||
/* Copy partattrs and fill other per-attribute info */
|
||||
memcpy(key->partattrs, attrs, key->partnatts * sizeof(int16));
|
||||
partexprs_item = list_head(key->partexprs);
|
||||
for (i = 0; i < key->partnatts; i++)
|
||||
{
|
||||
AttrNumber attno = key->partattrs[i];
|
||||
HeapTuple opclasstup;
|
||||
Form_pg_opclass opclassform;
|
||||
Oid funcid;
|
||||
|
||||
/* Collect opfamily information */
|
||||
opclasstup = SearchSysCache1(CLAOID,
|
||||
ObjectIdGetDatum(opclass->values[i]));
|
||||
if (!HeapTupleIsValid(opclasstup))
|
||||
elog(ERROR, "cache lookup failed for opclass %u", opclass->values[i]);
|
||||
|
||||
opclassform = (Form_pg_opclass) GETSTRUCT(opclasstup);
|
||||
key->partopfamily[i] = opclassform->opcfamily;
|
||||
key->partopcintype[i] = opclassform->opcintype;
|
||||
|
||||
/* Get a support function for the specified opfamily and datatypes */
|
||||
funcid = get_opfamily_proc(opclassform->opcfamily,
|
||||
opclassform->opcintype,
|
||||
opclassform->opcintype,
|
||||
procnum);
|
||||
if (!OidIsValid(funcid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("operator class \"%s\" of access method %s is missing support function %d for type %s",
|
||||
NameStr(opclassform->opcname),
|
||||
(key->strategy == PARTITION_STRATEGY_HASH) ?
|
||||
"hash" : "btree",
|
||||
procnum,
|
||||
format_type_be(opclassform->opcintype))));
|
||||
|
||||
fmgr_info_cxt(funcid, &key->partsupfunc[i], partkeycxt);
|
||||
|
||||
/* Collation */
|
||||
key->partcollation[i] = collation->values[i];
|
||||
|
||||
/* Collect type information */
|
||||
if (attno != 0)
|
||||
{
|
||||
Form_pg_attribute att = TupleDescAttr(relation->rd_att, attno - 1);
|
||||
|
||||
key->parttypid[i] = att->atttypid;
|
||||
key->parttypmod[i] = att->atttypmod;
|
||||
key->parttypcoll[i] = att->attcollation;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (partexprs_item == NULL)
|
||||
elog(ERROR, "wrong number of partition key expressions");
|
||||
|
||||
key->parttypid[i] = exprType(lfirst(partexprs_item));
|
||||
key->parttypmod[i] = exprTypmod(lfirst(partexprs_item));
|
||||
key->parttypcoll[i] = exprCollation(lfirst(partexprs_item));
|
||||
|
||||
partexprs_item = lnext(partexprs_item);
|
||||
}
|
||||
get_typlenbyvalalign(key->parttypid[i],
|
||||
&key->parttyplen[i],
|
||||
&key->parttypbyval[i],
|
||||
&key->parttypalign[i]);
|
||||
|
||||
ReleaseSysCache(opclasstup);
|
||||
}
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
/*
|
||||
* Success --- reparent our context and make the relcache point to the
|
||||
* newly constructed key
|
||||
*/
|
||||
MemoryContextSetParent(partkeycxt, CacheMemoryContext);
|
||||
relation->rd_partkeycxt = partkeycxt;
|
||||
relation->rd_partkey = key;
|
||||
}
|
||||
|
||||
/*
|
||||
* equalRuleLocks
|
||||
*
|
||||
|
Reference in New Issue
Block a user