git.postgresql.org Git - postgresql.git/commitdiff

git projects / postgresql.git / commitdiff
? search:
summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: e23014f)
Allow escaping of option values for options passed at connection start.
2014年8月28日 11:59:29 +0000 (13:59 +0200)
2014年8月28日 11:59:29 +0000 (13:59 +0200)
This is useful to allow to set GUCs to values that include spaces;
something that wasn't previously possible. The primary case motivating
this is the desire to set default_transaction_isolation to 'repeatable
read' on a per connection basis, but other usecases like seach_path do
also exist.

This introduces a slight backward incompatibility: Previously a \ in
an option value would have been passed on literally, now it'll be
taken as an escape.

The relevant mailing list discussion starts with
20140204125823.GJ12016@awork2.anarazel.de.


diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index e519ff96b90a4bee5c1476df2af46917bfeaa8d7..a8a09e4f0ec63f5fe586ccfc1f4caaa996e54baa 100644 (file)
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -4734,7 +4734,10 @@ StartupMessage (F)
set at backend start time might be listed. Such settings
will be applied during backend start (after parsing the
command-line options if any). The values will act as
- session defaults.
+ session defaults. Spaces in option values need to be escaped
+ with a backslash (<literal>\</>). A literal backslash can be
+ passed by escaping it with another backslash
+ (i.e <literal>\\</>).
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index b190cf51136f4a9c753695c5c988ceb9946fb286..14535c8b35a6cf07011e41531ebd238aa41de5fe 100644 (file)
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4083,8 +4083,7 @@ BackendRun(Port *port)
/*
* Pass any backend switches specified with -o on the postmaster's own
- * command line. We assume these are secure. (It's OK to mangle
- * ExtraOptions now, since we're safely inside a subprocess.)
+ * command line. We assume these are secure.
*/
pg_split_opts(av, &ac, ExtraOptions);
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index a5b98217739e7bc1a7d331aa0169829ac1d93e14..304be047892c663f665477bbb3f69e71a22a124a 100644 (file)
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -409,32 +409,57 @@ InitCommunication(void)
/*
* pg_split_opts -- split a string of options and append it to an argv array
*
- * NB: the input string is destructively modified! Also, caller is responsible
- * for ensuring the argv array is large enough. The maximum possible number
- * of arguments added by this routine is (strlen(optstr) + 1) / 2.
+ * The caller is responsible for ensuring the argv array is large enough. The
+ * maximum possible number of arguments added by this routine is
+ * (strlen(optstr) + 1) / 2.
*
- * Since no current POSTGRES arguments require any quoting characters,
- * we can use the simple-minded tactic of assuming each set of space-
- * delimited characters is a separate argv element.
- *
- * If you don't like that, well, we *used* to pass the whole option string
- * as ONE argument to execl(), which was even less intelligent...
+ * Because some option values can contain spaces we allow escaping using
+ * backslashes, with \\ representing a literal backslash.
*/
void
pg_split_opts(char **argv, int *argcp, char *optstr)
{
+ StringInfoData s;
+
+ initStringInfo(&s);
+
while (*optstr)
{
+ bool last_was_escape = false;
+
+ resetStringInfo(&s);
+
+ /* skip over leading space */
while (isspace((unsigned char) *optstr))
optstr++;
+
if (*optstr == '0円')
break;
- argv[(*argcp)++] = optstr;
- while (*optstr && !isspace((unsigned char) *optstr))
+
+ /*
+ * Parse a single option + value, stopping at the first space, unless
+ * it's escaped.
+ */
+ while (*optstr)
+ {
+ if (isspace(*optstr) && !last_was_escape)
+ break;
+
+ if (!last_was_escape && *optstr == '\\')
+ last_was_escape = true;
+ else
+ {
+ last_was_escape = false;
+ appendStringInfoChar(&s, *optstr);
+ }
+
optstr++;
- if (*optstr)
- *optstr++ = '0円';
+ }
+
+ /* now store the option */
+ argv[(*argcp)++] = pstrdup(s.data);
}
+ resetStringInfo(&s);
}
/*
@@ -981,7 +1006,6 @@ process_startup_options(Port *port, bool am_superuser)
av[ac++] = "postgres";
- /* Note this mangles port->cmdline_options */
pg_split_opts(av, &ac, port->cmdline_options);
av[ac] = NULL;
This is the main PostgreSQL git repository.
RSS Atom

AltStyle によって変換されたページ (->オリジナル) /