From ec2b2d7d78a5ce9d75eb253ae3db45cc4a9d7a13 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Fri, 27 Nov 2020 06:18:42 +0530 Subject: [PATCH v2] postgres_fdw server level option, keep_connection to not cache connection This patch adds a new server level option, keep_connection, default being on, when set to off, the local session doesn't cache the connections associated with the foreign server. --- contrib/postgres_fdw/connection.c | 22 +++++++++++++++++++--- contrib/postgres_fdw/option.c | 9 ++++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c index 85217188b5..c13e1a3cc8 100644 --- a/contrib/postgres_fdw/connection.c +++ b/contrib/postgres_fdw/connection.c @@ -60,6 +60,8 @@ typedef struct ConnCacheEntry bool invalidated; /* true if reconnect is pending */ uint32 server_hashvalue; /* hash value of foreign server OID */ uint32 mapping_hashvalue; /* hash value of user mapping OID */ + /* Keep or discard this connection at the end of xact */ + bool keep_connection; } ConnCacheEntry; /* @@ -120,6 +122,8 @@ GetConnection(UserMapping *user, bool will_prep_stmt) ConnCacheEntry *entry; ConnCacheKey key; MemoryContext ccxt = CurrentMemoryContext; + ListCell *lc; + ForeignServer *server; /* First time through, initialize connection cache hashtable */ if (ConnectionHash == NULL) @@ -260,6 +264,15 @@ GetConnection(UserMapping *user, bool will_prep_stmt) begin_remote_xact(entry); } + server = GetForeignServer(user->serverid); + foreach(lc, server->options) + { + DefElem *def = (DefElem *) lfirst(lc); + + if (strcmp(def->defname, "keep_connection") == 0) + entry->keep_connection = defGetBoolean(def); + } + /* Remember if caller will prepare statements */ entry->have_prep_stmt |= will_prep_stmt; @@ -283,6 +296,7 @@ make_new_connection(ConnCacheEntry *entry, UserMapping *user) entry->have_error = false; entry->changing_xact_state = false; entry->invalidated = false; + entry->keep_connection = true; entry->server_hashvalue = GetSysCacheHashValue1(FOREIGNSERVEROID, ObjectIdGetDatum(server->serverid)); @@ -956,14 +970,16 @@ pgfdw_xact_callback(XactEvent event, void *arg) * If the connection isn't in a good idle state, discard it to recover. * Next GetConnection will open a new connection when required. * - * If the keep_connections GUC is false and this connection is used in - * current xact, then also discard it. + * Also discard the connection if it is used in current xact and if the + * GUC is set to off or if the GUC is on but the server level option is + * set to off. Note that keep_connections GUC overrides the server + * level keep_connection option. */ if ((PQstatus(entry->conn) != CONNECTION_OK || PQtransactionStatus(entry->conn) != PQTRANS_IDLE || entry->changing_xact_state) || (used_in_current_xact && - !keep_connections)) + (!keep_connections || !entry->keep_connection))) { elog(DEBUG3, "discarding connection %p", entry->conn); disconnect_pg_server(entry); diff --git a/contrib/postgres_fdw/option.c b/contrib/postgres_fdw/option.c index 1a03e02263..0fe2eff878 100644 --- a/contrib/postgres_fdw/option.c +++ b/contrib/postgres_fdw/option.c @@ -107,7 +107,8 @@ postgres_fdw_validator(PG_FUNCTION_ARGS) * Validate option value, when we can do so without any context. */ if (strcmp(def->defname, "use_remote_estimate") == 0 || - strcmp(def->defname, "updatable") == 0) + strcmp(def->defname, "updatable") == 0 || + strcmp(def->defname, "keep_connection") == 0) { /* these accept only boolean values */ (void) defGetBoolean(def); @@ -213,6 +214,12 @@ InitPgFdwOptions(void) {"sslcert", UserMappingRelationId, true}, {"sslkey", UserMappingRelationId, true}, + /* + * If true, cache the connection associated with this server, otherwise + * remove it at the end of the xact. Default is true. + */ + {"keep_connection", ForeignServerRelationId, false}, + {NULL, InvalidOid, false} }; -- 2.25.1