pg_basebkup_recvxlog_dump_conn_str_v2.patch
application/octet-stream
Filename: pg_basebkup_recvxlog_dump_conn_str_v2.patch
Type: application/octet-stream
Part: 0
Patch
Format: context
Series: patch v2
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/pg_basebackup.sgml | 13 | 0 |
| doc/src/sgml/ref/pg_dumpall.sgml | 13 | 0 |
| doc/src/sgml/ref/pg_dump.sgml | 13 | 0 |
| doc/src/sgml/ref/pg_receivexlog.sgml | 13 | 0 |
| src/bin/pg_basebackup/pg_basebackup.c | 6 | 0 |
| src/bin/pg_basebackup/pg_receivexlog.c | 6 | 0 |
| src/bin/pg_basebackup/streamutil.c | 88 | 0 |
| src/bin/pg_basebackup/streamutil.h | 1 | 0 |
| src/bin/pg_dump/dumputils.c | 1 | 0 |
| src/bin/pg_dump/dumputils.h | 1 | 0 |
| src/bin/pg_dump/pg_backup_db.c | 83 | 0 |
| src/bin/pg_dump/pg_dumpall.c | 95 | 0 |
| src/bin/pg_dump/pg_dump.c | 7 | 0 |
| src/include/pg_config_manual.h | 8 | 0 |
| src/interfaces/libpq/exports.txt | 2 | 0 |
| src/interfaces/libpq/fe-connect.c | 79 | 0 |
| src/interfaces/libpq/libpq-fe.h | 9 | 0 |
*** a/doc/src/sgml/ref/pg_basebackup.sgml
--- b/doc/src/sgml/ref/pg_basebackup.sgml
***************
*** 357,362 **** PostgreSQL documentation
--- 357,375 ----
<para>
The following command-line options control the database connection parameters.
+ <variablelist>
+ <varlistentry>
+ <term><option>-C <replaceable class="parameter">"OPTIONS"</replaceable></option></term>
+ <term><option>--connection-string=<replaceable class="parameter">"OPTIONS"</replaceable></option></term>
+ <listitem>
+ <para>
+ Specifies connection string options, used for connecting to server.
+ These options can be used along with other user supplied options.
+ In case of conflicting option, user supplied option is choosen.
+ </para>
+ </listitem>
+ </varlistentry>
+
<variablelist>
<varlistentry>
<term><option>-h <replaceable class="parameter">host</replaceable></option></term>
*** a/doc/src/sgml/ref/pg_dump.sgml
--- b/doc/src/sgml/ref/pg_dump.sgml
***************
*** 815,820 **** PostgreSQL documentation
--- 815,833 ----
<para>
The following command-line options control the database connection parameters.
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-K <replaceable class="parameter">"OPTIONS"</replaceable></option></term>
+ <term><option>--connection-string=<replaceable class="parameter">"OPTIONS"</replaceable></option></term>
+ <listitem>
+ <para>
+ Specifies connection string options, used for connecting to server.
+ These options can be used along with other user supplied options.
+ In case of conflicting option, user supplied option is choosen.
+ </para>
+ </listitem>
+ </varlistentry>
<variablelist>
<varlistentry>
*** a/doc/src/sgml/ref/pg_dumpall.sgml
--- b/doc/src/sgml/ref/pg_dumpall.sgml
***************
*** 403,408 **** PostgreSQL documentation
--- 403,421 ----
<para>
The following command-line options control the database connection parameters.
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-K <replaceable class="parameter">"OPTIONS"</replaceable></option></term>
+ <term><option>--connection-string=<replaceable class="parameter">"OPTIONS"</replaceable></option></term>
+ <listitem>
+ <para>
+ Specifies connection string options, used for connecting to server.
+ These options can be used along with other user supplied options.
+ In case of conflicting option, user supplied option is choosen.
+ </para>
+ </listitem>
+ </varlistentry>
<variablelist>
<varlistentry>
*** a/doc/src/sgml/ref/pg_receivexlog.sgml
--- b/doc/src/sgml/ref/pg_receivexlog.sgml
***************
*** 121,126 **** PostgreSQL documentation
--- 121,139 ----
<para>
The following command-line options control the database connection parameters.
+ <variablelist>
+ <varlistentry>
+ <term><option>-C <replaceable class="parameter">"OPTIONS"</replaceable></option></term>
+ <term><option>--connection-string=<replaceable class="parameter">"OPTIONS"</replaceable></option></term>
+ <listitem>
+ <para>
+ Specifies connection string options, used for connecting to server.
+ These options can be used along with other user supplied options.
+ In case of conflicting option, user supplied option is choosen.
+ </para>
+ </listitem>
+ </varlistentry>
+
<variablelist>
<varlistentry>
<term><option>-h <replaceable class="parameter">host</replaceable></option></term>
*** a/src/bin/pg_basebackup/pg_basebackup.c
--- b/src/bin/pg_basebackup/pg_basebackup.c
***************
*** 126,131 **** usage(void)
--- 126,132 ----
printf(_(" -V, --version output version information, then exit\n"));
printf(_(" -?, --help show this help, then exit\n"));
printf(_("\nConnection options:\n"));
+ printf(_(" -C, --connection-string=\"OPTIONS\" connect to server using OPTIONS\n"));
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
printf(_(" -p, --port=PORT database server port number\n"));
printf(_(" -s, --status-interval=INTERVAL\n"
***************
*** 1534,1539 **** main(int argc, char **argv)
--- 1535,1541 ----
{"pgdata", required_argument, NULL, 'D'},
{"format", required_argument, NULL, 'F'},
{"checkpoint", required_argument, NULL, 'c'},
+ {"connection-string", required_argument, NULL, 'C'},
{"write-recovery-conf", no_argument, NULL, 'R'},
{"xlog", no_argument, NULL, 'x'},
{"xlog-method", required_argument, NULL, 'X'},
***************
*** 1572,1578 **** main(int argc, char **argv)
}
}
! while ((c = getopt_long(argc, argv, "D:F:RxX:l:zZ:c:h:p:U:s:wWvP",
long_options, &option_index)) != -1)
{
switch (c)
--- 1574,1580 ----
}
}
! while ((c = getopt_long(argc, argv, "D:F:RxX:l:zZ:C:c:h:p:U:s:wWvP",
long_options, &option_index)) != -1)
{
switch (c)
***************
*** 1663,1668 **** main(int argc, char **argv)
--- 1665,1673 ----
exit(1);
}
break;
+ case 'C':
+ connection_string = pg_strdup(optarg);
+ break;
case 'h':
dbhost = pg_strdup(optarg);
break;
*** a/src/bin/pg_basebackup/pg_receivexlog.c
--- b/src/bin/pg_basebackup/pg_receivexlog.c
***************
*** 58,63 **** usage(void)
--- 58,64 ----
printf(_(" -V, --version output version information, then exit\n"));
printf(_(" -?, --help show this help, then exit\n"));
printf(_("\nConnection options:\n"));
+ printf(_(" -C, --connection-string=\"OPTIONS\" connect to server using OPTIONS\n"));
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
printf(_(" -p, --port=PORT database server port number\n"));
printf(_(" -s, --status-interval=INTERVAL\n"
***************
*** 305,310 **** main(int argc, char **argv)
--- 306,312 ----
static struct option long_options[] = {
{"help", no_argument, NULL, '?'},
{"version", no_argument, NULL, 'V'},
+ {"connection-string", required_argument, NULL, 'C'},
{"directory", required_argument, NULL, 'D'},
{"host", required_argument, NULL, 'h'},
{"port", required_argument, NULL, 'p'},
***************
*** 338,348 **** main(int argc, char **argv)
}
}
! while ((c = getopt_long(argc, argv, "D:h:p:U:s:nwWv",
long_options, &option_index)) != -1)
{
switch (c)
{
case 'D':
basedir = pg_strdup(optarg);
break;
--- 340,353 ----
}
}
! while ((c = getopt_long(argc, argv, "C:D:h:p:U:s:nwWv",
long_options, &option_index)) != -1)
{
switch (c)
{
+ case 'C':
+ connection_string = pg_strdup(optarg);
+ break;
case 'D':
basedir = pg_strdup(optarg);
break;
*** a/src/bin/pg_basebackup/streamutil.c
--- b/src/bin/pg_basebackup/streamutil.c
***************
*** 24,29 **** char *dbport = NULL;
--- 24,31 ----
int dbgetpassword = 0; /* 0=auto, -1=never, 1=always */
static char *dbpassword = NULL;
PGconn *conn = NULL;
+ char *connection_string = NULL;
+
/*
* Connect to the server. Returns a valid PGconn pointer if connected,
***************
*** 34,64 **** PGconn *
GetConnection(void)
{
PGconn *tmpconn;
! int argcount = 4; /* dbname, replication, fallback_app_name,
! * password */
! int i;
const char **keywords;
const char **values;
char *password = NULL;
const char *tmpparam;
- if (dbhost)
- argcount++;
- if (dbuser)
- argcount++;
- if (dbport)
- argcount++;
-
- keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
- values = pg_malloc0((argcount + 1) * sizeof(*values));
-
- keywords[0] = "dbname";
- values[0] = "replication";
- keywords[1] = "replication";
- values[1] = "true";
- keywords[2] = "fallback_application_name";
- values[2] = progname;
- i = 3;
if (dbhost)
{
keywords[i] = "host";
--- 36,97 ----
GetConnection(void)
{
PGconn *tmpconn;
! int i = 0;
const char **keywords;
const char **values;
char *password = NULL;
const char *tmpparam;
+ PQconninfoOption *conn_opts = NULL,
+ *conn_opts_merged = NULL;
+ PQconninfoOption *conn_opt;
+ char *err_msg = NULL;
+
+
+ keywords = pg_malloc0(MAX_CONNINFO_OPTIONS * sizeof(*keywords));
+ values = pg_malloc0(MAX_CONNINFO_OPTIONS * sizeof(*values));
+
+ /*
+ * Merge the connection info inputs given in form of connection string,
+ * options and default values (dbname=replication, replication=true,
+ * etc.). We could have written new function to connect using
+ * PQconninfoOption, but it's not a lot of code to iterate through the
+ * PGconnInfoOption array and turn it back into keywords and values
+ * arrays, so just do that straight in the client code.
+ */
+
+ if (connection_string)
+ {
+ conn_opts = PQconninfoParse(connection_string, &err_msg);
+ if (conn_opts != NULL)
+ {
+ for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
+ {
+ if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
+ {
+ keywords[i] = conn_opt->keyword;
+ values[i] = conn_opt->val;
+ i++;
+ }
+ }
+ }
+ else
+ {
+ fprintf(stderr, "%s: %s\n", progname, err_msg);
+ return NULL;
+ }
+
+ }
+
+ keywords[i] = "dbname";
+ values[i] = "replication";
+ i++;
+ keywords[i] = "replication";
+ values[i] = "true";
+ i++;
+ keywords[i] = "fallback_application_name";
+ values[i] = progname;
+ i++;
if (dbhost)
{
keywords[i] = "host";
***************
*** 78,83 **** GetConnection(void)
--- 111,143 ----
i++;
}
+ if (connection_string)
+ {
+ conn_opts_merged = PQconninfoParseParams(keywords, values,
+ true, &err_msg);
+ if (conn_opts_merged != NULL)
+ {
+ i = 0;
+ MemSet(keywords, 0, MAX_CONNINFO_OPTIONS * sizeof(*keywords));
+ MemSet(values, 0, MAX_CONNINFO_OPTIONS * sizeof(*values));
+ for (conn_opt = conn_opts_merged; conn_opt->keyword != NULL; conn_opt++)
+ {
+ if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
+ {
+ keywords[i] = conn_opt->keyword;
+ values[i] = conn_opt->val;
+ i++;
+ }
+ }
+ }
+ else
+ {
+ fprintf(stderr, "%s: %s\n", progname, err_msg);
+ PQconninfoFree(conn_opts);
+ return NULL;
+ }
+ }
+
while (true)
{
if (password)
***************
*** 90,104 **** GetConnection(void)
* meaning this is the call for a second session to the same
* database, so just forcibly reuse that password.
*/
! keywords[argcount - 1] = "password";
! values[argcount - 1] = dbpassword;
dbgetpassword = -1; /* Don't try again if this fails */
}
else if (dbgetpassword == 1)
{
password = simple_prompt(_("Password: "), 100, false);
! keywords[argcount - 1] = "password";
! values[argcount - 1] = password;
}
tmpconn = PQconnectdbParams(keywords, values, true);
--- 150,164 ----
* meaning this is the call for a second session to the same
* database, so just forcibly reuse that password.
*/
! keywords[i] = "password";
! values[i] = dbpassword;
dbgetpassword = -1; /* Don't try again if this fails */
}
else if (dbgetpassword == 1)
{
password = simple_prompt(_("Password: "), 100, false);
! keywords[i] = "password";
! values[i] = password;
}
tmpconn = PQconnectdbParams(keywords, values, true);
***************
*** 130,141 **** GetConnection(void)
--- 190,205 ----
PQfinish(tmpconn);
free(values);
free(keywords);
+ PQconninfoFree(conn_opts);
+ PQconninfoFree(conn_opts_merged);
return NULL;
}
/* Connection ok! */
free(values);
free(keywords);
+ PQconninfoFree(conn_opts);
+ PQconninfoFree(conn_opts_merged);
/*
* Ensure we have the same value of integer timestamps as the server
*** a/src/bin/pg_basebackup/streamutil.h
--- b/src/bin/pg_basebackup/streamutil.h
***************
*** 5,10 **** extern char *dbhost;
--- 5,11 ----
extern char *dbuser;
extern char *dbport;
extern int dbgetpassword;
+ extern char *connection_string;
/* Connection kept global so we can disconnect easily */
extern PGconn *conn;
*** a/src/bin/pg_dump/dumputils.c
--- b/src/bin/pg_dump/dumputils.c
***************
*** 28,33 **** extern const int NumFEScanKeywords;
--- 28,34 ----
/* Globals exported by this file */
int quote_all_identifiers = 0;
const char *progname = NULL;
+ char *connection_string = NULL;
#define MAX_ON_EXIT_NICELY 20
*** a/src/bin/pg_dump/dumputils.h
--- b/src/bin/pg_dump/dumputils.h
***************
*** 44,49 **** typedef void (*on_exit_nicely_callback) (int code, void *arg);
--- 44,50 ----
extern int quote_all_identifiers;
extern const char *progname;
+ extern char *connection_string;
extern void init_parallel_dump_utils(void);
extern const char *fmtId(const char *identifier);
*** a/src/bin/pg_dump/pg_backup_db.c
--- b/src/bin/pg_dump/pg_backup_db.c
***************
*** 254,283 **** ConnectDatabase(Archive *AHX,
*/
do
{
! #define PARAMS_ARRAY_SIZE 7
! const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
! const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
- keywords[0] = "host";
- values[0] = pghost;
- keywords[1] = "port";
- values[1] = pgport;
- keywords[2] = "user";
- values[2] = username;
- keywords[3] = "password";
- values[3] = password;
- keywords[4] = "dbname";
- values[4] = dbname;
- keywords[5] = "fallback_application_name";
- values[5] = progname;
- keywords[6] = NULL;
- values[6] = NULL;
new_pass = false;
AH->connection = PQconnectdbParams(keywords, values, true);
free(keywords);
free(values);
if (!AH->connection)
exit_horribly(modulename, "failed to connect to database\n");
--- 254,349 ----
*/
do
{
! const char **keywords = pg_malloc(MAX_CONNINFO_OPTIONS * sizeof(*keywords));
! const char **values = pg_malloc(MAX_CONNINFO_OPTIONS * sizeof(*values));
! PQconninfoOption *conn_opts = NULL,
! *conn_opts_merged = NULL;
! PQconninfoOption *conn_opt;
! char *err_msg = NULL;
! int i = 0;
!
! /*
! * Merge the connection info inputs given in form of connection string
! * and options. We could have written new function to connect using
! * PQconninfoOption, but it's not a lot of code to iterate through the
! * PGconnInfoOption array and turn it back into keywords and values
! * arrays, so just do that straight in the client code.
! */
! if (connection_string)
! {
! conn_opts = PQconninfoParse(connection_string, &err_msg);
! if (conn_opts != NULL)
! {
! for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
! {
! if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
! {
! keywords[i] = conn_opt->keyword;
! values[i] = conn_opt->val;
! i++;
! }
! }
! }
! else
! exit_horribly(modulename, "%s\n", err_msg);
! }
!
! keywords[i] = "host";
! values[i] = pghost;
! i++;
! keywords[i] = "port";
! values[i] = pgport;
! i++;
! keywords[i] = "user";
! values[i] = username;
! i++;
! keywords[i] = "password";
! values[i] = password;
! i++;
! keywords[i] = "dbname";
! values[i] = dbname;
! i++;
! keywords[i] = "fallback_application_name";
! values[i] = progname;
! i++;
! keywords[i] = NULL;
! values[i] = NULL;
!
! if (connection_string)
! {
! conn_opts_merged = PQconninfoParseParams(keywords, values,
! true, &err_msg);
! if (conn_opts_merged != NULL)
! {
! i = 0;
! MemSet(keywords, 0, MAX_CONNINFO_OPTIONS * sizeof(*keywords));
! MemSet(values, 0, MAX_CONNINFO_OPTIONS * sizeof(*values));
! for (conn_opt = conn_opts_merged; conn_opt->keyword != NULL; conn_opt++)
! {
! if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
! {
! keywords[i] = conn_opt->keyword;
! values[i] = conn_opt->val;
! i++;
! }
! }
! }
! else
! {
! PQconninfoFree(conn_opts);
! exit_horribly(modulename, "%s\n", err_msg);
!
! }
! }
new_pass = false;
AH->connection = PQconnectdbParams(keywords, values, true);
free(keywords);
free(values);
+ PQconninfoFree(conn_opts);
+ PQconninfoFree(conn_opts_merged);
if (!AH->connection)
exit_horribly(modulename, "failed to connect to database\n");
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
***************
*** 311,316 **** main(int argc, char **argv)
--- 311,317 ----
{"format", required_argument, NULL, 'F'},
{"host", required_argument, NULL, 'h'},
{"ignore-version", no_argument, NULL, 'i'},
+ {"connection-string", required_argument, NULL, 'K'},
{"no-reconnect", no_argument, NULL, 'R'},
{"oids", no_argument, NULL, 'o'},
{"no-owner", no_argument, NULL, 'O'},
***************
*** 387,393 **** main(int argc, char **argv)
}
}
! while ((c = getopt_long(argc, argv, "abcCE:f:F:h:in:N:oOp:RsS:t:T:U:vwWxZ:",
long_options, &optindex)) != -1)
{
switch (c)
--- 388,394 ----
}
}
! while ((c = getopt_long(argc, argv, "abcCE:f:F:h:iK:n:N:oOp:RsS:t:T:U:vwWxZ:",
long_options, &optindex)) != -1)
{
switch (c)
***************
*** 428,433 **** main(int argc, char **argv)
--- 429,438 ----
/* ignored, deprecated option */
break;
+ case 'K':
+ connection_string = pg_strdup(optarg);
+ break;
+
case 'n': /* include schema(s) */
simple_string_list_append(&schema_include_patterns, optarg);
include_everything = false;
***************
*** 872,877 **** help(const char *progname)
--- 877,883 ----
" ALTER OWNER commands to set ownership\n"));
printf(_("\nConnection options:\n"));
+ printf(_(" -K, --connection-string=\"OPTIONS\" connect to server using OPTIONS\n"));
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
printf(_(" -p, --port=PORT database server port number\n"));
printf(_(" -U, --username=NAME connect as specified database user\n"));
*** a/src/bin/pg_dump/pg_dumpall.c
--- b/src/bin/pg_dump/pg_dumpall.c
***************
*** 79,85 **** static int server_version;
static FILE *OPF;
static char *filename = NULL;
-
int
main(int argc, char *argv[])
{
--- 79,84 ----
***************
*** 90,95 **** main(int argc, char *argv[])
--- 89,95 ----
{"globals-only", no_argument, NULL, 'g'},
{"host", required_argument, NULL, 'h'},
{"ignore-version", no_argument, NULL, 'i'},
+ {"connection-string", required_argument, NULL, 'K'},
{"database", required_argument, NULL, 'l'},
{"oids", no_argument, NULL, 'o'},
{"no-owner", no_argument, NULL, 'O'},
***************
*** 187,193 **** main(int argc, char *argv[])
pgdumpopts = createPQExpBuffer();
! while ((c = getopt_long(argc, argv, "acf:gh:il:oOp:rsS:tU:vwWx", long_options, &optindex)) != -1)
{
switch (c)
{
--- 187,193 ----
pgdumpopts = createPQExpBuffer();
! while ((c = getopt_long(argc, argv, "acf:gh:iK:l:oOp:rsS:tU:vwWx", long_options, &optindex)) != -1)
{
switch (c)
{
***************
*** 220,225 **** main(int argc, char *argv[])
--- 220,231 ----
/* ignored, deprecated option */
break;
+ case 'K':
+ connection_string = pg_strdup(optarg);
+ appendPQExpBuffer(pgdumpopts, " -K ");
+ doShellQuoting(pgdumpopts, connection_string);
+ break;
+
case 'l':
pgdb = pg_strdup(optarg);
break;
***************
*** 567,572 **** help(void)
--- 573,579 ----
" ALTER OWNER commands to set ownership\n"));
printf(_("\nConnection options:\n"));
+ printf(_(" -K, --connection-string=\"OPTIONS\" connect to server using OPTIONS\n"));
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
printf(_(" -l, --database=DBNAME alternative default database\n"));
printf(_(" -p, --port=PORT database server port number\n"));
***************
*** 1710,1739 **** connectDatabase(const char *dbname, const char *pghost, const char *pgport,
*/
do
{
! #define PARAMS_ARRAY_SIZE 7
! const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
! const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
!
! keywords[0] = "host";
! values[0] = pghost;
! keywords[1] = "port";
! values[1] = pgport;
! keywords[2] = "user";
! values[2] = pguser;
! keywords[3] = "password";
! values[3] = password;
! keywords[4] = "dbname";
! values[4] = dbname;
! keywords[5] = "fallback_application_name";
! values[5] = progname;
! keywords[6] = NULL;
! values[6] = NULL;
new_pass = false;
conn = PQconnectdbParams(keywords, values, true);
free(keywords);
free(values);
if (!conn)
{
--- 1717,1814 ----
*/
do
{
! const char **keywords = pg_malloc(MAX_CONNINFO_OPTIONS * sizeof(*keywords));
! const char **values = pg_malloc(MAX_CONNINFO_OPTIONS * sizeof(*values));
! PQconninfoOption *conn_opts = NULL,
! *conn_opts_merged = NULL;
! PQconninfoOption *conn_opt;
! char *err_msg = NULL;
! int i = 0;
!
! /*
! * Merge the connection info inputs given in form of connection string
! * and options. We could have written new function to connect using
! * PQconninfoOption, but it's not a lot of code to iterate through the
! * PGconnInfoOption array and turn it back into keywords and values
! * arrays, so just do that straight in the client code.
! */
! if (connection_string)
! {
! conn_opts = PQconninfoParse(connection_string, &err_msg);
! if (conn_opts != NULL)
! {
! for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
! {
! if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
! {
! keywords[i] = conn_opt->keyword;
! values[i] = conn_opt->val;
! i++;
! }
! }
! }
! else
! {
! fprintf(stderr, "%s: %s\n", progname, err_msg);
! return NULL;
! }
! }
!
! keywords[i] = "host";
! values[i] = pghost;
! i++;
! keywords[i] = "port";
! values[i] = pgport;
! i++;
! keywords[i] = "user";
! values[i] = pguser;
! i++;
! keywords[i] = "password";
! values[i] = password;
! i++;
! keywords[i] = "dbname";
! values[i] = dbname;
! i++;
! keywords[i] = "fallback_application_name";
! values[i] = progname;
! i++;
! keywords[i] = NULL;
! values[i] = NULL;
!
! if (connection_string)
! {
! conn_opts_merged = PQconninfoParseParams(keywords, values,
! true, &err_msg);
! if (conn_opts_merged != NULL)
! {
! i = 0;
! MemSet(keywords, 0, MAX_CONNINFO_OPTIONS * sizeof(*keywords));
! MemSet(values, 0, MAX_CONNINFO_OPTIONS * sizeof(*values));
! for (conn_opt = conn_opts_merged; conn_opt->keyword != NULL; conn_opt++)
! {
! if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
! {
! keywords[i] = conn_opt->keyword;
! values[i] = conn_opt->val;
! i++;
! }
! }
! }
! else
! {
! fprintf(stderr, "%s: %s\n", progname, err_msg);
! PQconninfoFree(conn_opts);
! return NULL;
! }
! }
new_pass = false;
conn = PQconnectdbParams(keywords, values, true);
free(keywords);
free(values);
+ PQconninfoFree(conn_opts);
+ PQconninfoFree(conn_opts_merged);
if (!conn)
{
*** a/src/include/pg_config_manual.h
--- b/src/include/pg_config_manual.h
***************
*** 200,205 ****
--- 200,213 ----
#endif
/*
+ * MAX_CONNINFO_OPTIONS: maximum number of options for connection.
+ * It refers to PQconninfoOptions, currently it is less than 50, kept
+ * this considering future additions, however it can be kept same.
+ */
+ #define MAX_CONNINFO_OPTIONS 50
+
+
+ /*
*------------------------------------------------------------------------
* The following symbols are for enabling debugging code, not for
* controlling user-visible features or resource limits.
*** a/src/interfaces/libpq/exports.txt
--- b/src/interfaces/libpq/exports.txt
***************
*** 165,167 **** lo_lseek64 162
--- 165,169 ----
lo_tell64 163
lo_truncate64 164
PQconninfo 165
+ PQconninfoParseParams 166
+ PQconninfodefaultsMerge 167
*** a/src/interfaces/libpq/fe-connect.c
--- b/src/interfaces/libpq/fe-connect.c
***************
*** 4002,4007 **** PQconninfoParse(const char *conninfo, char **errmsg)
--- 4002,4086 ----
}
/*
+ * PQconninfoParseParams
+ *
+ * Parse a string like PQconnectdbParams() would do and return the
+ * resulting connection options array. NULL is returned on failure.
+ * The result contains only options specified directly in the array,
+ * not any possible default values.
+ *
+ * If errmsg isn't NULL, *errmsg is set to NULL on success, or a malloc'd
+ * string on failure (use PQfreemem to free it). In out-of-memory conditions
+ * both *errmsg and the result could be NULL.
+ *
+ * NOTE: the returned array is dynamically allocated and should
+ * be freed when no longer needed via PQconninfoFree().
+ */
+ PQconninfoOption *
+ PQconninfoParseParams(const char *const * keywords,
+ const char *const * values, int expand_dbname,
+ char **errmsg)
+ {
+ PQExpBufferData errorBuf;
+ PQconninfoOption *connOptions;
+
+ if (errmsg)
+ *errmsg = NULL; /* default */
+ initPQExpBuffer(&errorBuf);
+ if (PQExpBufferDataBroken(errorBuf))
+ return NULL; /* out of memory already :-( */
+ connOptions = conninfo_array_parse(keywords, values,
+ &errorBuf,
+ false, expand_dbname);
+
+ if (connOptions == NULL && errmsg)
+ *errmsg = errorBuf.data;
+ else
+ termPQExpBuffer(&errorBuf);
+ return connOptions;
+ }
+
+ /*
+ * PQconninfodefaultsMerge
+ *
+ * Add the default values for any unspecified options to the connection
+ * options array.
+ *
+ * Defaults are obtained from a service file, environment variables, etc.
+ *
+ * Returns 1 if successful, otherwise 0; connOptions is freed and errmsg is
+ * filled in upon failure. Note that failure to locate a default value is
+ * not an error condition here --- we just leave the option's value as NULL.
+ *
+ * If errmsg isn't NULL, *errmsg is set to NULL on success, or a malloc'd
+ * string on failure (use PQfreemem to free it). In out-of-memory conditions
+ * both *errmsg and the result could be NULL.
+ */
+ int
+ PQconninfodefaultsMerge(PQconninfoOption *connOptions, char **errmsg)
+ {
+ PQExpBufferData errorBuf;
+
+ if (errmsg)
+ *errmsg = NULL;
+ initPQExpBuffer(&errorBuf);
+ if (PQExpBufferDataBroken(errorBuf))
+ {
+ PQconninfoFree(connOptions);
+ return 0;
+ }
+ if (!conninfo_add_defaults(connOptions, &errorBuf))
+ {
+ if (errmsg)
+ *errmsg = errorBuf.data;
+ PQconninfoFree(connOptions);
+ return 0;
+ }
+ termPQExpBuffer(&errorBuf);
+ return 1;
+ }
+
+ /*
* Build a working copy of the constant PQconninfoOptions array.
*/
static PQconninfoOption *
*** a/src/interfaces/libpq/libpq-fe.h
--- b/src/interfaces/libpq/libpq-fe.h
***************
*** 267,276 **** extern PQconninfoOption *PQconndefaults(void);
/* parse connection options in same way as PQconnectdb */
extern PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
/* return the connection options used by a live connection */
extern PQconninfoOption *PQconninfo(PGconn *conn);
! /* free the data structure returned by PQconndefaults() or PQconninfoParse() */
extern void PQconninfoFree(PQconninfoOption *connOptions);
/*
--- 267,284 ----
/* parse connection options in same way as PQconnectdb */
extern PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
+ /* parse connection options in same way as PQconnectdbParams */
+ extern PQconninfoOption *PQconninfoParseParams(const char *const * keywords,
+ const char *const * values, int expand_dbname,
+ char **errmsg);
+
+ /* Merge default connection options into an existing PQconninfoOption struct */
+ extern int PQconninfodefaultsMerge(PQconninfoOption *connOptions, char **errmsg);
+
/* return the connection options used by a live connection */
extern PQconninfoOption *PQconninfo(PGconn *conn);
! /* free the data structure returned by PQconndefaults(), PQconninfoParse(), or PQconninfoParseParams() */
extern void PQconninfoFree(PQconninfoOption *connOptions);
/*