@@ -65,7 +65,8 @@ static backslashResult exec_command(const char *cmd,
6565 PQExpBuffer query_buf );
6666static bool do_edit (const char * filename_arg , PQExpBuffer query_buf ,
6767 int lineno , bool * edited );
68- static bool do_connect (char * dbname , char * user , char * host , char * port );
68+ static bool do_connect (enum trivalue reuse_previous_specification ,
69+ char * dbname , char * user , char * host , char * port );
6970static bool do_shell (const char * command );
7071static bool do_watch (PQExpBuffer query_buf , double sleep );
7172static bool lookup_object_oid (EditableObjectType obj_type , const char * desc ,
@@ -231,12 +232,9 @@ exec_command(const char *cmd,
231232 /*
232233 * \c or \connect -- connect to database using the specified parameters.
233234 *
234- * \c dbname user host port
235+ * \c [-reuse-previous=BOOL] dbname user host port
235236 *
236- * If any of these parameters are omitted or specified as '-', the current
237- * value of the parameter will be used instead. If the parameter has no
238- * current value, the default value for that parameter will be used. Some
239- * examples:
237+ * Specifying a parameter as '-' is equivalent to omitting it. Examples:
240238 *
241239 * \c - - hst Connect to current database on current port of host
242240 * "hst" as current user. \c - usr - prt Connect to current database on
@@ -245,17 +243,31 @@ exec_command(const char *cmd,
245243 */
246244 else if (strcmp (cmd , "c" ) == 0 || strcmp (cmd , "connect" ) == 0 )
247245 {
246+ static const char prefix [] = "-reuse-previous=" ;
248247 char * opt1 ,
249248 * opt2 ,
250249 * opt3 ,
251250 * opt4 ;
251+ enum trivalue reuse_previous ;
252252
253253 opt1 = read_connect_arg (scan_state );
254+ if (opt1 != NULL && strncmp (opt1 , prefix , sizeof (prefix ) - 1 ) == 0 )
255+ {
256+ reuse_previous =
257+ ParseVariableBool (opt1 + sizeof (prefix ) - 1 , prefix ) ?
258+ TRI_YES : TRI_NO ;
259+
260+ free (opt1 );
261+ opt1 = read_connect_arg (scan_state );
262+ }
263+ else
264+ reuse_previous = TRI_DEFAULT ;
265+
254266 opt2 = read_connect_arg (scan_state );
255267 opt3 = read_connect_arg (scan_state );
256268 opt4 = read_connect_arg (scan_state );
257269
258- success = do_connect (opt1 , opt2 , opt3 , opt4 );
270+ success = do_connect (reuse_previous , opt1 , opt2 , opt3 , opt4 );
259271
260272 free (opt1 );
261273 free (opt2 );
@@ -1754,22 +1766,25 @@ param_is_newly_set(const char *old_val, const char *new_val)
17541766/*
17551767 * do_connect -- handler for \connect
17561768 *
1757- * Connects to a database with given parameters. If there exists an
1758- * established connection, NULL values will be replaced with the ones
1759- * in the current connection. Otherwise NULL will be passed for that
1760- * parameter to PQconnectdbParams(), so the libpq defaults will be used.
1769+ * Connects to a database with given parameters. Absent an established
1770+ * connection, all parameters are required. Given -reuse-previous=off or a
1771+ * connection string without -reuse-previous=on, NULL values will pass through
1772+ * to PQconnectdbParams(), so the libpq defaults will be used. Otherwise, NULL
1773+ * values will be replaced with the ones in the current connection.
17611774 *
17621775 * In interactive mode, if connection fails with the given parameters,
17631776 * the old connection will be kept.
17641777 */
17651778static bool
1766- do_connect (char * dbname , char * user , char * host , char * port )
1779+ do_connect (enum trivalue reuse_previous_specification ,
1780+ char * dbname , char * user , char * host , char * port )
17671781{
17681782 PGconn * o_conn = pset .db ,
17691783 * n_conn ;
17701784 char * password = NULL ;
17711785 bool keep_password ;
17721786 bool has_connection_string ;
1787+ bool reuse_previous ;
17731788
17741789 if (!o_conn && (!dbname || !user || !host || !port ))
17751790 {
@@ -1783,17 +1798,36 @@ do_connect(char *dbname, char *user, char *host, char *port)
17831798 return false;
17841799 }
17851800
1786- /* grab values from the old connection, unless supplied by caller */
1787- if (!user )
1801+ has_connection_string = dbname ?
1802+ recognized_connection_string (dbname ) : false;
1803+ switch (reuse_previous_specification )
1804+ {
1805+ case TRI_YES :
1806+ reuse_previous = true;
1807+ break ;
1808+ case TRI_NO :
1809+ reuse_previous = false;
1810+ break ;
1811+ default :
1812+ reuse_previous = !has_connection_string ;
1813+ break ;
1814+ }
1815+ /* Silently ignore arguments subsequent to a connection string. */
1816+ if (has_connection_string )
1817+ {
1818+ user = NULL ;
1819+ host = NULL ;
1820+ port = NULL ;
1821+ }
1822+
1823+ /* grab missing values from the old connection */
1824+ if (!user && reuse_previous )
17881825 user = PQuser (o_conn );
1789- if (!host )
1826+ if (!host && reuse_previous )
17901827 host = PQhost (o_conn );
1791- if (!port )
1828+ if (!port && reuse_previous )
17921829 port = PQport (o_conn );
17931830
1794- has_connection_string =
1795- dbname ? recognized_connection_string (dbname ) : false;
1796-
17971831 /*
17981832 * Any change in the parameters read above makes us discard the password.
17991833 * We also discard it if we're to use a conninfo rather than the
@@ -1808,10 +1842,10 @@ do_connect(char *dbname, char *user, char *host, char *port)
18081842 (port && PQport (o_conn ) && strcmp (port , PQport (o_conn )) == 0 );
18091843
18101844 /*
1811- * Grab dbname from old connection unless supplied by caller . No password
1812- * discard if this changes: passwords aren't (usually) database-specific.
1845+ * Grab missing dbname from old connection. No password discard if this
1846+ * changes: passwords aren't (usually) database-specific.
18131847 */
1814- if (!dbname )
1848+ if (!dbname && reuse_previous )
18151849 dbname = PQdb (o_conn );
18161850
18171851 /*
@@ -1842,20 +1876,27 @@ do_connect(char *dbname, char *user, char *host, char *port)
18421876#define PARAMS_ARRAY_SIZE 8
18431877 const char * * keywords = pg_malloc (PARAMS_ARRAY_SIZE * sizeof (* keywords ));
18441878 const char * * values = pg_malloc (PARAMS_ARRAY_SIZE * sizeof (* values ));
1845- int paramnum = 0 ;
1879+ int paramnum = -1 ;
18461880
1847- keywords [0 ] = "dbname" ;
1848- values [0 ] = dbname ;
1881+ keywords [++ paramnum ] = "host" ;
1882+ values [paramnum ] = host ;
1883+ keywords [++ paramnum ] = "port" ;
1884+ values [paramnum ] = port ;
1885+ keywords [++ paramnum ] = "user" ;
1886+ values [paramnum ] = user ;
18491887
1850- if (!has_connection_string )
1851- {
1852- keywords [++ paramnum ] = "host" ;
1853- values [paramnum ] = host ;
1854- keywords [++ paramnum ] = "port" ;
1855- values [paramnum ] = port ;
1856- keywords [++ paramnum ] = "user" ;
1857- values [paramnum ] = user ;
1858- }
1888+ /*
1889+ * Position in the array matters when the dbname is a connection
1890+ * string, because settings in a connection string override earlier
1891+ * array entries only. Thus, user= in the connection string always
1892+ * takes effect, but client_encoding= often will not.
1893+ *
1894+ * If you change this code, also change the initial-connection code in
1895+ * main(). For no good reason, a connection string password= takes
1896+ * precedence in main() but not here.
1897+ */
1898+ keywords [++ paramnum ] = "dbname" ;
1899+ values [paramnum ] = dbname ;
18591900 keywords [++ paramnum ] = "password" ;
18601901 values [paramnum ] = password ;
18611902 keywords [++ paramnum ] = "fallback_application_name" ;
0 commit comments