On 01/26/2010 02:55 PM, Guillaume Lelarge wrote:
> Le 26/01/2010 19:43, Joe Conway a écrit :
>> On 01/25/2010 03:21 PM, Guillaume Lelarge wrote:
>>> I didn't put any documentation before knowing which one will be choosen.
>>> So we still need to work on the manual.
>>
>> Please send the documentation as a separate patch. Once I have that I
>> will commit the posted patch, barring any objections in the meantime.
> 
> You'll find it attached with this mail. Please read it carefully, my
> written english is not that good.

Final committed patch attached.

One last code correction -- in psql/startup.c the original patch defines
the keywords array in the body of the code, rather than at the top of
the block.

Minor improvements ( hopefully ;-)) to the documentation as well.

Joe
Index: doc/src/sgml/libpq.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v
retrieving revision 1.295
diff -c -r1.295 libpq.sgml
*** doc/src/sgml/libpq.sgml	21 Jan 2010 14:58:52 -0000	1.295
--- doc/src/sgml/libpq.sgml	28 Jan 2010 06:26:29 -0000
***************
*** 56,62 ****
     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
     <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.
--- 56,63 ----
     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</>,
!    <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.
***************
*** 91,125 ****
  
     <variablelist>
      <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>.  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.
        </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>
--- 92,124 ----
  
     <variablelist>
      <varlistentry>
!      <term><function>PQconnectdbParams</function><indexterm><primary>PQconnectdbParams</></></term>
       <listitem>
        <para>
         Makes a new connection to the database server.
  
         <synopsis>
!         PGconn *PQconnectdbParams(const char **keywords, const char **values);
         </synopsis>
        </para>
  
        <para>
         This function opens a new database connection using the parameters taken
!        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 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>
***************
*** 478,483 ****
--- 477,515 ----
      </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>
        <para>
***************
*** 532,537 ****
--- 564,570 ----
      </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>
***************
*** 540,545 ****
--- 573,582 ----
         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,577 ****
        </para>
  
        <para>
!        These two 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.
        </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>.
        </para>
        <para>
!        Neither <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.
           </para>
          </listitem>
  
--- 586,622 ----
        </para>
  
        <para>
!        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>PQconnectdbParams</> or <function>PQconnectdb</>, and so the
!        application can manage this operation in parallel with other activities.
        </para>
  
        <para>
!        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>
!        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>PQconnectdbParams</function> above for details.
           </para>
          </listitem>
  
***************
*** 592,597 ****
--- 637,647 ----
        </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</>
         structure. Otherwise, a valid <structname>PGconn</> pointer is returned (though not yet
***************
*** 883,889 ****
         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</>.
        </para>
  
        <para>
--- 933,940 ----
         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>PQconnectStartParams</>, <function>PQconnectStart</>
!        and <function>PQconnectPoll</>.
        </para>
  
        <para>
***************
*** 1096,1104 ****
        </para>
  
        <para>
!        See the entry for <function>PQconnectStart</> and <function>PQconnectPoll</> with regards
!        to other status codes
!        that might be seen.
        </para>
       </listitem>
      </varlistentry>
--- 1147,1155 ----
        </para>
  
        <para>
!        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: src/bin/psql/startup.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/startup.c,v
retrieving revision 1.158
diff -c -r1.158 startup.c
*** src/bin/psql/startup.c	2 Jan 2010 16:57:59 -0000	1.158
--- src/bin/psql/startup.c	28 Jan 2010 06:26:29 -0000
***************
*** 90,95 ****
--- 90,97 ----
  	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,181 ****
  	/* 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);
  
  		if (PQstatus(pset.db) == CONNECTION_BAD &&
  			PQconnectionNeedsPassword(pset.db) &&
--- 173,192 ----
  	/* loop until we have a password if requested by backend */
  	do
  	{
!         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: src/interfaces/libpq/exports.txt
===================================================================
RCS file: /cvsroot/pgsql/src/interfaces/libpq/exports.txt,v
retrieving revision 1.24
diff -c -r1.24 exports.txt
*** src/interfaces/libpq/exports.txt	21 Jan 2010 14:58:53 -0000	1.24
--- src/interfaces/libpq/exports.txt	28 Jan 2010 06:26:29 -0000
***************
*** 155,157 ****
--- 155,159 ----
  PQinitOpenSSL             153
  PQescapeLiteral           154
  PQescapeIdentifier        155
+ PQconnectdbParams         156
+ PQconnectStartParams      157
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.384
diff -c -r1.384 fe-connect.c
*** src/interfaces/libpq/fe-connect.c	20 Jan 2010 21:15:21 -0000	1.384
--- src/interfaces/libpq/fe-connect.c	28 Jan 2010 06:26:29 -0000
***************
*** 262,271 ****
--- 262,275 ----
  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,312 ****
  /*
   *		Connecting to a Database
   *
!  * There are now four 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.
   *
   * To connect in an asynchronous (non-blocking) manner, use the functions
!  * PQconnectStart, and PQconnectPoll.
   *
   * Internally, the static functions connectDBStart, connectDBComplete
   * are part of the connection procedure.
   */
  
  /*
   *		PQconnectdb
   *
   * establishes a connection to a postgres backend through the postmaster
--- 294,353 ----
  /*
   *		Connecting to a Database
   *
!  * 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 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 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
   *
   * establishes a connection to a postgres backend through the postmaster
***************
*** 340,351 ****
  }
  
  /*
!  *		PQconnectStart
   *
   * Begins the establishment of a connection to a postgres backend through the
!  * postmaster using connection information in a string.
   *
!  * 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
--- 381,392 ----
  }
  
  /*
!  *		PQconnectStartParams
   *
   * Begins the establishment of a connection to a postgres backend through the
!  * postmaster using connection information in a struct.
   *
!  * 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,367 ****
   * See PQconnectPoll for more info.
   */
  PGconn *
! PQconnectStart(const char *conninfo)
  {
! 	PGconn	   *conn;
  
  	/*
  	 * Allocate memory for the conn structure
--- 400,409 ----
   * See PQconnectPoll for more info.
   */
  PGconn *
! PQconnectStartParams(const char **keywords, const char **values)
  {
! 	PGconn			   *conn;
! 	PQconninfoOption   *connOptions;
  
  	/*
  	 * Allocate memory for the conn structure
***************
*** 371,380 ****
  		return NULL;
  
  	/*
! 	 * Parse the conninfo string
  	 */
! 	if (!connectOptions1(conn, conninfo))
! 		return conn;
  
  	/*
  	 * Compute derived options
--- 413,438 ----
  		return NULL;
  
  	/*
! 	 * Parse the conninfo arrays
  	 */
! 	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,427 ****
  }
  
  /*
!  *		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;
! 	char	   *tmp;
  
  	/*
  	 * 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
  	 *
--- 453,517 ----
  }
  
  /*
!  *		PQconnectStart
   *
!  * Begins the establishment of a connection to a postgres backend through the
!  * postmaster using connection information in a string.
   *
!  * 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.
   */
! PGconn *
! PQconnectStart(const char *conninfo)
  {
! 	PGconn	   *conn;
! 
! 	/*
! 	 * Allocate memory for the conn structure
! 	 */
! 	conn = makeEmptyPGconn();
! 	if (conn == NULL)
! 		return NULL;
  
  	/*
  	 * Parse the conninfo string
  	 */
! 	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;
  	}
  
+ 	return conn;
+ }
+ 
+ static void
+ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
+ {
+ 	char	   *tmp;
+ 
  	/*
  	 * Move option values into conn structure
  	 *
***************
*** 482,487 ****
--- 572,610 ----
  #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,3603 ****
--- 3721,3869 ----
  	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: src/interfaces/libpq/libpq-fe.h
===================================================================
RCS file: /cvsroot/pgsql/src/interfaces/libpq/libpq-fe.h,v
retrieving revision 1.149
diff -c -r1.149 libpq-fe.h
*** src/interfaces/libpq/libpq-fe.h	21 Jan 2010 14:58:53 -0000	1.149
--- src/interfaces/libpq/libpq-fe.h	28 Jan 2010 06:26:29 -0000
***************
*** 226,235 ****
--- 226,237 ----
  /* 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,

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to