#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"
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
*
#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"
#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"
#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"
#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"
#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"
#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"
#include "optimizer/inherit.h"
#include "optimizer/planner.h"
#include "optimizer/prep.h"
+#include "partitioning/partdesc.h"
#include "utils/rel.h"
#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"
#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"
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
* src/backend/partitioning/partbounds.c
*
*-------------------------------------------------------------------------
-*/
+ */
+
#include "postgres.h"
#include "access/heapam.h"
#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"
--- /dev/null
+/*-------------------------------------------------------------------------
+ *
+ * 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;
+}
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
*
#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"
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);
/*
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
*
/* 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,
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);
--- /dev/null
+/*-------------------------------------------------------------------------
+ *
+ * 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 */
} PartitionKeyData;
extern void RelationBuildPartitionKey(Relation relation);
-extern void RelationBuildPartitionDesc(Relation rel);
extern List *RelationGetPartitionQual(Relation rel);
extern Expr *get_partition_qual_relid(Oid relid);