Commit e3f36838 authored by Joe Conway's avatar Joe Conway

Introduce two new libpq connection functions, PQconnectdbParams and

PQconnectStartParams. These are analogous to PQconnectdb and PQconnectStart
respectively. They differ from the legacy functions in that they accept
two NULL-terminated arrays, keywords and values, rather than conninfo
strings. This avoids the need to build the conninfo string in cases
where it might be inconvenient to do so. Includes documentation.

Also modify psql to utilize PQconnectdbParams rather than PQsetdbLogin.
This allows the new config parameter application_name to be set, which
in turn is displayed in the pg_stat_activity view and included in CSV
log entries. This will also ensure both new functions get regularly
exercised.

Patch by Guillaume Lelarge with review and minor adjustments by
Joe Conway.
parent 83cb7da7
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.295 2010/01/21 14:58:52 rhaas Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.296 2010/01/28 06:28:26 joe Exp $ -->
<chapter id="libpq"> <chapter id="libpq">
<title><application>libpq</application> - C Library</title> <title><application>libpq</application> - C Library</title>
...@@ -56,7 +56,8 @@ ...@@ -56,7 +56,8 @@
one time. (One reason to do that is to access more than one one time. (One reason to do that is to access more than one
database.) Each connection is represented by a database.) Each connection is represented by a
<structname>PGconn</><indexterm><primary>PGconn</></> object, which <structname>PGconn</><indexterm><primary>PGconn</></> object, which
is obtained from the function <function>PQconnectdb</> or is obtained from the function <function>PQconnectdb</>,
<function>PQconnectdbParams</>, or
<function>PQsetdbLogin</>. Note that these functions will always <function>PQsetdbLogin</>. Note that these functions will always
return a non-null object pointer, unless perhaps there is too return a non-null object pointer, unless perhaps there is too
little memory even to allocate the <structname>PGconn</> object. little memory even to allocate the <structname>PGconn</> object.
...@@ -91,35 +92,33 @@ ...@@ -91,35 +92,33 @@
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><function>PQconnectdb</function><indexterm><primary>PQconnectdb</></></term> <term><function>PQconnectdbParams</function><indexterm><primary>PQconnectdbParams</></></term>
<listitem> <listitem>
<para> <para>
Makes a new connection to the database server. Makes a new connection to the database server.
<synopsis> <synopsis>
PGconn *PQconnectdb(const char *conninfo); PGconn *PQconnectdbParams(const char **keywords, const char **values);
</synopsis> </synopsis>
</para> </para>
<para> <para>
This function opens a new database connection using the parameters taken This function opens a new database connection using the parameters taken
from the string <literal>conninfo</literal>. Unlike <function>PQsetdbLogin</> below, from two <symbol>NULL</symbol>-terminated arrays. The first,
the parameter set can be extended without changing the function signature, <literal>keywords</literal>, is defined as an array of strings, each one
so use of this function (or its nonblocking analogues <function>PQconnectStart</> being a key word. The second, <literal>values</literal>, gives the value
and <function>PQconnectPoll</function>) is preferred for new application programming. for each key word. Unlike <function>PQsetdbLogin</> below, the parameter
set can be extended without changing the function signature, so use of
this function (or its nonblocking analogs <function>PQconnectStartParams</>
and <function>PQconnectPoll</function>) is preferred for new application
programming.
</para> </para>
<para> <para>
The passed string The passed arrays can be empty to use all default parameters, or can
can be empty to use all default parameters, or it can contain one or more contain one or more parameter settings. They should be matched in length.
parameter settings separated by whitespace. Processing will stop with the last non-<symbol>NULL</symbol> element
Each parameter setting is in the form <literal>keyword = value</literal>. of the <literal>keywords</literal> array.
Spaces around the equal sign are optional.
To write an empty value or a value containing
spaces, surround it with single quotes, e.g.,
<literal>keyword = 'a value'</literal>.
Single quotes and backslashes within the value must be escaped with a
backslash, i.e., <literal>\'</literal> and <literal>\\</literal>.
</para> </para>
<para> <para>
...@@ -477,6 +476,39 @@ ...@@ -477,6 +476,39 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><function>PQconnectdb</function><indexterm><primary>PQconnectdb</></></term>
<listitem>
<para>
Makes a new connection to the database server.
<synopsis>
PGconn *PQconnectdb(const char *conninfo);
</synopsis>
</para>
<para>
This function opens a new database connection using the parameters taken
from the string <literal>conninfo</literal>.
</para>
<para>
The passed string can be empty to use all default parameters, or it can
contain one or more parameter settings separated by whitespace.
Each parameter setting is in the form <literal>keyword = value</literal>.
Spaces around the equal sign are optional. To write an empty value,
or a value containing spaces, surround it with single quotes, e.g.,
<literal>keyword = 'a value'</literal>. Single quotes and backslashes
within the value must be escaped with a backslash, i.e.,
<literal>\'</literal> and <literal>\\</literal>.
</para>
<para>
The currently recognized parameter key words are the same as above.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><function>PQsetdbLogin</function><indexterm><primary>PQsetdbLogin</></></term> <term><function>PQsetdbLogin</function><indexterm><primary>PQsetdbLogin</></></term>
<listitem> <listitem>
...@@ -532,6 +564,7 @@ PGconn *PQsetdb(char *pghost, ...@@ -532,6 +564,7 @@ PGconn *PQsetdb(char *pghost,
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><function>PQconnectStartParams</function><indexterm><primary>PQconnectStartParams</></></term>
<term><function>PQconnectStart</function><indexterm><primary>PQconnectStart</></></term> <term><function>PQconnectStart</function><indexterm><primary>PQconnectStart</></></term>
<term><function>PQconnectPoll</function><indexterm><primary>PQconnectPoll</></></term> <term><function>PQconnectPoll</function><indexterm><primary>PQconnectPoll</></></term>
<listitem> <listitem>
...@@ -539,6 +572,10 @@ PGconn *PQsetdb(char *pghost, ...@@ -539,6 +572,10 @@ PGconn *PQsetdb(char *pghost,
<indexterm><primary>nonblocking connection</primary></indexterm> <indexterm><primary>nonblocking connection</primary></indexterm>
Make a connection to the database server in a nonblocking manner. Make a connection to the database server in a nonblocking manner.
<synopsis>
PGconn *PQconnectStartParams(const char **keywords, const char **values);
</synopsis>
<synopsis> <synopsis>
PGconn *PQconnectStart(const char *conninfo); PGconn *PQconnectStart(const char *conninfo);
</synopsis> </synopsis>
...@@ -549,29 +586,37 @@ PGconn *PQsetdb(char *pghost, ...@@ -549,29 +586,37 @@ PGconn *PQsetdb(char *pghost,
</para> </para>
<para> <para>
These two functions are used to open a connection to a database server such These three functions are used to open a connection to a database server such
that your application's thread of execution is not blocked on remote I/O that your application's thread of execution is not blocked on remote I/O
whilst doing so. whilst doing so. The point of this approach is that the waits for I/O to
The point of this approach is that the waits for I/O to complete can occur complete can occur in the application's main loop, rather than down inside
in the application's main loop, rather than down inside <function>PQconnectdbParams</> or <function>PQconnectdb</>, and so the
<function>PQconnectdb</>, and so the application can manage this application can manage this operation in parallel with other activities.
operation in parallel with other activities.
</para> </para>
<para> <para>
The database connection is made using the parameters taken from the string With <function>PQconnectStartParams</function>, the database connection is made
<literal>conninfo</literal>, passed to <function>PQconnectStart</function>. This string is in using the parameters taken from the <literal>keywords</literal> and
the same format as described above for <function>PQconnectdb</function>. <literal>values</literal> arrays, as described above for
<function>PQconnectdbParams</function>.
</para> </para>
<para> <para>
Neither <function>PQconnectStart</function> nor <function>PQconnectPoll</function> will block, so long as a number of With <function>PQconnectStart</function>, the database connection is made
using the parameters taken from the string <literal>conninfo</literal> as
described above for <function>PQconnectdb</function>.
</para>
<para>
Neither <function>PQconnectStartParams</function> nor <function>PQconnectStart</function>
nor <function>PQconnectPoll</function> will block, so long as a number of
restrictions are met: restrictions are met:
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
The <literal>hostaddr</> and <literal>host</> parameters are used appropriately to ensure that The <literal>hostaddr</> and <literal>host</> parameters are used appropriately to ensure that
name and reverse name queries are not made. See the documentation of name and reverse name queries are not made. See the documentation of
these parameters under <function>PQconnectdb</function> above for details. these parameters under <function>PQconnectdbParams</function> above for details.
</para> </para>
</listitem> </listitem>
...@@ -591,6 +636,11 @@ PGconn *PQsetdb(char *pghost, ...@@ -591,6 +636,11 @@ PGconn *PQsetdb(char *pghost,
</itemizedlist> </itemizedlist>
</para> </para>
<para>
Note: use of <function>PQconnectStartParams</> is analogous to
<function>PQconnectStart</> shown below.
</para>
<para> <para>
To begin a nonblocking connection request, call <literal>conn = PQconnectStart("<replaceable>connection_info_string</>")</literal>. To begin a nonblocking connection request, call <literal>conn = PQconnectStart("<replaceable>connection_info_string</>")</literal>.
If <varname>conn</varname> is null, then <application>libpq</> has been unable to allocate a new <structname>PGconn</> If <varname>conn</varname> is null, then <application>libpq</> has been unable to allocate a new <structname>PGconn</>
...@@ -883,7 +933,8 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); ...@@ -883,7 +933,8 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
parameters previously used. This can be useful for error recovery if a parameters previously used. This can be useful for error recovery if a
working connection is lost. They differ from <function>PQreset</function> (above) in that they working connection is lost. They differ from <function>PQreset</function> (above) in that they
act in a nonblocking manner. These functions suffer from the same act in a nonblocking manner. These functions suffer from the same
restrictions as <function>PQconnectStart</> and <function>PQconnectPoll</>. restrictions as <function>PQconnectStartParams</>, <function>PQconnectStart</>
and <function>PQconnectPoll</>.
</para> </para>
<para> <para>
...@@ -1096,9 +1147,9 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); ...@@ -1096,9 +1147,9 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
</para> </para>
<para> <para>
See the entry for <function>PQconnectStart</> and <function>PQconnectPoll</> with regards See the entry for <function>PQconnectStartParams</>, <function>PQconnectStart</>
to other status codes and <function>PQconnectPoll</> with regards to other status codes that
that might be seen. might be seen.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2010, PostgreSQL Global Development Group * Copyright (c) 2000-2010, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.158 2010/01/02 16:57:59 momjian Exp $ * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.159 2010/01/28 06:28:26 joe Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
...@@ -90,6 +90,8 @@ main(int argc, char *argv[]) ...@@ -90,6 +90,8 @@ main(int argc, char *argv[])
char *password = NULL; char *password = NULL;
char *password_prompt = NULL; char *password_prompt = NULL;
bool new_pass; bool new_pass;
const char *keywords[] = {"host","port","dbname","user",
"password","application_name",NULL};
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql")); set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql"));
...@@ -171,11 +173,20 @@ main(int argc, char *argv[]) ...@@ -171,11 +173,20 @@ main(int argc, char *argv[])
/* loop until we have a password if requested by backend */ /* loop until we have a password if requested by backend */
do do
{ {
new_pass = false; const char *values[] = {
pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.host,
options.action == ACT_LIST_DB && options.dbname == NULL ? options.port,
"postgres" : options.dbname, (options.action == ACT_LIST_DB &&
options.username, password); options.dbname == NULL) ? "postgres" : options.dbname,
options.username,
password,
pset.progname,
NULL
};
new_pass = false;
pset.db = PQconnectdbParams(keywords, values);
if (PQstatus(pset.db) == CONNECTION_BAD && if (PQstatus(pset.db) == CONNECTION_BAD &&
PQconnectionNeedsPassword(pset.db) && PQconnectionNeedsPassword(pset.db) &&
......
# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.24 2010/01/21 14:58:53 rhaas Exp $ # $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.25 2010/01/28 06:28:26 joe Exp $
# Functions to be exported by libpq DLLs # Functions to be exported by libpq DLLs
PQconnectdb 1 PQconnectdb 1
PQsetdbLogin 2 PQsetdbLogin 2
...@@ -155,3 +155,5 @@ PQconninfoParse 152 ...@@ -155,3 +155,5 @@ PQconninfoParse 152
PQinitOpenSSL 153 PQinitOpenSSL 153
PQescapeLiteral 154 PQescapeLiteral 154
PQescapeIdentifier 155 PQescapeIdentifier 155
PQconnectdbParams 156
PQconnectStartParams 157
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.149 2010/01/21 14:58:53 rhaas Exp $ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.150 2010/01/28 06:28:26 joe Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -226,10 +226,12 @@ typedef struct pgresAttDesc ...@@ -226,10 +226,12 @@ typedef struct pgresAttDesc
/* make a new client connection to the backend */ /* make a new client connection to the backend */
/* Asynchronous (non-blocking) */ /* Asynchronous (non-blocking) */
extern PGconn *PQconnectStart(const char *conninfo); extern PGconn *PQconnectStart(const char *conninfo);
extern PGconn *PQconnectStartParams(const char **keywords, const char **values);
extern PostgresPollingStatusType PQconnectPoll(PGconn *conn); extern PostgresPollingStatusType PQconnectPoll(PGconn *conn);
/* Synchronous (blocking) */ /* Synchronous (blocking) */
extern PGconn *PQconnectdb(const char *conninfo); extern PGconn *PQconnectdb(const char *conninfo);
extern PGconn *PQconnectdbParams(const char **keywords, const char **values);
extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport, extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
const char *pgoptions, const char *pgtty, const char *pgoptions, const char *pgtty,
const char *dbName, const char *dbName,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment