Skip to content

Commit 7d4667c

Browse files
author
Etsuro Fujita
committed
Revert "postgres_fdw: Inherit the local transaction's access/deferrable modes."
We concluded that commit e5a3c9d is a feature rather than a fix; since it was added after feature freeze, revert it. Reported-by: Fujii Masao <masao.fujii@oss.nttdata.com> Reported-by: Michael Paquier <michael@paquier.xyz> Reported-by: Robert Haas <robertmhaas@gmail.com> Discussion: https://postgr.es/m/ed2296f1-1a6b-4932-b870-5bb18c2591ae%40oss.nttdata.com
1 parent 73e26cb commit 7d4667c

File tree

6 files changed

+8
-347
lines changed

6 files changed

+8
-347
lines changed

contrib/postgres_fdw/connection.c

Lines changed: 8 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ typedef struct ConnCacheEntry
5858
/* Remaining fields are invalid when conn is NULL: */
5959
int xact_depth; /* 0 = no xact open, 1 = main xact open, 2 =
6060
* one level of subxact open, etc */
61-
bool xact_read_only; /* xact r/o state */
6261
bool have_prep_stmt; /* have we prepared any stmts in this xact? */
6362
bool have_error; /* have any subxacts aborted in this xact? */
6463
bool changing_xact_state; /* xact state change in process */
@@ -85,12 +84,6 @@ static unsigned int prep_stmt_number = 0;
8584
/* tracks whether any work is needed in callback functions */
8685
static bool xact_got_connection = false;
8786

88-
/*
89-
* tracks the nesting level of the topmost read-only transaction determined
90-
* by GetTopReadOnlyTransactionNestLevel()
91-
*/
92-
static int top_read_only_level = 0;
93-
9487
/* custom wait event values, retrieved from shared memory */
9588
static uint32 pgfdw_we_cleanup_result = 0;
9689
static uint32 pgfdw_we_connect = 0;
@@ -379,7 +372,6 @@ make_new_connection(ConnCacheEntry *entry, UserMapping *user)
379372

380373
/* Reset all transient state fields, to be sure all are clean */
381374
entry->xact_depth = 0;
382-
entry->xact_read_only = false;
383375
entry->have_prep_stmt = false;
384376
entry->have_error = false;
385377
entry->changing_xact_state = false;
@@ -851,81 +843,29 @@ do_sql_command_end(PGconn *conn, const char *sql, bool consume_input)
851843
* those scans. A disadvantage is that we can't provide sane emulation of
852844
* READ COMMITTED behavior --- it would be nice if we had some other way to
853845
* control which remote queries share a snapshot.
854-
*
855-
* Note also that we always start the remote transaction with the same
856-
* read/write and deferrable properties as the local transaction, and start
857-
* the remote subtransaction with the same read/write property as the local
858-
* subtransaction.
859846
*/
860847
static void
861848
begin_remote_xact(ConnCacheEntry *entry)
862849
{
863850
int curlevel = GetCurrentTransactionNestLevel();
864851

865-
/*
866-
* Set the nesting level of the topmost read-only transaction if the
867-
* current transaction is read-only and we haven't yet. Once it's set,
868-
* it's retained until that transaction is committed/aborted, and then
869-
* reset (see pgfdw_xact_callback and pgfdw_subxact_callback).
870-
*/
871-
if (XactReadOnly)
872-
{
873-
if (top_read_only_level == 0)
874-
top_read_only_level = GetTopReadOnlyTransactionNestLevel();
875-
Assert(top_read_only_level > 0);
876-
}
877-
else
878-
Assert(top_read_only_level == 0);
879-
880-
/*
881-
* Start main transaction if we haven't yet; otherwise, change the
882-
* already-started remote transaction/subtransaction to read-only if the
883-
* local transaction/subtransaction have been done so after starting them
884-
* and we haven't yet.
885-
*/
852+
/* Start main transaction if we haven't yet */
886853
if (entry->xact_depth <= 0)
887854
{
888-
StringInfoData sql;
889-
bool ro = (top_read_only_level == 1);
855+
const char *sql;
890856

891857
elog(DEBUG3, "starting remote transaction on connection %p",
892858
entry->conn);
893859

894-
initStringInfo(&sql);
895-
appendStringInfoString(&sql, "START TRANSACTION ISOLATION LEVEL ");
896860
if (IsolationIsSerializable())
897-
appendStringInfoString(&sql, "SERIALIZABLE");
861+
sql = "START TRANSACTION ISOLATION LEVEL SERIALIZABLE";
898862
else
899-
appendStringInfoString(&sql, "REPEATABLE READ");
900-
if (ro)
901-
appendStringInfoString(&sql, " READ ONLY");
902-
if (XactDeferrable)
903-
appendStringInfoString(&sql, " DEFERRABLE");
863+
sql = "START TRANSACTION ISOLATION LEVEL REPEATABLE READ";
904864
entry->changing_xact_state = true;
905-
do_sql_command(entry->conn, sql.data);
865+
do_sql_command(entry->conn, sql);
906866
entry->xact_depth = 1;
907-
if (ro)
908-
{
909-
Assert(!entry->xact_read_only);
910-
entry->xact_read_only = true;
911-
}
912867
entry->changing_xact_state = false;
913868
}
914-
else if (!entry->xact_read_only)
915-
{
916-
Assert(top_read_only_level == 0 ||
917-
entry->xact_depth <= top_read_only_level);
918-
if (entry->xact_depth == top_read_only_level)
919-
{
920-
entry->changing_xact_state = true;
921-
do_sql_command(entry->conn, "SET transaction_read_only = on");
922-
entry->xact_read_only = true;
923-
entry->changing_xact_state = false;
924-
}
925-
}
926-
else
927-
Assert(top_read_only_level > 0 &&
928-
entry->xact_depth >= top_read_only_level);
929869

930870
/*
931871
* If we're in a subtransaction, stack up savepoints to match our level.
@@ -934,21 +874,12 @@ begin_remote_xact(ConnCacheEntry *entry)
934874
*/
935875
while (entry->xact_depth < curlevel)
936876
{
937-
StringInfoData sql;
938-
bool ro = (entry->xact_depth + 1 == top_read_only_level);
877+
char sql[64];
939878

940-
initStringInfo(&sql);
941-
appendStringInfo(&sql, "SAVEPOINT s%d", entry->xact_depth + 1);
942-
if (ro)
943-
appendStringInfoString(&sql, "; SET transaction_read_only = on");
879+
snprintf(sql, sizeof(sql), "SAVEPOINT s%d", entry->xact_depth + 1);
944880
entry->changing_xact_state = true;
945-
do_sql_command(entry->conn, sql.data);
881+
do_sql_command(entry->conn, sql);
946882
entry->xact_depth++;
947-
if (ro)
948-
{
949-
Assert(!entry->xact_read_only);
950-
entry->xact_read_only = true;
951-
}
952883
entry->changing_xact_state = false;
953884
}
954885
}
@@ -1243,9 +1174,6 @@ pgfdw_xact_callback(XactEvent event, void *arg)
12431174

12441175
/* Also reset cursor numbering for next transaction */
12451176
cursor_number = 0;
1246-
1247-
/* Likewise for top_read_only_level */
1248-
top_read_only_level = 0;
12491177
}
12501178

12511179
/*
@@ -1344,10 +1272,6 @@ pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid,
13441272
false);
13451273
}
13461274
}
1347-
1348-
/* If in the topmost read-only transaction, reset top_read_only_level */
1349-
if (curlevel == top_read_only_level)
1350-
top_read_only_level = 0;
13511275
}
13521276

13531277
/*
@@ -1450,9 +1374,6 @@ pgfdw_reset_xact_state(ConnCacheEntry *entry, bool toplevel)
14501374
/* Reset state to show we're out of a transaction */
14511375
entry->xact_depth = 0;
14521376

1453-
/* Reset xact r/o state */
1454-
entry->xact_read_only = false;
1455-
14561377
/*
14571378
* If the connection isn't in a good idle state, it is marked as
14581379
* invalid or keep_connections option of its server is disabled, then
@@ -1473,10 +1394,6 @@ pgfdw_reset_xact_state(ConnCacheEntry *entry, bool toplevel)
14731394
{
14741395
/* Reset state to show we're out of a subtransaction */
14751396
entry->xact_depth--;
1476-
1477-
/* If in the topmost read-only transaction, reset xact r/o state */
1478-
if (entry->xact_depth + 1 == top_read_only_level)
1479-
entry->xact_read_only = false;
14801397
}
14811398
}
14821399

contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 0 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -12384,140 +12384,6 @@ SELECT count(*) FROM remote_application_name
1238412384
DROP FOREIGN TABLE remote_application_name;
1238512385
DROP VIEW my_application_name;
1238612386
-- ===================================================================
12387-
-- test read-only and/or deferrable transactions
12388-
-- ===================================================================
12389-
CREATE TABLE loct (f1 int, f2 text);
12390-
CREATE FUNCTION locf() RETURNS SETOF loct LANGUAGE SQL AS
12391-
'UPDATE public.loct SET f2 = f2 || f2 RETURNING *';
12392-
CREATE VIEW locv AS SELECT t.* FROM locf() t;
12393-
CREATE FOREIGN TABLE remt (f1 int, f2 text)
12394-
SERVER loopback OPTIONS (table_name 'locv');
12395-
CREATE FOREIGN TABLE remt2 (f1 int, f2 text)
12396-
SERVER loopback2 OPTIONS (table_name 'locv');
12397-
INSERT INTO loct VALUES (1, 'foo'), (2, 'bar');
12398-
START TRANSACTION READ ONLY;
12399-
SAVEPOINT s;
12400-
SELECT * FROM remt; -- should fail
12401-
ERROR: cannot execute UPDATE in a read-only transaction
12402-
CONTEXT: SQL function "locf" statement 1
12403-
remote SQL command: SELECT f1, f2 FROM public.locv
12404-
ROLLBACK TO s;
12405-
RELEASE SAVEPOINT s;
12406-
SELECT * FROM remt; -- should fail
12407-
ERROR: cannot execute UPDATE in a read-only transaction
12408-
CONTEXT: SQL function "locf" statement 1
12409-
remote SQL command: SELECT f1, f2 FROM public.locv
12410-
ROLLBACK;
12411-
START TRANSACTION;
12412-
SAVEPOINT s;
12413-
SET transaction_read_only = on;
12414-
SELECT * FROM remt; -- should fail
12415-
ERROR: cannot execute UPDATE in a read-only transaction
12416-
CONTEXT: SQL function "locf" statement 1
12417-
remote SQL command: SELECT f1, f2 FROM public.locv
12418-
ROLLBACK TO s;
12419-
RELEASE SAVEPOINT s;
12420-
SET transaction_read_only = on;
12421-
SELECT * FROM remt; -- should fail
12422-
ERROR: cannot execute UPDATE in a read-only transaction
12423-
CONTEXT: SQL function "locf" statement 1
12424-
remote SQL command: SELECT f1, f2 FROM public.locv
12425-
ROLLBACK;
12426-
START TRANSACTION;
12427-
SAVEPOINT s;
12428-
SELECT * FROM remt; -- should work
12429-
f1 | f2
12430-
----+--------
12431-
1 | foofoo
12432-
2 | barbar
12433-
(2 rows)
12434-
12435-
SET transaction_read_only = on;
12436-
SELECT * FROM remt; -- should fail
12437-
ERROR: cannot execute UPDATE in a read-only transaction
12438-
CONTEXT: SQL function "locf" statement 1
12439-
remote SQL command: SELECT f1, f2 FROM public.locv
12440-
ROLLBACK TO s;
12441-
RELEASE SAVEPOINT s;
12442-
SELECT * FROM remt; -- should work
12443-
f1 | f2
12444-
----+--------
12445-
1 | foofoo
12446-
2 | barbar
12447-
(2 rows)
12448-
12449-
SET transaction_read_only = on;
12450-
SELECT * FROM remt; -- should fail
12451-
ERROR: cannot execute UPDATE in a read-only transaction
12452-
CONTEXT: SQL function "locf" statement 1
12453-
remote SQL command: SELECT f1, f2 FROM public.locv
12454-
ROLLBACK;
12455-
START TRANSACTION;
12456-
SAVEPOINT s;
12457-
SELECT * FROM remt; -- should work
12458-
f1 | f2
12459-
----+--------
12460-
1 | foofoo
12461-
2 | barbar
12462-
(2 rows)
12463-
12464-
SET transaction_read_only = on;
12465-
SELECT * FROM remt2; -- should fail
12466-
ERROR: cannot execute UPDATE in a read-only transaction
12467-
CONTEXT: SQL function "locf" statement 1
12468-
remote SQL command: SELECT f1, f2 FROM public.locv
12469-
ROLLBACK TO s;
12470-
RELEASE SAVEPOINT s;
12471-
SELECT * FROM remt; -- should work
12472-
f1 | f2
12473-
----+--------
12474-
1 | foofoo
12475-
2 | barbar
12476-
(2 rows)
12477-
12478-
SET transaction_read_only = on;
12479-
SELECT * FROM remt2; -- should fail
12480-
ERROR: cannot execute UPDATE in a read-only transaction
12481-
CONTEXT: SQL function "locf" statement 1
12482-
remote SQL command: SELECT f1, f2 FROM public.locv
12483-
ROLLBACK;
12484-
DROP FOREIGN TABLE remt;
12485-
CREATE FOREIGN TABLE remt (f1 int, f2 text)
12486-
SERVER loopback OPTIONS (table_name 'loct');
12487-
START TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY;
12488-
SELECT * FROM remt;
12489-
f1 | f2
12490-
----+-----
12491-
1 | foo
12492-
2 | bar
12493-
(2 rows)
12494-
12495-
COMMIT;
12496-
START TRANSACTION ISOLATION LEVEL SERIALIZABLE DEFERRABLE;
12497-
SELECT * FROM remt;
12498-
f1 | f2
12499-
----+-----
12500-
1 | foo
12501-
2 | bar
12502-
(2 rows)
12503-
12504-
COMMIT;
12505-
START TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY DEFERRABLE;
12506-
SELECT * FROM remt;
12507-
f1 | f2
12508-
----+-----
12509-
1 | foo
12510-
2 | bar
12511-
(2 rows)
12512-
12513-
COMMIT;
12514-
-- Clean up
12515-
DROP FOREIGN TABLE remt;
12516-
DROP FOREIGN TABLE remt2;
12517-
DROP VIEW locv;
12518-
DROP FUNCTION locf();
12519-
DROP TABLE loct;
12520-
-- ===================================================================
1252112387
-- test parallel commit and parallel abort
1252212388
-- ===================================================================
1252312389
ALTER SERVER loopback OPTIONS (ADD parallel_commit 'true');

0 commit comments

Comments
 (0)