From 92608d497d779000077d13dae6c2064549c3785f Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <lic@highgo.com>
Date: Sat, 11 Oct 2025 13:13:32 +0800
Subject: [PATCH v1] Fixed a bug in pg_dump about determining NotNull

In determineNotNullFlags(), a check should be done against
tbinfo->notnull_islocal[j], but "[j]" was missing. However,
this bug cannot be actually fired, see the discussion.

This commit fixes the bug and adds a TAP test of determining
NotNull for pg_dump.

Author: Chao Li <lic@highgo.com>
Discussion: https://www.postgresql.org/message-id/CAEudQAo7ah%3D4TDheuEjtb0dsv6bHoK7uBNqv53Tsub2h-xBSJw%40mail.gmail.com
---
 src/bin/pg_dump/meson.build                  |  1 +
 src/bin/pg_dump/pg_dump.c                    |  2 +-
 src/bin/pg_dump/t/011_dump_determine_null.pl | 59 ++++++++++++++++++++
 3 files changed, 61 insertions(+), 1 deletion(-)
 create mode 100644 src/bin/pg_dump/t/011_dump_determine_null.pl

diff --git a/src/bin/pg_dump/meson.build b/src/bin/pg_dump/meson.build
index a2233b0a1b4..47225b818da 100644
--- a/src/bin/pg_dump/meson.build
+++ b/src/bin/pg_dump/meson.build
@@ -103,6 +103,7 @@ tests += {
       't/004_pg_dump_parallel.pl',
       't/005_pg_dump_filterfile.pl',
       't/010_dump_connstr.pl',
+      't/011_dump_determine_null.pl',
     ],
   },
 }
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 641bece12c7..9dc9396a34d 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -10074,7 +10074,7 @@ determineNotNullFlags(Archive *fout, PGresult *res, int r,
 			 */
 			if ((dopt->binary_upgrade &&
 				 !tbinfo->ispartition &&
-				 !tbinfo->notnull_islocal) ||
+				 !tbinfo->notnull_islocal[j]) ||
 				!PQgetisnull(res, r, i_notnull_comment))
 			{
 				tbinfo->notnull_constrs[j] =
diff --git a/src/bin/pg_dump/t/011_dump_determine_null.pl b/src/bin/pg_dump/t/011_dump_determine_null.pl
new file mode 100644
index 00000000000..11d93135dd8
--- /dev/null
+++ b/src/bin/pg_dump/t/011_dump_determine_null.pl
@@ -0,0 +1,59 @@
+# Copyright (c) 2021-2025, PostgreSQL Global Development Group
+
+use strict;
+use warnings FATAL => 'all';
+
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+my $tempdir   = PostgreSQL::Test::Utils::tempdir;
+my $node      = PostgreSQL::Test::Cluster->new('main');
+my $port      = $node->port;
+my $backupdir = $node->backup_dir;
+my $plainfile = "$backupdir/plain.sql";
+
+# Init & start the node (no extra args; follow conventions used by other tests)
+$node->init;
+$node->start;
+
+# Setup parent/child table for binary upgrade NOT NULL check
+$node->safe_psql('postgres', "CREATE TABLE parent_nn(a int NOT NULL, b int)");
+$node->safe_psql('postgres', "CREATE TABLE child_nn() INHERITS (parent_nn)");
+
+# Add a local NOT NULL to child column 'b'
+$node->safe_psql('postgres', "ALTER TABLE child_nn ALTER COLUMN b SET NOT NULL");
+
+# Do a schema-only pg_dump through the tap helper
+command_ok(
+    [
+        'pg_dump',
+        '--file' => $plainfile,
+        '--schema-only',
+		'--binary-upgrade',
+        '--port' => $port,
+        'postgres'
+    ],
+    'pg_dump schema-only succeeds'
+);
+
+# Read dump and assert expected NOT NULL markings
+my $dump = slurp_file($plainfile);
+
+# Check parent table that NOT NULL is there
+ok($dump =~ qr/CREATE TABLE public\.parent_nn\s*\(\s*a integer NOT NULL/m,
+   "parent NOT NULL column 'a' is there");
+
+# Check parent table that NULL-able is there
+ok($dump =~ qr/CREATE TABLE public\.parent_nn\s*\(\s*a.*,\s*b integer/m,
+   "parent NULL-able column 'b' is there");
+
+# Check child table that inherited NOT NULL is preserved
+ok($dump =~ qr/CREATE TABLE public\.child_nn\s*\(\s*a integer CONSTRAINT parent_nn_a_not_null NOT NULL/m,
+   "inherited NOT NULL column 'a' preserved");
+
+# Check child table that locally added NOT NULL is preserved
+ok($dump =~ qr/CREATE TABLE public\.child_nn\s*\(\s*a.*,\s*b integer NOT NULL/m,
+   "child local NOT NULL column 'b' preserved");
+
+done_testing();
-- 
2.39.5 (Apple Git-154)

