88 * Darko Prenosil <Darko.Prenosil@finteh.hr>
99 * Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
1010 *
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 $
1212 * Copyright (c) 2001-2009, PostgreSQL Global Development Group
1313 * ALL RIGHTS RESERVED;
1414 *
4646#include "catalog/pg_type.h"
4747#include "executor/executor.h"
4848#include "executor/spi.h"
49+ #include "foreign/foreign.h"
4950#include "lib/stringinfo.h"
5051#include "miscadmin.h"
5152#include "nodes/execnodes.h"
@@ -96,6 +97,8 @@ static char *generate_relation_name(Oid relid);
9697static void dblink_connstr_check (const char * connstr );
9798static void dblink_security_check (PGconn * conn , remoteConn * rconn );
9899static 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 );
99102
100103/* Global */
101104static remoteConn * pconn = NULL ;
@@ -165,7 +168,11 @@ typedef struct remoteConnHashEnt
165168 } \
166169 else \
167170 { \
168- connstr = conname_or_str; \
171+ connstr = get_connect_string(conname_or_str); \
172+ if (connstr == NULL) \
173+ { \
174+ connstr = conname_or_str; \
175+ } \
169176 dblink_connstr_check(connstr); \
170177 conn = PQconnectdb(connstr); \
171178 if (PQstatus(conn) == CONNECTION_BAD) \
@@ -210,6 +217,7 @@ PG_FUNCTION_INFO_V1(dblink_connect);
210217Datum
211218dblink_connect (PG_FUNCTION_ARGS )
212219{
220+ char * conname_or_str = NULL ;
213221 char * connstr = NULL ;
214222 char * connname = NULL ;
215223 char * msg ;
@@ -220,16 +228,21 @@ dblink_connect(PG_FUNCTION_ARGS)
220228
221229 if (PG_NARGS () == 2 )
222230 {
223- connstr = text_to_cstring (PG_GETARG_TEXT_PP (1 ));
231+ conname_or_str = text_to_cstring (PG_GETARG_TEXT_PP (1 ));
224232 connname = text_to_cstring (PG_GETARG_TEXT_PP (0 ));
225233 }
226234 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 ));
228236
229237 if (connname )
230238 rconn = (remoteConn * ) MemoryContextAlloc (TopMemoryContext ,
231239 sizeof (remoteConn ));
232240
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+
233246 /* check password in connection string if not superuser */
234247 dblink_connstr_check (connstr );
235248 conn = PQconnectdb (connstr );
@@ -2353,3 +2366,86 @@ dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_
23532366 errcontext ("Error occurred on dblink connection named \"%s\": %s." ,
23542367 dblink_context_conname , dblink_context_msg )));
23552368}
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