From 4b79a78ec9bc1886aa7e3fd9cefdf1a54a45cc77 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Tue, 25 Jul 2023 14:18:13 +0200
Subject: [PATCH v17 3/3] Have psql print the NOT NULL constraints on \d+

---
 contrib/test_decoding/expected/ddl.out        | 12 +++
 src/bin/psql/describe.c                       | 39 ++++++++
 src/test/regress/expected/create_table.out    |  6 ++
 .../regress/expected/create_table_like.out    | 10 ++
 src/test/regress/expected/foreign_data.out    | 97 +++++++++++++++++++
 src/test/regress/expected/generated.out       |  2 +
 src/test/regress/expected/identity.out        |  4 +
 src/test/regress/expected/publication.out     |  6 ++
 .../regress/expected/replica_identity.out     |  8 ++
 src/test/regress/expected/rowsecurity.out     |  2 +
 10 files changed, 186 insertions(+)

diff --git a/contrib/test_decoding/expected/ddl.out b/contrib/test_decoding/expected/ddl.out
index 5713b8ab1c..95a0722c33 100644
--- a/contrib/test_decoding/expected/ddl.out
+++ b/contrib/test_decoding/expected/ddl.out
@@ -492,6 +492,9 @@ WITH (user_catalog_table = true)
  options  | text[]  |           |          |                                                  | extended |              | 
 Indexes:
     "replication_metadata_pkey" PRIMARY KEY, btree (id)
+Not null constraints:
+    "replication_metadata_id_not_null" NOT NULL "id"
+    "replication_metadata_relation_not_null" NOT NULL "relation"
 Options: user_catalog_table=true
 
 INSERT INTO replication_metadata(relation, options)
@@ -506,6 +509,9 @@ ALTER TABLE replication_metadata RESET (user_catalog_table);
  options  | text[]  |           |          |                                                  | extended |              | 
 Indexes:
     "replication_metadata_pkey" PRIMARY KEY, btree (id)
+Not null constraints:
+    "replication_metadata_id_not_null" NOT NULL "id"
+    "replication_metadata_relation_not_null" NOT NULL "relation"
 
 INSERT INTO replication_metadata(relation, options)
 VALUES ('bar', ARRAY['a', 'b']);
@@ -519,6 +525,9 @@ ALTER TABLE replication_metadata SET (user_catalog_table = true);
  options  | text[]  |           |          |                                                  | extended |              | 
 Indexes:
     "replication_metadata_pkey" PRIMARY KEY, btree (id)
+Not null constraints:
+    "replication_metadata_id_not_null" NOT NULL "id"
+    "replication_metadata_relation_not_null" NOT NULL "relation"
 Options: user_catalog_table=true
 
 INSERT INTO replication_metadata(relation, options)
@@ -538,6 +547,9 @@ ALTER TABLE replication_metadata SET (user_catalog_table = false);
  rewritemeornot | integer |           |          |                                                  | plain    |              | 
 Indexes:
     "replication_metadata_pkey" PRIMARY KEY, btree (id)
+Not null constraints:
+    "replication_metadata_id_not_null" NOT NULL "id"
+    "replication_metadata_relation_not_null" NOT NULL "relation"
 Options: user_catalog_table=false
 
 INSERT INTO replication_metadata(relation, options)
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 45f6a86b87..d1dc8fa066 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -3050,6 +3050,45 @@ describeOneTableDetails(const char *schemaname,
 			}
 			PQclear(result);
 		}
+
+		/* If verbose, print NOT NULL constraints */
+		if (verbose)
+		{
+			printfPQExpBuffer(&buf,
+							  "SELECT co.conname, at.attname, co.connoinherit, co.conislocal\n"
+							  "FROM pg_catalog.pg_constraint co JOIN\n"
+							  "pg_catalog.pg_attribute at ON\n"
+							  "(at.attnum = co.conkey[1])\n"
+							  "WHERE co.contype = 'n' AND\n"
+							  "co.conrelid = '%s'::pg_catalog.regclass AND\n"
+							  "at.attrelid = '%s'::pg_catalog.regclass",
+							  oid,
+							  oid);
+
+			result = PSQLexec(buf.data);
+			if (!result)
+				goto error_return;
+			else
+				tuples = PQntuples(result);
+
+			if (tuples > 0)
+				printTableAddFooter(&cont, _("Not null constraints:"));
+
+			/* Might be an empty set - that's ok */
+			for (i = 0; i < tuples; i++)
+			{
+				printfPQExpBuffer(&buf, "    \"%s\" NOT NULL \"%s\"%s",
+								  PQgetvalue(result, i, 0),
+								  PQgetvalue(result, i, 1),
+								  PQgetvalue(result, i, 2)[0] == 't' ?
+								  " NO INHERIT" :
+								  PQgetvalue(result, i, 3)[0] == 'f' ?
+								  " (inherited)" : "");
+
+				printTableAddFooter(&cont, buf.data);
+			}
+			PQclear(result);
+		}
 	}
 
 	/* Get view_def if table is a view or materialized view */
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index 3e761f1328..3f6516c3f8 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -854,6 +854,8 @@ drop table test_part_coll_posix;
  b      | integer |           | not null | 1       | plain    |              | 
 Partition of: parted FOR VALUES IN ('b')
 Partition constraint: ((a IS NOT NULL) AND (a = 'b'::text))
+Not null constraints:
+    "part_b_b_not_null" NOT NULL "b"
 
 -- Both partition bound and partition key in describe output
 \d+ part_c
@@ -865,6 +867,8 @@ Partition constraint: ((a IS NOT NULL) AND (a = 'b'::text))
 Partition of: parted FOR VALUES IN ('c')
 Partition constraint: ((a IS NOT NULL) AND (a = 'c'::text))
 Partition key: RANGE (b)
+Not null constraints:
+    "part_c_b_not_null" NOT NULL "b"
 Partitions: part_c_1_10 FOR VALUES FROM (1) TO (10)
 
 -- a level-2 partition's constraint will include the parent's expressions
@@ -876,6 +880,8 @@ Partitions: part_c_1_10 FOR VALUES FROM (1) TO (10)
  b      | integer |           | not null | 0       | plain    |              | 
 Partition of: part_c FOR VALUES FROM (1) TO (10)
 Partition constraint: ((a IS NOT NULL) AND (a = 'c'::text) AND (b IS NOT NULL) AND (b >= 1) AND (b < 10))
+Not null constraints:
+    "part_c_b_not_null" NOT NULL "b" (inherited)
 
 -- Show partition count in the parent's describe output
 -- Tempted to include \d+ output listing partitions with bound info but
diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out
index 0ed94f1d2f..ecac822adb 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -333,6 +333,8 @@ CREATE TABLE ctlt12_storage (LIKE ctlt1 INCLUDING STORAGE, LIKE ctlt2 INCLUDING
  a      | text |           | not null |         | main     |              | 
  b      | text |           |          |         | extended |              | 
  c      | text |           |          |         | external |              | 
+Not null constraints:
+    "ctlt12_storage_a_not_null" NOT NULL "a"
 
 CREATE TABLE ctlt12_comments (LIKE ctlt1 INCLUDING COMMENTS, LIKE ctlt2 INCLUDING COMMENTS);
 \d+ ctlt12_comments
@@ -342,6 +344,8 @@ CREATE TABLE ctlt12_comments (LIKE ctlt1 INCLUDING COMMENTS, LIKE ctlt2 INCLUDIN
  a      | text |           | not null |         | extended |              | A
  b      | text |           |          |         | extended |              | B
  c      | text |           |          |         | extended |              | C
+Not null constraints:
+    "ctlt12_comments_a_not_null" NOT NULL "a"
 
 CREATE TABLE ctlt1_inh (LIKE ctlt1 INCLUDING CONSTRAINTS INCLUDING COMMENTS) INHERITS (ctlt1);
 NOTICE:  merging column "a" with inherited definition
@@ -355,6 +359,8 @@ NOTICE:  merging constraint "ctlt1_a_check" with inherited definition
  b      | text |           |          |         | extended |              | B
 Check constraints:
     "ctlt1_a_check" CHECK (length(a) > 2)
+Not null constraints:
+    "ctlt1_inh_a_not_null" NOT NULL "a"
 Inherits: ctlt1
 
 SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 'ctlt1_inh'::regclass;
@@ -376,6 +382,8 @@ Check constraints:
     "ctlt1_a_check" CHECK (length(a) > 2)
     "ctlt3_a_check" CHECK (length(a) < 5)
     "ctlt3_c_check" CHECK (length(c) < 7)
+Not null constraints:
+    "ctlt13_inh_a_not_null" NOT NULL "a" (inherited)
 Inherits: ctlt1,
           ctlt3
 
@@ -394,6 +402,8 @@ Check constraints:
     "ctlt1_a_check" CHECK (length(a) > 2)
     "ctlt3_a_check" CHECK (length(a) < 5)
     "ctlt3_c_check" CHECK (length(c) < 7)
+Not null constraints:
+    "ctlt13_like_a_not_null" NOT NULL "a" (inherited)
 Inherits: ctlt1
 
 SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 'ctlt13_like'::regclass;
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index e90f4f846b..5b242081ae 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -742,6 +742,8 @@ COMMENT ON COLUMN ft1.c1 IS 'ft1.c1';
 Check constraints:
     "ft1_c2_check" CHECK (c2 <> ''::text)
     "ft1_c3_check" CHECK (c3 >= '01-01-1994'::date AND c3 <= '01-31-1994'::date)
+Not null constraints:
+    "ft1_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 
@@ -864,6 +866,9 @@ ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET STORAGE PLAIN;
 Check constraints:
     "ft1_c2_check" CHECK (c2 <> ''::text)
     "ft1_c3_check" CHECK (c3 >= '01-01-1994'::date AND c3 <= '01-31-1994'::date)
+Not null constraints:
+    "ft1_c1_not_null" NOT NULL "c1"
+    "ft1_c6_not_null" NOT NULL "c6"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 
@@ -1404,6 +1409,8 @@ CREATE FOREIGN TABLE ft2 () INHERITS (fd_pt1)
  c1     | integer |           | not null |         | plain    |              | 
  c2     | text    |           |          |         | extended |              | 
  c3     | date    |           |          |         | plain    |              | 
+Not null constraints:
+    "fd_pt1_c1_not_null" NOT NULL "c1"
 Child tables: ft2, FOREIGN
 
 \d+ ft2
@@ -1413,6 +1420,8 @@ Child tables: ft2, FOREIGN
  c1     | integer |           | not null |         |             | plain    |              | 
  c2     | text    |           |          |         |             | extended |              | 
  c3     | date    |           |          |         |             | plain    |              | 
+Not null constraints:
+    "fd_pt1_c1_not_null" NOT NULL "c1" (inherited)
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 Inherits: fd_pt1
@@ -1425,6 +1434,8 @@ DROP FOREIGN TABLE ft2;
  c1     | integer |           | not null |         | plain    |              | 
  c2     | text    |           |          |         | extended |              | 
  c3     | date    |           |          |         | plain    |              | 
+Not null constraints:
+    "fd_pt1_c1_not_null" NOT NULL "c1"
 
 CREATE FOREIGN TABLE ft2 (
 	c1 integer NOT NULL,
@@ -1438,6 +1449,8 @@ CREATE FOREIGN TABLE ft2 (
  c1     | integer |           | not null |         |             | plain    |              | 
  c2     | text    |           |          |         |             | extended |              | 
  c3     | date    |           |          |         |             | plain    |              | 
+Not null constraints:
+    "ft2_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 
@@ -1449,6 +1462,8 @@ ALTER FOREIGN TABLE ft2 INHERIT fd_pt1;
  c1     | integer |           | not null |         | plain    |              | 
  c2     | text    |           |          |         | extended |              | 
  c3     | date    |           |          |         | plain    |              | 
+Not null constraints:
+    "fd_pt1_c1_not_null" NOT NULL "c1"
 Child tables: ft2, FOREIGN
 
 \d+ ft2
@@ -1458,6 +1473,8 @@ Child tables: ft2, FOREIGN
  c1     | integer |           | not null |         |             | plain    |              | 
  c2     | text    |           |          |         |             | extended |              | 
  c3     | date    |           |          |         |             | plain    |              | 
+Not null constraints:
+    "ft2_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 Inherits: fd_pt1
@@ -1479,6 +1496,8 @@ NOTICE:  merging column "c3" with inherited definition
  c1     | integer |           | not null |         |             | plain    |              | 
  c2     | text    |           |          |         |             | extended |              | 
  c3     | date    |           |          |         |             | plain    |              | 
+Not null constraints:
+    "ft2_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 Inherits: fd_pt1
@@ -1492,6 +1511,8 @@ Child tables: ct3,
  c1     | integer |           | not null |         | plain    |              | 
  c2     | text    |           |          |         | extended |              | 
  c3     | date    |           |          |         | plain    |              | 
+Not null constraints:
+    "ft2_c1_not_null" NOT NULL "c1" (inherited)
 Inherits: ft2
 
 \d+ ft3
@@ -1501,6 +1522,8 @@ Inherits: ft2
  c1     | integer |           | not null |         |             | plain    |              | 
  c2     | text    |           |          |         |             | extended |              | 
  c3     | date    |           |          |         |             | plain    |              | 
+Not null constraints:
+    "ft3_c1_not_null" NOT NULL "c1"
 Server: s0
 Inherits: ft2
 
@@ -1522,6 +1545,9 @@ ALTER TABLE fd_pt1 ADD COLUMN c8 integer;
  c6     | integer |           |          |         | plain    |              | 
  c7     | integer |           | not null |         | plain    |              | 
  c8     | integer |           |          |         | plain    |              | 
+Not null constraints:
+    "fd_pt1_c1_not_null" NOT NULL "c1"
+    "fd_pt1_c7_not_null" NOT NULL "c7"
 Child tables: ft2, FOREIGN
 
 \d+ ft2
@@ -1536,6 +1562,9 @@ Child tables: ft2, FOREIGN
  c6     | integer |           |          |         |             | plain    |              | 
  c7     | integer |           | not null |         |             | plain    |              | 
  c8     | integer |           |          |         |             | plain    |              | 
+Not null constraints:
+    "fd_pt1_c7_not_null" NOT NULL "c7" (inherited)
+    "ft2_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 Inherits: fd_pt1
@@ -1554,6 +1583,9 @@ Child tables: ct3,
  c6     | integer |           |          |         | plain    |              | 
  c7     | integer |           | not null |         | plain    |              | 
  c8     | integer |           |          |         | plain    |              | 
+Not null constraints:
+    "fd_pt1_c7_not_null" NOT NULL "c7" (inherited)
+    "ft2_c1_not_null" NOT NULL "c1" (inherited)
 Inherits: ft2
 
 \d+ ft3
@@ -1568,6 +1600,9 @@ Inherits: ft2
  c6     | integer |           |          |         |             | plain    |              | 
  c7     | integer |           | not null |         |             | plain    |              | 
  c8     | integer |           |          |         |             | plain    |              | 
+Not null constraints:
+    "fd_pt1_c7_not_null" NOT NULL "c7" (inherited)
+    "ft3_c1_not_null" NOT NULL "c1"
 Server: s0
 Inherits: ft2
 
@@ -1596,6 +1631,9 @@ ALTER TABLE fd_pt1 ALTER COLUMN c8 SET STORAGE EXTERNAL;
  c6     | integer |           | not null |         | plain    |              | 
  c7     | integer |           |          |         | plain    |              | 
  c8     | text    |           |          |         | external |              | 
+Not null constraints:
+    "fd_pt1_c1_not_null" NOT NULL "c1"
+    "fd_pt1_c6_not_null" NOT NULL "c6"
 Child tables: ft2, FOREIGN
 
 \d+ ft2
@@ -1610,6 +1648,9 @@ Child tables: ft2, FOREIGN
  c6     | integer |           | not null |         |             | plain    |              | 
  c7     | integer |           |          |         |             | plain    |              | 
  c8     | text    |           |          |         |             | external |              | 
+Not null constraints:
+    "fd_pt1_c6_not_null" NOT NULL "c6" (inherited)
+    "ft2_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 Inherits: fd_pt1
@@ -1629,6 +1670,8 @@ ALTER TABLE fd_pt1 DROP COLUMN c8;
  c1     | integer |           | not null |         | plain    | 10000        | 
  c2     | text    |           |          |         | extended |              | 
  c3     | date    |           |          |         | plain    |              | 
+Not null constraints:
+    "fd_pt1_c1_not_null" NOT NULL "c1"
 Child tables: ft2, FOREIGN
 
 \d+ ft2
@@ -1638,6 +1681,8 @@ Child tables: ft2, FOREIGN
  c1     | integer |           | not null |         |             | plain    | 10000        | 
  c2     | text    |           |          |         |             | extended |              | 
  c3     | date    |           |          |         |             | plain    |              | 
+Not null constraints:
+    "ft2_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 Inherits: fd_pt1
@@ -1670,6 +1715,8 @@ SELECT relname, conname, contype, conislocal, coninhcount, connoinherit
 Check constraints:
     "fd_pt1chk1" CHECK (c1 > 0) NO INHERIT
     "fd_pt1chk2" CHECK (c2 <> ''::text)
+Not null constraints:
+    "fd_pt1_c1_not_null" NOT NULL "c1"
 Child tables: ft2, FOREIGN
 
 \d+ ft2
@@ -1681,6 +1728,8 @@ Child tables: ft2, FOREIGN
  c3     | date    |           |          |         |             | plain    |              | 
 Check constraints:
     "fd_pt1chk2" CHECK (c2 <> ''::text)
+Not null constraints:
+    "ft2_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 Inherits: fd_pt1
@@ -1717,6 +1766,8 @@ ALTER FOREIGN TABLE ft2 INHERIT fd_pt1;
 Check constraints:
     "fd_pt1chk1" CHECK (c1 > 0) NO INHERIT
     "fd_pt1chk2" CHECK (c2 <> ''::text)
+Not null constraints:
+    "fd_pt1_c1_not_null" NOT NULL "c1"
 Child tables: ft2, FOREIGN
 
 \d+ ft2
@@ -1728,6 +1779,8 @@ Child tables: ft2, FOREIGN
  c3     | date    |           |          |         |             | plain    |              | 
 Check constraints:
     "fd_pt1chk2" CHECK (c2 <> ''::text)
+Not null constraints:
+    "ft2_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 Inherits: fd_pt1
@@ -1747,6 +1800,8 @@ ALTER TABLE fd_pt1 ADD CONSTRAINT fd_pt1chk3 CHECK (c2 <> '') NOT VALID;
  c3     | date    |           |          |         | plain    |              | 
 Check constraints:
     "fd_pt1chk3" CHECK (c2 <> ''::text) NOT VALID
+Not null constraints:
+    "fd_pt1_c1_not_null" NOT NULL "c1"
 Child tables: ft2, FOREIGN
 
 \d+ ft2
@@ -1759,6 +1814,8 @@ Child tables: ft2, FOREIGN
 Check constraints:
     "fd_pt1chk2" CHECK (c2 <> ''::text)
     "fd_pt1chk3" CHECK (c2 <> ''::text) NOT VALID
+Not null constraints:
+    "ft2_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 Inherits: fd_pt1
@@ -1774,6 +1831,8 @@ ALTER TABLE fd_pt1 VALIDATE CONSTRAINT fd_pt1chk3;
  c3     | date    |           |          |         | plain    |              | 
 Check constraints:
     "fd_pt1chk3" CHECK (c2 <> ''::text)
+Not null constraints:
+    "fd_pt1_c1_not_null" NOT NULL "c1"
 Child tables: ft2, FOREIGN
 
 \d+ ft2
@@ -1786,6 +1845,8 @@ Child tables: ft2, FOREIGN
 Check constraints:
     "fd_pt1chk2" CHECK (c2 <> ''::text)
     "fd_pt1chk3" CHECK (c2 <> ''::text)
+Not null constraints:
+    "ft2_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 Inherits: fd_pt1
@@ -1805,6 +1866,8 @@ ALTER TABLE fd_pt1 RENAME CONSTRAINT fd_pt1chk3 TO f2_check;
  f3     | date    |           |          |         | plain    |              | 
 Check constraints:
     "f2_check" CHECK (f2 <> ''::text)
+Not null constraints:
+    "fd_pt1_c1_not_null" NOT NULL "f1"
 Child tables: ft2, FOREIGN
 
 \d+ ft2
@@ -1817,6 +1880,8 @@ Child tables: ft2, FOREIGN
 Check constraints:
     "f2_check" CHECK (f2 <> ''::text)
     "fd_pt1chk2" CHECK (f2 <> ''::text)
+Not null constraints:
+    "ft2_c1_not_null" NOT NULL "f1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 Inherits: fd_pt1
@@ -1863,6 +1928,8 @@ CREATE FOREIGN TABLE fd_pt2_1 PARTITION OF fd_pt2 FOR VALUES IN (1)
  c2     | text    |           |          |         | extended |              | 
  c3     | date    |           |          |         | plain    |              | 
 Partition key: LIST (c1)
+Not null constraints:
+    "fd_pt2_c1_not_null" NOT NULL "c1"
 Partitions: fd_pt2_1 FOR VALUES IN (1), FOREIGN
 
 \d+ fd_pt2_1
@@ -1874,6 +1941,8 @@ Partitions: fd_pt2_1 FOR VALUES IN (1), FOREIGN
  c3     | date    |           |          |         |             | plain    |              | 
 Partition of: fd_pt2 FOR VALUES IN (1)
 Partition constraint: ((c1 IS NOT NULL) AND (c1 = 1))
+Not null constraints:
+    "fd_pt2_c1_not_null" NOT NULL "c1" (inherited)
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 
@@ -1893,6 +1962,8 @@ CREATE FOREIGN TABLE fd_pt2_1 (
  c2     | text         |           |          |         |             | extended |              | 
  c3     | date         |           |          |         |             | plain    |              | 
  c4     | character(1) |           |          |         |             | extended |              | 
+Not null constraints:
+    "fd_pt2_1_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 
@@ -1908,6 +1979,8 @@ DROP FOREIGN TABLE fd_pt2_1;
  c2     | text    |           |          |         | extended |              | 
  c3     | date    |           |          |         | plain    |              | 
 Partition key: LIST (c1)
+Not null constraints:
+    "fd_pt2_c1_not_null" NOT NULL "c1"
 Number of partitions: 0
 
 CREATE FOREIGN TABLE fd_pt2_1 (
@@ -1922,6 +1995,8 @@ CREATE FOREIGN TABLE fd_pt2_1 (
  c1     | integer |           | not null |         |             | plain    |              | 
  c2     | text    |           |          |         |             | extended |              | 
  c3     | date    |           |          |         |             | plain    |              | 
+Not null constraints:
+    "fd_pt2_1_c1_not_null" NOT NULL "c1"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 
@@ -1935,6 +2010,8 @@ ALTER TABLE fd_pt2 ATTACH PARTITION fd_pt2_1 FOR VALUES IN (1);
  c2     | text    |           |          |         | extended |              | 
  c3     | date    |           |          |         | plain    |              | 
 Partition key: LIST (c1)
+Not null constraints:
+    "fd_pt2_c1_not_null" NOT NULL "c1"
 Partitions: fd_pt2_1 FOR VALUES IN (1), FOREIGN
 
 \d+ fd_pt2_1
@@ -1946,6 +2023,8 @@ Partitions: fd_pt2_1 FOR VALUES IN (1), FOREIGN
  c3     | date    |           |          |         |             | plain    |              | 
 Partition of: fd_pt2 FOR VALUES IN (1)
 Partition constraint: ((c1 IS NOT NULL) AND (c1 = 1))
+Not null constraints:
+    "fd_pt2_1_c1_not_null" NOT NULL "c1" (inherited)
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 
@@ -1963,6 +2042,8 @@ ALTER TABLE fd_pt2_1 ADD CONSTRAINT p21chk CHECK (c2 <> '');
  c2     | text    |           |          |         | extended |              | 
  c3     | date    |           |          |         | plain    |              | 
 Partition key: LIST (c1)
+Not null constraints:
+    "fd_pt2_c1_not_null" NOT NULL "c1"
 Partitions: fd_pt2_1 FOR VALUES IN (1), FOREIGN
 
 \d+ fd_pt2_1
@@ -1976,6 +2057,9 @@ Partition of: fd_pt2 FOR VALUES IN (1)
 Partition constraint: ((c1 IS NOT NULL) AND (c1 = 1))
 Check constraints:
     "p21chk" CHECK (c2 <> ''::text)
+Not null constraints:
+    "fd_pt2_1_c1_not_null" NOT NULL "c1" (inherited)
+    "fd_pt2_1_c3_not_null" NOT NULL "c3"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 
@@ -1993,6 +2077,9 @@ ALTER TABLE fd_pt2 ALTER c2 SET NOT NULL;
  c2     | text    |           | not null |         | extended |              | 
  c3     | date    |           |          |         | plain    |              | 
 Partition key: LIST (c1)
+Not null constraints:
+    "fd_pt2_c1_not_null" NOT NULL "c1"
+    "fd_pt2_c2_not_null" NOT NULL "c2"
 Number of partitions: 0
 
 \d+ fd_pt2_1
@@ -2004,6 +2091,9 @@ Number of partitions: 0
  c3     | date    |           | not null |         |             | plain    |              | 
 Check constraints:
     "p21chk" CHECK (c2 <> ''::text)
+Not null constraints:
+    "fd_pt2_1_c1_not_null" NOT NULL "c1"
+    "fd_pt2_1_c3_not_null" NOT NULL "c3"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 
@@ -2023,6 +2113,9 @@ ALTER TABLE fd_pt2 ADD CONSTRAINT fd_pt2chk1 CHECK (c1 > 0);
 Partition key: LIST (c1)
 Check constraints:
     "fd_pt2chk1" CHECK (c1 > 0)
+Not null constraints:
+    "fd_pt2_c1_not_null" NOT NULL "c1"
+    "fd_pt2_c2_not_null" NOT NULL "c2"
 Number of partitions: 0
 
 \d+ fd_pt2_1
@@ -2034,6 +2127,10 @@ Number of partitions: 0
  c3     | date    |           | not null |         |             | plain    |              | 
 Check constraints:
     "p21chk" CHECK (c2 <> ''::text)
+Not null constraints:
+    "fd_pt2_1_c1_not_null" NOT NULL "c1"
+    "fd_pt2_1_c2_not_null" NOT NULL "c2"
+    "fd_pt2_1_c3_not_null" NOT NULL "c3"
 Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 
diff --git a/src/test/regress/expected/generated.out b/src/test/regress/expected/generated.out
index f5d802b9d1..930c5790fb 100644
--- a/src/test/regress/expected/generated.out
+++ b/src/test/regress/expected/generated.out
@@ -315,6 +315,8 @@ NOTICE:  merging column "b" with inherited definition
  a      | integer |           | not null |                                     | plain   |              | 
  b      | integer |           |          | generated always as (a * 22) stored | plain   |              | 
  x      | integer |           |          |                                     | plain   |              | 
+Not null constraints:
+    "gtestx_a_not_null" NOT NULL "a" (inherited)
 Inherits: gtest1
 
 CREATE TABLE gtestxx_1 (a int NOT NULL, b int);
diff --git a/src/test/regress/expected/identity.out b/src/test/regress/expected/identity.out
index 5f03d8e14f..733dda74b9 100644
--- a/src/test/regress/expected/identity.out
+++ b/src/test/regress/expected/identity.out
@@ -506,6 +506,10 @@ TABLE itest8;
  f3     | integer |           | not null | generated by default as identity | plain   |              | 
  f4     | bigint  |           | not null | generated always as identity     | plain   |              | 
  f5     | bigint  |           |          |                                  | plain   |              | 
+Not null constraints:
+    "itest8_f2_not_null" NOT NULL "f2"
+    "itest8_f3_not_null" NOT NULL "f3"
+    "itest8_f4_not_null" NOT NULL "f4"
 
 \d itest8_f2_seq
                    Sequence "public.itest8_f2_seq"
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 69dc6cfd85..f0ccc39630 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -193,6 +193,8 @@ Indexes:
     "testpub_tbl2_pkey" PRIMARY KEY, btree (id)
 Publications:
     "testpub_foralltables"
+Not null constraints:
+    "testpub_tbl2_id_not_null" NOT NULL "id"
 
 \dRp+ testpub_foralltables
                               Publication testpub_foralltables
@@ -1147,6 +1149,8 @@ Publications:
     "testpib_ins_trunct"
     "testpub_default"
     "testpub_fortbl"
+Not null constraints:
+    "testpub_tbl1_id_not_null" NOT NULL "id"
 
 \dRp+ testpub_default
                                 Publication testpub_default
@@ -1172,6 +1176,8 @@ Indexes:
 Publications:
     "testpib_ins_trunct"
     "testpub_fortbl"
+Not null constraints:
+    "testpub_tbl1_id_not_null" NOT NULL "id"
 
 -- verify relation cache invalidation when a primary key is added using
 -- an existing index
diff --git a/src/test/regress/expected/replica_identity.out b/src/test/regress/expected/replica_identity.out
index 0a62b28823..4d4cb95732 100644
--- a/src/test/regress/expected/replica_identity.out
+++ b/src/test/regress/expected/replica_identity.out
@@ -170,6 +170,10 @@ Indexes:
     "test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
     "test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
     "test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
+Not null constraints:
+    "test_replica_identity_id_not_null" NOT NULL "id"
+    "test_replica_identity_keya_not_null" NOT NULL "keya"
+    "test_replica_identity_keyb_not_null" NOT NULL "keyb"
 Replica Identity: FULL
 
 ALTER TABLE test_replica_identity REPLICA IDENTITY NOTHING;
@@ -252,6 +256,8 @@ ALTER TABLE ONLY test_replica_identity4_1
 Partition key: LIST (id)
 Indexes:
     "test_replica_identity4_pkey" PRIMARY KEY, btree (id) INVALID REPLICA IDENTITY
+Not null constraints:
+    "test_replica_identity4_id_not_null" NOT NULL "id"
 Partitions: test_replica_identity4_1 FOR VALUES IN (1)
 
 ALTER INDEX test_replica_identity4_pkey
@@ -264,6 +270,8 @@ ALTER INDEX test_replica_identity4_pkey
 Partition key: LIST (id)
 Indexes:
     "test_replica_identity4_pkey" PRIMARY KEY, btree (id) REPLICA IDENTITY
+Not null constraints:
+    "test_replica_identity4_id_not_null" NOT NULL "id"
 Partitions: test_replica_identity4_1 FOR VALUES IN (1)
 
 -- Dropping the primary key is not allowed if that would leave the replica
diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out
index 97ca9bf72c..0e45c03d43 100644
--- a/src/test/regress/expected/rowsecurity.out
+++ b/src/test/regress/expected/rowsecurity.out
@@ -955,6 +955,8 @@ Policies:
     POLICY "pp1r" AS RESTRICTIVE
       TO regress_rls_dave
       USING ((cid < 55))
+Not null constraints:
+    "part_document_dlevel_not_null" NOT NULL "dlevel"
 Partitions: part_document_fiction FOR VALUES FROM (11) TO (12),
             part_document_nonfiction FOR VALUES FROM (99) TO (100),
             part_document_satire FOR VALUES FROM (55) TO (56)
-- 
2.39.2

