aboutsummaryrefslogtreecommitdiff
path: root/src/fe_utils/string_utils.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-04-01 21:44:54 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2017-04-01 21:44:54 -0400
commitf833c847b8fa4782efab45c8371d3cee64292d9b (patch)
tree85f93d92d7f7ab45bab157bb24ff482c6f47b97b /src/fe_utils/string_utils.c
parent41bd155dd656e7f17c02855be7aff234843347cd (diff)
downloadpostgresql-f833c847b8fa4782efab45c8371d3cee64292d9b.tar.gz
postgresql-f833c847b8fa4782efab45c8371d3cee64292d9b.zip
Allow psql variable substitution to occur in backtick command strings.
Previously, text between backquotes in a psql metacommand's arguments was always passed to the shell literally. That considerably hobbles the usefulness of the feature for scripting, so we'd foreseen for a long time that we'd someday want to allow substitution of psql variables into the shell command. IMO the addition of \if metacommands has brought us to that point, since \if can greatly benefit from some sort of client-side expression evaluation capability, and psql itself is not going to grow any such thing in time for v10. Hence, this patch. It allows :VARIABLE to be replaced by the exact contents of the named variable, while :'VARIABLE' is replaced by the variable's contents suitably quoted to become a single shell-command argument. (The quoting rules for that are different from those for SQL literals, so this is a bit of an abuse of the :'VARIABLE' notation, but I doubt anyone will be confused.) As with other situations in psql, no substitution occurs if the word following a colon is not a known variable name. That limits the risk of compatibility problems for existing psql scripts; but the risk isn't zero, so this needs to be called out in the v10 release notes. Discussion: https://postgr.es/m/9561.1490895211@sss.pgh.pa.us
Diffstat (limited to 'src/fe_utils/string_utils.c')
-rw-r--r--src/fe_utils/string_utils.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/src/fe_utils/string_utils.c b/src/fe_utils/string_utils.c
index d1a9ddc4c6c..dc84d32a097 100644
--- a/src/fe_utils/string_utils.c
+++ b/src/fe_utils/string_utils.c
@@ -425,13 +425,30 @@ appendByteaLiteral(PQExpBuffer buf, const unsigned char *str, size_t length,
* arguments containing LF or CR characters. A future major release should
* reject those characters in CREATE ROLE and CREATE DATABASE, because use
* there eventually leads to errors here.
+ *
+ * appendShellString() simply prints an error and dies if LF or CR appears.
+ * appendShellStringNoError() omits those characters from the result, and
+ * returns false if there were any.
*/
void
appendShellString(PQExpBuffer buf, const char *str)
{
+ if (!appendShellStringNoError(buf, str))
+ {
+ fprintf(stderr,
+ _("shell command argument contains a newline or carriage return: \"%s\"\n"),
+ str);
+ exit(EXIT_FAILURE);
+ }
+}
+
+bool
+appendShellStringNoError(PQExpBuffer buf, const char *str)
+{
#ifdef WIN32
int backslash_run_length = 0;
#endif
+ bool ok = true;
const char *p;
/*
@@ -442,7 +459,7 @@ appendShellString(PQExpBuffer buf, const char *str)
strspn(str, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_./:") == strlen(str))
{
appendPQExpBufferStr(buf, str);
- return;
+ return ok;
}
#ifndef WIN32
@@ -451,10 +468,8 @@ appendShellString(PQExpBuffer buf, const char *str)
{
if (*p == '\n' || *p == '\r')
{
- fprintf(stderr,
- _("shell command argument contains a newline or carriage return: \"%s\"\n"),
- str);
- exit(EXIT_FAILURE);
+ ok = false;
+ continue;
}
if (*p == '\'')
@@ -481,10 +496,8 @@ appendShellString(PQExpBuffer buf, const char *str)
{
if (*p == '\n' || *p == '\r')
{
- fprintf(stderr,
- _("shell command argument contains a newline or carriage return: \"%s\"\n"),
- str);
- exit(EXIT_FAILURE);
+ ok = false;
+ continue;
}
/* Change N backslashes before a double quote to 2N+1 backslashes. */
@@ -524,6 +537,8 @@ appendShellString(PQExpBuffer buf, const char *str)
}
appendPQExpBufferStr(buf, "^\"");
#endif /* WIN32 */
+
+ return ok;
}