-- -- XC_FOR_UPDATE -- set enable_fast_query_shipping=true; -- create some tables create table t1(val int, val2 int); create table t2(val int, val2 int); create table t3(val int, val2 int); create table p1(a int, b int); create table c1(d int, e int) inherits (p1); -- insert some rows in them insert into t1 values(1,11),(2,11); insert into t2 values(3,11),(4,11); insert into t3 values(5,11),(6,11); insert into p1 values(55,66),(77,88); insert into c1 values(111,222,333,444),(123,345,567,789); select * from t1 order by val; select * from t2 order by val; select * from t3 order by val; select * from p1 order by a; select * from c1 order by a; -- create a view too create view v1 as select * from t1 for update; -- test a few queries with row marks select * from t1 order by 1 for update of t1 nowait; --select * from t1, t2, t3 order by 1 for update; select * from v1 order by val; --WITH q1 AS (SELECT * from t1 order by 1 FOR UPDATE) SELECT * FROM q1,t2 order by 1 FOR UPDATE; WITH q1 AS (SELECT * from t1 order by 1) SELECT * FROM q1; WITH q1 AS (SELECT * from t1 order by 1) SELECT * FROM q1 FOR UPDATE; WITH q1 AS (SELECT * from t1 order by 1 FOR UPDATE) SELECT * FROM q1 FOR UPDATE; -- confirm that in various join scenarios for update gets to the remote query -- single table case explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 for update of t1 nowait; -- two table case explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2 where t1.val = t2.val for update nowait; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2 where t1.val = t2.val for update; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2 where t1.val = t2.val for share; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2 where t1.val = t2.val; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2 for update; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2 for update nowait; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2 for share nowait; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2 for share; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2 for share of t2; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 join t2 on (t1.val = t2.val) for share; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 left join t2 on (t1.val = t2.val) for share; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 right join t2 on (t1.val = t2.val) for share; select * from t1 join t2 on (t1.val = t2.val) for share; select * from t1 left join t2 on (t1.val = t2.val) for share; select * from t1 right join t2 on (t1.val = t2.val) for share; -- three table case explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2, t3; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2, t3 for update; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2, t3 for update of t1; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2, t3 for update of t1,t3; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2, t3 for update of t1,t3 nowait; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2, t3 for share of t1,t2 nowait; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 join t2 on (t1.val2 = t2.val2) join t3 on (t1.val2 = t3.val2); explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 join t2 on (t1.val2 = t2.val2) join t3 on (t1.val2 = t3.val2) for update; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 join t2 on (t1.val2 = t2.val2) join t3 on (t1.val2 = t3.val2) for update of t1; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 join t2 on (t1.val2 = t2.val2) join t3 on (t1.val2 = t3.val2) for update of t1,t3; select * from t1 join t2 on (t1.val2 = t2.val2) join t3 on (t1.val2 = t3.val2); select * from t1 join t2 on (t1.val2 = t2.val2) join t3 on (t1.val2 = t3.val2) for update; select * from t1 join t2 on (t1.val2 = t2.val2) join t3 on (t1.val2 = t3.val2) for update of t1; select * from t1 join t2 on (t1.val2 = t2.val2) join t3 on (t1.val2 = t3.val2) for update of t1,t3; -- check a few subquery cases explain (costs off, num_nodes off, nodes off, verbose on) select * from (select * from t1 for update of t1 nowait) as foo; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 where val in (select val from t2 for update of t2 nowait) for update; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 where val in (select val from t2 for update of t2 nowait); -- test multiple row marks explain (costs off, num_nodes off, nodes off, verbose on) select * from t1, t2 for share of t2 for update of t1; -- make sure FOR UPDATE takes prioriy over FOR SHARE when mentioned for the same table explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 for share of t1 for update of t1; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 for update of t1 for share of t1; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 for share of t1 for share of t1 for update of t1; explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 for share of t1 for share of t1 for share of t1; -- make sure NOWAIT is used in remote query even if it is not mentioned with FOR UPDATE clause explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 for share of t1 for share of t1 nowait for update of t1; -- same table , different aliases and different row marks for different aliases explain (costs off, num_nodes off, nodes off, verbose on) select * from t1 a,t1 b for share of a for update of b; -- test WITH queries -- join of a WITH table and a normal table explain (costs off, num_nodes off, nodes off, verbose on) WITH q1 AS (SELECT * from t1 FOR UPDATE) SELECT * FROM q1,t2 FOR UPDATE; explain (costs off, num_nodes off, nodes off, verbose on) WITH q1 AS (SELECT * from t1) SELECT * FROM q1; -- make sure row marks are no ops for queries on WITH tables explain (costs off, num_nodes off, nodes off, verbose on) WITH q1 AS (SELECT * from t1) SELECT * FROM q1 FOR UPDATE; explain (costs off, num_nodes off, nodes off, verbose on) WITH q1 AS (SELECT * from t1 FOR UPDATE) SELECT * FROM q1 FOR UPDATE; -- test case of inheried tables select * from p1 order by 1 for update; explain (costs off, num_nodes off, nodes off, verbose on) select * from p1 for update; select * from c1 order by 1 for update; explain (costs off, num_nodes off, nodes off, verbose on) select * from c1 for update; -- confirm that in various join scenarios for update gets to the remote query -- single table case select * from t1 for update of t1 nowait; -- two table case select * from t1, t2 where t1.val = t2.val for update nowait; select * from t1, t2 where t1.val = t2.val for update; select * from t1, t2 where t1.val = t2.val for share; select * from t1, t2 where t1.val = t2.val; select * from t1, t2; select * from t1, t2 for update; select * from t1, t2 for update nowait; select * from t1, t2 for share nowait; select * from t1, t2 for share; select * from t1, t2 for share of t2; -- three table case select * from t1, t2, t3; select * from t1, t2, t3 for update; select * from t1, t2, t3 for update of t1; select * from t1, t2, t3 for update of t1,t3; select * from t1, t2, t3 for update of t1,t3 nowait; select * from t1, t2, t3 for share of t1,t2 nowait; -- check a few subquery cases select * from (select * from t1 for update of t1 nowait) as foo; select * from t1 where val in (select val from t2 for update of t2 nowait) for update; select * from t1 where val in (select val from t2 for update of t2 nowait); -- test multiple row marks select * from t1, t2 for share of t2 for update of t1; -- make sure FOR UPDATE takes prioriy over FOR SHARE when mentioned for the same table select * from t1 for share of t1 for update of t1; select * from t1 for update of t1 for share of t1; select * from t1 for share of t1 for share of t1 for update of t1; select * from t1 for share of t1 for share of t1 for share of t1; -- make sure NOWAIT is used in remote query even if it is not mentioned with FOR UPDATE clause select * from t1 for share of t1 for share of t1 nowait for update of t1; -- same table , different aliases and different row marks for different aliases select * from t1 a,t1 b for share of a for update of b; -- test WITH queries -- join of a WITH table and a normal table WITH q1 AS (SELECT * from t1 FOR UPDATE) SELECT * FROM q1,t2 FOR UPDATE; WITH q1 AS (SELECT * from t1) SELECT * FROM q1; -- make sure row marks are no ops for queries on WITH tables WITH q1 AS (SELECT * from t1) SELECT * FROM q1 FOR UPDATE; WITH q1 AS (SELECT * from t1 FOR UPDATE) SELECT * FROM q1 FOR UPDATE; -- drop objects created drop table c1; drop table p1; drop view v1; drop table t1; drop table t2; drop table t3; ------------------------------------------- -- Tests for concurrent transactions ------------------------------------------- -- create some tables create table mytab1(val int, val2 int, val3 int); create table mytab3(val int, val2 int); create table mytab4(val int, val2 int); -- create index,rule,trgger & view on one of the tables CREATE UNIQUE INDEX test_idx ON mytab1 (val); CREATE RULE test_rule AS ON INSERT TO mytab1 DO ALSO SELECT * FROM mytab3; CREATE VIEW v1 as select * from mytab1 where val = 2; -- insert some rows insert into mytab1 values(1,11,1122),(2,11,3344); ------------------------------------------- -- Case 1 where we have a SELECT FOR UPDATE ------------------------------------------- -- A transaction that holds ACCESS EXCLUSIVE lock on a table can later acquire ACCESS SHARE lock on the same table begin; declare c1 cursor for select * from mytab1 for update; fetch 1 from c1; declare c2 cursor for select * from mytab1 for share; fetch 1 from c2; end; -- prepare a transaction that holds a ACCESS EXCLUSIVE (ROW SHARE) lock on a table begin; declare c1 cursor for select * from mytab1 for update; fetch 1 from c1; prepare transaction 'tbl_mytab1_locked'; set statement_timeout to 1000; -- When a transaction holds a ACCESS EXCLUSIVE (ROW SHARE) lock on a table (Like a SELECT FOR UPDATE would do) -- Can onther transaction do these to the same table -- 1. select some rows (Should pass) select * from mytab1 order by 1; -- 2. insert a row (Should pass) insert into mytab1 values(123,456); -- 3. update a row (Should fail) update mytab1 set val2=33 where val = 1; -- 4. delete a row -- Newly Inserted (Should pass) delete from mytab1 where val2=456; -- Previously Inserted (Should fail) delete from mytab1 where val=1; -- 5. inherit form it (Should pass) create table chld_mytab1(d int, e int) inherits (mytab1); -- 6. create a view on it (Should pass) create view v2 as select * from mytab1 where val = 1; -- 7. comment on it (Should pass) comment on table mytab1 is 'Hello table'; -- 8. Alter it (Should fail) alter table mytab1 drop column val2; -- 9. drop it (Should fail) drop table mytab1; -- 10. vacuum it (Should pass) vacuum mytab1; -- 11. obtain any of these locks on it -- ACCESS SHARE (Should pass) begin; lock table mytab1 in ACCESS SHARE mode nowait; end; -- ROW SHARE (Should pass) begin; lock table mytab1 in ROW SHARE mode nowait; end; -- ROW EXCLUSIVE (Should pass) begin; lock table mytab1 in ROW EXCLUSIVE mode nowait; end; -- SHARE UPDATE EXCLUSIVE (Should pass) begin; lock table mytab1 in SHARE UPDATE EXCLUSIVE mode nowait; end; -- SHARE (Should pass) begin; lock table mytab1 in SHARE mode nowait; end; -- SHARE ROW EXCLUSIVE (Should pass) begin; lock table mytab1 in SHARE ROW EXCLUSIVE mode nowait; end; -- EXCLUSIVE (Should fail) begin; lock table mytab1 in EXCLUSIVE mode nowait; end; -- ACCESS EXCLUSIVE (Should fail) begin; lock table mytab1 in ACCESS EXCLUSIVE mode nowait; end; -- 12. do a SELECT FOR SHARE on it (Should fail) begin; declare c1 cursor for select * from mytab1 for share nowait; fetch 1 from c1; end; -- 13. do a SELECT FOR UPDATE on it (Should fail) begin; declare c1 cursor for select * from mytab1 for update nowait; fetch 1 from c1; end; -- 14. alter already defined index on it (Should fail) ALTER INDEX test_idx RENAME TO mytab1_idx; -- 15. alter already defined view on it (Should pass) ALTER VIEW v1 RENAME TO vv1; -- 16. drop already defined index on it (Should fail) drop index test_idx; -- 17. drop already defined rule on it (Should fail) drop rule test_rule on mytab1; -- 18. drop already defined view on it (Should pass) drop view vv1; -- 19. reindex an alredy defined index on it (Should fail) reindex index test_idx; -- 20. truncate it (Should fail) truncate table mytab1; -- 21. create rule on it (Should fail) CREATE RULE test_rule2 AS ON INSERT TO mytab1 DO ALSO SELECT * FROM mytab1_insert_log; -- clean up COMMIT PREPARED 'tbl_mytab1_locked'; drop table chld_mytab1; drop view v2; -- create the view again to carry out the next test case CREATE VIEW v1 as select * from mytab1 where val = 2; ------------------------------------------- -- Case 2 where we have a SELECT FOR SHARE ------------------------------------------- -- A transaction that holds ACCESS SHARE lock on a table can later acquire ACCESS EXCLUSIVE lock on the same table begin; declare c1 cursor for select * from mytab1 for share; fetch 1 from c1; declare c2 cursor for select * from mytab1 for update; fetch 1 from c2; end; -- prepare a transaction that holds a ACCESS SHARE (ROW SHARE) lock on a table begin; declare c1 cursor for select * from mytab1 for share; fetch 1 from c1; prepare transaction 'tbl_mytab1_locked'; set statement_timeout to 1000; -- When a transaction holds a ACCESS SHARE (ROW SHARE) lock on a table (Like a SELECT FOR SHARE would do) -- Can onther transaction do these to the same table -- 1. select some rows (Should pass) select * from mytab1 order by 1 ; -- 2. insert a row (Should pass) insert into mytab1 values(123,456); -- 3. update a row (Should fail) update mytab1 set val2=33 where val = 1; -- 4. delete a row -- Newly Inserted (Should pass) delete from mytab1 where val2=456; -- Previously Inserted (Should fail) delete from mytab1 where val=1; -- 5. inherit form it (Should pass) create table chld_mytab1(d int, e int) inherits (mytab1); -- 6. create a view on it (Should pass) create view v2 as select * from mytab1 where val = 1; -- 7. comment on it (Should pass) comment on table mytab1 is 'Hello table'; -- 8. Alter it (Should fail) alter table mytab1 drop column val2; -- 9. drop it (Should fail) drop table mytab1; -- 10. vacuum it (Should pass) vacuum mytab1; -- 11. obtain any of these locks on it -- ACCESS SHARE (Should pass) begin; lock table mytab1 in ACCESS SHARE mode nowait; end; -- ROW SHARE (Should pass) begin; lock table mytab1 in ROW SHARE mode nowait; end; -- ROW EXCLUSIVE (Should pass) begin; lock table mytab1 in ROW EXCLUSIVE mode nowait; end; -- SHARE UPDATE EXCLUSIVE (Should pass) begin; lock table mytab1 in SHARE UPDATE EXCLUSIVE mode nowait; end; -- SHARE (Should pass) begin; lock table mytab1 in SHARE mode nowait; end; -- SHARE ROW EXCLUSIVE (Should pass) begin; lock table mytab1 in SHARE ROW EXCLUSIVE mode nowait; end; -- EXCLUSIVE (Should fail) begin; lock table mytab1 in EXCLUSIVE mode nowait; end; -- ACCESS EXCLUSIVE (Should fail) begin; lock table mytab1 in ACCESS EXCLUSIVE mode nowait; end; -- 12. do a SELECT FOR SHARE on it (Should pass) -- This is the difference between FOR SHARE & FOR UPDATE, This test should pass in case of FOR SHARE, but fail in case of FOR UPDATE begin; declare c1 cursor for select * from mytab1 for share nowait; fetch 1 from c1; end; -- 13. do a SELECT FOR UPDATE on it (Should fail) begin; declare c1 cursor for select * from mytab1 for update nowait; fetch 1 from c1; end; -- 14. alter already defined index on it (Should fail) ALTER INDEX test_idx RENAME TO mytab1_idx; -- 15. alter already defined view on it (Should pass) ALTER VIEW v1 RENAME TO vv1; -- 16. drop already defined index on it (Should fail) drop index test_idx; -- 17. drop already defined rule on it (Should fail) drop rule test_rule on mytab1; -- 18. drop already defined view on it (Should pass) drop view vv1; -- 19. reindex an alredy defined index on it (Should fail) reindex index test_idx; -- 20. truncate it (Should fail) truncate table mytab1; -- 21. create rule on it (Should fail) CREATE RULE test_rule2 AS ON INSERT TO mytab1 DO ALSO SELECT * FROM mytab1_insert_log; -- clean up COMMIT PREPARED 'tbl_mytab1_locked'; drop table chld_mytab1; drop view v2; drop table mytab1 cascade; drop table mytab4 cascade; drop table mytab3 cascade; -- Test to make sure prepared transactions are working as expected -- If a transcation is preared and contains only a select with for share/update, it should be preapred on data nodes -- create some tables create table t1(val int, val2 int) DISTRIBUTE BY REPLICATION; create table t2(val int, val2 int) DISTRIBUTE BY REPLICATION; create table t3(val int, val2 int) DISTRIBUTE BY REPLICATION; create table p1(a int, b int) DISTRIBUTE BY REPLICATION; create table c1(d int, e int) inherits (p1) DISTRIBUTE BY REPLICATION; -- insert some rows in them insert into t1 values(1,11),(2,11); insert into t2 values(3,11),(4,11); insert into t3 values(5,11),(6,11); insert into p1 values(55,66),(77,88); insert into c1 values(111,222,333,444),(123,345,567,789); -- **** begin; select * from t1 order by 1 for update of t1 nowait; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1, t2, t3 order by 1 for update; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; --WITH q1 AS (SELECT * from t1 order by 1 FOR UPDATE) SELECT * FROM q1,t2 order by 1 FOR UPDATE; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; WITH q1 AS (SELECT * from t1 order by 1) SELECT * FROM q1 FOR UPDATE; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- false commit prepared 'pt_1'; -- **** begin; WITH q1 AS (SELECT * from t1 order by 1 FOR UPDATE) SELECT * FROM q1 FOR UPDATE; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1, t2 where t1.val = t2.val for share; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1, t2 for share of t2; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from (select * from t1 for update of t1 nowait) as foo; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 where val in (select val from t2 for update of t2 nowait) for update; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 where val in (select val from t2 for update of t2 nowait); prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1, t2 for share of t2 for update of t1; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 for share of t1 for update of t1; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 for update of t1 for share of t1; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 for share of t1 for share of t1 for update of t1; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 for share of t1 for share of t1 for share of t1; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 for share of t1 for share of t1 nowait for update of t1; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 a,t1 b for share of a for update of b; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from p1 order by 1 for update; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from p1 for update; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); --true commit prepared 'pt_1'; -- **** begin; select * from c1 order by 1 for update; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from c1 for update; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- ********************************** -- repeat all tests with FQS disabled -- ********************************** set enable_fast_query_shipping=false; -- **** begin; select * from t1 order by 1 for update of t1 nowait; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1, t2, t3 order by 1 for update; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; --WITH q1 AS (SELECT * from t1 order by 1 FOR UPDATE) SELECT * FROM q1,t2 order by 1 FOR UPDATE; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; WITH q1 AS (SELECT * from t1 order by 1) SELECT * FROM q1 FOR UPDATE; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- false commit prepared 'pt_1'; -- **** begin; WITH q1 AS (SELECT * from t1 order by 1 FOR UPDATE) SELECT * FROM q1 FOR UPDATE; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1, t2 where t1.val = t2.val for share; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1, t2 for share of t2; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from (select * from t1 for update of t1 nowait) as foo; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 where val in (select val from t2 for update of t2 nowait) for update; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 where val in (select val from t2 for update of t2 nowait); prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1, t2 for share of t2 for update of t1; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 for share of t1 for update of t1; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 for update of t1 for share of t1; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 for share of t1 for share of t1 for update of t1; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 for share of t1 for share of t1 for share of t1; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 for share of t1 for share of t1 nowait for update of t1; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from t1 a,t1 b for share of a for update of b; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from p1 order by 1 for update; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from p1 for update; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); --true commit prepared 'pt_1'; -- **** begin; select * from c1 order by 1 for update; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** begin; select * from c1 for update; prepare transaction 'pt_1'; select gid from pg_prepared_xacts where gid = 'pt_1'; select is_prepared_on_node('pt_1', 1); -- true commit prepared 'pt_1'; -- **** set enable_fast_query_shipping=true; -- **** delete from t3 where val != 5; PREPARE my_plan(int) as select * from t3 for update; execute my_plan(1); -- **** -- drop objects created drop table c1; drop table p1; drop table t1; drop table t2; drop table t3;