From 5c068038ff69469c7ba7c6b88da27ed734ee4ad1 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 24 Apr 2008 20:17:50 +0000
Subject: [PATCH] Fix ALTER TABLE ADD COLUMN ... PRIMARY KEY so that the new
 column is correctly checked to see if it's been initialized to all non-nulls.
  The implicit NOT NULL constraint was not being checked during the ALTER (in
 fact, not even if there was an explicit NOT NULL too), because
 ATExecAddColumn neglected to set the flag needed to make the test happen. 
 This has been broken since the capability was first added, in 8.0.

Brendan Jurd, per a report from Kaloyan Iliev.
---
 src/backend/commands/tablecmds.c          |  7 ++++++-
 src/test/regress/expected/alter_table.out | 12 ++++++++++++
 src/test/regress/sql/alter_table.sql      | 10 ++++++++++
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index b507f17b7b6..9d6939bbc11 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.250 2008/03/31 03:34:27 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.251 2008/04/24 20:17:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3332,6 +3332,11 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
 		tab->newvals = lappend(tab->newvals, newval);
 	}
 
+	/*
+	 * If the new column is NOT NULL, tell Phase 3 it needs to test that.
+	 */
+	tab->new_notnull |= colDef->is_not_null;
+
 	/*
 	 * Add needed dependency entries for the new column.
 	 */
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index cba489d1d86..51d5afa81fd 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -505,6 +505,18 @@ create table atacc1 ( test int );
 alter table atacc1 add constraint atacc_test1 primary key (test1);
 ERROR:  column "test1" named in key does not exist
 drop table atacc1;
+-- adding a new column as primary key to a non-empty table.
+-- should fail unless the column has a non-null default value.
+create table atacc1 ( test int );
+insert into atacc1 (test) values (0);
+-- add a primary key column without a default (fails).
+alter table atacc1 add column test2 int primary key;
+NOTICE:  ALTER TABLE / ADD PRIMARY KEY will create implicit index "atacc1_pkey" for table "atacc1"
+ERROR:  column "test2" contains null values
+-- now add a primary key column with a default (succeeds).
+alter table atacc1 add column test2 int default 0 primary key;
+NOTICE:  ALTER TABLE / ADD PRIMARY KEY will create implicit index "atacc1_pkey" for table "atacc1"
+drop table atacc1;
 -- something a little more complicated
 create table atacc1 ( test int, test2 int);
 -- add a primary key constraint
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index d52d6c822e2..81cc70612d5 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -506,6 +506,16 @@ create table atacc1 ( test int );
 alter table atacc1 add constraint atacc_test1 primary key (test1);
 drop table atacc1;
 
+-- adding a new column as primary key to a non-empty table.
+-- should fail unless the column has a non-null default value.
+create table atacc1 ( test int );
+insert into atacc1 (test) values (0);
+-- add a primary key column without a default (fails).
+alter table atacc1 add column test2 int primary key;
+-- now add a primary key column with a default (succeeds).
+alter table atacc1 add column test2 int default 0 primary key;
+drop table atacc1;
+
 -- something a little more complicated
 create table atacc1 ( test int, test2 int);
 -- add a primary key constraint
-- 
GitLab