Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf45dc59

Browse files
committed
Improve pg_regress.c's infrastructure for issuing psql commands.
Support issuing more than one "-c command" switch to a singlepsql invocation. This allows combining some things that formerlyrequired two or more backend launches into a single session.In particular, we can issue DROP DATABASE as one of the -c commandswithout getting "DROP DATABASE cannot run inside a transaction block".In addition to reducing the number of sessions needed, this patchalso suppresses "NOTICE: database "foo" does not exist, skipping"chatter that was formerly generated during pg_regress's DROP DATABASE(or ROLE) IF NOT EXISTS calls. That moves us another step closerto the ideal of not seeing any messages during successful build/test.This also eliminates some hard-coded restrictions on the length ofthe commands issued. I don't think we were anywhere near hittingthose, but getting rid of the limit is comforting.Patch by me, but thanks to Nathan Bossart for starting the discussion.Discussion:https://postgr.es/m/DCBAE0E4-BD56-482F-8A70-7FD0DC0860BE@amazon.com
1 parentcd124d2 commitf45dc59

File tree

1 file changed

+104
-44
lines changed

1 file changed

+104
-44
lines changed

‎src/test/regress/pg_regress.c

Lines changed: 104 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ static void make_directory(const char *dir);
122122

123123
staticvoidheader(constchar*fmt,...)pg_attribute_printf(1,2);
124124
staticvoidstatus(constchar*fmt,...)pg_attribute_printf(1,2);
125-
staticvoidpsql_command(constchar*database,constchar*query,...)pg_attribute_printf(2,3);
125+
staticStringInfopsql_start_command(void);
126+
staticvoidpsql_add_command(StringInfobuf,constchar*query,...)pg_attribute_printf(2,3);
127+
staticvoidpsql_end_command(StringInfobuf,constchar*database);
126128

127129
/*
128130
* allow core files if possible.
@@ -1136,51 +1138,94 @@ config_sspi_auth(const char *pgdata, const char *superuser_name)
11361138
#endif/* ENABLE_SSPI */
11371139

11381140
/*
1139-
* Issue a command via psql, connecting to the specified database
1141+
* psql_start_command, psql_add_command, psql_end_command
1142+
*
1143+
* Issue one or more commands within one psql call.
1144+
* Set up with psql_start_command, then add commands one at a time
1145+
* with psql_add_command, and finally execute with psql_end_command.
11401146
*
11411147
* Since we use system(), this doesn't return until the operation finishes
11421148
*/
1149+
staticStringInfo
1150+
psql_start_command(void)
1151+
{
1152+
StringInfobuf=makeStringInfo();
1153+
1154+
appendStringInfo(buf,
1155+
"\"%s%spsql\" -X",
1156+
bindir ?bindir :"",
1157+
bindir ?"/" :"");
1158+
returnbuf;
1159+
}
1160+
11431161
staticvoid
1144-
psql_command(constchar*database,constchar*query,...)
1162+
psql_add_command(StringInfobuf,constchar*query,...)
11451163
{
1146-
charquery_formatted[1024];
1147-
charquery_escaped[2048];
1148-
charpsql_cmd[MAXPGPATH+2048];
1149-
va_listargs;
1150-
char*s;
1151-
char*d;
1164+
StringInfoDatacmdbuf;
1165+
constchar*cmdptr;
1166+
1167+
/* Add each command as a -c argument in the psql call */
1168+
appendStringInfoString(buf," -c \"");
11521169

11531170
/* Generate the query with insertion of sprintf arguments */
1154-
va_start(args,query);
1155-
vsnprintf(query_formatted,sizeof(query_formatted),query,args);
1156-
va_end(args);
1171+
initStringInfo(&cmdbuf);
1172+
for (;;)
1173+
{
1174+
va_listargs;
1175+
intneeded;
1176+
1177+
va_start(args,query);
1178+
needed=appendStringInfoVA(&cmdbuf,query,args);
1179+
va_end(args);
1180+
if (needed==0)
1181+
break;/* success */
1182+
enlargeStringInfo(&cmdbuf,needed);
1183+
}
11571184

11581185
/* Now escape any shell double-quote metacharacters */
1159-
d=query_escaped;
1160-
for (s=query_formatted;*s;s++)
1186+
for (cmdptr=cmdbuf.data;*cmdptr;cmdptr++)
11611187
{
1162-
if (strchr("\\\"$`",*s))
1163-
*d++='\\';
1164-
*d++=*s;
1188+
if (strchr("\\\"$`",*cmdptr))
1189+
appendStringInfoChar(buf,'\\');
1190+
appendStringInfoChar(buf,*cmdptr);
11651191
}
1166-
*d='\0';
11671192

1168-
/* And now we can build and execute the shell command */
1169-
snprintf(psql_cmd,sizeof(psql_cmd),
1170-
"\"%s%spsql\" -X -c \"%s\" \"%s\"",
1171-
bindir ?bindir :"",
1172-
bindir ?"/" :"",
1173-
query_escaped,
1174-
database);
1193+
appendStringInfoChar(buf,'"');
1194+
1195+
pfree(cmdbuf.data);
1196+
}
1197+
1198+
staticvoid
1199+
psql_end_command(StringInfobuf,constchar*database)
1200+
{
1201+
/* Add the database name --- assume it needs no extra escaping */
1202+
appendStringInfo(buf,
1203+
" \"%s\"",
1204+
database);
11751205

1176-
if (system(psql_cmd)!=0)
1206+
/* And now we can execute the shell command */
1207+
if (system(buf->data)!=0)
11771208
{
11781209
/* psql probably already reported the error */
1179-
fprintf(stderr,_("command failed: %s\n"),psql_cmd);
1210+
fprintf(stderr,_("command failed: %s\n"),buf->data);
11801211
exit(2);
11811212
}
1213+
1214+
/* Clean up */
1215+
pfree(buf->data);
1216+
pfree(buf);
11821217
}
11831218

1219+
/*
1220+
* Shorthand macro for the common case of a single command
1221+
*/
1222+
#definepsql_command(database, ...) \
1223+
do { \
1224+
StringInfo cmdbuf = psql_start_command(); \
1225+
psql_add_command(cmdbuf, __VA_ARGS__); \
1226+
psql_end_command(cmdbuf, database); \
1227+
} while (0)
1228+
11841229
/*
11851230
* Spawn a process to execute the given shell command; don't wait for it
11861231
*
@@ -2012,13 +2057,19 @@ open_result_files(void)
20122057
staticvoid
20132058
drop_database_if_exists(constchar*dbname)
20142059
{
2060+
StringInfobuf=psql_start_command();
2061+
20152062
header(_("dropping database \"%s\""),dbname);
2016-
psql_command("postgres","DROP DATABASE IF EXISTS \"%s\"",dbname);
2063+
/* Set warning level so we don't see chatter about nonexistent DB */
2064+
psql_add_command(buf,"SET client_min_messages = warning");
2065+
psql_add_command(buf,"DROP DATABASE IF EXISTS \"%s\"",dbname);
2066+
psql_end_command(buf,"postgres");
20172067
}
20182068

20192069
staticvoid
20202070
create_database(constchar*dbname)
20212071
{
2072+
StringInfobuf=psql_start_command();
20222073
_stringlist*sl;
20232074

20242075
/*
@@ -2027,19 +2078,20 @@ create_database(const char *dbname)
20272078
*/
20282079
header(_("creating database \"%s\""),dbname);
20292080
if (encoding)
2030-
psql_command("postgres","CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'%s",dbname,encoding,
2031-
(nolocale) ?" LC_COLLATE='C' LC_CTYPE='C'" :"");
2081+
psql_add_command(buf,"CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'%s",dbname,encoding,
2082+
(nolocale) ?" LC_COLLATE='C' LC_CTYPE='C'" :"");
20322083
else
2033-
psql_command("postgres","CREATE DATABASE \"%s\" TEMPLATE=template0%s",dbname,
2034-
(nolocale) ?" LC_COLLATE='C' LC_CTYPE='C'" :"");
2035-
psql_command(dbname,
2036-
"ALTER DATABASE \"%s\" SET lc_messages TO 'C';"
2037-
"ALTER DATABASE \"%s\" SET lc_monetary TO 'C';"
2038-
"ALTER DATABASE \"%s\" SET lc_numeric TO 'C';"
2039-
"ALTER DATABASE \"%s\" SET lc_time TO 'C';"
2040-
"ALTER DATABASE \"%s\" SET bytea_output TO 'hex';"
2041-
"ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';",
2042-
dbname,dbname,dbname,dbname,dbname,dbname);
2084+
psql_add_command(buf,"CREATE DATABASE \"%s\" TEMPLATE=template0%s",dbname,
2085+
(nolocale) ?" LC_COLLATE='C' LC_CTYPE='C'" :"");
2086+
psql_add_command(buf,
2087+
"ALTER DATABASE \"%s\" SET lc_messages TO 'C';"
2088+
"ALTER DATABASE \"%s\" SET lc_monetary TO 'C';"
2089+
"ALTER DATABASE \"%s\" SET lc_numeric TO 'C';"
2090+
"ALTER DATABASE \"%s\" SET lc_time TO 'C';"
2091+
"ALTER DATABASE \"%s\" SET bytea_output TO 'hex';"
2092+
"ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';",
2093+
dbname,dbname,dbname,dbname,dbname,dbname);
2094+
psql_end_command(buf,"postgres");
20432095

20442096
/*
20452097
* Install any requested extensions. We use CREATE IF NOT EXISTS so that
@@ -2055,20 +2107,28 @@ create_database(const char *dbname)
20552107
staticvoid
20562108
drop_role_if_exists(constchar*rolename)
20572109
{
2110+
StringInfobuf=psql_start_command();
2111+
20582112
header(_("dropping role \"%s\""),rolename);
2059-
psql_command("postgres","DROP ROLE IF EXISTS \"%s\"",rolename);
2113+
/* Set warning level so we don't see chatter about nonexistent role */
2114+
psql_add_command(buf,"SET client_min_messages = warning");
2115+
psql_add_command(buf,"DROP ROLE IF EXISTS \"%s\"",rolename);
2116+
psql_end_command(buf,"postgres");
20602117
}
20612118

20622119
staticvoid
20632120
create_role(constchar*rolename,const_stringlist*granted_dbs)
20642121
{
2122+
StringInfobuf=psql_start_command();
2123+
20652124
header(_("creating role \"%s\""),rolename);
2066-
psql_command("postgres","CREATE ROLE \"%s\" WITH LOGIN",rolename);
2125+
psql_add_command(buf,"CREATE ROLE \"%s\" WITH LOGIN",rolename);
20672126
for (;granted_dbs!=NULL;granted_dbs=granted_dbs->next)
20682127
{
2069-
psql_command("postgres","GRANT ALL ON DATABASE \"%s\" TO \"%s\"",
2070-
granted_dbs->str,rolename);
2128+
psql_add_command(buf,"GRANT ALL ON DATABASE \"%s\" TO \"%s\"",
2129+
granted_dbs->str,rolename);
20712130
}
2131+
psql_end_command(buf,"postgres");
20722132
}
20732133

20742134
staticvoid

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp