v01-17-july-use-appendShellString-to-append-file-names.noci

application/octet-stream

Filename: v01-17-july-use-appendShellString-to-append-file-names.noci
Type: application/octet-stream
Part: 0
Message: Re: Non-text mode for pg_dumpall
From 6ff7c873d4842c47da22666d7efaba7551fb110b Mon Sep 17 00:00:00 2001
From: Mahendra Singh Thalor <mahi6run@gmail.com>
Date: Thu, 17 Jul 2025 15:24:25 +0530
Subject: [PATCH] use appendShellString to append file names

---
 doc/src/sgml/ref/pg_restore.sgml |  6 ++-
 src/bin/pg_dump/pg_dumpall.c     | 67 ++++++++++++++++++--------------
 src/bin/pg_dump/pg_restore.c     | 28 +++++++------
 3 files changed, 60 insertions(+), 41 deletions(-)

diff --git a/doc/src/sgml/ref/pg_restore.sgml b/doc/src/sgml/ref/pg_restore.sgml
index b649bd3a5ae..f4eb31f2324 100644
--- a/doc/src/sgml/ref/pg_restore.sgml
+++ b/doc/src/sgml/ref/pg_restore.sgml
@@ -150,7 +150,9 @@ PostgreSQL documentation
         Access privileges for the database itself are also restored,
         unless <option>--no-acl</option> is specified.
         <option>--create</option> is required when restoring multiple databases
-        from an archive created by <application>pg_dumpall</application>.
+        from an archive created by <application>pg_dumpall</application> and if
+        database is already created, then this will restore database without any
+        error.
        </para>
 
        <para>
@@ -621,6 +623,8 @@ PostgreSQL documentation
        </para>
        <para>
         This option is only relevant when restoring from an archive made using <application>pg_dumpall</application>.
+        If there is no database connection exist, then <replaceable class="parameter">pattern</replaceable> will be considered
+        as <replaceable class="parameter">name</replaceable> only.
        </para>
       </listitem>
      </varlistentry>
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 3cbcad65c5f..746c1f073c2 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -1622,8 +1622,8 @@ dumpDatabases(PGconn *conn, ArchiveFormat archDumpFormat)
 {
 	PGresult   *res;
 	int			i;
-	char		db_subdir[MAXPGPATH];
-	char		dbfilepath[MAXPGPATH];
+	PQExpBufferData	db_subdir;
+	PQExpBufferData	dbfilepath;
 	FILE	   *map_file = NULL;
 
 	/*
@@ -1653,20 +1653,28 @@ dumpDatabases(PGconn *conn, ArchiveFormat archDumpFormat)
 	 */
 	if (archDumpFormat != archNull)
 	{
-		char		map_file_path[MAXPGPATH];
+		PQExpBufferData map_file_path;
 
-		snprintf(db_subdir, MAXPGPATH, "%s/databases", filename);
+		initPQExpBuffer(&db_subdir);
+		initPQExpBuffer(&dbfilepath);
+		initPQExpBuffer(&map_file_path);
+
+		appendShellString(&db_subdir, filename);
+		appendPQExpBufferChar(&db_subdir, '/');
+		appendPQExpBufferStr(&db_subdir, "databases");
 
 		/* Create a subdirectory with 'databases' name under main directory. */
-		if (mkdir(db_subdir, pg_dir_create_mode) != 0)
-			pg_fatal("could not create directory \"%s\": %m", db_subdir);
+		if (mkdir(db_subdir.data, pg_dir_create_mode) != 0)
+			pg_fatal("could not create directory \"%s\": %m", db_subdir.data);
 
-		snprintf(map_file_path, MAXPGPATH, "%s/map.dat", filename);
+		appendShellString(&map_file_path, filename);
+		appendPQExpBufferChar(&map_file_path, '/');
+		appendPQExpBufferStr(&map_file_path, "map.dat");
 
 		/* Create a map file (to store dboid and dbname) */
-		map_file = fopen(map_file_path, PG_BINARY_W);
+		map_file = fopen(map_file_path.data, PG_BINARY_W);
 		if (!map_file)
-			pg_fatal("could not open file \"%s\": %m", map_file_path);
+			pg_fatal("could not open file \"%s\": %m", map_file_path.data);
 	}
 
 	for (i = 0; i < PQntuples(res); i++)
@@ -1693,12 +1701,16 @@ dumpDatabases(PGconn *conn, ArchiveFormat archDumpFormat)
 		 */
 		if (archDumpFormat != archNull)
 		{
+			resetPQExpBuffer(&dbfilepath);
+
+			appendShellString(&dbfilepath, db_subdir.data);
+			appendPQExpBufferChar(&dbfilepath, '/');
+			appendShellString(&dbfilepath, oid);
+
 			if (archDumpFormat == archCustom)
-				snprintf(dbfilepath, MAXPGPATH, "\"%s\"/\"%s\".dmp", db_subdir, oid);
+				appendPQExpBufferStr(&dbfilepath, ".dmp");
 			else if (archDumpFormat == archTar)
-				snprintf(dbfilepath, MAXPGPATH, "\"%s\"/\"%s\".tar", db_subdir, oid);
-			else
-				snprintf(dbfilepath, MAXPGPATH, "\"%s\"/\"%s\"", db_subdir, oid);
+				appendPQExpBufferStr(&dbfilepath, ".tar");
 
 			/* Put one line entry for dboid and dbname in map file. */
 			fprintf(map_file, "%s %s\n", oid, dbname);
@@ -1731,23 +1743,20 @@ dumpDatabases(PGconn *conn, ArchiveFormat archDumpFormat)
 		if (filename)
 			fclose(OPF);
 
-		ret = runPgDump(dbname, create_opts, dbfilepath, archDumpFormat);
+		ret = runPgDump(dbname, create_opts, dbfilepath.data, archDumpFormat);
 		if (ret != 0)
 			pg_fatal("pg_dump failed on database \"%s\", exiting", dbname);
 
-		if (filename)
+		/*
+		 * For non-plain mode, no need to re-open file as only once we write
+		 * data into file.
+		 */
+		if (filename && archDumpFormat == archNull)
 		{
-			char		global_path[MAXPGPATH];
-
-			if (archDumpFormat != archNull)
-				snprintf(global_path, MAXPGPATH, "%s/global.dat", filename);
-			else
-				snprintf(global_path, MAXPGPATH, "%s", filename);
-
-			OPF = fopen(global_path, PG_BINARY_A);
+			OPF = fopen(filename, PG_BINARY_A);
 			if (!OPF)
 				pg_fatal("could not re-open the output file \"%s\": %m",
-						 global_path);
+						 filename);
 		}
 	}
 
@@ -1774,14 +1783,17 @@ runPgDump(const char *dbname, const char *create_opts, char *dbfile,
 	initPQExpBuffer(&connstrbuf);
 	initPQExpBuffer(&cmd);
 
+	printfPQExpBuffer(&cmd, "\"%s\" %s %s ", pg_dump_bin,
+			pgdumpopts->data, create_opts);
+
 	/*
 	 * If this is not a plain format dump, then append file name and dump
 	 * format to the pg_dump command to get archive dump.
 	 */
 	if (archDumpFormat != archNull)
 	{
-		printfPQExpBuffer(&cmd, "\"%s\" -f %s %s", pg_dump_bin,
-						  dbfile, create_opts);
+
+		printfPQExpBuffer(&cmd, " -f %s ", dbfile);
 
 		if (archDumpFormat == archDirectory)
 			appendPQExpBufferStr(&cmd, "  --format=directory ");
@@ -1792,9 +1804,6 @@ runPgDump(const char *dbname, const char *create_opts, char *dbfile,
 	}
 	else
 	{
-		printfPQExpBuffer(&cmd, "\"%s\" %s %s", pg_dump_bin,
-						  pgdumpopts->data, create_opts);
-
 		/*
 		 * If we have a filename, use the undocumented plain-append pg_dump
 		 * format.
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
index 6ef789cb06d..4bb10971884 100644
--- a/src/bin/pg_dump/pg_restore.c
+++ b/src/bin/pg_dump/pg_restore.c
@@ -1038,7 +1038,7 @@ get_dbname_oid_list_from_mfile(const char *dumpdirpath, SimplePtrList *dbname_oi
 {
 	StringInfoData linebuf;
 	FILE	   *pfile;
-	char		map_file_path[MAXPGPATH];
+	PQExpBufferData		map_file_path;
 	int			count = 0;
 
 
@@ -1052,13 +1052,16 @@ get_dbname_oid_list_from_mfile(const char *dumpdirpath, SimplePtrList *dbname_oi
 		return 0;
 	}
 
-	snprintf(map_file_path, MAXPGPATH, "%s/map.dat", dumpdirpath);
+	initPQExpBuffer(&map_file_path);
+	appendShellString(&map_file_path, dumpdirpath);
+	appendPQExpBufferChar(&map_file_path, '/');
+	appendPQExpBufferStr(&map_file_path, "map.dat");
 
 	/* Open map.dat file. */
-	pfile = fopen(map_file_path, PG_BINARY_R);
+	pfile = fopen(map_file_path.data, PG_BINARY_R);
 
 	if (pfile == NULL)
-		pg_fatal("could not open file \"%s\": %m", map_file_path);
+		pg_fatal("could not open file \"%s\": %m", map_file_path.data);
 
 	initStringInfo(&linebuf);
 
@@ -1086,11 +1089,11 @@ get_dbname_oid_list_from_mfile(const char *dumpdirpath, SimplePtrList *dbname_oi
 
 		/* Report error and exit if the file has any corrupted data. */
 		if (!OidIsValid(db_oid) || namelen <= 1)
-			pg_fatal("invalid entry in file \"%s\" on line %d", map_file_path,
+			pg_fatal("invalid entry in file \"%s\" on line %d", map_file_path.data,
 					 count + 1);
 
 		pg_log_info("found database \"%s\" (OID: %u) in file \"%s\"",
-					dbname, db_oid, map_file_path);
+					dbname, db_oid, map_file_path.data);
 
 		dbidname = pg_malloc(offsetof(DbOidName, str) + namelen + 1);
 		dbidname->oid = db_oid;
@@ -1306,20 +1309,23 @@ restore_all_databases(PGconn *conn, const char *dumpdirpath,
 static int
 process_global_sql_commands(PGconn *conn, const char *dumpdirpath, const char *outfile)
 {
-	char		global_file_path[MAXPGPATH];
+	PQExpBufferData		global_file_path;
 	PGresult   *result;
 	StringInfoData sqlstatement,
 				user_create;
 	FILE	   *pfile;
 	int			n_errors = 0;
 
-	snprintf(global_file_path, MAXPGPATH, "%s/global.dat", dumpdirpath);
+	initPQExpBuffer(&global_file_path);
+	appendShellString(&global_file_path, dumpdirpath);
+	appendPQExpBufferChar(&global_file_path, '/');
+	appendPQExpBufferStr(&global_file_path, "global.dat");
 
 	/* Open global.dat file. */
-	pfile = fopen(global_file_path, PG_BINARY_R);
+	pfile = fopen(global_file_path.data, PG_BINARY_R);
 
 	if (pfile == NULL)
-		pg_fatal("could not open file \"%s\": %m", global_file_path);
+		pg_fatal("could not open file \"%s\": %m", global_file_path.data);
 
 	/*
 	 * If outfile is given, then just copy all global.dat file data into
@@ -1369,7 +1375,7 @@ process_global_sql_commands(PGconn *conn, const char *dumpdirpath, const char *o
 	if (n_errors)
 		pg_log_warning(ngettext("ignored %d error in file \"%s\"",
 								"ignored %d errors in file \"%s\"", n_errors),
-					   n_errors, global_file_path);
+					   n_errors, global_file_path.data);
 	fclose(pfile);
 
 	return n_errors;
-- 
2.39.3