/*
* Connection cache hash table entry
*
- * The lookup key in this hash table is the foreign server OID plus the user
- * mapping OID. (We use just one connection per user per foreign server,
- * so that we can ensure all scans use the same snapshot during a query.)
+ * The lookup key in this hash table is the user mapping OID. We use just one
+ * connection per user mapping ID, which ensures that all the scans use the
+ * same snapshot during a query. Using the user mapping OID rather than
+ * the foreign server OID + user OID avoids creating multiple connections when
+ * the public user mapping applies to all user OIDs.
*
* The "conn" pointer can be NULL if we don't currently have a live connection.
* When we do have a connection, xact_depth tracks the current depth of
* ourselves, so that rolling back a subtransaction will kill the right
* queries and not the wrong ones.
*/
-typedef struct ConnCacheKey
-{
- Oid serverid; /* OID of foreign server */
- Oid userid; /* OID of local user whose mapping we use */
-} ConnCacheKey;
+typedef Oid ConnCacheKey;
typedef struct ConnCacheEntry
{
* mid-transaction anyway.
*/
PGconn *
-GetConnection(ForeignServer *server, UserMapping *user,
- bool will_prep_stmt)
+GetConnection(UserMapping *user, bool will_prep_stmt)
{
bool found;
ConnCacheEntry *entry;
xact_got_connection = true;
/* Create hash key for the entry. Assume no pad bytes in key struct */
- key.serverid = server->serverid;
- key.userid = user->userid;
+ key = user->umid;
/*
* Find or create cached entry for requested connection.
*/
if (entry->conn == NULL)
{
+ ForeignServer *server = GetForeignServer(user->serverid);
+
entry->xact_depth = 0; /* just to be sure */
entry->have_prep_stmt = false;
entry->have_error = false;
entry->conn = connect_pg_server(server, user);
- elog(DEBUG3, "new postgres_fdw connection %p for server \"%s\"",
- entry->conn, server->servername);
+
+ elog(DEBUG3, "new postgres_fdw connection %p for server \"%s\ (user mapping oid %d, userid %d)",
+ entry->conn, server->servername, user->umid, user->userid);
}
/*
RangeTblEntry *rte;
Oid userid;
ForeignTable *table;
- ForeignServer *server;
UserMapping *user;
int numParams;
int i;
/* Get info about foreign table. */
fsstate->rel = node->ss.ss_currentRelation;
table = GetForeignTable(RelationGetRelid(fsstate->rel));
- server = GetForeignServer(table->serverid);
- user = GetUserMapping(userid, server->serverid);
+ user = GetUserMapping(userid, table->serverid);
/*
* Get connection to the foreign server. Connection manager will
* establish new connection if necessary.
*/
- fsstate->conn = GetConnection(server, user, false);
+ fsstate->conn = GetConnection(user, false);
/* Assign a unique ID for my cursor */
fsstate->cursor_number = GetCursorNumber(fsstate->conn);
RangeTblEntry *rte;
Oid userid;
ForeignTable *table;
- ForeignServer *server;
UserMapping *user;
AttrNumber n_params;
Oid typefnoid;
/* Get info about foreign table. */
table = GetForeignTable(RelationGetRelid(rel));
- server = GetForeignServer(table->serverid);
- user = GetUserMapping(userid, server->serverid);
+ user = GetUserMapping(userid, table->serverid);
/* Open connection; report that we'll create a prepared statement. */
- fmstate->conn = GetConnection(server, user, true);
+ fmstate->conn = GetConnection(user, true);
fmstate->p_name = NULL; /* prepared statement not made yet */
/* Deconstruct fdw_private data. */
appendOrderByClause(&sql, root, baserel, pathkeys);
/* Get the remote estimate */
- conn = GetConnection(fpinfo->server, fpinfo->user, false);
+ conn = GetConnection(fpinfo->user, false);
get_remote_estimate(sql.data, conn, &rows, &width,
&startup_cost, &total_cost);
ReleaseConnection(conn);
BlockNumber *totalpages)
{
ForeignTable *table;
- ForeignServer *server;
UserMapping *user;
PGconn *conn;
StringInfoData sql;
* owner, even if the ANALYZE was started by some other user.
*/
table = GetForeignTable(RelationGetRelid(relation));
- server = GetForeignServer(table->serverid);
- user = GetUserMapping(relation->rd_rel->relowner, server->serverid);
- conn = GetConnection(server, user, false);
+ user = GetUserMapping(relation->rd_rel->relowner, table->serverid);
+ conn = GetConnection(user, false);
/*
* Construct command to get page count for relation.
{
PgFdwAnalyzeState astate;
ForeignTable *table;
- ForeignServer *server;
UserMapping *user;
PGconn *conn;
unsigned int cursor_number;
* owner, even if the ANALYZE was started by some other user.
*/
table = GetForeignTable(RelationGetRelid(relation));
- server = GetForeignServer(table->serverid);
- user = GetUserMapping(relation->rd_rel->relowner, server->serverid);
- conn = GetConnection(server, user, false);
+ user = GetUserMapping(relation->rd_rel->relowner, table->serverid);
+ conn = GetConnection(user, false);
/*
* Construct cursor that retrieves whole rows from remote.
*/
server = GetForeignServer(serverOid);
mapping = GetUserMapping(GetUserId(), server->serverid);
- conn = GetConnection(server, mapping, false);
+ conn = GetConnection(mapping, false);
/* Don't attempt to import collation if remote server hasn't got it */
if (PQserverVersion(conn) < 90100)