diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index d0215a5eed..7dba4e50dd 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -69,6 +69,7 @@ #include "parser/parse_collate.h" #include "parser/parse_expr.h" #include "parser/parse_relation.h" +#include "partitioning/partdesc.h" #include "storage/lmgr.h" #include "storage/predicate.h" #include "storage/smgr.h" diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 0d3bc3a2c7..3ccdaff8c4 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -253,22 +253,6 @@ has_partition_attrs(Relation rel, Bitmapset *attnums, bool *used_in_expr) return false; } -/* - * get_default_oid_from_partdesc - * - * Given a partition descriptor, return the OID of the default partition, if - * one exists; else, return InvalidOid. - */ -Oid -get_default_oid_from_partdesc(PartitionDesc partdesc) -{ - if (partdesc && partdesc->boundinfo && - partition_bound_has_default(partdesc->boundinfo)) - return partdesc->oids[partdesc->boundinfo->default_index]; - - return InvalidOid; -} - /* * get_default_partition_oid * diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index ad836e0d98..b6145593a3 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -24,7 +24,6 @@ #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/objectaccess.h" -#include "catalog/partition.h" #include "catalog/pg_constraint.h" #include "catalog/pg_operator.h" #include "catalog/pg_type.h" diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 7352b9e341..5dcedc337a 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -24,7 +24,6 @@ #include "catalog/catalog.h" #include "catalog/index.h" #include "catalog/indexing.h" -#include "catalog/partition.h" #include "catalog/pg_am.h" #include "catalog/pg_constraint.h" #include "catalog/pg_inherits.h" @@ -46,6 +45,7 @@ #include "parser/parse_coerce.h" #include "parser/parse_func.h" #include "parser/parse_oper.h" +#include "partitioning/partdesc.h" #include "rewrite/rewriteManip.h" #include "storage/lmgr.h" #include "storage/proc.h" diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 715c6a221c..35bdb0e0c6 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -74,6 +74,7 @@ #include "parser/parse_utilcmd.h" #include "parser/parser.h" #include "partitioning/partbounds.h" +#include "partitioning/partdesc.h" #include "pgstat.h" #include "rewrite/rewriteDefine.h" #include "rewrite/rewriteHandler.h" diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 409bee24f8..7e5bf0d27f 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -42,6 +42,7 @@ #include "parser/parse_func.h" #include "parser/parse_relation.h" #include "parser/parsetree.h" +#include "partitioning/partdesc.h" #include "pgstat.h" #include "rewrite/rewriteManip.h" #include "storage/bufmgr.h" diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index ab69404daa..e121c6c8ff 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -24,6 +24,7 @@ #include "miscadmin.h" #include "nodes/makefuncs.h" #include "partitioning/partbounds.h" +#include "partitioning/partdesc.h" #include "partitioning/partprune.h" #include "rewrite/rewriteManip.h" #include "utils/lsyscache.h" diff --git a/src/backend/optimizer/util/inherit.c b/src/backend/optimizer/util/inherit.c index eaf788e578..faba493200 100644 --- a/src/backend/optimizer/util/inherit.c +++ b/src/backend/optimizer/util/inherit.c @@ -23,6 +23,7 @@ #include "optimizer/inherit.h" #include "optimizer/planner.h" #include "optimizer/prep.h" +#include "partitioning/partdesc.h" #include "utils/rel.h" diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index d6dc83ca80..78a96b4ee2 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -27,7 +27,6 @@ #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/heap.h" -#include "catalog/partition.h" #include "catalog/pg_am.h" #include "catalog/pg_proc.h" #include "catalog/pg_statistic_ext.h" @@ -41,6 +40,7 @@ #include "optimizer/plancat.h" #include "optimizer/prep.h" #include "partitioning/partbounds.h" +#include "partitioning/partdesc.h" #include "parser/parse_relation.h" #include "parser/parsetree.h" #include "rewrite/rewriteManip.h" diff --git a/src/backend/partitioning/Makefile b/src/backend/partitioning/Makefile index 278fac3afa..82093c615f 100644 --- a/src/backend/partitioning/Makefile +++ b/src/backend/partitioning/Makefile @@ -12,6 +12,6 @@ subdir = src/backend/partitioning top_builddir = ../../.. include $(top_builddir)/src/Makefile.global -OBJS = partprune.o partbounds.o +OBJS = partbounds.o partdesc.o partprune.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c index d478ae7e19..e71eb3793b 100644 --- a/src/backend/partitioning/partbounds.c +++ b/src/backend/partitioning/partbounds.c @@ -10,7 +10,8 @@ * src/backend/partitioning/partbounds.c * *------------------------------------------------------------------------- -*/ + */ + #include "postgres.h" #include "access/heapam.h" @@ -23,8 +24,9 @@ #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "parser/parse_coerce.h" -#include "partitioning/partprune.h" #include "partitioning/partbounds.h" +#include "partitioning/partdesc.h" +#include "partitioning/partprune.h" #include "utils/builtins.h" #include "utils/datum.h" #include "utils/fmgroids.h" diff --git a/src/backend/partitioning/partdesc.c b/src/backend/partitioning/partdesc.c new file mode 100644 index 0000000000..8a4b63aa26 --- /dev/null +++ b/src/backend/partitioning/partdesc.c @@ -0,0 +1,221 @@ +/*------------------------------------------------------------------------- + * + * partdesc.c + * Support routines for manipulating partition descriptors + * + * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/partitioning/partdesc.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "catalog/partition.h" +#include "catalog/pg_inherits.h" +#include "partitioning/partbounds.h" +#include "partitioning/partdesc.h" +#include "utils/builtins.h" +#include "utils/lsyscache.h" +#include "utils/memutils.h" +#include "utils/rel.h" +#include "utils/partcache.h" +#include "utils/syscache.h" + +/* + * 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; +} + +/* + * equalPartitionDescs + * Compare two partition descriptors for logical equality + */ +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; +} + +/* + * get_default_oid_from_partdesc + * + * Given a partition descriptor, return the OID of the default partition, if + * one exists; else, return InvalidOid. + */ +Oid +get_default_oid_from_partdesc(PartitionDesc partdesc) +{ + if (partdesc && partdesc->boundinfo && + partition_bound_has_default(partdesc->boundinfo)) + return partdesc->oids[partdesc->boundinfo->default_index]; + + return InvalidOid; +} diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c index 1b50f283c5..2b55f25e75 100644 --- a/src/backend/utils/cache/partcache.c +++ b/src/backend/utils/cache/partcache.c @@ -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 * diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 721c9dab95..54a40ef00b 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -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 * diff --git a/src/include/catalog/partition.h b/src/include/catalog/partition.h index 5685d2fd57..d84e325983 100644 --- a/src/include/catalog/partition.h +++ b/src/include/catalog/partition.h @@ -19,20 +19,6 @@ /* Seed for the extended hash function */ #define HASH_PARTITION_SEED UINT64CONST(0x7A5B22367996DCFD) -/* - * Information about partitions of a partitioned table. - */ -typedef struct PartitionDescData -{ - int nparts; /* Number of partitions */ - Oid *oids; /* Array of 'nparts' elements containing - * partition OIDs in order of the their bounds */ - bool *is_leaf; /* Array of 'nparts' elements storing whether - * the corresponding 'oids' element belongs to - * a leaf partition or not */ - PartitionBoundInfo boundinfo; /* collection of partition bounds */ -} PartitionDescData; - extern Oid get_partition_parent(Oid relid); extern List *get_partition_ancestors(Oid relid); extern List *map_partition_varattnos(List *expr, int fromrel_varno, @@ -41,7 +27,6 @@ extern List *map_partition_varattnos(List *expr, int fromrel_varno, extern bool has_partition_attrs(Relation rel, Bitmapset *attnums, bool *used_in_expr); -extern Oid get_default_oid_from_partdesc(PartitionDesc partdesc); extern Oid get_default_partition_oid(Oid parentId); extern void update_default_partition_oid(Oid parentId, Oid defaultPartId); extern List *get_proposed_default_constraint(List *new_part_constaints); diff --git a/src/include/partitioning/partdesc.h b/src/include/partitioning/partdesc.h new file mode 100644 index 0000000000..f72b70dded --- /dev/null +++ b/src/include/partitioning/partdesc.h @@ -0,0 +1,39 @@ +/*------------------------------------------------------------------------- + * + * partdesc.h + * + * Copyright (c) 1996-2018, PostgreSQL Global Development Group + * + * src/include/utils/partdesc.h + * + *------------------------------------------------------------------------- + */ + +#ifndef PARTDESC_H +#define PARTDESC_H + +#include "partitioning/partdefs.h" +#include "utils/relcache.h" + +/* + * Information about partitions of a partitioned table. + */ +typedef struct PartitionDescData +{ + int nparts; /* Number of partitions */ + Oid *oids; /* Array of 'nparts' elements containing + * partition OIDs in order of the their bounds */ + bool *is_leaf; /* Array of 'nparts' elements storing whether + * the corresponding 'oids' element belongs to + * a leaf partition or not */ + PartitionBoundInfo boundinfo; /* collection of partition bounds */ +} PartitionDescData; + +extern void RelationBuildPartitionDesc(Relation rel); + +extern Oid get_default_oid_from_partdesc(PartitionDesc partdesc); + +extern bool equalPartitionDescs(PartitionKey key, PartitionDesc partdesc1, + PartitionDesc partdesc2); + +#endif /* PARTCACHE_H */ diff --git a/src/include/utils/partcache.h b/src/include/utils/partcache.h index 7c2f973f68..823ad2eeb6 100644 --- a/src/include/utils/partcache.h +++ b/src/include/utils/partcache.h @@ -47,7 +47,6 @@ typedef struct PartitionKeyData } PartitionKeyData; extern void RelationBuildPartitionKey(Relation relation); -extern void RelationBuildPartitionDesc(Relation rel); extern List *RelationGetPartitionQual(Relation rel); extern Expr *get_partition_qual_relid(Oid relid);