Skip to content

Commit 6c34f18

Browse files
committed
Forbid marking an identity column as nullable.
GENERATED ALWAYS AS IDENTITY implies NOT NULL, but the code failed to complain if you overrode that with "GENERATED ALWAYS AS IDENTITY NULL". One might think the old behavior was a feature, but it was inconsistent because the outcome varied depending on the order of the clauses, so it seems to have been just an oversight. Per bug #16913 from Pavel Boev. Back-patch to v10 where identity columns were introduced. Vik Fearing (minor tweaks by me) Discussion: https://postgr.es/m/16913-3b5198410f67d8c6@postgresql.org
1 parent ddd4cc0 commit 6c34f18

File tree

4 files changed

+33
-0
lines changed

4 files changed

+33
-0
lines changed

doc/src/sgml/ref/create_table.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,7 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
750750
column</firstterm>. It will have an implicit sequence attached to it
751751
and the column in new rows will automatically have values from the
752752
sequence assigned to it.
753+
Such a column is implicitly <literal>NOT NULL</literal>.
753754
</para>
754755

755756
<para>

src/backend/parser/parse_utilcmd.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,17 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
726726

727727
column->identity = constraint->generated_when;
728728
saw_identity = true;
729+
730+
/* An identity column is implicitly NOT NULL */
731+
if (saw_nullable && !column->is_not_null)
732+
ereport(ERROR,
733+
(errcode(ERRCODE_SYNTAX_ERROR),
734+
errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
735+
column->colname, cxt->relation->relname),
736+
parser_errposition(cxt->pstate,
737+
constraint->location)));
729738
column->is_not_null = true;
739+
saw_nullable = true;
730740
break;
731741
}
732742

src/test/regress/expected/identity.out

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,3 +386,16 @@ CREATE TABLE itest_child PARTITION OF itest_parent (
386386
) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- error
387387
ERROR: identity columns are not supported on partitions
388388
DROP TABLE itest_parent;
389+
-- Identity columns must be NOT NULL (cf bug #16913)
390+
CREATE TABLE itest15 (id integer GENERATED ALWAYS AS IDENTITY NULL); -- fail
391+
ERROR: conflicting NULL/NOT NULL declarations for column "id" of table "itest15"
392+
LINE 1: ...ABLE itest15 (id integer GENERATED ALWAYS AS IDENTITY NULL);
393+
^
394+
CREATE TABLE itest15 (id integer NULL GENERATED ALWAYS AS IDENTITY); -- fail
395+
ERROR: conflicting NULL/NOT NULL declarations for column "id" of table "itest15"
396+
LINE 1: CREATE TABLE itest15 (id integer NULL GENERATED ALWAYS AS ID...
397+
^
398+
CREATE TABLE itest15 (id integer GENERATED ALWAYS AS IDENTITY NOT NULL);
399+
DROP TABLE itest15;
400+
CREATE TABLE itest15 (id integer NOT NULL GENERATED ALWAYS AS IDENTITY);
401+
DROP TABLE itest15;

src/test/regress/sql/identity.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,12 @@ CREATE TABLE itest_child PARTITION OF itest_parent (
246246
f3 WITH OPTIONS GENERATED ALWAYS AS IDENTITY
247247
) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- error
248248
DROP TABLE itest_parent;
249+
250+
-- Identity columns must be NOT NULL (cf bug #16913)
251+
252+
CREATE TABLE itest15 (id integer GENERATED ALWAYS AS IDENTITY NULL); -- fail
253+
CREATE TABLE itest15 (id integer NULL GENERATED ALWAYS AS IDENTITY); -- fail
254+
CREATE TABLE itest15 (id integer GENERATED ALWAYS AS IDENTITY NOT NULL);
255+
DROP TABLE itest15;
256+
CREATE TABLE itest15 (id integer NOT NULL GENERATED ALWAYS AS IDENTITY);
257+
DROP TABLE itest15;

0 commit comments

Comments
 (0)