diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a698ab1958dd89ccf53c136d13691c76f915bcb1..c7131fea4c44cdf241d3c4f3bd08ec2097bd8f6f 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.296 2010/01/28 06:28:26 joe Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.297 2010/02/05 03:09:04 joe Exp $ -->
 
 <chapter id="libpq">
  <title><application>libpq</application> - C Library</title>
@@ -98,7 +98,7 @@
        Makes a new connection to the database server.
 
        <synopsis>
-        PGconn *PQconnectdbParams(const char **keywords, const char **values);
+        PGconn *PQconnectdbParams(const char **keywords, const char **values, int expand_dbname);
        </synopsis>
       </para>
 
@@ -114,6 +114,12 @@
        programming.
       </para>
 
+      <para>
+       When <literal>expand_dbname</literal> is non-zero, the
+       <parameter>dbname</parameter> key word value is allowed to be recognized
+       as a <parameter>conninfo</parameter> string. See below for details.
+      </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.
@@ -473,6 +479,24 @@
        is checked. If the  environment  variable is not set either,
        then the indicated built-in defaults are used.
       </para>
+
+      <para>
+        If <literal>expand_dbname</literal> is non-zero and 
+        <parameter>dbname</parameter> contains an <symbol>=</symbol> sign, it
+        is taken as a <parameter>conninfo</parameter> string in exactly the same way as
+        if it had been passed to <function>PQconnectdb</function>(see below). Previously
+        processed key words will be overridden by key words in the
+        <parameter>conninfo</parameter> string.
+      </para>
+
+      <para>
+        In general key words are processed from the beginning of these arrays in index
+        order. The effect of this is that when key words are repeated, the last processed
+        value is retained. Therefore, through careful placement of the
+        <parameter>dbname</parameter> key word, it is possible to determine what may
+        be overridden by a <parameter>conninfo</parameter> string, and what may not.
+      </para>
+
      </listitem>
     </varlistentry>
 
@@ -573,7 +597,7 @@ PGconn *PQsetdb(char *pghost,
        Make a connection to the database server in a nonblocking manner.
 
        <synopsis>
-        PGconn *PQconnectStartParams(const char **keywords, const char **values);
+        PGconn *PQconnectStartParams(const char **keywords, const char **values, int expand_dbname);
        </synopsis>
 
        <synopsis>
@@ -597,8 +621,8 @@ PGconn *PQsetdb(char *pghost,
       <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>.
+       <literal>values</literal> arrays, and controlled by <literal>expand_dbname</literal>,
+       as described above for <function>PQconnectdbParams</function>.
       </para>
 
       <para>
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index 1d72d6dd7e2470e8aa1f66b66c6f512cc21a08bd..4aa10135bb06ea7e64a08164b9205cb390aa6328 100644
--- a/src/bin/pg_dump/pg_backup_db.c
+++ b/src/bin/pg_dump/pg_backup_db.c
@@ -5,7 +5,7 @@
  *	Implements the basic DB functions used by the archiver.
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.85 2009/12/14 00:39:11 itagaki Exp $
+ *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.86 2010/02/05 03:09:05 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -154,10 +154,34 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
 
 	do
 	{
+#define PARAMS_ARRAY_SIZE	7
+		const char **keywords = malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
+		const char **values = malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
+
+		if (!keywords || !values)
+			die_horribly(AH, modulename, "out of memory\n");
+
+		keywords[0]	= "host";
+		values[0]	= PQhost(AH->connection);
+		keywords[1]	= "port";
+		values[1]	= PQport(AH->connection);
+		keywords[2]	= "user";
+		values[2]	= newuser;
+		keywords[3]	= "password";
+		values[3]	= password;
+		keywords[4]	= "dbname";
+		values[4]	= newdb;
+		keywords[5]	= "fallback_application_name";
+		values[5]	= progname;
+		keywords[6]	= NULL;
+		values[6]	= NULL;
+
 		new_pass = false;
-		newConn = PQsetdbLogin(PQhost(AH->connection), PQport(AH->connection),
-							   NULL, NULL, newdb,
-							   newuser, password);
+		newConn = PQconnectdbParams(keywords, values, true);
+
+		free(keywords);
+		free(values);
+
 		if (!newConn)
 			die_horribly(AH, modulename, "failed to reconnect to database\n");
 
@@ -237,9 +261,33 @@ ConnectDatabase(Archive *AHX,
 	 */
 	do
 	{
+#define PARAMS_ARRAY_SIZE	7
+		const char **keywords = malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
+		const char **values = malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
+
+		if (!keywords || !values)
+			die_horribly(AH, modulename, "out of memory\n");
+
+		keywords[0]	= "host";
+		values[0]	= pghost;
+		keywords[1]	= "port";
+		values[1]	= pgport;
+		keywords[2]	= "user";
+		values[2]	= username;
+		keywords[3]	= "password";
+		values[3]	= password;
+		keywords[4]	= "dbname";
+		values[4]	= dbname;
+		keywords[5]	= "fallback_application_name";
+		values[5]	= progname;
+		keywords[6]	= NULL;
+		values[6]	= NULL;
+
 		new_pass = false;
-		AH->connection = PQsetdbLogin(pghost, pgport, NULL, NULL,
-									  dbname, username, password);
+		AH->connection = PQconnectdbParams(keywords, values, true);
+
+		free(keywords);
+		free(values);
 
 		if (!AH->connection)
 			die_horribly(AH, modulename, "failed to connect to database\n");
@@ -697,3 +745,4 @@ _isDQChar(unsigned char c, bool atStart)
 	else
 		return false;
 }
+
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 48084db12f880813943981b9975deb901979531a..f1d74574313c94c8a8e2cedbc9a27accf21df8b4 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.131 2010/01/06 03:34:41 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.132 2010/02/05 03:09:05 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1618,8 +1618,36 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
 	 */
 	do
 	{
+#define PARAMS_ARRAY_SIZE	7
+		const char **keywords = malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
+		const char **values = malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
+
+		if (!keywords || !values)
+		{
+			fprintf(stderr, _("%s: out of memory\n"), progname);
+			exit(1);
+		}
+
+		keywords[0]	= "host";
+		values[0]	= pghost;
+		keywords[1]	= "port";
+		values[1]	= pgport;
+		keywords[2]	= "user";
+		values[2]	= pguser;
+		keywords[3]	= "password";
+		values[3]	= password;
+		keywords[4]	= "dbname";
+		values[4]	= dbname;
+		keywords[5]	= "fallback_application_name";
+		values[5]	= progname;
+		keywords[6]	= NULL;
+		values[6]	= NULL;
+
 		new_pass = false;
-		conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password);
+		conn = PQconnectdbParams(keywords, values, true);
+
+		free(keywords);
+		free(values);
 
 		if (!conn)
 		{
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 10f36dc22d451ebc332986eb946451e83947751e..74119fd29f0c927ba132c7502c6c2ba6f8c15abe 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2010, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.213 2010/01/02 16:57:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.214 2010/02/05 03:09:05 joe Exp $
  */
 #include "postgres_fe.h"
 #include "command.h"
@@ -1213,7 +1213,7 @@ param_is_newly_set(const char *old_val, const char *new_val)
  * Connects to a database with given parameters. If there exists an
  * established connection, NULL values will be replaced with the ones
  * in the current connection. Otherwise NULL will be passed for that
- * parameter to PQsetdbLogin(), so the libpq defaults will be used.
+ * parameter to PQconnectdbParams(), so the libpq defaults will be used.
  *
  * In interactive mode, if connection fails with the given parameters,
  * the old connection will be kept.
@@ -1255,8 +1255,29 @@ do_connect(char *dbname, char *user, char *host, char *port)
 
 	while (true)
 	{
-		n_conn = PQsetdbLogin(host, port, NULL, NULL,
-							  dbname, user, password);
+#define PARAMS_ARRAY_SIZE	7
+		const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
+		const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
+
+		keywords[0]	= "host";
+		values[0]	= host;
+		keywords[1]	= "port";
+		values[1]	= port;
+		keywords[2]	= "user";
+		values[2]	= user;
+		keywords[3]	= "password";
+		values[3]	= password;
+		keywords[4]	= "dbname";
+		values[4]	= dbname;
+		keywords[5]	= "fallback_application_name";
+		values[5]	= pset.progname;
+		keywords[6]	= NULL;
+		values[6]	= NULL;
+
+		n_conn = PQconnectdbParams(keywords, values, true);
+
+		free(keywords);
+		free(values);
 
 		/* We can immediately discard the password -- no longer needed */
 		if (password)
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index b29c84fdaec26f697f38a18f08da280a19c86541..c45a869d92cd0f72f070319ea216b5be3e92224f 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2010, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.159 2010/01/28 06:28:26 joe Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.160 2010/02/05 03:09:05 joe Exp $
  */
 #include "postgres_fe.h"
 
@@ -90,8 +90,6 @@ 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"));
 
@@ -173,20 +171,31 @@ main(int argc, char *argv[])
 	/* 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);
+#define PARAMS_ARRAY_SIZE	7
+		const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
+		const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
+
+		keywords[0]	= "host";
+		values[0]	= options.host;
+		keywords[1]	= "port";
+		values[1]	= options.port;
+		keywords[2]	= "user";
+		values[2]	= options.username;
+		keywords[3]	= "password";
+		values[3]	= password;
+		keywords[4]	= "dbname";
+		values[4]	= (options.action == ACT_LIST_DB &&
+						options.dbname == NULL) ?
+						"postgres" : options.dbname;
+		keywords[5]	= "fallback_application_name";
+		values[5]	= pset.progname;
+		keywords[6]	= NULL;
+		values[6]	= NULL;
+
+		new_pass = false;
+		pset.db = PQconnectdbParams(keywords, values, true);
+		free(keywords);
+		free(values);
 
 		if (PQstatus(pset.db) == CONNECTION_BAD &&
 			PQconnectionNeedsPassword(pset.db) &&
diff --git a/src/bin/scripts/common.c b/src/bin/scripts/common.c
index 27aafa102c404f92ee54c9c0969d6f840856966a..026eb80a025fd941ca3a7a451d8393af5ad7287b 100644
--- a/src/bin/scripts/common.c
+++ b/src/bin/scripts/common.c
@@ -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/bin/scripts/common.c,v 1.38 2010/01/02 16:58:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/scripts/common.c,v 1.39 2010/02/05 03:09:05 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -108,8 +108,36 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
 	 */
 	do
 	{
+#define PARAMS_ARRAY_SIZE	7
+		const char **keywords = malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
+		const char **values = malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
+
+		if (!keywords || !values)
+		{
+			fprintf(stderr, _("%s: out of memory\n"), progname);
+			exit(1);
+		}
+
+		keywords[0]	= "host";
+		values[0]	= pghost;
+		keywords[1]	= "port";
+		values[1]	= pgport;
+		keywords[2]	= "user";
+		values[2]	= pguser;
+		keywords[3]	= "password";
+		values[3]	= password;
+		keywords[4]	= "dbname";
+		values[4]	= dbname;
+		keywords[5]	= "fallback_application_name";
+		values[5]	= progname;
+		keywords[6]	= NULL;
+		values[6]	= NULL;
+
 		new_pass = false;
-		conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password);
+		conn = PQconnectdbParams(keywords, values, true);
+
+		free(keywords);
+		free(values);
 
 		if (!conn)
 		{
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 048c438527b81492dd726d2d0affd5ad776f0b9f..994b70b190487888b88af7b8775faf1d962ddc08 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.385 2010/01/28 06:28:26 joe Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.386 2010/02/05 03:09:05 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -269,7 +269,7 @@ 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);
+				bool use_defaults, int expand_dbname);
 static char *conninfo_getval(PQconninfoOption *connOptions,
 				const char *keyword);
 static void defaultNoticeReceiver(void *arg, const PGresult *res);
@@ -336,9 +336,11 @@ pgthreadlock_t pg_g_threadlock = default_threadlock;
  * call succeeded.
  */
 PGconn *
-PQconnectdbParams(const char **keywords, const char **values)
+PQconnectdbParams(const char **keywords,
+				  const char **values,
+				  int expand_dbname)
 {
-	PGconn	   *conn = PQconnectStartParams(keywords, values);
+	PGconn	   *conn = PQconnectStartParams(keywords, values, expand_dbname);
 
 	if (conn && conn->status != CONNECTION_BAD)
 		(void) connectDBComplete(conn);
@@ -400,7 +402,9 @@ PQconnectdb(const char *conninfo)
  * See PQconnectPoll for more info.
  */
 PGconn *
-PQconnectStartParams(const char **keywords, const char **values)
+PQconnectStartParams(const char **keywords,
+					 const char **values,
+					 int expand_dbname)
 {
 	PGconn			   *conn;
 	PQconninfoOption   *connOptions;
@@ -416,7 +420,8 @@ PQconnectStartParams(const char **keywords, const char **values)
 	 * Parse the conninfo arrays
 	 */
 	connOptions = conninfo_array_parse(keywords, values,
-									   &conn->errorMessage, true);
+									   &conn->errorMessage,
+									   true, expand_dbname);
 	if (connOptions == NULL)
 	{
 		conn->status = CONNECTION_BAD;
@@ -3729,16 +3734,53 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
  * left in errorMessage.
  * Defaults are supplied (from a service file, environment variables, etc)
  * for unspecified options, but only if use_defaults is TRUE.
+ *
+ * If expand_dbname is non-zero, and the value passed for keyword "dbname"
+ * contains an "=", assume it is a conninfo string and process it,
+ * overriding any previously processed conflicting keywords. Subsequent
+ * keywords will take precedence, however.
  */
 static PQconninfoOption *
 conninfo_array_parse(const char **keywords, const char **values,
-					 PQExpBuffer errorMessage, bool use_defaults)
+					 PQExpBuffer errorMessage, bool use_defaults,
+					 int expand_dbname)
 {
 	char			   *tmp;
 	PQconninfoOption   *options;
+	PQconninfoOption   *str_options = NULL;
 	PQconninfoOption   *option;
 	int					i = 0;
 
+	/*
+	 * If expand_dbname is non-zero, check keyword "dbname"
+	 * to see if val is actually a conninfo string
+	 */
+	while(expand_dbname && keywords[i])
+	{
+		const char *pname = keywords[i];
+		const char *pvalue  = values[i];
+
+		/* first find "dbname" if any */
+		if (strcmp(pname, "dbname") == 0)
+		{
+			/* next look for "=" in the value */
+			if (pvalue && strchr(pvalue, '='))
+			{
+				/*
+				 * Must be a conninfo string, so parse it, but do not
+				 * use defaults here -- those get picked up later.
+				 * We only want to override for those parameters actually
+				 * passed.
+				 */
+				str_options = conninfo_parse(pvalue, errorMessage, false);
+				if (str_options == NULL)
+					return NULL;
+			}
+			break;
+		}
+		++i;
+	}
+
 	/* Make a working copy of PQconninfoOptions */
 	options = malloc(sizeof(PQconninfoOptions));
 	if (options == NULL)
@@ -3749,6 +3791,7 @@ conninfo_array_parse(const char **keywords, const char **values,
 	}
 	memcpy(options, PQconninfoOptions, sizeof(PQconninfoOptions));
 
+	i = 0;
 	/* Parse the keywords/values arrays */
 	while(keywords[i])
 	{
@@ -3774,22 +3817,54 @@ conninfo_array_parse(const char **keywords, const char **values,
 				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;
-		    }
+			/*
+			 * If we are on the dbname parameter, and we have a parsed
+			 * conninfo string, copy those parameters across, overriding
+			 * any existing previous settings
+			 */
+			if (strcmp(pname, "dbname") == 0 && str_options)
+			{
+				PQconninfoOption *str_option;
+
+				for (str_option = str_options; str_option->keyword != NULL; str_option++)
+				{
+					if (str_option->val != NULL)
+					{
+						int			k;
+
+						for (k = 0; options[k].keyword; k++)
+						{
+							if (strcmp(options[k].keyword, str_option->keyword) == 0)
+							{
+								if (options[k].val)
+									free(options[k].val);
+								options[k].val = strdup(str_option->val);
+								break;
+							}
+						}
+					}
+				}
+			}
+			else
+			{
+				/*
+				 * Store the value, overriding previous settings
+				 */
+				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;
 	}
+	PQconninfoFree(str_options);
 
 	/*
 	 * Stop here if caller doesn't want defaults filled in.
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 5f59da0f753bc76c0cc8e2b4b0269b159b660976..c2698fe257e1c2667c31cecf44b3cd24a1cf2fe1 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -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.150 2010/01/28 06:28:26 joe Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.151 2010/02/05 03:09:05 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -226,12 +226,14 @@ 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 PGconn *PQconnectStartParams(const char **keywords,
+			 const char **values, int expand_dbname);
 extern PostgresPollingStatusType PQconnectPoll(PGconn *conn);
 
 /* Synchronous (blocking) */
 extern PGconn *PQconnectdb(const char *conninfo);
-extern PGconn *PQconnectdbParams(const char **keywords, const char **values);
+extern PGconn *PQconnectdbParams(const char **keywords,
+			 const char **values, int expand_dbname);
 extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
 			 const char *pgoptions, const char *pgtty,
 			 const char *dbName,