From 99135eec747b0f115b8fbdbf092c85808a70da85 Mon Sep 17 00:00:00 2001
From: Yugo Nagata <nagata@sraoss.co.jp>
Date: Thu, 30 Aug 2018 18:48:00 +0900
Subject: [PATCH] Allow pg_verify_checksums to specify a database to scan

---
 doc/src/sgml/ref/pg_verify_checksums.sgml     | 20 +++++++++++
 .../pg_verify_checksums/pg_verify_checksums.c | 35 ++++++++++++++++---
 2 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/doc/src/sgml/ref/pg_verify_checksums.sgml b/doc/src/sgml/ref/pg_verify_checksums.sgml
index 3a3433b1c8..782cf35ca0 100644
--- a/doc/src/sgml/ref/pg_verify_checksums.sgml
+++ b/doc/src/sgml/ref/pg_verify_checksums.sgml
@@ -70,6 +70,26 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>-d <replaceable>oid</replaceable></option></term>
+      <term><option>--dboid=<replaceable>oid</replaceable></option></term>
+      <listitem>
+       <para>
+        Only validate checksums in the relations in the database with specified OID.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-g</option></term>
+      <term><option>--globel-only</option></term>
+      <listitem>
+       <para>
+        Only validate checksums in the relations in the shared database.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-r <replaceable>relfilenode</replaceable></option></term>
       <listitem>
diff --git a/src/bin/pg_verify_checksums/pg_verify_checksums.c b/src/bin/pg_verify_checksums/pg_verify_checksums.c
index 1eb3bed2b9..0b9c03ac30 100644
--- a/src/bin/pg_verify_checksums/pg_verify_checksums.c
+++ b/src/bin/pg_verify_checksums/pg_verify_checksums.c
@@ -31,6 +31,8 @@ static int64 badblocks = 0;
 static ControlFileData *ControlFile;
 
 static char *only_relfilenode = NULL;
+static char *only_dboid = NULL;
+static bool only_global = false;
 static bool verbose = false;
 
 static const char *progname;
@@ -44,6 +46,8 @@ usage()
 	printf(_("\nOptions:\n"));
 	printf(_(" [-D, --pgdata=]DATADIR  data directory\n"));
 	printf(_("  -v, --verbose          output verbose messages, list all checked files\n"));
+	printf(_("  -d, --dboid=OID        check only relations in database with specified OID\n"));
+	printf(_("  -g, --global-only      check only shared relations\n"));
 	printf(_("  -r RELFILENODE         check only relation with specified relfilenode\n"));
 	printf(_("  -V, --version          output version information, then exit\n"));
 	printf(_("  -?, --help             show this help, then exit\n"));
@@ -198,7 +202,13 @@ scan_directory(char *basedir, char *subdir)
 #else
 		else if (S_ISDIR(st.st_mode) || pgwin32_is_junction(fn))
 #endif
+		{
+			if (atoi(de->d_name) != 0 && strcmp(subdir, "pg_tblspc") &&
+				only_dboid && strcmp(only_dboid, de->d_name) != 0)
+				continue;
+
 			scan_directory(path, de->d_name);
+		}
 	}
 	closedir(dir);
 }
@@ -208,6 +218,8 @@ main(int argc, char *argv[])
 {
 	static struct option long_options[] = {
 		{"pgdata", required_argument, NULL, 'D'},
+		{"dboid", required_argument, NULL, 'd'},
+		{"global-only", no_argument, NULL, 'g'},
 		{"verbose", no_argument, NULL, 'v'},
 		{NULL, 0, NULL, 0}
 	};
@@ -235,7 +247,7 @@ main(int argc, char *argv[])
 		}
 	}
 
-	while ((c = getopt_long(argc, argv, "D:r:v", long_options, &option_index)) != -1)
+	while ((c = getopt_long(argc, argv, "D:r:d:gv", long_options, &option_index)) != -1)
 	{
 		switch (c)
 		{
@@ -253,6 +265,17 @@ main(int argc, char *argv[])
 				}
 				only_relfilenode = pstrdup(optarg);
 				break;
+			case 'd':
+				if (atoi(optarg) <= 0)
+				{
+					fprintf(stderr, _("%s: invalid database oid specification, must be numeric: %s\n"), progname, optarg);
+					exit(1);
+				}
+				only_dboid = pstrdup(optarg);
+				break;
+			case 'g':
+				only_global = true;
+				break;
 			default:
 				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
 				exit(1);
@@ -307,9 +330,13 @@ main(int argc, char *argv[])
 	}
 
 	/* Scan all files */
-	scan_directory(DataDir, "global");
-	scan_directory(DataDir, "base");
-	scan_directory(DataDir, "pg_tblspc");
+	if (!only_dboid)
+		scan_directory(DataDir, "global");
+	if (!only_global)
+	{
+		scan_directory(DataDir, "base");
+		scan_directory(DataDir, "pg_tblspc");
+	}
 
 	printf(_("Checksum scan completed\n"));
 	printf(_("Data checksum version: %d\n"), ControlFile->data_checksum_version);
-- 
2.17.1

