1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-16 06:01:02 +03:00

Don't explicitly mark range partitioning columns NOT NULL.

This seemed like a good idea originally because there's no way to mark
a range partition as accepting NULL, but that now seems more like a
current limitation than something we want to lock down for all time.
For example, there's a proposal to add the notion of a default
partition which accepts all rows not otherwise routed, which directly
conflicts with the idea that a range-partitioned table should never
allow nulls anywhere.  So let's change this while we still can, by
putting the NOT NULL test into the partition constraint instead of
changing the column properties.

Amit Langote and Robert Haas, reviewed by Amit Kapila

Discussion: http://postgr.es/m/8e2dd63d-c6fb-bb74-3c2b-ed6d63629c9d@lab.ntt.co.jp
This commit is contained in:
Robert Haas
2017-05-18 13:48:10 -04:00
parent 2df537e43f
commit 3ec76ff1f2
9 changed files with 64 additions and 138 deletions

View File

@ -805,13 +805,11 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
if (stmt->partspec)
{
char strategy;
int partnatts,
i;
int partnatts;
AttrNumber partattrs[PARTITION_MAX_KEYS];
Oid partopclass[PARTITION_MAX_KEYS];
Oid partcollation[PARTITION_MAX_KEYS];
List *partexprs = NIL;
List *cmds = NIL;
/*
* We need to transform the raw parsetrees corresponding to partition
@ -828,33 +826,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
partnatts = list_length(stmt->partspec->partParams);
StorePartitionKey(rel, strategy, partnatts, partattrs, partexprs,
partopclass, partcollation);
/* Force key columns to be NOT NULL when using range partitioning */
if (strategy == PARTITION_STRATEGY_RANGE)
{
for (i = 0; i < partnatts; i++)
{
AttrNumber partattno = partattrs[i];
Form_pg_attribute attform = descriptor->attrs[partattno - 1];
if (partattno != 0 && !attform->attnotnull)
{
/* Add a subcommand to make this one NOT NULL */
AlterTableCmd *cmd = makeNode(AlterTableCmd);
cmd->subtype = AT_SetNotNull;
cmd->name = pstrdup(NameStr(attform->attname));
cmds = lappend(cmds, cmd);
}
}
/*
* Although, there cannot be any partitions yet, we still need to
* pass true for recurse; ATPrepSetNotNull() complains if we don't
*/
if (cmds != NIL)
AlterTableInternal(RelationGetRelid(rel), cmds, true);
}
}
/*
@ -5702,32 +5673,6 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
heap_close(parent, AccessShareLock);
}
/*
* If the table is a range partitioned table, check that the column is not
* in the partition key.
*/
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
PartitionKey key = RelationGetPartitionKey(rel);
if (get_partition_strategy(key) == PARTITION_STRATEGY_RANGE)
{
int partnatts = get_partition_natts(key),
i;
for (i = 0; i < partnatts; i++)
{
AttrNumber partattnum = get_partition_col_attnum(key, i);
if (partattnum == attnum)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("column \"%s\" is in range partition key",
colName)));
}
}
}
/*
* Okay, actually perform the catalog change ... if needed
*/