-<!-- $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">
<title><application>libpq</application> - C Library</title>
one time. (One reason to do that is to access more than one
database.) Each connection is represented by a
<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
return a non-null object pointer, unless perhaps there is too
little memory even to allocate the <structname>PGconn</> object.
<variablelist>
<varlistentry>
- <term><function>PQconnectdb</function><indexterm><primary>PQconnectdb</></></term>
+ <term><function>PQconnectdbParams</function><indexterm><primary>PQconnectdbParams</></></term>
<listitem>
<para>
Makes a new connection to the database server.
<synopsis>
- PGconn *PQconnectdb(const char *conninfo);
+ PGconn *PQconnectdbParams(const char **keywords, const char **values);
</synopsis>
</para>
<para>
This function opens a new database connection using the parameters taken
- from the string <literal>conninfo</literal>. Unlike <function>PQsetdbLogin</> below,
- the parameter set can be extended without changing the function signature,
- so use of this function (or its nonblocking analogues <function>PQconnectStart</>
- and <function>PQconnectPoll</function>) is preferred for new application programming.
+ from two <symbol>NULL</symbol>-terminated arrays. The first,
+ <literal>keywords</literal>, is defined as an array of strings, each one
+ being a key word. The second, <literal>values</literal>, gives the value
+ 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>
- 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>.
+ The passed arrays can be empty to use all default parameters, or can
+ contain one or more parameter settings. They should be matched in length.
+ Processing will stop with the last non-<symbol>NULL</symbol> element
+ of the <literal>keywords</literal> array.
</para>
<para>
</listitem>
</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>
<term><function>PQsetdbLogin</function><indexterm><primary>PQsetdbLogin</></></term>
<listitem>
</varlistentry>
<varlistentry>
+ <term><function>PQconnectStartParams</function><indexterm><primary>PQconnectStartParams</></></term>
<term><function>PQconnectStart</function><indexterm><primary>PQconnectStart</></></term>
<term><function>PQconnectPoll</function><indexterm><primary>PQconnectPoll</></></term>
<listitem>
<indexterm><primary>nonblocking connection</primary></indexterm>
Make a connection to the database server in a nonblocking manner.
+ <synopsis>
+ PGconn *PQconnectStartParams(const char **keywords, const char **values);
+ </synopsis>
+
<synopsis>
PGconn *PQconnectStart(const char *conninfo);
</synopsis>
</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
- whilst doing so.
- The point of this approach is that the waits for I/O to complete can occur
- in the application's main loop, rather than down inside
- <function>PQconnectdb</>, and so the application can manage this
- operation in parallel with other activities.
+ whilst doing so. The point of this approach is that the waits for I/O to
+ complete can occur in the application's main loop, rather than down inside
+ <function>PQconnectdbParams</> or <function>PQconnectdb</>, and so the
+ application can manage this operation in parallel with other activities.
</para>
<para>
- The database connection is made using the parameters taken from the string
- <literal>conninfo</literal>, passed to <function>PQconnectStart</function>. This string is in
- the same format as described above for <function>PQconnectdb</function>.
+ With <function>PQconnectStartParams</function>, the database connection is made
+ using the parameters taken from the <literal>keywords</literal> and
+ <literal>values</literal> arrays, as described above for
+ <function>PQconnectdbParams</function>.
</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:
<itemizedlist>
<listitem>
<para>
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
- these parameters under <function>PQconnectdb</function> above for details.
+ these parameters under <function>PQconnectdbParams</function> above for details.
</para>
</listitem>
</itemizedlist>
</para>
+ <para>
+ Note: use of <function>PQconnectStartParams</> is analogous to
+ <function>PQconnectStart</> shown below.
+ </para>
+
<para>
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</>
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
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>
- See the entry for <function>PQconnectStart</> and <function>PQconnectPoll</> with regards
- to other status codes
- that might be seen.
+ See the entry for <function>PQconnectStartParams</>, <function>PQconnectStart</>
+ and <function>PQconnectPoll</> with regards to other status codes that
+ might be seen.
</para>
</listitem>
</varlistentry>
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.384 2010/01/20 21:15:21 petere Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.385 2010/01/28 06:28:26 joe Exp $
*
*-------------------------------------------------------------------------
*/
static int connectDBStart(PGconn *conn);
static int connectDBComplete(PGconn *conn);
static PGconn *makeEmptyPGconn(void);
+static void fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
static void freePGconn(PGconn *conn);
static void closePGconn(PGconn *conn);
static PQconninfoOption *conninfo_parse(const char *conninfo,
PQExpBuffer errorMessage, bool use_defaults);
+static PQconninfoOption *conninfo_array_parse(const char **keywords,
+ const char **values, PQExpBuffer errorMessage,
+ bool use_defaults);
static char *conninfo_getval(PQconninfoOption *connOptions,
const char *keyword);
static void defaultNoticeReceiver(void *arg, const PGresult *res);
/*
* Connecting to a Database
*
- * There are now four different ways a user of this API can connect to the
+ * There are now six different ways a user of this API can connect to the
* database. Two are not recommended for use in new code, because of their
* lack of extensibility with respect to the passing of options to the
* backend. These are PQsetdb and PQsetdbLogin (the former now being a macro
* to the latter).
*
* If it is desired to connect in a synchronous (blocking) manner, use the
- * function PQconnectdb.
+ * function PQconnectdb or PQconnectdbParams. The former accepts a string
+ * of option = value pairs which must be parsed; the latter takes two NULL
+ * terminated arrays instead.
*
* To connect in an asynchronous (non-blocking) manner, use the functions
- * PQconnectStart, and PQconnectPoll.
+ * PQconnectStart or PQconnectStartParams (which differ in the same way as
+ * PQconnectdb and PQconnectdbParams) and PQconnectPoll.
*
* Internally, the static functions connectDBStart, connectDBComplete
* are part of the connection procedure.
*/
+/*
+ * PQconnectdbParams
+ *
+ * establishes a connection to a postgres backend through the postmaster
+ * using connection information in two arrays.
+ *
+ * The keywords array is defined as
+ *
+ * const char *params[] = {"option1", "option2", NULL}
+ *
+ * The values array is defined as
+ *
+ * const char *values[] = {"value1", "value2", NULL}
+ *
+ * Returns a PGconn* which is needed for all subsequent libpq calls, or NULL
+ * if a memory allocation failed.
+ * If the status field of the connection returned is CONNECTION_BAD,
+ * then some fields may be null'ed out instead of having valid values.
+ *
+ * You should call PQfinish (if conn is not NULL) regardless of whether this
+ * call succeeded.
+ */
+PGconn *
+PQconnectdbParams(const char **keywords, const char **values)
+{
+ PGconn *conn = PQconnectStartParams(keywords, values);
+
+ if (conn && conn->status != CONNECTION_BAD)
+ (void) connectDBComplete(conn);
+
+ return conn;
+
+}
+
/*
* PQconnectdb
*
}
/*
- * PQconnectStart
+ * PQconnectStartParams
*
* Begins the establishment of a connection to a postgres backend through the
- * postmaster using connection information in a string.
+ * postmaster using connection information in a struct.
*
- * See comment for PQconnectdb for the definition of the string format.
+ * See comment for PQconnectdbParams for the definition of the string format.
*
* Returns a PGconn*. If NULL is returned, a malloc error has occurred, and
* you should not attempt to proceed with this connection. If the status
* See PQconnectPoll for more info.
*/
PGconn *
-PQconnectStart(const char *conninfo)
+PQconnectStartParams(const char **keywords, const char **values)
{
- PGconn *conn;
+ PGconn *conn;
+ PQconninfoOption *connOptions;
/*
* Allocate memory for the conn structure
return NULL;
/*
- * Parse the conninfo string
+ * Parse the conninfo arrays
*/
- if (!connectOptions1(conn, conninfo))
- return conn;
+ connOptions = conninfo_array_parse(keywords, values,
+ &conn->errorMessage, true);
+ if (connOptions == NULL)
+ {
+ conn->status = CONNECTION_BAD;
+ /* errorMessage is already set */
+ return false;
+ }
+
+ /*
+ * Move option values into conn structure
+ */
+ fillPGconn(conn, connOptions);
+
+ /*
+ * Free the option info - all is in conn now
+ */
+ PQconninfoFree(connOptions);
/*
* Compute derived options
}
/*
- * connectOptions1
+ * PQconnectStart
*
- * Internal subroutine to set up connection parameters given an already-
- * created PGconn and a conninfo string. Derived settings should be
- * processed by calling connectOptions2 next. (We split them because
- * PQsetdbLogin overrides defaults in between.)
+ * Begins the establishment of a connection to a postgres backend through the
+ * postmaster using connection information in a string.
*
- * Returns true if OK, false if trouble (in which case errorMessage is set
- * and so is conn->status).
+ * See comment for PQconnectdb for the definition of the string format.
+ *
+ * Returns a PGconn*. If NULL is returned, a malloc error has occurred, and
+ * you should not attempt to proceed with this connection. If the status
+ * field of the connection returned is CONNECTION_BAD, an error has
+ * occurred. In this case you should call PQfinish on the result, (perhaps
+ * inspecting the error message first). Other fields of the structure may not
+ * be valid if that occurs. If the status field is not CONNECTION_BAD, then
+ * this stage has succeeded - call PQconnectPoll, using select(2) to see when
+ * this is necessary.
+ *
+ * See PQconnectPoll for more info.
*/
-static bool
-connectOptions1(PGconn *conn, const char *conninfo)
+PGconn *
+PQconnectStart(const char *conninfo)
{
- PQconninfoOption *connOptions;
- char *tmp;
+ PGconn *conn;
+
+ /*
+ * Allocate memory for the conn structure
+ */
+ conn = makeEmptyPGconn();
+ if (conn == NULL)
+ return NULL;
/*
* Parse the conninfo string
*/
- connOptions = conninfo_parse(conninfo, &conn->errorMessage, true);
- if (connOptions == NULL)
+ if (!connectOptions1(conn, conninfo))
+ return conn;
+
+ /*
+ * Compute derived options
+ */
+ if (!connectOptions2(conn))
+ return conn;
+
+ /*
+ * Connect to the database
+ */
+ if (!connectDBStart(conn))
{
+ /* Just in case we failed to set it in connectDBStart */
conn->status = CONNECTION_BAD;
- /* errorMessage is already set */
- return false;
}
+ return conn;
+}
+
+static void
+fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
+{
+ char *tmp;
+
/*
* Move option values into conn structure
*
#endif
tmp = conninfo_getval(connOptions, "replication");
conn->replication = tmp ? strdup(tmp) : NULL;
+}
+
+/*
+ * connectOptions1
+ *
+ * Internal subroutine to set up connection parameters given an already-
+ * created PGconn and a conninfo string. Derived settings should be
+ * processed by calling connectOptions2 next. (We split them because
+ * PQsetdbLogin overrides defaults in between.)
+ *
+ * Returns true if OK, false if trouble (in which case errorMessage is set
+ * and so is conn->status).
+ */
+static bool
+connectOptions1(PGconn *conn, const char *conninfo)
+{
+ PQconninfoOption *connOptions;
+
+ /*
+ * Parse the conninfo string
+ */
+ connOptions = conninfo_parse(conninfo, &conn->errorMessage, true);
+ if (connOptions == NULL)
+ {
+ conn->status = CONNECTION_BAD;
+ /* errorMessage is already set */
+ return false;
+ }
+
+ /*
+ * Move option values into conn structure
+ */
+ fillPGconn(conn, connOptions);
/*
* Free the option info - all is in conn now
return options;
}
+/*
+ * Conninfo array parser routine
+ *
+ * If successful, a malloc'd PQconninfoOption array is returned.
+ * If not successful, NULL is returned and an error message is
+ * left in errorMessage.
+ * Defaults are supplied (from a service file, environment variables, etc)
+ * for unspecified options, but only if use_defaults is TRUE.
+ */
+static PQconninfoOption *
+conninfo_array_parse(const char **keywords, const char **values,
+ PQExpBuffer errorMessage, bool use_defaults)
+{
+ char *tmp;
+ PQconninfoOption *options;
+ PQconninfoOption *option;
+ int i = 0;
+
+ /* Make a working copy of PQconninfoOptions */
+ options = malloc(sizeof(PQconninfoOptions));
+ if (options == NULL)
+ {
+ printfPQExpBuffer(errorMessage,
+ libpq_gettext("out of memory\n"));
+ return NULL;
+ }
+ memcpy(options, PQconninfoOptions, sizeof(PQconninfoOptions));
+
+ /* Parse the keywords/values arrays */
+ while(keywords[i])
+ {
+ const char *pname = keywords[i];
+ const char *pvalue = values[i];
+
+ if (pvalue != NULL)
+ {
+ /* Search for the param record */
+ for (option = options; option->keyword != NULL; option++)
+ {
+ if (strcmp(option->keyword, pname) == 0)
+ break;
+ }
+
+ /* Check for invalid connection option */
+ if (option->keyword == NULL)
+ {
+ printfPQExpBuffer(errorMessage,
+ libpq_gettext("invalid connection option \"%s\"\n"),
+ pname);
+ PQconninfoFree(options);
+ return NULL;
+ }
+
+ /*
+ * Store the value
+ */
+ if (option->val)
+ free(option->val);
+ option->val = strdup(pvalue);
+ if (!option->val)
+ {
+ printfPQExpBuffer(errorMessage,
+ libpq_gettext("out of memory\n"));
+ PQconninfoFree(options);
+ return NULL;
+ }
+ }
+ ++i;
+ }
+
+ /*
+ * Stop here if caller doesn't want defaults filled in.
+ */
+ if (!use_defaults)
+ return options;
+
+ /*
+ * If there's a service spec, use it to obtain any not-explicitly-given
+ * parameters.
+ */
+ if (parseServiceInfo(options, errorMessage))
+ {
+ PQconninfoFree(options);
+ return NULL;
+ }
+
+ /*
+ * Get the fallback resources for parameters not specified in the conninfo
+ * string nor the service.
+ */
+ for (option = options; option->keyword != NULL; option++)
+ {
+ if (option->val != NULL)
+ continue; /* Value was in conninfo or service */
+
+ /*
+ * Try to get the environment variable fallback
+ */
+ if (option->envvar != NULL)
+ {
+ if ((tmp = getenv(option->envvar)) != NULL)
+ {
+ option->val = strdup(tmp);
+ if (!option->val)
+ {
+ printfPQExpBuffer(errorMessage,
+ libpq_gettext("out of memory\n"));
+ PQconninfoFree(options);
+ return NULL;
+ }
+ continue;
+ }
+ }
+
+ /*
+ * No environment variable specified or this one isn't set - try
+ * compiled in
+ */
+ if (option->compiled != NULL)
+ {
+ option->val = strdup(option->compiled);
+ if (!option->val)
+ {
+ printfPQExpBuffer(errorMessage,
+ libpq_gettext("out of memory\n"));
+ PQconninfoFree(options);
+ return NULL;
+ }
+ continue;
+ }
+
+ /*
+ * Special handling for user
+ */
+ if (strcmp(option->keyword, "user") == 0)
+ {
+ option->val = pg_fe_getauthname(errorMessage);
+ continue;
+ }
+ }
+
+ return options;
+}
static char *
conninfo_getval(PQconninfoOption *connOptions,