@@ -56,7 +56,8 @@ static backslashResult exec_command(const char *cmd,
56
56
PQExpBuffer query_buf );
57
57
static bool do_edit (const char * filename_arg ,PQExpBuffer query_buf ,
58
58
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 );
60
61
static bool do_shell (const char * command );
61
62
static bool do_watch (PQExpBuffer query_buf ,long sleep );
62
63
static bool lookup_function_oid (const char * desc ,Oid * foid );
@@ -217,12 +218,9 @@ exec_command(const char *cmd,
217
218
/*
218
219
* \c or \connect -- connect to database using the specified parameters.
219
220
*
220
- * \c dbname user host port
221
+ * \c[-reuse-previous=BOOL] dbname user host port
221
222
*
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:
226
224
*
227
225
* \c - - hstConnect to current database on current port of host
228
226
* "hst" as current user. \c - usr - prt Connect to current database on
@@ -231,17 +229,31 @@ exec_command(const char *cmd,
231
229
*/
232
230
else if (strcmp (cmd ,"c" )== 0 || strcmp (cmd ,"connect" )== 0 )
233
231
{
232
+ static const char prefix []= "-reuse-previous=" ;
234
233
char * opt1 ,
235
234
* opt2 ,
236
235
* opt3 ,
237
236
* opt4 ;
237
+ enum trivalue reuse_previous ;
238
238
239
239
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
+
240
252
opt2 = read_connect_arg (scan_state );
241
253
opt3 = read_connect_arg (scan_state );
242
254
opt4 = read_connect_arg (scan_state );
243
255
244
- success = do_connect (opt1 ,opt2 ,opt3 ,opt4 );
256
+ success = do_connect (reuse_previous , opt1 ,opt2 ,opt3 ,opt4 );
245
257
246
258
free (opt1 );
247
259
free (opt2 );
@@ -1599,22 +1611,25 @@ param_is_newly_set(const char *old_val, const char *new_val)
1599
1611
/*
1600
1612
* do_connect -- handler for \connect
1601
1613
*
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.
1606
1619
*
1607
1620
* In interactive mode, if connection fails with the given parameters,
1608
1621
* the old connection will be kept.
1609
1622
*/
1610
1623
static 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 )
1612
1626
{
1613
1627
PGconn * o_conn = pset .db ,
1614
1628
* n_conn ;
1615
1629
char * password = NULL ;
1616
1630
bool keep_password ;
1617
1631
bool has_connection_string ;
1632
+ bool reuse_previous ;
1618
1633
1619
1634
if (!o_conn && (!dbname || !user || !host || !port ))
1620
1635
{
@@ -1628,17 +1643,36 @@ do_connect(char *dbname, char *user, char *host, char *port)
1628
1643
return false;
1629
1644
}
1630
1645
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 )
1633
1670
user = PQuser (o_conn );
1634
- if (!host )
1671
+ if (!host && reuse_previous )
1635
1672
host = PQhost (o_conn );
1636
- if (!port )
1673
+ if (!port && reuse_previous )
1637
1674
port = PQport (o_conn );
1638
1675
1639
- has_connection_string =
1640
- dbname ?recognized_connection_string (dbname ) : false;
1641
-
1642
1676
/*
1643
1677
* Any change in the parameters read above makes us discard the password.
1644
1678
* 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)
1655
1689
(port && PQport (o_conn )&& strcmp (port ,PQport (o_conn ))== 0 );
1656
1690
1657
1691
/*
1658
- * Grab dbname from old connection unless supplied by caller . No password
1659
- *discard if this changes: passwords aren't (usually) database-specific.
1692
+ * Grabmissing dbname from old connection. No password discard if this
1693
+ * changes: passwords aren't (usually) database-specific.
1660
1694
*/
1661
- if (!dbname )
1695
+ if (!dbname && reuse_previous )
1662
1696
dbname = PQdb (o_conn );
1663
1697
1664
1698
/*
@@ -1689,20 +1723,27 @@ do_connect(char *dbname, char *user, char *host, char *port)
1689
1723
#define PARAMS_ARRAY_SIZE 8
1690
1724
const char * * keywords = pg_malloc (PARAMS_ARRAY_SIZE * sizeof (* keywords ));
1691
1725
const char * * values = pg_malloc (PARAMS_ARRAY_SIZE * sizeof (* values ));
1692
- int paramnum = 0 ;
1726
+ int paramnum = -1 ;
1693
1727
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 ;
1696
1734
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 ;
1706
1747
keywords [++ paramnum ]= "password" ;
1707
1748
values [paramnum ]= password ;
1708
1749
keywords [++ paramnum ]= "fallback_application_name" ;