8
8
* Darko Prenosil <Darko.Prenosil@finteh.hr>
9
9
* Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
10
10
*
11
- * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.78 2009/06/02 03:21 :56 joe Exp $
11
+ * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.79 2009/06/06 21:27 :56 joe Exp $
12
12
* Copyright (c) 2001-2009, PostgreSQL Global Development Group
13
13
* ALL RIGHTS RESERVED;
14
14
*
46
46
#include "catalog/pg_type.h"
47
47
#include "executor/executor.h"
48
48
#include "executor/spi.h"
49
+ #include "foreign/foreign.h"
49
50
#include "lib/stringinfo.h"
50
51
#include "miscadmin.h"
51
52
#include "nodes/execnodes.h"
@@ -96,6 +97,8 @@ static char *generate_relation_name(Oid relid);
96
97
static void dblink_connstr_check (const char * connstr );
97
98
static void dblink_security_check (PGconn * conn , remoteConn * rconn );
98
99
static void dblink_res_error (const char * conname , PGresult * res , const char * dblink_context_msg , bool fail );
100
+ static char * get_connect_string (const char * servername );
101
+ static char * escape_param_str (const char * from );
99
102
100
103
/* Global */
101
104
static remoteConn * pconn = NULL ;
@@ -165,7 +168,11 @@ typedef struct remoteConnHashEnt
165
168
} \
166
169
else \
167
170
{ \
168
- connstr = conname_or_str; \
171
+ connstr = get_connect_string(conname_or_str); \
172
+ if (connstr == NULL) \
173
+ { \
174
+ connstr = conname_or_str; \
175
+ } \
169
176
dblink_connstr_check(connstr); \
170
177
conn = PQconnectdb(connstr); \
171
178
if (PQstatus(conn) == CONNECTION_BAD) \
@@ -210,6 +217,7 @@ PG_FUNCTION_INFO_V1(dblink_connect);
210
217
Datum
211
218
dblink_connect (PG_FUNCTION_ARGS )
212
219
{
220
+ char * conname_or_str = NULL ;
213
221
char * connstr = NULL ;
214
222
char * connname = NULL ;
215
223
char * msg ;
@@ -220,16 +228,21 @@ dblink_connect(PG_FUNCTION_ARGS)
220
228
221
229
if (PG_NARGS () == 2 )
222
230
{
223
- connstr = text_to_cstring (PG_GETARG_TEXT_PP (1 ));
231
+ conname_or_str = text_to_cstring (PG_GETARG_TEXT_PP (1 ));
224
232
connname = text_to_cstring (PG_GETARG_TEXT_PP (0 ));
225
233
}
226
234
else if (PG_NARGS () == 1 )
227
- connstr = text_to_cstring (PG_GETARG_TEXT_PP (0 ));
235
+ conname_or_str = text_to_cstring (PG_GETARG_TEXT_PP (0 ));
228
236
229
237
if (connname )
230
238
rconn = (remoteConn * ) MemoryContextAlloc (TopMemoryContext ,
231
239
sizeof (remoteConn ));
232
240
241
+ /* first check for valid foreign data server */
242
+ connstr = get_connect_string (conname_or_str );
243
+ if (connstr == NULL )
244
+ connstr = conname_or_str ;
245
+
233
246
/* check password in connection string if not superuser */
234
247
dblink_connstr_check (connstr );
235
248
conn = PQconnectdb (connstr );
@@ -2353,3 +2366,86 @@ dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_
2353
2366
errcontext ("Error occurred on dblink connection named \"%s\": %s." ,
2354
2367
dblink_context_conname , dblink_context_msg )));
2355
2368
}
2369
+
2370
+ /*
2371
+ * Obtain connection string for a foreign server
2372
+ */
2373
+ static char *
2374
+ get_connect_string (const char * servername )
2375
+ {
2376
+ ForeignServer * foreign_server = NULL ;
2377
+ UserMapping * user_mapping ;
2378
+ ListCell * cell ;
2379
+ StringInfo buf = makeStringInfo ();
2380
+ ForeignDataWrapper * fdw ;
2381
+ AclResult aclresult ;
2382
+
2383
+ /* first gather the server connstr options */
2384
+ if (strlen (servername ) < NAMEDATALEN )
2385
+ foreign_server = GetForeignServerByName (servername , true);
2386
+
2387
+ if (foreign_server )
2388
+ {
2389
+ Oid serverid = foreign_server -> serverid ;
2390
+ Oid fdwid = foreign_server -> fdwid ;
2391
+ Oid userid = GetUserId ();
2392
+
2393
+ user_mapping = GetUserMapping (userid , serverid );
2394
+ fdw = GetForeignDataWrapper (fdwid );
2395
+
2396
+ /* Check permissions, user must have usage on the server. */
2397
+ aclresult = pg_foreign_server_aclcheck (serverid , userid , ACL_USAGE );
2398
+ if (aclresult != ACLCHECK_OK )
2399
+ aclcheck_error (aclresult , ACL_KIND_FOREIGN_SERVER , foreign_server -> servername );
2400
+
2401
+ foreach (cell , fdw -> options )
2402
+ {
2403
+ DefElem * def = lfirst (cell );
2404
+
2405
+ appendStringInfo (buf , "%s='%s' " , def -> defname ,
2406
+ escape_param_str (strVal (def -> arg )));
2407
+ }
2408
+
2409
+ foreach (cell , foreign_server -> options )
2410
+ {
2411
+ DefElem * def = lfirst (cell );
2412
+
2413
+ appendStringInfo (buf , "%s='%s' " , def -> defname ,
2414
+ escape_param_str (strVal (def -> arg )));
2415
+ }
2416
+
2417
+ foreach (cell , user_mapping -> options )
2418
+ {
2419
+
2420
+ DefElem * def = lfirst (cell );
2421
+
2422
+ appendStringInfo (buf , "%s='%s' " , def -> defname ,
2423
+ escape_param_str (strVal (def -> arg )));
2424
+ }
2425
+
2426
+ return buf -> data ;
2427
+ }
2428
+ else
2429
+ return NULL ;
2430
+ }
2431
+
2432
+ /*
2433
+ * Escaping libpq connect parameter strings.
2434
+ *
2435
+ * Replaces "'" with "\'" and "\" with "\\".
2436
+ */
2437
+ static char *
2438
+ escape_param_str (const char * str )
2439
+ {
2440
+ const char * cp ;
2441
+ StringInfo buf = makeStringInfo ();
2442
+
2443
+ for (cp = str ; * cp ; cp ++ )
2444
+ {
2445
+ if (* cp == '\\' || * cp == '\'' )
2446
+ appendStringInfoChar (buf , '\\' );
2447
+ appendStringInfoChar (buf , * cp );
2448
+ }
2449
+
2450
+ return buf -> data ;
2451
+ }
0 commit comments