Clean up command argument assembly
Several commands internally assemble command lines to call other commands. This includes initdb, pg_dumpall, and pg_regress. (Also pg_ctl, but that is different enough that I didn't consider it here.) This has all evolved a bit organically, with fixed-size buffers, and various optional command-line arguments being injected with confusing-looking code, and the spacing between options handled in inconsistent ways. Clean all this up a bit to look clearer and be more easily extensible with new arguments and options. We start each command with printfPQExpBuffer(), and then append arguments as necessary with appendPQExpBuffer(). Also standardize on using initPQExpBuffer() over createPQExpBuffer() where possible. pg_regress uses StringInfo instead of PQExpBuffer, but many of the same ideas apply. Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi> Discussion: https://www.postgresql.org/message-id/flat/16d0beac-a141-e5d3-60e9-323da75f49bf@eisentraut.org
This commit is contained in:
parent
fa88928470
commit
cccdbc5d95
@ -309,16 +309,16 @@ void initialize_data_directory(void);
|
|||||||
/*
|
/*
|
||||||
* macros for running pipes to postgres
|
* macros for running pipes to postgres
|
||||||
*/
|
*/
|
||||||
#define PG_CMD_DECL char cmd[MAXPGPATH]; FILE *cmdfd
|
#define PG_CMD_DECL FILE *cmdfd
|
||||||
|
|
||||||
#define PG_CMD_OPEN \
|
#define PG_CMD_OPEN(cmd) \
|
||||||
do { \
|
do { \
|
||||||
cmdfd = popen_check(cmd, "w"); \
|
cmdfd = popen_check(cmd, "w"); \
|
||||||
if (cmdfd == NULL) \
|
if (cmdfd == NULL) \
|
||||||
exit(1); /* message already printed by popen_check */ \
|
exit(1); /* message already printed by popen_check */ \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define PG_CMD_CLOSE \
|
#define PG_CMD_CLOSE() \
|
||||||
do { \
|
do { \
|
||||||
if (pclose_check(cmdfd)) \
|
if (pclose_check(cmdfd)) \
|
||||||
exit(1); /* message already printed by pclose_check */ \
|
exit(1); /* message already printed by pclose_check */ \
|
||||||
@ -1138,13 +1138,15 @@ test_config_settings(void)
|
|||||||
static bool
|
static bool
|
||||||
test_specific_config_settings(int test_conns, int test_buffs)
|
test_specific_config_settings(int test_conns, int test_buffs)
|
||||||
{
|
{
|
||||||
PQExpBuffer cmd = createPQExpBuffer();
|
PQExpBufferData cmd;
|
||||||
_stringlist *gnames,
|
_stringlist *gnames,
|
||||||
*gvalues;
|
*gvalues;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
initPQExpBuffer(&cmd);
|
||||||
|
|
||||||
/* Set up the test postmaster invocation */
|
/* Set up the test postmaster invocation */
|
||||||
printfPQExpBuffer(cmd,
|
printfPQExpBuffer(&cmd,
|
||||||
"\"%s\" --check %s %s "
|
"\"%s\" --check %s %s "
|
||||||
"-c max_connections=%d "
|
"-c max_connections=%d "
|
||||||
"-c shared_buffers=%d "
|
"-c shared_buffers=%d "
|
||||||
@ -1158,18 +1160,18 @@ test_specific_config_settings(int test_conns, int test_buffs)
|
|||||||
gnames != NULL; /* assume lists have the same length */
|
gnames != NULL; /* assume lists have the same length */
|
||||||
gnames = gnames->next, gvalues = gvalues->next)
|
gnames = gnames->next, gvalues = gvalues->next)
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(cmd, " -c %s=", gnames->str);
|
appendPQExpBuffer(&cmd, " -c %s=", gnames->str);
|
||||||
appendShellString(cmd, gvalues->str);
|
appendShellString(&cmd, gvalues->str);
|
||||||
}
|
}
|
||||||
|
|
||||||
appendPQExpBuffer(cmd,
|
appendPQExpBuffer(&cmd,
|
||||||
" < \"%s\" > \"%s\" 2>&1",
|
" < \"%s\" > \"%s\" 2>&1",
|
||||||
DEVNULL, DEVNULL);
|
DEVNULL, DEVNULL);
|
||||||
|
|
||||||
fflush(NULL);
|
fflush(NULL);
|
||||||
status = system(cmd->data);
|
status = system(cmd.data);
|
||||||
|
|
||||||
destroyPQExpBuffer(cmd);
|
termPQExpBuffer(&cmd);
|
||||||
|
|
||||||
return (status == 0);
|
return (status == 0);
|
||||||
}
|
}
|
||||||
@ -1469,6 +1471,7 @@ static void
|
|||||||
bootstrap_template1(void)
|
bootstrap_template1(void)
|
||||||
{
|
{
|
||||||
PG_CMD_DECL;
|
PG_CMD_DECL;
|
||||||
|
PQExpBufferData cmd;
|
||||||
char **line;
|
char **line;
|
||||||
char **bki_lines;
|
char **bki_lines;
|
||||||
char headerline[MAXPGPATH];
|
char headerline[MAXPGPATH];
|
||||||
@ -1530,16 +1533,17 @@ bootstrap_template1(void)
|
|||||||
/* Also ensure backend isn't confused by this environment var: */
|
/* Also ensure backend isn't confused by this environment var: */
|
||||||
unsetenv("PGCLIENTENCODING");
|
unsetenv("PGCLIENTENCODING");
|
||||||
|
|
||||||
snprintf(cmd, sizeof(cmd),
|
initPQExpBuffer(&cmd);
|
||||||
"\"%s\" --boot -X %d %s %s %s %s",
|
|
||||||
backend_exec,
|
printfPQExpBuffer(&cmd, "\"%s\" --boot %s %s", backend_exec, boot_options, extra_options);
|
||||||
wal_segment_size_mb * (1024 * 1024),
|
appendPQExpBuffer(&cmd, " -X %d", wal_segment_size_mb * (1024 * 1024));
|
||||||
data_checksums ? "-k" : "",
|
if (data_checksums)
|
||||||
boot_options, extra_options,
|
appendPQExpBuffer(&cmd, " -k");
|
||||||
debug ? "-d 5" : "");
|
if (debug)
|
||||||
|
appendPQExpBuffer(&cmd, " -d 5");
|
||||||
|
|
||||||
|
|
||||||
PG_CMD_OPEN;
|
PG_CMD_OPEN(cmd.data);
|
||||||
|
|
||||||
for (line = bki_lines; *line != NULL; line++)
|
for (line = bki_lines; *line != NULL; line++)
|
||||||
{
|
{
|
||||||
@ -1547,8 +1551,9 @@ bootstrap_template1(void)
|
|||||||
free(*line);
|
free(*line);
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_CMD_CLOSE;
|
PG_CMD_CLOSE();
|
||||||
|
|
||||||
|
termPQExpBuffer(&cmd);
|
||||||
free(bki_lines);
|
free(bki_lines);
|
||||||
|
|
||||||
check_ok();
|
check_ok();
|
||||||
@ -2951,6 +2956,7 @@ void
|
|||||||
initialize_data_directory(void)
|
initialize_data_directory(void)
|
||||||
{
|
{
|
||||||
PG_CMD_DECL;
|
PG_CMD_DECL;
|
||||||
|
PQExpBufferData cmd;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
setup_signals();
|
setup_signals();
|
||||||
@ -3014,12 +3020,11 @@ initialize_data_directory(void)
|
|||||||
fputs(_("performing post-bootstrap initialization ... "), stdout);
|
fputs(_("performing post-bootstrap initialization ... "), stdout);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
snprintf(cmd, sizeof(cmd),
|
initPQExpBuffer(&cmd);
|
||||||
"\"%s\" %s %s template1 >%s",
|
printfPQExpBuffer(&cmd, "\"%s\" %s %s template1 >%s",
|
||||||
backend_exec, backend_options, extra_options,
|
backend_exec, backend_options, extra_options, DEVNULL);
|
||||||
DEVNULL);
|
|
||||||
|
|
||||||
PG_CMD_OPEN;
|
PG_CMD_OPEN(cmd.data);
|
||||||
|
|
||||||
setup_auth(cmdfd);
|
setup_auth(cmdfd);
|
||||||
|
|
||||||
@ -3054,7 +3059,8 @@ initialize_data_directory(void)
|
|||||||
|
|
||||||
make_postgres(cmdfd);
|
make_postgres(cmdfd);
|
||||||
|
|
||||||
PG_CMD_CLOSE;
|
PG_CMD_CLOSE();
|
||||||
|
termPQExpBuffer(&cmd);
|
||||||
|
|
||||||
check_ok();
|
check_ok();
|
||||||
}
|
}
|
||||||
|
@ -1564,11 +1564,14 @@ dumpDatabases(PGconn *conn)
|
|||||||
static int
|
static int
|
||||||
runPgDump(const char *dbname, const char *create_opts)
|
runPgDump(const char *dbname, const char *create_opts)
|
||||||
{
|
{
|
||||||
PQExpBuffer connstrbuf = createPQExpBuffer();
|
PQExpBufferData connstrbuf;
|
||||||
PQExpBuffer cmd = createPQExpBuffer();
|
PQExpBufferData cmd;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
appendPQExpBuffer(cmd, "\"%s\" %s %s", pg_dump_bin,
|
initPQExpBuffer(&connstrbuf);
|
||||||
|
initPQExpBuffer(&cmd);
|
||||||
|
|
||||||
|
printfPQExpBuffer(&cmd, "\"%s\" %s %s", pg_dump_bin,
|
||||||
pgdumpopts->data, create_opts);
|
pgdumpopts->data, create_opts);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1576,27 +1579,27 @@ runPgDump(const char *dbname, const char *create_opts)
|
|||||||
* format.
|
* format.
|
||||||
*/
|
*/
|
||||||
if (filename)
|
if (filename)
|
||||||
appendPQExpBufferStr(cmd, " -Fa ");
|
appendPQExpBufferStr(&cmd, " -Fa ");
|
||||||
else
|
else
|
||||||
appendPQExpBufferStr(cmd, " -Fp ");
|
appendPQExpBufferStr(&cmd, " -Fp ");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Append the database name to the already-constructed stem of connection
|
* Append the database name to the already-constructed stem of connection
|
||||||
* string.
|
* string.
|
||||||
*/
|
*/
|
||||||
appendPQExpBuffer(connstrbuf, "%s dbname=", connstr);
|
appendPQExpBuffer(&connstrbuf, "%s dbname=", connstr);
|
||||||
appendConnStrVal(connstrbuf, dbname);
|
appendConnStrVal(&connstrbuf, dbname);
|
||||||
|
|
||||||
appendShellString(cmd, connstrbuf->data);
|
appendShellString(&cmd, connstrbuf.data);
|
||||||
|
|
||||||
pg_log_info("running \"%s\"", cmd->data);
|
pg_log_info("running \"%s\"", cmd.data);
|
||||||
|
|
||||||
fflush(NULL);
|
fflush(NULL);
|
||||||
|
|
||||||
ret = system(cmd->data);
|
ret = system(cmd.data);
|
||||||
|
|
||||||
destroyPQExpBuffer(cmd);
|
termPQExpBuffer(&cmd);
|
||||||
destroyPQExpBuffer(connstrbuf);
|
termPQExpBuffer(&connstrbuf);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2293,6 +2293,7 @@ regression_main(int argc, char *argv[],
|
|||||||
|
|
||||||
if (temp_instance)
|
if (temp_instance)
|
||||||
{
|
{
|
||||||
|
StringInfoData cmd;
|
||||||
FILE *pg_conf;
|
FILE *pg_conf;
|
||||||
const char *env_wait;
|
const char *env_wait;
|
||||||
int wait_seconds;
|
int wait_seconds;
|
||||||
@ -2318,23 +2319,28 @@ regression_main(int argc, char *argv[],
|
|||||||
make_directory(buf);
|
make_directory(buf);
|
||||||
|
|
||||||
/* initdb */
|
/* initdb */
|
||||||
snprintf(buf, sizeof(buf),
|
initStringInfo(&cmd);
|
||||||
"\"%s%sinitdb\" -D \"%s/data\" --no-clean --no-sync%s%s > \"%s/log/initdb.log\" 2>&1",
|
appendStringInfo(&cmd,
|
||||||
bindir ? bindir : "",
|
"\"%s%sinitdb\" -D \"%s/data\" --no-clean --no-sync",
|
||||||
bindir ? "/" : "",
|
bindir ? bindir : "",
|
||||||
temp_instance,
|
bindir ? "/" : "",
|
||||||
debug ? " --debug" : "",
|
temp_instance);
|
||||||
nolocale ? " --no-locale" : "",
|
if (debug)
|
||||||
outputdir);
|
appendStringInfo(&cmd, " --debug");
|
||||||
|
if (nolocale)
|
||||||
|
appendStringInfo(&cmd, " --no-locale");
|
||||||
|
appendStringInfo(&cmd, " > \"%s/log/initdb.log\" 2>&1", outputdir);
|
||||||
fflush(NULL);
|
fflush(NULL);
|
||||||
if (system(buf))
|
if (system(cmd.data))
|
||||||
{
|
{
|
||||||
bail("initdb failed\n"
|
bail("initdb failed\n"
|
||||||
"# Examine \"%s/log/initdb.log\" for the reason.\n"
|
"# Examine \"%s/log/initdb.log\" for the reason.\n"
|
||||||
"# Command was: %s",
|
"# Command was: %s",
|
||||||
outputdir, buf);
|
outputdir, cmd.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pfree(cmd.data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust the default postgresql.conf for regression testing. The user
|
* Adjust the default postgresql.conf for regression testing. The user
|
||||||
* can specify a file to be appended; in any case we expand logging
|
* can specify a file to be appended; in any case we expand logging
|
||||||
|
Loading…
x
Reference in New Issue
Block a user