diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c index 8a8d3b4481..c50e86c6a1 100644 --- a/contrib/postgres_fdw/connection.c +++ b/contrib/postgres_fdw/connection.c @@ -61,6 +61,8 @@ typedef struct ConnCacheEntry bool have_prep_stmt; /* have we prepared any stmts in this xact? */ bool have_error; /* have any subxacts aborted in this xact? */ bool changing_xact_state; /* xact state change in process */ + bool inherit_read_only; /* do we open xacts in read-only mode? */ + bool inherit_deferrable; /* do we open xacts in dederrable mode? */ bool parallel_commit; /* do we commit (sub)xacts in parallel? */ bool parallel_abort; /* do we abort (sub)xacts in parallel? */ bool invalidated; /* true if reconnect is pending */ @@ -391,6 +393,9 @@ make_new_connection(ConnCacheEntry *entry, UserMapping *user) * * By default, all the connections to any foreign servers are kept open. * + * Also determine whether to open transactions in read-only and/or + * deferrable modes on the remote server, which is disabled by default. + * * Also determine whether to commit/abort (sub)transactions opened on the * remote server in parallel at (sub)transaction end, which is disabled by * default. @@ -400,6 +405,8 @@ make_new_connection(ConnCacheEntry *entry, UserMapping *user) * re-made later. */ entry->keep_connections = true; + entry->inherit_read_only = false; + entry->inherit_deferrable = false; entry->parallel_commit = false; entry->parallel_abort = false; foreach(lc, server->options) @@ -408,6 +415,10 @@ make_new_connection(ConnCacheEntry *entry, UserMapping *user) if (strcmp(def->defname, "keep_connections") == 0) entry->keep_connections = defGetBoolean(def); + else if (strcmp(def->defname, "inherit_read_only") == 0) + entry->inherit_read_only = defGetBoolean(def); + else if (strcmp(def->defname, "inherit_deferrable") == 0) + entry->inherit_deferrable = defGetBoolean(def); else if (strcmp(def->defname, "parallel_commit") == 0) entry->parallel_commit = defGetBoolean(def); else if (strcmp(def->defname, "parallel_abort") == 0) @@ -831,17 +842,26 @@ begin_remote_xact(ConnCacheEntry *entry) /* Start main transaction if we haven't yet */ if (entry->xact_depth <= 0) { - const char *sql; + StringInfoData sql; elog(DEBUG3, "starting remote transaction on connection %p", entry->conn); + initStringInfo(&sql); + appendStringInfoString(&sql, "START TRANSACTION ISOLATION LEVEL "); if (IsolationIsSerializable()) - sql = "START TRANSACTION ISOLATION LEVEL SERIALIZABLE"; + appendStringInfoString(&sql, "SERIALIZABLE"); else - sql = "START TRANSACTION ISOLATION LEVEL REPEATABLE READ"; + appendStringInfoString(&sql, "REPEATABLE READ"); + + /* Append access/deferrable modes if needed */ + if (entry->inherit_read_only && XactReadOnly) + appendStringInfoString(&sql, " READ ONLY"); + if (entry->inherit_deferrable && XactDeferrable) + appendStringInfoString(&sql, " DEFERRABLE"); + entry->changing_xact_state = true; - do_sql_command(entry->conn, sql); + do_sql_command(entry->conn, sql.data); entry->xact_depth = 1; entry->changing_xact_state = false; } diff --git a/contrib/postgres_fdw/option.c b/contrib/postgres_fdw/option.c index d0766f007d..e411150318 100644 --- a/contrib/postgres_fdw/option.c +++ b/contrib/postgres_fdw/option.c @@ -123,6 +123,8 @@ postgres_fdw_validator(PG_FUNCTION_ARGS) strcmp(def->defname, "updatable") == 0 || strcmp(def->defname, "truncatable") == 0 || strcmp(def->defname, "async_capable") == 0 || + strcmp(def->defname, "inherit_read_only") == 0 || + strcmp(def->defname, "inherit_deferrable") == 0 || strcmp(def->defname, "parallel_commit") == 0 || strcmp(def->defname, "parallel_abort") == 0 || strcmp(def->defname, "keep_connections") == 0) @@ -270,6 +272,8 @@ InitPgFdwOptions(void) /* async_capable is available on both server and table */ {"async_capable", ForeignServerRelationId, false}, {"async_capable", ForeignTableRelationId, false}, + {"inherit_read_only", ForeignServerRelationId, false}, + {"inherit_deferrable", ForeignServerRelationId, false}, {"parallel_commit", ForeignServerRelationId, false}, {"parallel_abort", ForeignServerRelationId, false}, {"keep_connections", ForeignServerRelationId, false}, diff --git a/doc/src/sgml/postgres-fdw.sgml b/doc/src/sgml/postgres-fdw.sgml index d2998c13d5..337a2d6252 100644 --- a/doc/src/sgml/postgres-fdw.sgml +++ b/doc/src/sgml/postgres-fdw.sgml @@ -524,6 +524,32 @@ OPTIONS (ADD password_required 'false'); + + inherit_read_only (boolean) + + + This option controls whether postgres_fdw opens + remote transactions in read-only mode on a foreign server in a local + transaction if the local transaction is read-only. + This option can only be specified for foreign servers, not per-table. + The default is false. + + + + + + inherit_deferrable (boolean) + + + This option controls whether postgres_fdw opens + remote transactions in deferrable mode on a foreign server in a local + transaction if the local transaction is deferrable. + This option can only be specified for foreign servers, not per-table. + The default is false. + + + + parallel_commit (boolean)