@@ -58,7 +58,8 @@ static backslashResult exec_command(const char *cmd,
58
58
PQExpBuffer query_buf );
59
59
static bool do_edit (const char * filename_arg , PQExpBuffer query_buf ,
60
60
int lineno , bool * edited );
61
- static bool do_connect (char * dbname , char * user , char * host , char * port );
61
+ static bool do_connect (enum trivalue reuse_previous_specification ,
62
+ char * dbname , char * user , char * host , char * port );
62
63
static bool do_shell (const char * command );
63
64
static bool lookup_function_oid (PGconn * conn , const char * desc , Oid * foid );
64
65
static bool get_create_function_cmd (PGconn * conn , Oid oid , PQExpBuffer buf );
@@ -216,12 +217,9 @@ exec_command(const char *cmd,
216
217
/*
217
218
* \c or \connect -- connect to database using the specified parameters.
218
219
*
219
- * \c dbname user host port
220
+ * \c [-reuse-previous=BOOL] dbname user host port
220
221
*
221
- * If any of these parameters are omitted or specified as '-', the current
222
- * value of the parameter will be used instead. If the parameter has no
223
- * current value, the default value for that parameter will be used. Some
224
- * examples:
222
+ * Specifying a parameter as '-' is equivalent to omitting it. Examples:
225
223
*
226
224
* \c - - hst Connect to current database on current port of host
227
225
* "hst" as current user. \c - usr - prt Connect to current database on
@@ -230,17 +228,31 @@ exec_command(const char *cmd,
230
228
*/
231
229
else if (strcmp (cmd , "c" ) == 0 || strcmp (cmd , "connect" ) == 0 )
232
230
{
231
+ static const char prefix [] = "-reuse-previous=" ;
233
232
char * opt1 ,
234
233
* opt2 ,
235
234
* opt3 ,
236
235
* opt4 ;
236
+ enum trivalue reuse_previous ;
237
237
238
238
opt1 = read_connect_arg (scan_state );
239
+ if (opt1 != NULL && strncmp (opt1 , prefix , sizeof (prefix ) - 1 ) == 0 )
6D4E
div>
240
+ {
241
+ reuse_previous =
242
+ ParseVariableBool (opt1 + sizeof (prefix ) - 1 , prefix ) ?
243
+ TRI_YES : TRI_NO ;
244
+
245
+ free (opt1 );
246
+ opt1 = read_connect_arg (scan_state );
247
+ }
248
+ else
249
+ reuse_previous = TRI_DEFAULT ;
250
+
239
251
opt2 = read_connect_arg (scan_state );
240
252
opt3 = read_connect_arg (scan_state );
241
253
opt4 = read_connect_arg (scan_state );
242
254
243
- success = do_connect (opt1 , opt2 , opt3 , opt4 );
255
+ success = do_connect (reuse_previous , opt1 , opt2 , opt3 , opt4 );
244
256
245
257
free (opt1 );
246
258
free (opt2 );
@@ -1453,34 +1465,57 @@ param_is_newly_set(const char *old_val, const char *new_val)
1453
1465
/*
1454
1466
* do_connect -- handler for \connect
1455
1467
*
1456
- * Connects to a database with given parameters. If there exists an
1457
- * established connection, NULL values will be replaced with the ones
1458
- * in the current connection. Otherwise NULL will be passed for that
1459
- * parameter to PQconnectdbParams(), so the libpq defaults will be used.
1468
+ * Connects to a database with given parameters. Absent an established
1469
+ * connection, all parameters are required. Given any of -reuse-previous=off,
1470
+ * a connection string without -reuse-previous=on, or lack of an established
1471
+ * connection, NULL values will pass through to PQconnectdbParams(), so the
1472
+ * libpq defaults will be used. Otherwise, NULL values will be replaced with
1473
+ * the ones in the current connection.
1460
1474
*
1461
1475
* In interactive mode, if connection fails with the given parameters,
1462
1476
* the old connection will be kept.
1463
1477
*/
1464
1478
static bool
1465
- do_connect (char * dbname , char * user , char * host , char * port )
1479
+ do_connect (enum trivalue reuse_previous_specification ,
1480
+ char * dbname , char * user , char * host , char * port )
1466
1481
{
1467
1482
PGconn * o_conn = pset .db ,
1468
1483
* n_conn ;
1469
1484
char * password = NULL ;
1470
1485
bool keep_password ;
1471
1486
bool has_connection_string ;
1487
+ bool reuse_previous ;
1472
1488
1473
- /* grab values from the old connection, unless supplied by caller */
1474
- if (!user )
1489
+ has_connection_string = dbname ?
1490
+ recognized_connection_string (dbname ) : false;
1491
+ switch (reuse_previous_specification )
1492
+ {
1493
+ case TRI_YES :
1494
+ reuse_previous = true;
1495
+ break ;
1496
+ case TRI_NO :
1497
+ reuse_previous = false;
1498
+ break ;
1499
+ default :
1500
+ reuse_previous = !has_connection_string ;
1501
+ break ;
1502
+ }
1503
+ /* Silently ignore arguments subsequent to a connection string. */
1504
+ if (has_connection_string )
1505
+ {
1506
+ user = NULL ;
1507
+ host = NULL ;
1508
+ port = NULL ;
1509
+ }
1510
+
1511
+ /* grab missing values from the old connection */
1512
+ if (!user && reuse_previous )
1475
1513
user = PQuser (o_conn );
1476
- if (!host )
1514
+ if (!host && reuse_previous )
1477
1515
host = PQhost (o_conn );
1478
- if (!port )
1516
+ if (!port && reuse_previous )
1479
1517
port = PQport (o_conn );
1480
1518
1481
- has_connection_string =
1482
- dbname ? recognized_connection_string (dbname ) : false;
1483
-
1484
1519
/*
1485
1520
* Any change in the parameters read above makes us discard the password.
1486
1521
* We also discard it if we're to use a conninfo rather than the
@@ -1497,10 +1532,10 @@ do_connect(char *dbname, char *user, char *host, char *port)
1497
1532
(port && PQport (o_conn ) && strcmp (port , PQport (o_conn )) == 0 );
1498
1533
1499
1534
/*
1500
- * Grab dbname from old connection unless supplied by caller . No password
1501
- * discard if this changes: passwords aren't (usually) database-specific.
1535
+ * Grab missing dbname from old connection. No password discard if this
1536
+ * changes: passwords aren't (usually) database-specific.
1502
1537
*/
1503
- if (!dbname )
1538
+ if (!dbname && reuse_previous )
1504
1539
dbname = PQdb (o_conn );
1505
1540
1506
1541
/*
@@ -1527,20 +1562,27 @@ do_connect(char *dbname, char *user, char *host, char *port)
1527
1562
#define PARAMS_ARRAY_SIZE 8
1528
1563
const char * * keywords = pg_malloc (PARAMS_ARRAY_SIZE * sizeof (* keywords ));
1529
1564
const char * * values = pg_malloc (PARAMS_ARRAY_SIZE * sizeof (* values ));
1530
- int paramnum = 0 ;
1565
+ int paramnum = -1 ;
1531
1566
1532
- keywords [0 ] = "dbname" ;
1533
- values [0 ] = dbname ;
1567
+ keywords [++ paramnum ] = "host" ;
1568
+ values [paramnum ] = host ;
1569
+ keywords [++ paramnum ] = "port" ;
1570
+ values [paramnum ] = port ;
1571
+ keywords [++ paramnum ] = "user" ;
1572
+ values [paramnum ] = user ;
1534
1573
1535
- if (!has_connection_string )
1536
- {
1537
- keywords [++ paramnum ] = "host" ;
1538
- values [paramnum ] = host ;
1539
- keywords [++ paramnum ] = "port" ;
1540
- values [paramnum ] = port ;
1541
- keywords [++ paramnum ] = "user" ;
1542
- values [paramnum ] = user ;
1543
- }
1574
+ /*
1575
+ * Position in the array matters when the dbname is a connection
1576
+ * string, because settings in a connection string override earlier
1577
+ * array entries only. Thus, user= in the connection string always
1578
+ * takes effect, but client_encoding= often will not.
1579
+ *
1580
+ * If you change this code, also change the initial-connection code in
1581
+ * main(). For no good reason, a connection string password= takes
1582
+ * precedence in main() but not here.
1583
+ */
1584
+ keywords [++ paramnum ] = "dbname" ;
1585
+ values [paramnum ] = dbname ;
1544
1586
keywords [++ paramnum ] = "password" ;
1545
1587
values [paramnum ] = password ;
1546
1588
keywords [++ paramnum ] = "fallback_application_name" ;
0 commit comments