@@ -65,7 +65,8 @@ static backslashResult exec_command(const char *cmd,
65
65
PQExpBuffer query_buf );
66
66
static bool do_edit (const char * filename_arg , PQExpBuffer query_buf ,
67
67
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 );
69
70
static bool do_shell (const char * command );
70
71
static bool do_watch (PQExpBuffer query_buf , double sleep );
71
72
static bool lookup_object_oid (EditableObjectType obj_type , const char * desc ,
@@ -231,12 +232,9 @@ exec_command(const char *cmd,
231
232
/*
232
233
* \c or \connect -- connect to database using the specified parameters.
233
234
*
234
- * \c dbname user host port
235
+ * \c [-reuse-previous=BOOL] dbname user host port
235
236
*
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:
240
238
*
241
239
* \c - - hst Connect to current database on current port of host
242
240
* "hst" as current user. \c - usr - prt Connect to current database on
@@ -245,17 +243,31 @@ exec_command(const char *cmd,
245
243
*/
246
244
else if (strcmp (cmd , "c" ) == 0 || strcmp (cmd , "connect" ) == 0 )
247
245
{
246
+ static const char prefix [] = "-reuse-previous=" ;
248
247
char * opt1 ,
249
248
* opt2 ,
250
249
* opt3 ,
251
250
* opt4 ;
251
+ enum trivalue reuse_previous ;
252
252
253
253
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
+
254
266
opt2 = read_connect_arg (scan_state );
255
267
opt3 = read_connect_arg (scan_state );
256
268
opt4 = read_connect_arg (scan_state );
257
269
258
- success = do_connect (opt1 , opt2 , opt3 , opt4 );
270
+ success = do_connect (reuse_previous , opt1 , opt2 , opt3 , opt4 );
259
271
260
272
free (opt1 );
261
273
free (opt2 );
@@ -1754,22 +1766,25 @@ param_is_newly_set(const char *old_val, const char *new_val)
1754
1766
/*
1755
1767
* do_connect -- handler for \connect
1756
1768
*
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.
1761
1774
*
1762
1775
* In interactive mode, if connection fails with the given parameters,
1763
1776
* the old connection will be kept.
1764
1777
*/
1765
1778
static 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 )
1767
1781
{
1768
1782
PGconn * o_conn = pset .db ,
1769
1783
* n_conn ;
1770
1784
char * password = NULL ;
1771
1785
bool keep_password ;
1772
1786
bool has_connection_string ;
1787
+ bool reuse_previous ;
1773
1788
1774
1789
if (!o_conn && (!dbname || !user || !host || !port ))
1775
1790
{
@@ -1783,17 +1798,36 @@ do_connect(char *dbname, char *user, char *host, char *port)
1783
1798
return false;
1784
1799
}
1785
1800
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 )
1788
1825
user = PQuser (o_conn );
1789
- if (!host )
1826
+ if (!host && reuse_previous )
1790
1827
host = PQhost (o_conn );
1791
- if (!port )
1828
+ if (!port && reuse_previous )
1792
1829
port = PQport (o_conn );
1793
1830
1794
- has_connection_string =
1795
- dbname ? recognized_connection_string (dbname ) : false;
1796
-
1797
1831
/*
1798
1832
* Any change in the parameters read above makes us discard the password.
1799
1833
* 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)
1808
1842
(port && PQport (o_conn ) && strcmp (port , PQport (o_conn )) == 0 );
1809
1843
1810
1844
/*
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.
1813
1847
*/
1814
- if (!dbname )
1848
+ if (!dbname && reuse_previous )
1815
1849
dbname = PQdb (o_conn );
1816
1850
1817
1851
/*
@@ -1842,20 +1876,27 @@ do_connect(char *dbname, char *user, char *host, char *port)
1842
1876
#define PARAMS_ARRAY_SIZE 8
1843
1877
const char * * keywords = pg_malloc (PARAMS_ARRAY_SIZE * sizeof (* keywords ));
1844
1878
const char * * values = pg_malloc (PARAMS_ARRAY_SIZE * sizeof (* values ));
1845
- int paramnum = 0 ;
1879
+ int paramnum = -1 ;
1846
1880
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 ;
1849
1887
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 ;
1859
1900
keywords [++ paramnum ] = "password" ;
1860
1901
values [paramnum ] = password ;
1861
1902
keywords [++ paramnum ] = "fallback_application_name" ;
0 commit comments