Commit 4b9a98e1 authored by Robert Haas's avatar Robert Haas

Clean up code, comments, and formatting for table partitioning.

Amit Langote, plus pgindent-ing by me.  Inspired in part by review
comments from Tomas Vondra.
parent acddbe22
...@@ -1887,6 +1887,10 @@ heap_drop_with_catalog(Oid relid) ...@@ -1887,6 +1887,10 @@ heap_drop_with_catalog(Oid relid)
if (parent) if (parent)
{ {
/*
* Invalidate the parent's relcache so that the partition is no longer
* included in its partition descriptor.
*/
CacheInvalidateRelcache(parent); CacheInvalidateRelcache(parent);
heap_close(parent, NoLock); /* keep the lock */ heap_close(parent, NoLock); /* keep the lock */
} }
......
...@@ -1492,7 +1492,7 @@ generate_partition_qual(Relation rel, bool recurse) ...@@ -1492,7 +1492,7 @@ generate_partition_qual(Relation rel, bool recurse)
* Construct values[] and isnull[] arrays for the partition key * Construct values[] and isnull[] arrays for the partition key
* of a tuple. * of a tuple.
* *
* pkinfo partition key execution info * pd Partition dispatch object of the partitioned table
* slot Heap tuple from which to extract partition key * slot Heap tuple from which to extract partition key
* estate executor state for evaluating any partition key * estate executor state for evaluating any partition key
* expressions (must be non-NULL) * expressions (must be non-NULL)
...@@ -1565,7 +1565,7 @@ FormPartitionKeyDatum(PartitionDispatch pd, ...@@ -1565,7 +1565,7 @@ FormPartitionKeyDatum(PartitionDispatch pd,
* the latter case. * the latter case.
*/ */
int int
get_partition_for_tuple(PartitionDispatch * pd, get_partition_for_tuple(PartitionDispatch *pd,
TupleTableSlot *slot, TupleTableSlot *slot,
EState *estate, EState *estate,
Oid *failed_at) Oid *failed_at)
......
...@@ -161,11 +161,11 @@ typedef struct CopyStateData ...@@ -161,11 +161,11 @@ typedef struct CopyStateData
ExprState **defexprs; /* array of default att expressions */ ExprState **defexprs; /* array of default att expressions */
bool volatile_defexprs; /* is any of defexprs volatile? */ bool volatile_defexprs; /* is any of defexprs volatile? */
List *range_table; List *range_table;
PartitionDispatch *partition_dispatch_info; PartitionDispatch *partition_dispatch_info;
int num_dispatch; int num_dispatch;
int num_partitions; int num_partitions;
ResultRelInfo *partitions; ResultRelInfo *partitions;
TupleConversionMap **partition_tupconv_maps; TupleConversionMap **partition_tupconv_maps;
/* /*
* These variables are used to reduce overhead in textual COPY FROM. * These variables are used to reduce overhead in textual COPY FROM.
...@@ -1403,31 +1403,28 @@ BeginCopy(ParseState *pstate, ...@@ -1403,31 +1403,28 @@ BeginCopy(ParseState *pstate,
errmsg("table \"%s\" does not have OIDs", errmsg("table \"%s\" does not have OIDs",
RelationGetRelationName(cstate->rel)))); RelationGetRelationName(cstate->rel))));
/* /* Initialize state for CopyFrom tuple routing. */
* Initialize state for CopyFrom tuple routing. Watch out for
* any foreign partitions.
*/
if (is_from && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) if (is_from && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{ {
PartitionDispatch *pd; List *leaf_parts;
List *leaf_parts; ListCell *cell;
ListCell *cell; int i,
int i, num_parted;
num_parted, ResultRelInfo *leaf_part_rri;
num_leaf_parts;
ResultRelInfo *leaf_part_rri;
/* Get the tuple-routing information and lock partitions */ /* Get the tuple-routing information and lock partitions */
pd = RelationGetPartitionDispatchInfo(rel, RowExclusiveLock, cstate->partition_dispatch_info =
&num_parted, &leaf_parts); RelationGetPartitionDispatchInfo(rel, RowExclusiveLock,
num_leaf_parts = list_length(leaf_parts); &num_parted,
cstate->partition_dispatch_info = pd; &leaf_parts);
cstate->num_dispatch = num_parted; cstate->num_dispatch = num_parted;
cstate->num_partitions = num_leaf_parts; cstate->num_partitions = list_length(leaf_parts);
cstate->partitions = (ResultRelInfo *) palloc(num_leaf_parts * cstate->partitions = (ResultRelInfo *)
sizeof(ResultRelInfo)); palloc(cstate->num_partitions *
sizeof(ResultRelInfo));
cstate->partition_tupconv_maps = (TupleConversionMap **) cstate->partition_tupconv_maps = (TupleConversionMap **)
palloc0(num_leaf_parts * sizeof(TupleConversionMap *)); palloc0(cstate->num_partitions *
sizeof(TupleConversionMap *));
leaf_part_rri = cstate->partitions; leaf_part_rri = cstate->partitions;
i = 0; i = 0;
...@@ -1438,8 +1435,8 @@ BeginCopy(ParseState *pstate, ...@@ -1438,8 +1435,8 @@ BeginCopy(ParseState *pstate,
/* /*
* We locked all the partitions above including the leaf * We locked all the partitions above including the leaf
* partitions. Note that each of the relations in * partitions. Note that each of the relations in
* cstate->partitions will be closed by CopyFrom() after * cstate->partitions will be closed by CopyFrom() after it's
* it's finished with its processing. * finished with its processing.
*/ */
partrel = heap_open(lfirst_oid(cell), NoLock); partrel = heap_open(lfirst_oid(cell), NoLock);
...@@ -1451,8 +1448,9 @@ BeginCopy(ParseState *pstate, ...@@ -1451,8 +1448,9 @@ BeginCopy(ParseState *pstate,
InitResultRelInfo(leaf_part_rri, InitResultRelInfo(leaf_part_rri,
partrel, partrel,
1, /* dummy */ 1, /* dummy */
false, /* no partition constraint check */ false, /* no partition constraint
* check */
0); 0);
/* Open partition indices */ /* Open partition indices */
...@@ -1460,9 +1458,9 @@ BeginCopy(ParseState *pstate, ...@@ -1460,9 +1458,9 @@ BeginCopy(ParseState *pstate,
if (!equalTupleDescs(tupDesc, RelationGetDescr(partrel))) if (!equalTupleDescs(tupDesc, RelationGetDescr(partrel)))
cstate->partition_tupconv_maps[i] = cstate->partition_tupconv_maps[i] =
convert_tuples_by_name(tupDesc, convert_tuples_by_name(tupDesc,
RelationGetDescr(partrel), RelationGetDescr(partrel),
gettext_noop("could not convert row type")); gettext_noop("could not convert row type"));
leaf_part_rri++; leaf_part_rri++;
i++; i++;
} }
...@@ -2486,8 +2484,8 @@ CopyFrom(CopyState cstate) ...@@ -2486,8 +2484,8 @@ CopyFrom(CopyState cstate)
* BEFORE/INSTEAD OF triggers, or we need to evaluate volatile default * BEFORE/INSTEAD OF triggers, or we need to evaluate volatile default
* expressions. Such triggers or expressions might query the table we're * expressions. Such triggers or expressions might query the table we're
* inserting to, and act differently if the tuples that have already been * inserting to, and act differently if the tuples that have already been
* processed and prepared for insertion are not there. We also can't * processed and prepared for insertion are not there. We also can't do
* do it if the table is partitioned. * it if the table is partitioned.
*/ */
if ((resultRelInfo->ri_TrigDesc != NULL && if ((resultRelInfo->ri_TrigDesc != NULL &&
(resultRelInfo->ri_TrigDesc->trig_insert_before_row || (resultRelInfo->ri_TrigDesc->trig_insert_before_row ||
...@@ -2572,7 +2570,7 @@ CopyFrom(CopyState cstate) ...@@ -2572,7 +2570,7 @@ CopyFrom(CopyState cstate)
/* Determine the partition to heap_insert the tuple into */ /* Determine the partition to heap_insert the tuple into */
if (cstate->partition_dispatch_info) if (cstate->partition_dispatch_info)
{ {
int leaf_part_index; int leaf_part_index;
TupleConversionMap *map; TupleConversionMap *map;
/* /*
...@@ -2584,7 +2582,7 @@ CopyFrom(CopyState cstate) ...@@ -2584,7 +2582,7 @@ CopyFrom(CopyState cstate)
* partition, respectively. * partition, respectively.
*/ */
leaf_part_index = ExecFindPartition(resultRelInfo, leaf_part_index = ExecFindPartition(resultRelInfo,
cstate->partition_dispatch_info, cstate->partition_dispatch_info,
slot, slot,
estate); estate);
Assert(leaf_part_index >= 0 && Assert(leaf_part_index >= 0 &&
...@@ -2601,7 +2599,7 @@ CopyFrom(CopyState cstate) ...@@ -2601,7 +2599,7 @@ CopyFrom(CopyState cstate)
if (resultRelInfo->ri_FdwRoutine) if (resultRelInfo->ri_FdwRoutine)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot route inserted tuples to a foreign table"))); errmsg("cannot route inserted tuples to a foreign table")));
/* /*
* For ExecInsertIndexTuples() to work on the partition's indexes * For ExecInsertIndexTuples() to work on the partition's indexes
...@@ -2752,7 +2750,7 @@ CopyFrom(CopyState cstate) ...@@ -2752,7 +2750,7 @@ CopyFrom(CopyState cstate)
/* Close all the partitioned tables, leaf partitions, and their indices */ /* Close all the partitioned tables, leaf partitions, and their indices */
if (cstate->partition_dispatch_info) if (cstate->partition_dispatch_info)
{ {
int i; int i;
/* /*
* Remember cstate->partition_dispatch_info[0] corresponds to the root * Remember cstate->partition_dispatch_info[0] corresponds to the root
......
...@@ -166,7 +166,7 @@ typedef struct AlteredTableInfo ...@@ -166,7 +166,7 @@ typedef struct AlteredTableInfo
Oid newTableSpace; /* new tablespace; 0 means no change */ Oid newTableSpace; /* new tablespace; 0 means no change */
bool chgPersistence; /* T if SET LOGGED/UNLOGGED is used */ bool chgPersistence; /* T if SET LOGGED/UNLOGGED is used */
char newrelpersistence; /* if above is true */ char newrelpersistence; /* if above is true */
List *partition_constraint; /* for attach partition validation */ List *partition_constraint; /* for attach partition validation */
/* Objects to rebuild after completing ALTER TYPE operations */ /* Objects to rebuild after completing ALTER TYPE operations */
List *changedConstraintOids; /* OIDs of constraints to rebuild */ List *changedConstraintOids; /* OIDs of constraints to rebuild */
List *changedConstraintDefs; /* string definitions of same */ List *changedConstraintDefs; /* string definitions of same */
...@@ -454,7 +454,7 @@ static void ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *pa ...@@ -454,7 +454,7 @@ static void ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *pa
static void CreateInheritance(Relation child_rel, Relation parent_rel); static void CreateInheritance(Relation child_rel, Relation parent_rel);
static void RemoveInheritance(Relation child_rel, Relation parent_rel); static void RemoveInheritance(Relation child_rel, Relation parent_rel);
static ObjectAddress ATExecAttachPartition(List **wqueue, Relation rel, static ObjectAddress ATExecAttachPartition(List **wqueue, Relation rel,
PartitionCmd *cmd); PartitionCmd *cmd);
static ObjectAddress ATExecDetachPartition(Relation rel, RangeVar *name); static ObjectAddress ATExecDetachPartition(Relation rel, RangeVar *name);
...@@ -630,7 +630,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ...@@ -630,7 +630,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
*/ */
localHasOids = interpretOidsOption(stmt->options, localHasOids = interpretOidsOption(stmt->options,
(relkind == RELKIND_RELATION || (relkind == RELKIND_RELATION ||
relkind == RELKIND_PARTITIONED_TABLE)); relkind == RELKIND_PARTITIONED_TABLE));
descriptor->tdhasoid = (localHasOids || parentOidCount > 0); descriptor->tdhasoid = (localHasOids || parentOidCount > 0);
if (stmt->partbound) if (stmt->partbound)
...@@ -791,19 +791,19 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ...@@ -791,19 +791,19 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
} }
/* /*
* Process the partitioning specification (if any) and store the * Process the partitioning specification (if any) and store the partition
* partition key information into the catalog. * key information into the catalog.
*/ */
if (stmt->partspec) if (stmt->partspec)
{ {
char strategy; char strategy;
int partnatts, int partnatts,
i; i;
AttrNumber partattrs[PARTITION_MAX_KEYS]; AttrNumber partattrs[PARTITION_MAX_KEYS];
Oid partopclass[PARTITION_MAX_KEYS]; Oid partopclass[PARTITION_MAX_KEYS];
Oid partcollation[PARTITION_MAX_KEYS]; Oid partcollation[PARTITION_MAX_KEYS];
List *partexprs = NIL; List *partexprs = NIL;
List *cmds = NIL; List *cmds = NIL;
/* /*
* We need to transform the raw parsetrees corresponding to partition * We need to transform the raw parsetrees corresponding to partition
...@@ -827,7 +827,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ...@@ -827,7 +827,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
for (i = 0; i < partnatts; i++) for (i = 0; i < partnatts; i++)
{ {
AttrNumber partattno = partattrs[i]; AttrNumber partattno = partattrs[i];
Form_pg_attribute attform = descriptor->attrs[partattno-1]; Form_pg_attribute attform = descriptor->attrs[partattno - 1];
if (partattno != 0 && !attform->attnotnull) if (partattno != 0 && !attform->attnotnull)
{ {
...@@ -1613,8 +1613,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence, ...@@ -1613,8 +1613,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
MaxHeapAttributeNumber))); MaxHeapAttributeNumber)));
/* /*
* In case of a partition, there are no new column definitions, only * In case of a partition, there are no new column definitions, only dummy
* dummy ColumnDefs created for column constraints. We merge these * ColumnDefs created for column constraints. We merge them with the
* constraints inherited from the parent. * constraints inherited from the parent.
*/ */
if (is_partition) if (is_partition)
...@@ -1704,9 +1704,9 @@ MergeAttributes(List *schema, List *supers, char relpersistence, ...@@ -1704,9 +1704,9 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
* the parent's relhassubclass field, if its previous children were * the parent's relhassubclass field, if its previous children were
* recently dropped. * recently dropped.
* *
* If the child table is a partition, then we instead grab an exclusive * If the child table is a partition, then we instead grab an
* lock on the parent because its partition descriptor will be changed * exclusive lock on the parent because its partition descriptor will
* by addition of the new partition. * be changed by addition of the new partition.
*/ */
if (!is_partition) if (!is_partition)
relation = heap_openrv(parent, ShareUpdateExclusiveLock); relation = heap_openrv(parent, ShareUpdateExclusiveLock);
...@@ -1714,8 +1714,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence, ...@@ -1714,8 +1714,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
relation = heap_openrv(parent, AccessExclusiveLock); relation = heap_openrv(parent, AccessExclusiveLock);
/* /*
* We do not allow partitioned tables and partitions to participate * We do not allow partitioned tables and partitions to participate in
* in regular inheritance. * regular inheritance.
*/ */
if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
!is_partition) !is_partition)
...@@ -1752,7 +1752,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, ...@@ -1752,7 +1752,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg(!is_partition errmsg(!is_partition
? "cannot inherit from temporary relation of another session" ? "cannot inherit from temporary relation of another session"
: "cannot create as partition of temporary relation of another session"))); : "cannot create as partition of temporary relation of another session")));
/* /*
...@@ -2030,8 +2030,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence, ...@@ -2030,8 +2030,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
newcollid; newcollid;
/* /*
* Partitions have only one parent, so conflict should never * Partitions have only one parent and have no column
* occur * definitions of their own, so conflict should never occur.
*/ */
Assert(!is_partition); Assert(!is_partition);
...@@ -2118,8 +2118,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence, ...@@ -2118,8 +2118,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
/* /*
* Now that we have the column definition list for a partition, we can * Now that we have the column definition list for a partition, we can
* check whether the columns referenced in column option specifications * check whether the columns referenced in the column constraint specs
* actually exist. Also, we merge the options into the corresponding * actually exist. Also, we merge the constraints into the corresponding
* column definitions. * column definitions.
*/ */
if (is_partition && list_length(saved_schema) > 0) if (is_partition && list_length(saved_schema) > 0)
...@@ -2139,14 +2139,14 @@ MergeAttributes(List *schema, List *supers, char relpersistence, ...@@ -2139,14 +2139,14 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
*/ */
if (coldef->typeName == NULL) if (coldef->typeName == NULL)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN), (errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" does not exist", errmsg("column \"%s\" does not exist",
coldef->colname))); coldef->colname)));
while (rest != NULL) while (rest != NULL)
{ {
ColumnDef *restdef = lfirst(rest); ColumnDef *restdef = lfirst(rest);
ListCell *next = lnext(rest); /* need to save it in case ListCell *next = lnext(rest); /* need to save it in case we
* we delete it */ * delete it */
if (strcmp(coldef->colname, restdef->colname) == 0) if (strcmp(coldef->colname, restdef->colname) == 0)
{ {
...@@ -3735,7 +3735,7 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode) ...@@ -3735,7 +3735,7 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode)
*/ */
if (((tab->relkind == RELKIND_RELATION || if (((tab->relkind == RELKIND_RELATION ||
tab->relkind == RELKIND_PARTITIONED_TABLE) && tab->relkind == RELKIND_PARTITIONED_TABLE) &&
tab->partition_constraint == NIL) || tab->partition_constraint == NIL) ||
tab->relkind == RELKIND_MATVIEW) tab->relkind == RELKIND_MATVIEW)
AlterTableCreateToastTable(tab->relid, (Datum) 0, lockmode); AlterTableCreateToastTable(tab->relid, (Datum) 0, lockmode);
} }
...@@ -4326,8 +4326,8 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) ...@@ -4326,8 +4326,8 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
{ {
needscan = true; needscan = true;
partqualstate = (List *) partqualstate = (List *)
ExecPrepareExpr((Expr *) tab->partition_constraint, ExecPrepareExpr((Expr *) tab->partition_constraint,
estate); estate);
} }
foreach(l, tab->newvals) foreach(l, tab->newvals)
...@@ -4522,7 +4522,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) ...@@ -4522,7 +4522,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
if (partqualstate && !ExecQual(partqualstate, econtext, true)) if (partqualstate && !ExecQual(partqualstate, econtext, true))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION), (errcode(ERRCODE_CHECK_VIOLATION),
errmsg("partition constraint is violated by some row"))); errmsg("partition constraint is violated by some row")));
/* Write the tuple out to the new relation */ /* Write the tuple out to the new relation */
if (newrel) if (newrel)
...@@ -5596,20 +5596,20 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) ...@@ -5596,20 +5596,20 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
if (tupDesc->attrs[parent_attnum - 1]->attnotnull) if (tupDesc->attrs[parent_attnum - 1]->attnotnull)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION), (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("column \"%s\" is marked NOT NULL in parent table", errmsg("column \"%s\" is marked NOT NULL in parent table",
colName))); colName)));
heap_close(parent, AccessShareLock); heap_close(parent, AccessShareLock);
} }
/* /*
* If the table is a range partitioned table, check that the column * If the table is a range partitioned table, check that the column is not
* is not in the partition key. * in the partition key.
*/ */
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{ {
PartitionKey key = RelationGetPartitionKey(rel); PartitionKey key = RelationGetPartitionKey(rel);
int partnatts = get_partition_natts(key), int partnatts = get_partition_natts(key),
i; i;
for (i = 0; i < partnatts; i++) for (i = 0; i < partnatts; i++)
{ {
...@@ -6093,11 +6093,11 @@ ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing, ...@@ -6093,11 +6093,11 @@ ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
static bool static bool
is_partition_attr(Relation rel, AttrNumber attnum, bool *used_in_expr) is_partition_attr(Relation rel, AttrNumber attnum, bool *used_in_expr)
{ {
PartitionKey key; PartitionKey key;
int partnatts; int partnatts;
List *partexprs; List *partexprs;
ListCell *partexprs_item; ListCell *partexprs_item;
int i; int i;
if (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) if (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
return false; return false;
...@@ -8258,9 +8258,9 @@ ATExecDropConstraint(Relation rel, const char *constrName, ...@@ -8258,9 +8258,9 @@ ATExecDropConstraint(Relation rel, const char *constrName,
} }
/* /*
* In case of a partitioned table, the constraint must be dropped from * In case of a partitioned table, the constraint must be dropped from the
* the partitions too. There is no such thing as NO INHERIT constraints * partitions too. There is no such thing as NO INHERIT constraints in
* in case of partitioned tables. * case of partitioned tables.
*/ */
if (!recurse && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) if (!recurse && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
ereport(ERROR, ereport(ERROR,
...@@ -8432,7 +8432,7 @@ ATPrepAlterColumnType(List **wqueue, ...@@ -8432,7 +8432,7 @@ ATPrepAlterColumnType(List **wqueue,
if (!is_expr) if (!is_expr)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION), (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("cannot alter type of column named in partition key"))); errmsg("cannot alter type of column named in partition key")));
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION), (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
...@@ -10704,7 +10704,8 @@ CreateInheritance(Relation child_rel, Relation parent_rel) ...@@ -10704,7 +10704,8 @@ CreateInheritance(Relation child_rel, Relation parent_rel)
/* /*
* Check for duplicates in the list of parents, and determine the highest * Check for duplicates in the list of parents, and determine the highest
* inhseqno already present; we'll use the next one for the new parent. * inhseqno already present; we'll use the next one for the new parent.
* Also, if proposed child is a partition, it cannot already be inheriting. * Also, if proposed child is a partition, it cannot already be
* inheriting.
* *
* Note: we do not reject the case where the child already inherits from * Note: we do not reject the case where the child already inherits from
* the parent indirectly; CREATE TABLE doesn't reject comparable cases. * the parent indirectly; CREATE TABLE doesn't reject comparable cases.
...@@ -11054,8 +11055,8 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) ...@@ -11054,8 +11055,8 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
static ObjectAddress static ObjectAddress
ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode) ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
{ {
ObjectAddress address; ObjectAddress address;
Relation parent_rel; Relation parent_rel;
if (rel->rd_rel->relispartition) if (rel->rd_rel->relispartition)
ereport(ERROR, ereport(ERROR,
...@@ -11154,15 +11155,15 @@ RemoveInheritance(Relation child_rel, Relation parent_rel) ...@@ -11154,15 +11155,15 @@ RemoveInheritance(Relation child_rel, Relation parent_rel)
if (child_is_partition) if (child_is_partition)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE), (errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("relation \"%s\" is not a partition of relation \"%s\"", errmsg("relation \"%s\" is not a partition of relation \"%s\"",
RelationGetRelationName(child_rel), RelationGetRelationName(child_rel),
RelationGetRelationName(parent_rel)))); RelationGetRelationName(parent_rel))));
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE), (errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("relation \"%s\" is not a parent of relation \"%s\"", errmsg("relation \"%s\" is not a parent of relation \"%s\"",
RelationGetRelationName(parent_rel), RelationGetRelationName(parent_rel),
RelationGetRelationName(child_rel)))); RelationGetRelationName(child_rel))));
} }
/* /*
...@@ -11283,6 +11284,7 @@ RemoveInheritance(Relation child_rel, Relation parent_rel) ...@@ -11283,6 +11284,7 @@ RemoveInheritance(Relation child_rel, Relation parent_rel)
drop_parent_dependency(RelationGetRelid(child_rel), drop_parent_dependency(RelationGetRelid(child_rel),
RelationRelationId, RelationRelationId,
RelationGetRelid(parent_rel)); RelationGetRelid(parent_rel));
/* /*
* Post alter hook of this inherits. Since object_access_hook doesn't take * Post alter hook of this inherits. Since object_access_hook doesn't take
* multiple object identifiers, we relay oid of parent relation using * multiple object identifiers, we relay oid of parent relation using
...@@ -12735,10 +12737,10 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, ...@@ -12735,10 +12737,10 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
static PartitionSpec * static PartitionSpec *
transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy) transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
{ {
PartitionSpec *newspec; PartitionSpec *newspec;
ParseState *pstate; ParseState *pstate;
RangeTblEntry *rte; RangeTblEntry *rte;
ListCell *l; ListCell *l;
newspec = (PartitionSpec *) makeNode(PartitionSpec); newspec = (PartitionSpec *) makeNode(PartitionSpec);
...@@ -12768,16 +12770,16 @@ transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy) ...@@ -12768,16 +12770,16 @@ transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
/* take care of any partition expressions */ /* take care of any partition expressions */
foreach(l, partspec->partParams) foreach(l, partspec->partParams)
{ {
ListCell *lc; ListCell *lc;
PartitionElem *pelem = (PartitionElem *) lfirst(l); PartitionElem *pelem = (PartitionElem *) lfirst(l);
/* Check for PARTITION BY ... (foo, foo) */ /* Check for PARTITION BY ... (foo, foo) */
foreach(lc, newspec->partParams) foreach(lc, newspec->partParams)
{ {
PartitionElem *pparam = (PartitionElem *) lfirst(lc); PartitionElem *pparam = (PartitionElem *) lfirst(lc);
if (pelem->name && pparam->name && if (pelem->name && pparam->name &&
!strcmp(pelem->name, pparam->name)) !strcmp(pelem->name, pparam->name))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_COLUMN), (errcode(ERRCODE_DUPLICATE_COLUMN),
errmsg("column \"%s\" appears more than once in partition key", errmsg("column \"%s\" appears more than once in partition key",
...@@ -12814,29 +12816,29 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs, ...@@ -12814,29 +12816,29 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
attn = 0; attn = 0;
foreach(lc, partParams) foreach(lc, partParams)
{ {
PartitionElem *pelem = (PartitionElem *) lfirst(lc); PartitionElem *pelem = (PartitionElem *) lfirst(lc);
Oid atttype; Oid atttype;
Oid attcollation; Oid attcollation;
if (pelem->name != NULL) if (pelem->name != NULL)
{ {
/* Simple attribute reference */ /* Simple attribute reference */
HeapTuple atttuple; HeapTuple atttuple;
Form_pg_attribute attform; Form_pg_attribute attform;
atttuple = SearchSysCacheAttName(RelationGetRelid(rel), pelem->name); atttuple = SearchSysCacheAttName(RelationGetRelid(rel), pelem->name);
if (!HeapTupleIsValid(atttuple)) if (!HeapTupleIsValid(atttuple))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN), (errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" named in partition key does not exist", errmsg("column \"%s\" named in partition key does not exist",
pelem->name))); pelem->name)));
attform = (Form_pg_attribute) GETSTRUCT(atttuple); attform = (Form_pg_attribute) GETSTRUCT(atttuple);
if (attform->attnum <= 0) if (attform->attnum <= 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN), (errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("cannot use system column \"%s\" in partition key", errmsg("cannot use system column \"%s\" in partition key",
pelem->name))); pelem->name)));
partattrs[attn] = attform->attnum; partattrs[attn] = attform->attnum;
atttype = attform->atttypid; atttype = attform->atttypid;
...@@ -12872,9 +12874,9 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs, ...@@ -12872,9 +12874,9 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
} }
else else
{ {
Bitmapset *expr_attrs = NULL; Bitmapset *expr_attrs = NULL;
partattrs[attn] = 0; /* marks the column as expression */ partattrs[attn] = 0; /* marks the column as expression */
*partexprs = lappend(*partexprs, expr); *partexprs = lappend(*partexprs, expr);
/* /*
...@@ -12896,8 +12898,8 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs, ...@@ -12896,8 +12898,8 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
errmsg("functions in partition key expression must be marked IMMUTABLE"))); errmsg("functions in partition key expression must be marked IMMUTABLE")));
/* /*
* While it is not exactly *wrong* for an expression to be * While it is not exactly *wrong* for an expression to be a
* a constant value, it seems better to prevent such input. * constant value, it seems better to prevent such input.
*/ */
if (IsA(expr, Const)) if (IsA(expr, Const))
ereport(ERROR, ereport(ERROR,
...@@ -12905,9 +12907,9 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs, ...@@ -12905,9 +12907,9 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
errmsg("cannot use constant expression as partition key"))); errmsg("cannot use constant expression as partition key")));
/* /*
* transformPartitionSpec() should have already rejected subqueries, * transformPartitionSpec() should have already rejected
* aggregates, window functions, and SRFs, based on the EXPR_KIND_ * subqueries, aggregates, window functions, and SRFs, based
* for partition expressions. * on the EXPR_KIND_ for partition expressions.
*/ */
/* Cannot have expressions containing whole-row references */ /* Cannot have expressions containing whole-row references */
...@@ -12929,8 +12931,8 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs, ...@@ -12929,8 +12931,8 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
/* /*
* Check we have a collation iff it's a collatable type. The only * Check we have a collation iff it's a collatable type. The only
* expected failures here are (1) COLLATE applied to a noncollatable * expected failures here are (1) COLLATE applied to a noncollatable
* type, or (2) partition expression had an unresolved collation. * type, or (2) partition expression had an unresolved collation. But
* But we might as well code this to be a complete consistency check. * we might as well code this to be a complete consistency check.
*/ */
if (type_is_collatable(atttype)) if (type_is_collatable(atttype))
{ {
...@@ -12962,8 +12964,8 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs, ...@@ -12962,8 +12964,8 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
if (!OidIsValid(partopclass[attn])) if (!OidIsValid(partopclass[attn]))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("data type %s has no default btree operator class", errmsg("data type %s has no default btree operator class",
format_type_be(atttype)), format_type_be(atttype)),
errhint("You must specify a btree operator class or define a default btree operator class for the data type."))); errhint("You must specify a btree operator class or define a default btree operator class for the data type.")));
} }
else else
...@@ -12984,11 +12986,11 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs, ...@@ -12984,11 +12986,11 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
static ObjectAddress static ObjectAddress
ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
{ {
PartitionKey key = RelationGetPartitionKey(rel); PartitionKey key = RelationGetPartitionKey(rel);
Relation attachRel, Relation attachRel,
catalog; catalog;
List *childrels; List *childrels;
TupleConstr *attachRel_constr; TupleConstr *attachRel_constr;
List *partConstraint, List *partConstraint,
*existConstraint; *existConstraint;
SysScanDesc scan; SysScanDesc scan;
...@@ -13053,8 +13055,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) ...@@ -13053,8 +13055,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
heap_close(catalog, AccessShareLock); heap_close(catalog, AccessShareLock);
/* /*
* Prevent circularity by seeing if rel is a partition of attachRel. * Prevent circularity by seeing if rel is a partition of attachRel. (In
* (In particular, this disallows making a rel a partition of itself.) * particular, this disallows making a rel a partition of itself.)
*/ */
childrels = find_all_inheritors(RelationGetRelid(attachRel), childrels = find_all_inheritors(RelationGetRelid(attachRel),
AccessShareLock, NULL); AccessShareLock, NULL);
...@@ -13079,30 +13081,30 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) ...@@ -13079,30 +13081,30 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
!rel->rd_islocaltemp) !rel->rd_islocaltemp)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot attach as partition of temporary relation of another session"))); errmsg("cannot attach as partition of temporary relation of another session")));
/* Ditto for the partition */ /* Ditto for the partition */
if (attachRel->rd_rel->relpersistence == RELPERSISTENCE_TEMP && if (attachRel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
!attachRel->rd_islocaltemp) !attachRel->rd_islocaltemp)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot attach temporary relation of another session as partition"))); errmsg("cannot attach temporary relation of another session as partition")));
/* If parent has OIDs then child must have OIDs */ /* If parent has OIDs then child must have OIDs */
if (rel->rd_rel->relhasoids && !attachRel->rd_rel->relhasoids) if (rel->rd_rel->relhasoids && !attachRel->rd_rel->relhasoids)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot attach table \"%s\" without OIDs as partition of" errmsg("cannot attach table \"%s\" without OIDs as partition of"
" table \"%s\" with OIDs", RelationGetRelationName(attachRel), " table \"%s\" with OIDs", RelationGetRelationName(attachRel),
RelationGetRelationName(rel)))); RelationGetRelationName(rel))));
/* OTOH, if parent doesn't have them, do not allow in attachRel either */ /* OTOH, if parent doesn't have them, do not allow in attachRel either */
if (attachRel->rd_rel->relhasoids && !rel->rd_rel->relhasoids) if (attachRel->rd_rel->relhasoids && !rel->rd_rel->relhasoids)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot attach table \"%s\" with OIDs as partition of table" errmsg("cannot attach table \"%s\" with OIDs as partition of table"
" \"%s\" without OIDs", RelationGetRelationName(attachRel), " \"%s\" without OIDs", RelationGetRelationName(attachRel),
RelationGetRelationName(rel)))); RelationGetRelationName(rel))));
/* Check if there are any columns in attachRel that aren't in the parent */ /* Check if there are any columns in attachRel that aren't in the parent */
tupleDesc = RelationGetDescr(attachRel); tupleDesc = RelationGetDescr(attachRel);
...@@ -13132,8 +13134,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) ...@@ -13132,8 +13134,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
/* /*
* Check that the new partition's bound is valid and does not overlap any * Check that the new partition's bound is valid and does not overlap any
* of existing partitions of the parent - note that it does not return * of existing partitions of the parent - note that it does not return on
* on error. * error.
*/ */
check_new_partition_bound(RelationGetRelationName(attachRel), rel, check_new_partition_bound(RelationGetRelationName(attachRel), rel,
cmd->bound); cmd->bound);
...@@ -13155,8 +13157,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) ...@@ -13155,8 +13157,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
partConstraint = list_make1(make_ands_explicit(partConstraint)); partConstraint = list_make1(make_ands_explicit(partConstraint));
/* /*
* Check if we can do away with having to scan the table being attached * Check if we can do away with having to scan the table being attached to
* to validate the partition constraint, by *proving* that the existing * validate the partition constraint, by *proving* that the existing
* constraints of the table *imply* the partition predicate. We include * constraints of the table *imply* the partition predicate. We include
* the table's check constraints and NOT NULL constraints in the list of * the table's check constraints and NOT NULL constraints in the list of
* clauses passed to predicate_implied_by(). * clauses passed to predicate_implied_by().
...@@ -13243,14 +13245,14 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) ...@@ -13243,14 +13245,14 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
skip_validate = true; skip_validate = true;
/* /*
* We choose to err on the safer side, ie, give up on skipping the * We choose to err on the safer side, ie, give up on skipping the the
* the validation scan, if the partition key column doesn't have * validation scan, if the partition key column doesn't have the NOT
* the NOT NULL constraint and the table is to become a list partition * NULL constraint and the table is to become a list partition that
* that does not accept nulls. In this case, the partition predicate * does not accept nulls. In this case, the partition predicate
* (partConstraint) does include an 'key IS NOT NULL' expression, * (partConstraint) does include an 'key IS NOT NULL' expression,
* however, because of the way predicate_implied_by_simple_clause() * however, because of the way predicate_implied_by_simple_clause() is
* is designed to handle IS NOT NULL predicates in the absence of a * designed to handle IS NOT NULL predicates in the absence of a IS
* IS NOT NULL clause, we cannot rely on just the above proof. * NOT NULL clause, we cannot rely on just the above proof.
* *
* That is not an issue in case of a range partition, because if there * That is not an issue in case of a range partition, because if there
* were no NOT NULL constraint defined on the key columns, an error * were no NOT NULL constraint defined on the key columns, an error
...@@ -13269,7 +13271,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) ...@@ -13269,7 +13271,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
*/ */
foreach(lc, part_constr) foreach(lc, part_constr)
{ {
Node *expr = lfirst(lc); Node *expr = lfirst(lc);
if (IsA(expr, NullTest) && if (IsA(expr, NullTest) &&
((NullTest *) expr)->nulltesttype == IS_NOT_NULL) ((NullTest *) expr)->nulltesttype == IS_NOT_NULL)
...@@ -13299,8 +13301,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) ...@@ -13299,8 +13301,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
/* /*
* Set up to have the table to be scanned to validate the partition * Set up to have the table to be scanned to validate the partition
* constraint (see partConstraint above). If it's a partitioned table, * constraint (see partConstraint above). If it's a partitioned table, we
* we instead schdule its leaf partitions to be scanned instead. * instead schdule its leaf partitions to be scanned instead.
*/ */
if (!skip_validate) if (!skip_validate)
{ {
...@@ -13310,7 +13312,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) ...@@ -13310,7 +13312,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
/* Take an exclusive lock on the partitions to be checked */ /* Take an exclusive lock on the partitions to be checked */
if (attachRel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) if (attachRel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
all_parts = find_all_inheritors(RelationGetRelid(attachRel), all_parts = find_all_inheritors(RelationGetRelid(attachRel),
AccessExclusiveLock, NULL); AccessExclusiveLock, NULL);
else else
all_parts = list_make1_oid(RelationGetRelid(attachRel)); all_parts = list_make1_oid(RelationGetRelid(attachRel));
...@@ -13351,8 +13353,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) ...@@ -13351,8 +13353,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
} }
/* /*
* Invalidate the relcache so that the new partition is now included * Invalidate the parent's relcache so that the new partition is now
* in rel's partition descriptor. * included its partition descriptor.
*/ */
CacheInvalidateRelcache(rel); CacheInvalidateRelcache(rel);
...@@ -13414,8 +13416,8 @@ ATExecDetachPartition(Relation rel, RangeVar *name) ...@@ -13414,8 +13416,8 @@ ATExecDetachPartition(Relation rel, RangeVar *name)
heap_close(classRel, RowExclusiveLock); heap_close(classRel, RowExclusiveLock);
/* /*
* Invalidate the relcache so that the partition is no longer included * Invalidate the parent's relcache so that the partition is no longer
* in our partition descriptor. * included in its partition descriptor.
*/ */
CacheInvalidateRelcache(rel); CacheInvalidateRelcache(rel);
......
...@@ -1718,26 +1718,26 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) ...@@ -1718,26 +1718,26 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (operation == CMD_INSERT && if (operation == CMD_INSERT &&
rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{ {
PartitionDispatch *pd;
int i, int i,
j, j,
num_parted, num_parted;
num_leaf_parts;
List *leaf_parts; List *leaf_parts;
ListCell *cell; ListCell *cell;
ResultRelInfo *leaf_part_rri; ResultRelInfo *leaf_part_rri;
/* Form the partition node tree and lock partitions */ /* Get the tuple-routing information and lock partitions */
pd = RelationGetPartitionDispatchInfo(rel, RowExclusiveLock, mtstate->mt_partition_dispatch_info =
&num_parted, &leaf_parts); RelationGetPartitionDispatchInfo(rel, RowExclusiveLock,
mtstate->mt_partition_dispatch_info = pd; &num_parted,
&leaf_parts);
mtstate->mt_num_dispatch = num_parted; mtstate->mt_num_dispatch = num_parted;
num_leaf_parts = list_length(leaf_parts); mtstate->mt_num_partitions = list_length(leaf_parts);
mtstate->mt_num_partitions = num_leaf_parts;
mtstate->mt_partitions = (ResultRelInfo *) mtstate->mt_partitions = (ResultRelInfo *)
palloc0(num_leaf_parts * sizeof(ResultRelInfo)); palloc0(mtstate->mt_num_partitions *
sizeof(ResultRelInfo));
mtstate->mt_partition_tupconv_maps = (TupleConversionMap **) mtstate->mt_partition_tupconv_maps = (TupleConversionMap **)
palloc0(num_leaf_parts * sizeof(TupleConversionMap *)); palloc0(mtstate->mt_num_partitions *
sizeof(TupleConversionMap *));
leaf_part_rri = mtstate->mt_partitions; leaf_part_rri = mtstate->mt_partitions;
i = j = 0; i = j = 0;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_partitioned_table.h $ * src/include/catalog/pg_partitioned_table.h
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -29,9 +29,9 @@ ...@@ -29,9 +29,9 @@
CATALOG(pg_partitioned_table,3350) BKI_WITHOUT_OIDS CATALOG(pg_partitioned_table,3350) BKI_WITHOUT_OIDS
{ {
Oid partrelid; /* partitioned table oid */ Oid partrelid; /* partitioned table oid */
char partstrat; /* partitioning strategy */ char partstrat; /* partitioning strategy */
int16 partnatts; /* number of partition key columns */ int16 partnatts; /* number of partition key columns */
/* /*
* variable-length fields start here, but we allow direct access to * variable-length fields start here, but we allow direct access to
...@@ -39,29 +39,27 @@ CATALOG(pg_partitioned_table,3350) BKI_WITHOUT_OIDS ...@@ -39,29 +39,27 @@ CATALOG(pg_partitioned_table,3350) BKI_WITHOUT_OIDS
* field of a heap tuple can be reliably accessed using its C struct * field of a heap tuple can be reliably accessed using its C struct
* offset, as previous fields are all non-nullable fixed-length fields. * offset, as previous fields are all non-nullable fixed-length fields.
*/ */
int2vector partattrs; /* each member of the array is the int2vector partattrs; /* each member of the array is the attribute
* attribute number of a partition key * number of a partition key column, or 0 if
* column, or 0 if the column is actually * the column is actually an expression */
* an expression */
#ifdef CATALOG_VARLEN #ifdef CATALOG_VARLEN
oidvector partclass; /* operator class to compare keys */ oidvector partclass; /* operator class to compare keys */
oidvector partcollation; /* user-specified collation for keys */ oidvector partcollation; /* user-specified collation for keys */
pg_node_tree partexprs; /* list of expressions in the partitioning pg_node_tree partexprs; /* list of expressions in the partition key;
* key; one item for each zero entry in * one item for each zero entry in partattrs[] */
* partattrs[] */
#endif #endif
} FormData_pg_partitioned_table; } FormData_pg_partitioned_table;
/* ---------------- /* ----------------
* Form_pg_partitioned_table corresponds to a pointer to a tuple with * Form_pg_partitioned_table corresponds to a pointer to a tuple with
* the format of pg_partitioned_table relation. * the format of pg_partitioned_table relation.
* ---------------- * ----------------
*/ */
typedef FormData_pg_partitioned_table *Form_pg_partitioned_table; typedef FormData_pg_partitioned_table *Form_pg_partitioned_table;
/* ---------------- /* ----------------
* compiler constants for pg_partitioned_table * compiler constants for pg_partitioned_table
* ---------------- * ----------------
*/ */
#define Natts_pg_partitioned_table 7 #define Natts_pg_partitioned_table 7
...@@ -70,7 +68,7 @@ typedef FormData_pg_partitioned_table *Form_pg_partitioned_table; ...@@ -70,7 +68,7 @@ typedef FormData_pg_partitioned_table *Form_pg_partitioned_table;
#define Anum_pg_partitioned_table_partnatts 3 #define Anum_pg_partitioned_table_partnatts 3
#define Anum_pg_partitioned_table_partattrs 4 #define Anum_pg_partitioned_table_partattrs 4
#define Anum_pg_partitioned_table_partclass 5 #define Anum_pg_partitioned_table_partclass 5
#define Anum_pg_partitioned_table_partcollation 6 #define Anum_pg_partitioned_table_partcollation 6
#define Anum_pg_partitioned_table_partexprs 7 #define Anum_pg_partitioned_table_partexprs 7
#endif /* PG_PARTITIONED_TABLE_H */ #endif /* PG_PARTITIONED_TABLE_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment