From 5c47c810568020830f9a44fa701d261bb91d1c3b Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Sun, 4 Feb 2024 18:32:16 +0100 Subject: [PATCH 2/2] WIP: pg_upgrade: No more "command too long" Use extensive buffers to assemble command lines instead of fixed size. Similar to the changes done for pg_rewind in a33e17f210. XXX requires exporting appendPQExpBufferVA() from libpq XXX should pg_upgrade be using StringInfo instead? --- src/bin/pg_upgrade/exec.c | 37 ++++++++++++++++---------------- src/interfaces/libpq/exports.txt | 1 + 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index fec8dc4c2f7..2ea231d6f62 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -13,6 +13,7 @@ #include "common/string.h" #include "pg_upgrade.h" +#include "pqexpbuffer.h" static void check_data_dir(ClusterInfo *cluster); static void check_bin_dir(ClusterInfo *cluster, bool check_versions); @@ -87,13 +88,11 @@ exec_prog(const char *log_filename, const char *opt_log_file, bool report_error, bool exit_on_error, const char *fmt,...) { int result = 0; - int written; char log_file[MAXPGPATH]; - -#define MAXCMDLEN (2 * MAXPGPATH) - char cmd[MAXCMDLEN]; + PQExpBufferData cmd; FILE *log; va_list ap; + bool done; #ifdef WIN32 static DWORD mainThreadId = 0; @@ -105,18 +104,16 @@ exec_prog(const char *log_filename, const char *opt_log_file, snprintf(log_file, MAXPGPATH, "%s/%s", log_opts.logdir, log_filename); - written = 0; - va_start(ap, fmt); - written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap); - va_end(ap); - if (written >= MAXCMDLEN) - pg_fatal("command too long"); - written += snprintf(cmd + written, MAXCMDLEN - written, - " >> \"%s\" 2>&1", log_file); - if (written >= MAXCMDLEN) - pg_fatal("command too long"); + initPQExpBuffer(&cmd); + do + { + va_start(ap, fmt); + done = appendPQExpBufferVA(&cmd, fmt, ap); + va_end(ap); + } while (!done); + appendPQExpBuffer(&cmd, " >> \"%s\" 2>&1", log_file); - pg_log(PG_VERBOSE, "%s", cmd); + pg_log(PG_VERBOSE, "%s", cmd.data); #ifdef WIN32 @@ -132,7 +129,7 @@ exec_prog(const char *log_filename, const char *opt_log_file, if (mainThreadId != GetCurrentThreadId()) { fflush(NULL); - result = system(cmd); + result = system(cmd.data); } #endif @@ -165,7 +162,7 @@ exec_prog(const char *log_filename, const char *opt_log_file, if (mainThreadId == GetCurrentThreadId()) fprintf(log, "\n\n"); #endif - fprintf(log, "command: %s\n", cmd); + fprintf(log, "command: %s\n", cmd.data); #ifdef WIN32 /* Are we printing "command:" after its output? */ if (mainThreadId != GetCurrentThreadId()) @@ -184,7 +181,7 @@ exec_prog(const char *log_filename, const char *opt_log_file, #endif { fflush(NULL); - result = system(cmd); + result = system(cmd.data); } if (result != 0 && report_error) @@ -193,7 +190,7 @@ exec_prog(const char *log_filename, const char *opt_log_file, report_status(PG_REPORT, "\n*failure*"); fflush(stdout); - pg_log(PG_VERBOSE, "There were problems executing \"%s\"", cmd); + pg_log(PG_VERBOSE, "There were problems executing \"%s\"", cmd.data); if (opt_log_file) pg_log(exit_on_error ? PG_FATAL : PG_REPORT, "Consult the last few lines of \"%s\" or \"%s\" for\n" @@ -221,6 +218,8 @@ exec_prog(const char *log_filename, const char *opt_log_file, fclose(log); #endif + termPQExpBuffer(&cmd); + return result == 0; } diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt index 088592deb16..2fc5130e7bf 100644 --- a/src/interfaces/libpq/exports.txt +++ b/src/interfaces/libpq/exports.txt @@ -193,3 +193,4 @@ PQsendClosePrepared 190 PQsendClosePortal 191 PQchangePassword 192 PQsendPipelineSync 193 +appendPQExpBufferVA 194 -- 2.43.0