@@ -48,7 +48,8 @@ struct WalReceiverConn
48
48
49
49
/* Prototypes for interface functions */
50
50
static WalReceiverConn * libpqrcv_connect (const char * conninfo ,
51
- bool logical , bool must_use_password ,
51
+ bool replication , bool logical ,
52
+ bool must_use_password ,
52
53
const char * appname , char * * err );
53
54
static void libpqrcv_check_conninfo (const char * conninfo ,
54
55
bool must_use_password );
@@ -57,6 +58,7 @@ static void libpqrcv_get_senderinfo(WalReceiverConn *conn,
57
58
char * * sender_host , int * sender_port );
58
59
static char * libpqrcv_identify_system (WalReceiverConn * conn ,
59
60
TimeLineID * primary_tli );
61
+ static char * libpqrcv_get_dbname_from_conninfo (const char * conninfo );
60
62
static int libpqrcv_server_version (WalReceiverConn * conn );
61
63
static void libpqrcv_readtimelinehistoryfile (WalReceiverConn * conn ,
62
64
TimeLineID tli , char * * filename ,
@@ -99,6 +101,7 @@ static WalReceiverFunctionsType PQWalReceiverFunctions = {
99
101
.walrcv_send = libpqrcv_send ,
100
102
.walrcv_create_slot = libpqrcv_create_slot ,
101
103
.walrcv_alter_slot = libpqrcv_alter_slot ,
104
+ .walrcv_get_dbname_from_conninfo = libpqrcv_get_dbname_from_conninfo ,
102
105
.walrcv_get_backend_pid = libpqrcv_get_backend_pid ,
103
106
.walrcv_exec = libpqrcv_exec ,
104
107
.walrcv_disconnect = libpqrcv_disconnect
@@ -121,7 +124,11 @@ _PG_init(void)
121
124
}
122
125
123
126
/*
124
- * Establish the connection to the primary server for XLOG streaming
127
+ * Establish the connection to the primary server.
128
+ *
129
+ * This function can be used for both replication and regular connections.
130
+ * If it is a replication connection, it could be either logical or physical
131
+ * based on input argument 'logical'.
125
132
*
126
133
* If an error occurs, this function will normally return NULL and set *err
127
134
* to a palloc'ed error message. However, if must_use_password is true and
@@ -132,8 +139,8 @@ _PG_init(void)
132
139
* case.
133
140
*/
134
141
static WalReceiverConn *
135
- libpqrcv_connect (const char * conninfo , bool logical , bool must_use_password ,
136
- const char * appname , char * * err )
142
+ libpqrcv_connect (const char * conninfo , bool replication , bool logical ,
143
+ bool must_use_password , const char * appname , char * * err )
137
144
{
138
145
WalReceiverConn * conn ;
139
146
PostgresPollingStatusType status ;
@@ -156,36 +163,46 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
156
163
*/
157
164
keys [i ] = "dbname" ;
158
165
vals [i ] = conninfo ;
159
- keys [++ i ] = "replication" ;
160
- vals [i ] = logical ? "database" : "true" ;
161
- if (!logical )
166
+
167
+ /* We can not have logical without replication */
168
+ Assert (replication || !logical );
169
+
170
+ if (replication )
162
171
{
163
- /*
164
- * The database name is ignored by the server in replication mode, but
165
- * specify "replication" for .pgpass lookup.
166
- */
167
- keys [++ i ] = "dbname" ;
168
- vals [i ] = "replication" ;
172
+ keys [++ i ] = "replication" ;
173
+ vals [i ] = logical ? "database" : "true" ;
174
+
175
+ if (logical )
176
+ {
177
+ /* Tell the publisher to translate to our encoding */
178
+ keys [++ i ] = "client_encoding" ;
179
+ vals [i ] = GetDatabaseEncodingName ();
180
+
181
+ /*
182
+ * Force assorted GUC parameters to settings that ensure that the
183
+ * publisher will output data values in a form that is unambiguous
184
+ * to the subscriber. (We don't want to modify the subscriber's
185
+ * GUC settings, since that might surprise user-defined code
186
+ * running in the subscriber, such as triggers.) This should
187
+ * match what pg_dump does.
188
+ */
189
+ keys [++ i ] = "options" ;
190
+ vals [i ] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3" ;
191
+ }
192
+ else
193
+ {
194
+ /*
195
+ * The database name is ignored by the server in replication mode,
196
+ * but specify "replication" for .pgpass lookup.
197
+ */
198
+ keys [++ i ] = "dbname" ;
199
+ vals [i ] = "replication" ;
200
+ }
169
201
}
202
+
170
203
keys [++ i ] = "fallback_application_name" ;
171
204
vals [i ] = appname ;
172
- if (logical )
173
- {
174
- /* Tell the publisher to translate to our encoding */
175
- keys [++ i ] = "client_encoding" ;
176
- vals [i ] = GetDatabaseEncodingName ();
177
205
178
- /*
179
- * Force assorted GUC parameters to settings that ensure that the
180
- * publisher will output data values in a form that is unambiguous to
181
- * the subscriber. (We don't want to modify the subscriber's GUC
182
- * settings, since that might surprise user-defined code running in
183
- * the subscriber, such as triggers.) This should match what pg_dump
184
- * does.
185
- */
186
- keys [++ i ] = "options" ;
187
- vals [i ] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3" ;
188
- }
189
206
keys [++ i ] = NULL ;
190
207
vals [i ] = NULL ;
191
208
@@ -471,6 +488,50 @@ libpqrcv_server_version(WalReceiverConn *conn)
471
488
return PQserverVersion (conn -> streamConn );
472
489
}
473
490
491
+ /*
492
+ * Get database name from the primary server's conninfo.
493
+ *
494
+ * If dbname is not found in connInfo, return NULL value.
495
+ */
496
+ static char *
497
+ libpqrcv_get_dbname_from_conninfo (const char * connInfo )
498
+ {
499
+ PQconninfoOption * opts ;
500
+ char * dbname = NULL ;
501
+ char * err = NULL ;
502
+
503
+ opts = PQconninfoParse (connInfo , & err );
504
+ if (opts == NULL )
505
+ {
506
+ /* The error string is malloc'd, so we must free it explicitly */
507
+ char * errcopy = err ? pstrdup (err ) : "out of memory" ;
508
+
509
+ PQfreemem (err );
510
+ ereport (ERROR ,
511
+ (errcode (ERRCODE_SYNTAX_ERROR ),
512
+ errmsg ("invalid connection string syntax: %s" , errcopy )));
513
+ }
514
+
515
+ for (PQconninfoOption * opt = opts ; opt -> keyword != NULL ; ++ opt )
516
+ {
517
+ /*
518
+ * If multiple dbnames are specified, then the last one will be
519
+ * returned
520
+ */
521
+ if (strcmp (opt -> keyword , "dbname" ) == 0 && opt -> val &&
522
+ * opt -> val )
523
+ {
524
+ if (dbname )
525
+ pfree (dbname );
526
+
527
+ dbname = pstrdup (opt -> val );
528
+ }
529
+ }
530
+
531
+ PQconninfoFree (opts );
532
+ return dbname ;
533
+ }
534
+
474
535
/*
475
536
* Start streaming WAL data from given streaming options.
476
537
*
0 commit comments