mirror of
https://github.com/postgres/postgres.git
synced 2025-05-02 11:44:50 +03:00
Allow escaping of option values for options passed at connection start.
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.
This commit is contained in:
parent
e23014f3d4
commit
11a020eb6e
@ -4734,7 +4734,10 @@ StartupMessage (F)
|
|||||||
set at backend start time might be listed. Such settings
|
set at backend start time might be listed. Such settings
|
||||||
will be applied during backend start (after parsing the
|
will be applied during backend start (after parsing the
|
||||||
command-line options if any). The values will act as
|
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>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -4083,8 +4083,7 @@ BackendRun(Port *port)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Pass any backend switches specified with -o on the postmaster's own
|
* Pass any backend switches specified with -o on the postmaster's own
|
||||||
* command line. We assume these are secure. (It's OK to mangle
|
* command line. We assume these are secure.
|
||||||
* ExtraOptions now, since we're safely inside a subprocess.)
|
|
||||||
*/
|
*/
|
||||||
pg_split_opts(av, &ac, ExtraOptions);
|
pg_split_opts(av, &ac, ExtraOptions);
|
||||||
|
|
||||||
|
@ -409,32 +409,57 @@ InitCommunication(void)
|
|||||||
/*
|
/*
|
||||||
* pg_split_opts -- split a string of options and append it to an argv array
|
* 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
|
* The caller is responsible for ensuring the argv array is large enough. The
|
||||||
* for ensuring the argv array is large enough. The maximum possible number
|
* maximum possible number of arguments added by this routine is
|
||||||
* of arguments added by this routine is (strlen(optstr) + 1) / 2.
|
* (strlen(optstr) + 1) / 2.
|
||||||
*
|
*
|
||||||
* Since no current POSTGRES arguments require any quoting characters,
|
* Because some option values can contain spaces we allow escaping using
|
||||||
* we can use the simple-minded tactic of assuming each set of space-
|
* backslashes, with \\ representing a literal backslash.
|
||||||
* 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...
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
pg_split_opts(char **argv, int *argcp, char *optstr)
|
pg_split_opts(char **argv, int *argcp, char *optstr)
|
||||||
{
|
{
|
||||||
|
StringInfoData s;
|
||||||
|
|
||||||
|
initStringInfo(&s);
|
||||||
|
|
||||||
while (*optstr)
|
while (*optstr)
|
||||||
{
|
{
|
||||||
|
bool last_was_escape = false;
|
||||||
|
|
||||||
|
resetStringInfo(&s);
|
||||||
|
|
||||||
|
/* skip over leading space */
|
||||||
while (isspace((unsigned char) *optstr))
|
while (isspace((unsigned char) *optstr))
|
||||||
optstr++;
|
optstr++;
|
||||||
|
|
||||||
if (*optstr == '\0')
|
if (*optstr == '\0')
|
||||||
break;
|
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++;
|
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";
|
av[ac++] = "postgres";
|
||||||
|
|
||||||
/* Note this mangles port->cmdline_options */
|
|
||||||
pg_split_opts(av, &ac, port->cmdline_options);
|
pg_split_opts(av, &ac, port->cmdline_options);
|
||||||
|
|
||||||
av[ac] = NULL;
|
av[ac] = NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user