]> granicus.if.org Git - postgresql/commitdiff
Introduce two new libpq connection functions, PQconnectdbParams and
authorJoe Conway <mail@joeconway.com>
Thu, 28 Jan 2010 06:28:26 +0000 (06:28 +0000)
committerJoe Conway <mail@joeconway.com>
Thu, 28 Jan 2010 06:28:26 +0000 (06:28 +0000)
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.

doc/src/sgml/libpq.sgml
src/bin/psql/startup.c
src/interfaces/libpq/exports.txt
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/libpq-fe.h

index 1d13e8b0b4e639e6ad9441f4ebba237905740f75..a698ab1958dd89ccf53c136d13691c76f915bcb1 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $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>
@@ -56,7 +56,8 @@
    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>
@@ -532,6 +564,7 @@ PGconn *PQsetdb(char *pghost,
     </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>
@@ -539,6 +572,10 @@ PGconn *PQsetdb(char *pghost,
        <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>
@@ -549,29 +586,37 @@ PGconn *PQsetdb(char *pghost,
       </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>
 
@@ -591,6 +636,11 @@ PGconn *PQsetdb(char *pghost,
        </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</>
@@ -883,7 +933,8 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
        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>
@@ -1096,9 +1147,9 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
       </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>
index 6ffe593786af298f3521a13e7295044e34ad85b5..b29c84fdaec26f697f38a18f08da280a19c86541 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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"
 
@@ -90,6 +90,8 @@ main(int argc, char *argv[])
        char       *password = NULL;
        char       *password_prompt = NULL;
        bool            new_pass;
+       const char *keywords[] = {"host","port","dbname","user",
+                                                         "password","application_name",NULL};
 
        set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql"));
 
@@ -171,11 +173,20 @@ main(int argc, char *argv[])
        /* loop until we have a password if requested by backend */
        do
        {
-               new_pass = false;
-               pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL,
-                                       options.action == ACT_LIST_DB && options.dbname == NULL ?
-                                                          "postgres" : options.dbname,
-                                                          options.username, password);
+        const char *values[] = {
+                  options.host,
+                  options.port,
+                  (options.action == ACT_LIST_DB && 
+                               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 &&
                        PQconnectionNeedsPassword(pset.db) &&
index a7a1b94e111ed0b81b55dbe0d939bbe68f579779..bdaa5857b7fd78f6cc6939c782ca3fd1cb5f63d9 100644 (file)
@@ -1,4 +1,4 @@
-# $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
 PQconnectdb               1
 PQsetdbLogin              2
@@ -155,3 +155,5 @@ PQconninfoParse           152
 PQinitOpenSSL             153
 PQescapeLiteral           154
 PQescapeIdentifier        155
+PQconnectdbParams         156
+PQconnectStartParams      157
index 4d7be078c0725994ef240cb98b14f3ce02b49665..048c438527b81492dd726d2d0affd5ad776f0b9f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -262,10 +262,14 @@ static bool connectOptions2(PGconn *conn);
 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);
@@ -290,22 +294,59 @@ pgthreadlock_t pg_g_threadlock = default_threadlock;
 /*
  *             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
  *
@@ -340,12 +381,12 @@ PQconnectdb(const char *conninfo)
 }
 
 /*
- *             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
@@ -359,9 +400,10 @@ PQconnectdb(const char *conninfo)
  * 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
@@ -371,10 +413,26 @@ PQconnectStart(const char *conninfo)
                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
@@ -395,33 +453,65 @@ PQconnectStart(const char *conninfo)
 }
 
 /*
- *             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
         *
@@ -482,6 +572,39 @@ connectOptions1(PGconn *conn, const char *conninfo)
 #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
@@ -3598,6 +3721,149 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
        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,
index 537bd231e8ff872487eddf63631998e8b30c84da..5f59da0f753bc76c0cc8e2b4b0269b159b660976 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * 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
 /* make a new client connection to the backend */
 /* Asynchronous (non-blocking) */
 extern PGconn *PQconnectStart(const char *conninfo);
+extern PGconn *PQconnectStartParams(const char **keywords, const char **values);
 extern PostgresPollingStatusType PQconnectPoll(PGconn *conn);
 
 /* Synchronous (blocking) */
 extern PGconn *PQconnectdb(const char *conninfo);
+extern PGconn *PQconnectdbParams(const char **keywords, const char **values);
 extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
                         const char *pgoptions, const char *pgtty,
                         const char *dbName,