@@ -59,7 +59,8 @@ static backslashResult exec_command(const char *cmd,
59
59
PQExpBuffer query_buf );
60
60
static bool do_edit (const char * filename_arg , PQExpBuffer query_buf ,
61
61
int lineno , bool * edited );
62
- static bool do_connect (char * dbname , char * user , char * host , char * port );
62
+ static bool do_connect (enum trivalue reuse_previous_specification ,
63
+ char * dbname , char * user , char * host , char * port );
63
64
static bool do_shell (const char * command );
64
65
static bool do_watch (PQExpBuffer query_buf , long sleep );
65
66
static bool lookup_function_oid (PGconn * conn , const char * desc , Oid * foid );
@@ -220,12 +221,9 @@ exec_command(const char *cmd,
220
221
/*
221
222
* \c or \connect -- connect to database using the specified parameters.
222
223
*
223
- * \c dbname user host port
224
+ * \c [-reuse-previous=BOOL] dbname user host port
224
225
*
225
- * If any of these parameters are omitted or specified as '-', the current
226
- * value of the parameter will be used instead. If the parameter has no
227
- * current value, the default value for that parameter will be used. Some
228
- * examples:
226
+ * Specifying a parameter as '-' is equivalent to omitting it. Examples:
229
227
*
230
228
* \c - - hst Connect to current database on current port of host
231
229
* "hst" as current user. \c - usr - prt Connect to current database on
@@ -234,17 +232,31 @@ exec_command(const char *cmd,
234
232
*/
235
233
else if (strcmp (cmd , "c" ) == 0 || strcmp (cmd , "connect" ) == 0 )
236
234
{
235
+ static const char prefix [] = "-reuse-previous=" ;
237
236
char * opt1 ,
238
237
* opt2 ,
239
238
* opt3 ,
240
239
* opt4 ;
240
+ enum trivalue reuse_previous ;
241
241
242
242
opt1 = read_connect_arg (scan_state );
243
+ if (opt1 != NULL && strncmp (opt1 , prefix , sizeof (prefix ) - 1 ) == 0 )
244
+ {
245
+ reuse_previous =
246
+ ParseVariableBool (opt1 + sizeof (prefix ) - 1 , prefix ) ?
247
+ TRI_YES : TRI_NO ;
248
+
249
+ free (opt1 );
250
+ opt1 = read_connect_arg (scan_state );
251
+ }
252
+ else
253
+ reuse_previous = TRI_DEFAULT ;
254
+
243
255
opt2 = read_connect_arg (scan_state );
244
256
opt3 = read_connect_arg (scan_state );
245
257
opt4 = read_connect_arg (scan_state );
246
258
247
- success = do_connect (opt1 , opt2 , opt3 , opt4 );
259
+ success = do_connect (reuse_previous , opt1 , opt2 , opt3 , opt4 );
248
260
249
261
free (opt1 );
250
262
free (opt2 );
@@ -1581,22 +1593,25 @@ param_is_newly_set(const char *old_val, const char *new_val)
1581
1593
/*
1582
1594
* do_connect -- handler for \connect
1583
1595
*
1584
- * Connects to a database with given parameters. If there exists an
1585
- * established connection, NULL values will be replaced with the ones
1586
- * in the current connection. Otherwise NULL will be passed for that
1587
- * parameter to PQconnectdbParams(), so the libpq defaults will be used.
1596
+ * Connects to a database with given parameters. Absent an established
1597
+ * connection, all parameters are required. Given -reuse-previous=off or a
1598
+ * connection string without -reuse-previous=on, NULL values will pass through
1599
+ * to PQconnectdbParams(), so the libpq defaults will be used. Otherwise, NULL
1600
+ * values will be replaced with the ones in the current connection.
1588
1601
*
1589
1602
* In interactive mode, if connection fails with the given parameters,
1590
1603
* the old connection will be kept.
1591
1604
*/
1592
1605
static bool
1593
- do_connect (char * dbname , char * user , char * host , char * port )
1606
+ do_connect (enum trivalue reuse_previous_specification ,
1607
+ char * dbname , char * user , char * host , char * port )
1594
1608
{
1595
1609
PGconn * o_conn = pset .db ,
1596
1610
* n_conn ;
1597
1611
char * password = NULL ;
1598
1612
bool keep_password ;
1599
1613
bool has_connection_string ;
1614
+ bool reuse_previous ;
1600
1615
1601
1616
if (!o_conn && (!dbname || !user || !host || !port ))
1602
1617
{
@@ -1610,17 +1625,36 @@ do_connect(char *dbname, char *user, char *host, char *port)
1610
1625
return false;
1611
1626
}
1612
1627
1613
- /* grab values from the old connection, unless supplied by caller */
1614
- if (!user )
1628
+ has_connection_string = dbname ?
1629
+ recognized_connection_string (dbname ) : false;
1630
+ switch (reuse_previous_specification )
1631
+ {
1632
+ case TRI_YES :
1633
+ reuse_previous = true;
1634
+ break ;
1635
+ case TRI_NO :
1636
+ reuse_previous = false;
1637
+ break ;
1638
+ default :
1639
+ reuse_previous = !has_connection_string ;
1640
+ break ;
1641
+ }
1642
+ /* Silently ignore arguments subsequent to a connection string. */
1643
+ if (has_connection_string )
1644
+ {
1645
+ user = NULL ;
1646
+ host = NULL ;
1647
+ port = NULL ;
1648
+ }
1649
+
1650
+ /* grab missing values from the old connection */
1651
+ if (!user && reuse_previous )
1615
1652
user = PQuser (o_conn );
1616
- if (!host )
1653
+ if (!host && reuse_previous )
1617
1654
host = PQhost (o_conn );
1618
- if (!port )
1655
+ if (!port && reuse_previous )
1619
1656
port = PQport (o_conn );
1620
1657
1621
- has_connection_string =
1622
- dbname ? recognized_connection_string (dbname ) : false;
1623
-
1624
1658
/*
1625
1659
* Any change in the parameters read above makes us discard the password.
1626
1660
* We also discard it if we're to use a conninfo rather than the
@@ -1637,10 +1671,10 @@ do_connect(char *dbname, char *user, char *host, char *port)
1637
1671
(port && PQport (o_conn ) && strcmp (port , PQport (o_conn )) == 0 );
1638
1672
1639
1673
/*
1640
- * Grab dbname from old connection unless supplied by caller . No password
1641
- * discard if this changes: passwords aren't (usually) database-specific.
1674
+ * Grab missing dbname from old connection. No password discard if this
1675
+ * changes: passwords aren't (usually) database-specific.
1642
1676
*/
1643
- if (!dbname )
1677
+ if (!dbname && reuse_previous )
1644
1678
dbname = PQdb (o_conn );
1645
1679
1646
1680
/*
@@ -1671,20 +1705,27 @@ do_connect(char *dbname, char *user, char *host, char *port)
1671
1705
#define PARAMS_ARRAY_SIZE 8
1672
1706
const char * * keywords = pg_malloc (PARAMS_ARRAY_SIZE * sizeof (* keywords ));
1673
1707
const char * * values = pg_malloc (PARAMS_ARRAY_SIZE * sizeof (* values ));
1674
- int paramnum = 0 ;
1708
+ int paramnum = -1 ;
1675
1709
1676
- keywords [0 ] = "dbname" ;
1677
- values [0 ] = dbname ;
1710
+ keywords [++ paramnum ] = "host" ;
1711
+ values [paramnum ] = host ;
1712
+ keywords [++ paramnum ] = "port" ;
1713
+ values [paramnum ] = port ;
1714
+ keywords [++ paramnum ] = "user" ;
1715
+ values [paramnum ] = user ;
1678
1716
1679
- if (!has_connection_string )
1680
- {
1681
- keywords [++ paramnum ] = "host" ;
1682
- values [paramnum ] = host ;
1683
- keywords [++ paramnum ] = "port" ;
1684
- values [paramnum ] = port ;
1685
- keywords [++ paramnum ] = "user" ;
1686
- values [paramnum ] = user ;
1687
- }
1717
+ /*
1718
+ * Position in the array matters when the dbname is a connection
1719
+ * string, because settings in a connection string override earlier
1720
+ * array entries only. Thus, user= in the connection string always
1721
+ * takes effect, but client_encoding= often will not.
1722
+ *
1723
+ * If you change this code, also change the initial-connection code in
1724
+ * main(). For no good reason, a connection string password= takes
1725
+ * precedence in main() but not here.
1726
+ */
1727
+ keywords [++ paramnum ] = "dbname" ;
1728
+ values [paramnum ] = dbname ;
1688
1729
keywords [++ paramnum ] = "password" ;
1689
1730
values [paramnum ] = password ;
1690
1731
keywords [++ paramnum ] = "fallback_application_name" ;
0 commit comments