@@ -56,7 +56,8 @@ static backslashResult exec_command(const char *cmd,
5656 PQExpBuffer query_buf );
5757static bool do_edit (const char * filename_arg , PQExpBuffer query_buf ,
5858 int lineno , bool * edited );
59- static bool do_connect (char * dbname , char * user , char * host , char * port );
59+ static bool do_connect (enum trivalue reuse_previous_specification ,
60+ char * dbname , char * user , char * host , char * port );
6061static bool do_shell (const char * command );
6162static bool do_watch (PQExpBuffer query_buf , long sleep );
6263static bool lookup_function_oid (const char * desc , Oid * foid );
@@ -217,12 +218,9 @@ exec_command(const char *cmd,
217218 /*
218219 * \c or \connect -- connect to database using the specified parameters.
219220 *
220- * \c dbname user host port
221+ * \c [-reuse-previous=BOOL] dbname user host port
221222 *
222- * If any of these parameters are omitted or specified as '-', the current
223- * value of the parameter will be used instead. If the parameter has no
224- * current value, the default value for that parameter will be used. Some
225- * examples:
223+ * Specifying a parameter as '-' is equivalent to omitting it. Examples:
226224 *
227225 * \c - - hst Connect to current database on current port of host
228226 * "hst" as current user. \c - usr - prt Connect to current database on
@@ -231,17 +229,31 @@ exec_command(const char *cmd,
231229 */
232230 else if (strcmp (cmd , "c" ) == 0 || strcmp (cmd , "connect" ) == 0 )
233231 {
232+ static const char prefix [] = "-reuse-previous=" ;
234233 char * opt1 ,
235234 * opt2 ,
236235 * opt3 ,
237236 * opt4 ;
237+ enum trivalue reuse_previous ;
238238
239239 opt1 = read_connect_arg (scan_state );
240+ if (opt1 != NULL && strncmp (opt1 , prefix , sizeof (prefix ) - 1 ) == 0 )
241+ {
242+ reuse_previous =
243+ ParseVariableBool (opt1 + sizeof (prefix ) - 1 , prefix ) ?
244+ TRI_YES : TRI_NO ;
245+
246+ free (opt1 );
247+ opt1 = read_connect_arg (scan_state );
248+ }
249+ else
250+ reuse_previous = TRI_DEFAULT ;
251+
240252 opt2 = read_connect_arg (scan_state );
241253 opt3 = read_connect_arg (scan_state );
242254 opt4 = read_connect_arg (scan_state );
243255
244- success = do_connect (opt1 , opt2 , opt3 , opt4 );
256+ success = do_connect (reuse_previous , opt1 , opt2 , opt3 , opt4 );
245257
246258 free (opt1 );
247259 free (opt2 );
@@ -1599,22 +1611,25 @@ param_is_newly_set(const char *old_val, const char *new_val)
15991611/*
16001612 * do_connect -- handler for \connect
16011613 *
1602- * Connects to a database with given parameters. If there exists an
1603- * established connection, NULL values will be replaced with the ones
1604- * in the current connection. Otherwise NULL will be passed for that
1605- * parameter to PQconnectdbParams(), so the libpq defaults will be used.
1614+ * Connects to a database with given parameters. Absent an established
1615+ * connection, all parameters are required. Given -reuse-previous=off or a
1616+ * connection string without -reuse-previous=on, NULL values will pass through
1617+ * to PQconnectdbParams(), so the libpq defaults will be used. Otherwise, NULL
1618+ * values will be replaced with the ones in the current connection.
16061619 *
16071620 * In interactive mode, if connection fails with the given parameters,
16081621 * the old connection will be kept.
16091622 */
16101623static bool
1611- do_connect (char * dbname , char * user , char * host , char * port )
1624+ do_connect (enum trivalue reuse_previous_specification ,
1625+ char * dbname , char * user , char * host , char * port )
16121626{
16131627 PGconn * o_conn = pset .db ,
16141628 * n_conn ;
16151629 char * password = NULL ;
16161630 bool keep_password ;
16171631 bool has_connection_string ;
1632+ bool reuse_previous ;
16181633
16191634 if (!o_conn && (!dbname || !user || !host || !port ))
16201635 {
@@ -1628,17 +1643,36 @@ do_connect(char *dbname, char *user, char *host, char *port)
16281643 return false;
16291644 }
16301645
1631- /* grab values from the old connection, unless supplied by caller */
1632- if (!user )
1646+ has_connection_string = dbname ?
1647+ recognized_connection_string (dbname ) : false;
1648+ switch (reuse_previous_specification )
1649+ {
1650+ case TRI_YES :
1651+ reuse_previous = true;
1652+ break ;
1653+ case TRI_NO :
1654+ reuse_previous = false;
1655+ break ;
1656+ default :
1657+ reuse_previous = !has_connection_string ;
1658+ break ;
1659+ }
1660+ /* Silently ignore arguments subsequent to a connection string. */
1661+ if (has_connection_string )
1662+ {
1663+ user = NULL ;
1664+ host = NULL ;
1665+ port = NULL ;
1666+ }
1667+
1668+ /* grab missing values from the old connection */
1669+ if (!user && reuse_previous )
16331670 user = PQuser (o_conn );
1634- if (!host )
1671+ if (!host && reuse_previous )
16351672 host = PQhost (o_conn );
1636- if (!port )
1673+ if (!port && reuse_previous )
16371674 port = PQport (o_conn );
16381675
1639- has_connection_string =
1640- dbname ? recognized_connection_string (dbname ) : false;
1641-
16421676 /*
16431677 * Any change in the parameters read above makes us discard the password.
16441678 * We also discard it if we're to use a conninfo rather than the
@@ -1655,10 +1689,10 @@ do_connect(char *dbname, char *user, char *host, char *port)
16551689 (port && PQport (o_conn ) && strcmp (port , PQport (o_conn )) == 0 );
16561690
16571691 /*
1658- * Grab dbname from old connection unless supplied by caller . No password
1659- * discard if this changes: passwords aren't (usually) database-specific.
1692+ * Grab missing dbname from old connection. No password discard if this
1693+ * changes: passwords aren't (usually) database-specific.
16601694 */
1661- if (!dbname )
1695+ if (!dbname && reuse_previous )
16621696 dbname = PQdb (o_conn );
16631697
16641698 /*
@@ -1689,20 +1723,27 @@ do_connect(char *dbname, char *user, char *host, char *port)
16891723#define PARAMS_ARRAY_SIZE 8
16901724 const char * * keywords = pg_malloc (PARAMS_ARRAY_SIZE * sizeof (* keywords ));
16911725 const char * * values = pg_malloc (PARAMS_ARRAY_SIZE * sizeof (* values ));
1692- int paramnum = 0 ;
1726+ int paramnum = -1 ;
16931727
1694- keywords [0 ] = "dbname" ;
1695- values [0 ] = dbname ;
1728+ keywords [++ paramnum ] = "host" ;
1729+ values [paramnum ] = host ;
1730+ keywords [++ paramnum ] = "port" ;
1731+ values [paramnum ] = port ;
1732+ keywords [++ paramnum ] = "user" ;
1733+ values [paramnum ] = user ;
16961734
1697- if (!has_connection_string )
1698- {
1699- keywords [++ paramnum ] = "host" ;
1700- values [paramnum ] = host ;
1701- keywords [++ paramnum ] = "port" ;
1702- values [paramnum ] = port ;
1703- keywords [++ paramnum ] = "user" ;
1704- values [paramnum ] = user ;
1705- }
1735+ /*
1736+ * Position in the array matters when the dbname is a connection
1737+ * string, because settings in a connection string override earlier
1738+ * array entries only. Thus, user= in the connection string always
1739+ * takes effect, but client_encoding= often will not.
1740+ *
1741+ * If you change this code, also change the initial-connection code in
1742+ * main(). For no good reason, a connection string password= takes
1743+ * precedence in main() but not here.
1744+ */
1745+ keywords [++ paramnum ] = "dbname" ;
1746+ values [paramnum ] = dbname ;
17061747 keywords [++ paramnum ] = "password" ;
17071748 values [paramnum ] = password ;
17081749 keywords [++ paramnum ] = "fallback_application_name" ;
0 commit comments