diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 255c5c1..e811672 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -496,6 +496,69 @@ typedef struct + + PQconninfoPQconninfo + + + Returns the connection options used by a live connection. + +PQconninfoOption *PQconninfo(PGconn *conn, int flags); + + + + + Returns a connection options array. This can be used to determine + all possible PQconnectdb options and the + values that were used to connect to the server. The return + value points to an array of PQconninfoOption + structures, which ends with an entry having a null keyword + pointer. All notes above for PQconndefaults also + apply to the result of PQconninfo. + + + + The parameter flags is used to filter which + connection options are returned. The flags are a bitmask that can be + ORed together to return parameters of multiple types at the same time. + + + + PG_CONNINFO_NORMAL + + + All normal connection options. + + + + + + PG_CONNINFO_PASSWORD + + + All connection options that include passwords or other + sensitive information. + + + + + + PG_CONNINFO_REPLICATION + + + All connection options only used for replication + connections. + + + + + + It is also possible to specify PG_CONNINFO_ALL, + which will return all options, regardless of type. + + + + + PQconninfoParsePQconninfoParse @@ -1178,28 +1241,6 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname - - requiressl - - - This option is deprecated in favor of the sslmode - setting. - - - - If set to 1, an SSL connection to the server - is required (this is equivalent to sslmode - require). libpq will then refuse - to connect if the server does not accept an - SSL connection. If set to 0 (default), - libpq will negotiate the connection type with - the server (equivalent to sslmode - prefer). This option is only available if - PostgreSQL is compiled with SSL support. - - - - sslcompression @@ -6574,16 +6615,6 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) - PGREQUIRESSL - - PGREQUIRESSL behaves the same as the connection parameter. - - - - - - PGSSLCOMPRESSION PGSSLCOMPRESSION behaves the same as the pghostaddr = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "host"); - conn->pghost = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "port"); - conn->pgport = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "tty"); - conn->pgtty = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "options"); - conn->pgoptions = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "application_name"); - conn->appname = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "fallback_application_name"); - conn->fbappname = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "dbname"); - conn->dbName = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "user"); - conn->pguser = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "password"); - conn->pgpass = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "connect_timeout"); - conn->connect_timeout = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "client_encoding"); - conn->client_encoding_initial = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "keepalives"); - conn->keepalives = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "keepalives_idle"); - conn->keepalives_idle = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "keepalives_interval"); - conn->keepalives_interval = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "keepalives_count"); - conn->keepalives_count = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "sslmode"); - conn->sslmode = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "sslcompression"); - conn->sslcompression = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "sslkey"); - conn->sslkey = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "sslcert"); - conn->sslcert = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "sslrootcert"); - conn->sslrootcert = tmp ? strdup(tmp) : NULL; - tmp = conninfo_getval(connOptions, "sslcrl"); - conn->sslcrl = tmp ? strdup(tmp) : NULL; -#ifdef USE_SSL - tmp = conninfo_getval(connOptions, "requiressl"); - if (tmp && tmp[0] == '1') + for (option = PQconninfoOptions; option->keyword; option++) { - /* here warn that the requiressl option is deprecated? */ - if (conn->sslmode) - free(conn->sslmode); - conn->sslmode = strdup("require"); + const char *tmp = conninfo_getval(connOptions, option->keyword); + + if (tmp && option->connofs >= 0) + { + char **connmember = (char **)((char *)conn + option->connofs); + + if (*connmember) + free(*connmember); + *connmember = tmp ? strdup(tmp) : NULL; + } } -#endif - tmp = conninfo_getval(connOptions, "requirepeer"); - conn->requirepeer = tmp ? strdup(tmp) : NULL; -#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI) - tmp = conninfo_getval(connOptions, "krbsrvname"); - conn->krbsrvname = tmp ? strdup(tmp) : NULL; -#endif -#if defined(ENABLE_GSS) && defined(ENABLE_SSPI) - tmp = conninfo_getval(connOptions, "gsslib"); - conn->gsslib = tmp ? strdup(tmp) : NULL; -#endif - tmp = conninfo_getval(connOptions, "replication"); - conn->replication = tmp ? strdup(tmp) : NULL; } /* @@ -884,7 +874,7 @@ PQconndefaults(void) if (PQExpBufferDataBroken(errorBuf)) return NULL; /* out of memory already :-( */ - connOptions = conninfo_init(&errorBuf); + connOptions = conninfo_init(&errorBuf, PG_CONNINFO_ALL); if (connOptions != NULL) { if (!conninfo_add_defaults(connOptions, &errorBuf)) @@ -4008,18 +3998,35 @@ PQconninfoParse(const char *conninfo, char **errmsg) * Build a working copy of the constant PQconninfoOptions array. */ static PQconninfoOption * -conninfo_init(PQExpBuffer errorMessage) +conninfo_init(PQExpBuffer errorMessage, int flags) { PQconninfoOption *options; + PQconninfoOption *opt_dest; + const internalPQconninfoOption *cur_opt; - options = (PQconninfoOption *) malloc(sizeof(PQconninfoOptions)); + /* + * Get enough memory for all optoins in PQconninfoOptions, even if some + * end up being filtered out. + */ + options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions)/sizeof(PQconninfoOptions[0])); if (options == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); return NULL; } - memcpy(options, PQconninfoOptions, sizeof(PQconninfoOptions)); + opt_dest = options; + + for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++) + { + if (!(cur_opt->flags & flags)) + continue; + + /* Only copy the public part of the struct, not the full internal */ + memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption)); + opt_dest++; + } + MemSet(opt_dest, 0, sizeof(PQconninfoOption)); return options; } @@ -4095,7 +4102,7 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, PQconninfoOption *options; /* Make a working copy of PQconninfoOptions */ - options = conninfo_init(errorMessage); + options = conninfo_init(errorMessage, PG_CONNINFO_ALL); if (options == NULL) return NULL; @@ -4295,7 +4302,7 @@ conninfo_array_parse(const char *const * keywords, const char *const * values, } /* Make a working copy of PQconninfoOptions */ - options = conninfo_init(errorMessage); + options = conninfo_init(errorMessage, PG_CONNINFO_ALL); if (options == NULL) { PQconninfoFree(dbname_options); @@ -4485,7 +4492,7 @@ conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, PQconninfoOption *options; /* Make a working copy of PQconninfoOptions */ - options = conninfo_init(errorMessage); + options = conninfo_init(errorMessage, PG_CONNINFO_ALL); if (options == NULL) return NULL; @@ -5066,6 +5073,50 @@ conninfo_find(PQconninfoOption *connOptions, const char *keyword) } +/* + * Return the connection options used for the connections + */ +PQconninfoOption * +PQconninfo(PGconn *conn, unsigned int flags) +{ + PQExpBufferData errorBuf; + PQconninfoOption *connOptions; + + if (conn == NULL) + return NULL; + + /* We don't actually report any errors here, but callees want a buffer */ + initPQExpBuffer(&errorBuf); + if (PQExpBufferDataBroken(errorBuf)) + return NULL; /* out of memory already :-( */ + + connOptions = conninfo_init(&errorBuf, flags); + + if (connOptions != NULL) + { + const internalPQconninfoOption *option; + + for (option = PQconninfoOptions; option->keyword; option++) + { + char **connmember; + + if (option->connofs < 0) + continue; + + connmember = (char **)((char *)conn + option->connofs); + + if (*connmember) + conninfo_storeval(connOptions, option->keyword, *connmember, + &errorBuf, false, false); + } + } + + termPQExpBuffer(&errorBuf); + + return connOptions; +} + + void PQconninfoFree(PQconninfoOption *connOptions) { diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h index 0b8d9a6..5038fce 100644 --- a/src/interfaces/libpq/libpq-fe.h +++ b/src/interfaces/libpq/libpq-fe.h @@ -36,6 +36,14 @@ extern "C" #define PG_COPYRES_EVENTS 0x04 #define PG_COPYRES_NOTICEHOOKS 0x08 +/* + * Option flags for PQconninfo + */ +#define PG_CONNINFO_NORMAL 0x01 +#define PG_CONNINFO_PASSWORD 0x02 +#define PG_CONNINFO_REPLICATION 0x04 +#define PG_CONNINFO_ALL 0xFFFFFFFF + /* Application-visible enum types */ /* @@ -262,6 +270,9 @@ 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, unsigned int flags); + /* free the data structure returned by PQconndefaults() or PQconninfoParse() */ extern void PQconninfoFree(PQconninfoOption *connOptions);