Skip to content

Commit a0fa18c

Browse files
committed
Fix check for child column generation status matching parent.
In commit 8bf6ec3, I mistakenly supposed that MergeAttributes' loop over saved_schema was reprocessing column definitions that had already been checked earlier: there is a variant syntax for creating a child partition in which that's not true. So we need to duplicate the full check appearing further up. (Actually, I believe that the "if (restdef->identity)" part is not reachable, because we reject identity on partitions earlier. But it seems wise to keep the check, in case that's ever relaxed, and to keep this code in sync with the other instance.) Per report from Alexander Lakhin. Discussion: https://postgr.es/m/4a8200ca-8378-653e-38ed-b2e1f1611aa6@gmail.com
1 parent afa7930 commit a0fa18c

File tree

3 files changed

+55
-10
lines changed

3 files changed

+55
-10
lines changed

src/backend/commands/tablecmds.c

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3015,17 +3015,34 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
30153015
coldef->is_not_null |= restdef->is_not_null;
30163016

30173017
/*
3018-
* As above, reject generated columns in partitions that
3019-
* are not generated in the parent.
3018+
* Check for conflicts related to generated columns.
3019+
*
3020+
* Same rules as above: generated-ness has to match the
3021+
* parent, but the contents of the generation expression
3022+
* can be different.
30203023
*/
3021-
if (restdef->generated && !coldef->generated)
3022-
ereport(ERROR,
3023-
(errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3024-
errmsg("child column \"%s\" specifies generation expression",
3025-
restdef->colname),
3026-
errhint("A child table column cannot be generated unless its parent column is.")));
3027-
/* Other way around should have been dealt with above */
3028-
Assert(!(coldef->generated && !restdef->generated));
3024+
if (coldef->generated)
3025+
{
3026+
if (restdef->raw_default && !restdef->generated)
3027+
ereport(ERROR,
3028+
(errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3029+
errmsg("column \"%s\" inherits from generated column but specifies default",
3030+
restdef->colname)));
3031+
if (restdef->identity)
3032+
ereport(ERROR,
3033+
(errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3034+
errmsg("column \"%s\" inherits from generated column but specifies identity",
3035+
restdef->colname)));
3036+
}
3037+
else
3038+
{
3039+
if (restdef->generated)
3040+
ereport(ERROR,
3041+
(errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3042+
errmsg("child column \"%s\" specifies generation expression",
3043+
restdef->colname),
3044+
errhint("A child table column cannot be generated unless its parent column is.")));
3045+
}
30293046

30303047
/*
30313048
* Override the parent's default value for this column

src/test/regress/expected/generated.out

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,10 +730,26 @@ CREATE TABLE gtest_child PARTITION OF gtest_parent
730730
CREATE TABLE gtest_child2 PARTITION OF gtest_parent (
731731
f3 WITH OPTIONS GENERATED ALWAYS AS (f2 * 22) STORED -- overrides gen expr
732732
) FOR VALUES FROM ('2016-08-01') TO ('2016-09-01');
733+
CREATE TABLE gtest_child3 PARTITION OF gtest_parent (
734+
f3 DEFAULT 42 -- error
735+
) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01');
736+
ERROR: column "f3" inherits from generated column but specifies default
737+
CREATE TABLE gtest_child3 PARTITION OF gtest_parent (
738+
f3 WITH OPTIONS GENERATED ALWAYS AS IDENTITY -- error
739+
) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01');
740+
ERROR: identity columns are not supported on partitions
733741
CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint);
734742
ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error
735743
ERROR: column "f3" in child table must be a generated column
736744
DROP TABLE gtest_child3;
745+
CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint DEFAULT 42);
746+
ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error
747+
ERROR: column "f3" in child table must be a generated column
748+
DROP TABLE gtest_child3;
749+
CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS IDENTITY);
750+
ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error
751+
ERROR: column "f3" in child table must be a generated column
752+
DROP TABLE gtest_child3;
737753
CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 33) STORED);
738754
ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01');
739755
\d gtest_child

src/test/regress/sql/generated.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,9 +390,21 @@ CREATE TABLE gtest_child PARTITION OF gtest_parent
390390
CREATE TABLE gtest_child2 PARTITION OF gtest_parent (
391391
f3 WITH OPTIONS GENERATED ALWAYS AS (f2 * 22) STORED -- overrides gen expr
392392
) FOR VALUES FROM ('2016-08-01') TO ('2016-09-01');
393+
CREATE TABLE gtest_child3 PARTITION OF gtest_parent (
394+
f3 DEFAULT 42 -- error
395+
) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01');
396+
CREATE TABLE gtest_child3 PARTITION OF gtest_parent (
397+
f3 WITH OPTIONS GENERATED ALWAYS AS IDENTITY -- error
398+
) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01');
393399
CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint);
394400
ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error
395401
DROP TABLE gtest_child3;
402+
CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint DEFAULT 42);
403+
ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error
404+
DROP TABLE gtest_child3;
405+
CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS IDENTITY);
406+
ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error
407+
DROP TABLE gtest_child3;
396408
CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 33) STORED);
397409
ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01');
398410
\d gtest_child

0 commit comments

Comments
 (0)