mirror of
https://github.com/postgres/postgres.git
synced 2025-06-30 21:42:05 +03:00
Fix several DDL issues of generated columns versus inheritance
Several combinations of generated columns and inheritance in CREATE TABLE were not handled correctly. Specifically: - Disallow a child column specifying a generation expression if the parent column is a generated column. The child column definition must be unadorned and the parent column's generation expression will be copied. - Prohibit a child column of a generated parent column specifying default values or identity. - Allow a child column of a not-generated parent column specifying itself as a generated column. This previously did not work, but it was possible to arrive at the state via other means (involving ALTER TABLE), so it seems sensible to support it. Add tests for each case. Also add documentation about the rules involving generated columns and inheritance. Discussion: https://www.postgresql.org/message-id/flat/15830.1575468847%40sss.pgh.pa.us https://www.postgresql.org/message-id/flat/2678bad1-048f-519a-ef24-b12962f41807%40enterprisedb.com https://www.postgresql.org/message-id/flat/CAJvUf_u4h0DxkCMCeEKAWCuzGUTnDP-G5iVmSwxLQSXn0_FWNQ%40mail.gmail.com
This commit is contained in:
@ -2618,12 +2618,55 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
|
||||
def->is_local = true;
|
||||
/* Merge of NOT NULL constraints = OR 'em together */
|
||||
def->is_not_null |= newdef->is_not_null;
|
||||
|
||||
/*
|
||||
* Check for conflicts related to generated columns.
|
||||
*
|
||||
* If the parent column is generated, the child column must be
|
||||
* unadorned and will be made a generated column. (We could
|
||||
* in theory allow the child column definition specifying the
|
||||
* exact same generation expression, but that's a bit
|
||||
* complicated to implement and doesn't seem very useful.) We
|
||||
* also check that the child column doesn't specify a default
|
||||
* value or identity, which matches the rules for a single
|
||||
* column in parse_util.c.
|
||||
*/
|
||||
if (def->generated)
|
||||
{
|
||||
if (newdef->generated)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
|
||||
errmsg("child column \"%s\" specifies generation expression",
|
||||
def->colname),
|
||||
errhint("Omit the generation expression in the definition of the child table column to inherit the generation expression from the parent table.")));
|
||||
if (newdef->raw_default && !newdef->generated)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
|
||||
errmsg("column \"%s\" inherits from generated column but specifies default",
|
||||
def->colname)));
|
||||
if (newdef->identity)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
|
||||
errmsg("column \"%s\" inherits from generated column but specifies identity",
|
||||
def->colname)));
|
||||
}
|
||||
/*
|
||||
* If the parent column is not generated, then take whatever
|
||||
* the child column definition says.
|
||||
*/
|
||||
else
|
||||
{
|
||||
if (newdef->generated)
|
||||
def->generated = newdef->generated;
|
||||
}
|
||||
|
||||
/* If new def has a default, override previous default */
|
||||
if (newdef->raw_default != NULL)
|
||||
{
|
||||
def->raw_default = newdef->raw_default;
|
||||
def->cooked_default = newdef->cooked_default;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2709,11 +2752,19 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
|
||||
ColumnDef *def = lfirst(entry);
|
||||
|
||||
if (def->cooked_default == &bogus_marker)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
|
||||
errmsg("column \"%s\" inherits conflicting default values",
|
||||
def->colname),
|
||||
errhint("To resolve the conflict, specify a default explicitly.")));
|
||||
{
|
||||
if (def->generated)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
|
||||
errmsg("column \"%s\" inherits conflicting generation expressions",
|
||||
def->colname)));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
|
||||
errmsg("column \"%s\" inherits conflicting default values",
|
||||
def->colname),
|
||||
errhint("To resolve the conflict, specify a default explicitly.")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user