diff --git a/Cluster.pm b/Cluster.pm index ea7860f695..fccda7aa1b 100644 --- a/Cluster.pm +++ b/Cluster.pm @@ -3,13 +3,31 @@ package Cluster; use strict; use warnings; -use PostgresNode; -use TestLib; use Test::More; use Cwd; use IPC::Run; use Socket; +our $pg_15_modules; + +BEGIN +{ + $pg_15_modules = eval + { + require PostgreSQL::Test::Cluster; + require PostgreSQL::Test::Utils; + return 1; + }; + + unless (defined $pg_15_modules) + { + $pg_15_modules = 0; + + require PostgresNode; + require TestLib; + } +} + our $last_port_assigned; our $mm_listen_address = '127.0.0.1'; @@ -38,10 +56,24 @@ sub mm_get_free_port # Check first that candidate port number is not included in # the list of already-registered nodes. $found = 1; - foreach my $node (@PostgresNode::all_nodes) + eval { - $found = 0 if ($node->port == $port); - } + if ($pg_15_modules) + { + foreach my $node (@PostgreSQL::Test::Cluster::all_nodes) + { + $found = 0 if ($node->port == $port); + } + } + else + { + foreach my $node (@PostgresNode::all_nodes) + { + $found = 0 if ($node->port == $port); + } + } + }; + # Check to see if anything else is listening on this TCP port. # Seek a port available for all possible listen_addresses values, @@ -57,15 +89,33 @@ sub mm_get_free_port # 0.0.0.0 is unnecessary on non-Windows systems. if ($found == 1) { - foreach my $addr (qw(127.0.0.1), - $PostgresNode::use_tcp && ($^O eq "linux" || $windows_os) ? qw(127.0.0.2 127.0.0.3 0.0.0.0) : ()) + eval { - if (!PostgresNode::can_bind($addr, $port)) + if ($pg_15_modules) { - $found = 0; - last; + foreach my $addr (qw(127.0.0.1), + $PostgreSQL::Test::Cluster::use_tcp && ($^O eq "linux" || $PostgreSQL::Test::Utils::windows_os) ? qw(127.0.0.2 127.0.0.3 0.0.0.0) : ()) + { + if (!PostgreSQL::Test::Cluster::can_bind($addr, $port)) + { + $found = 0; + last; + } + } } - } + else + { + foreach my $addr (qw(127.0.0.1), + $PostgresNode::use_tcp && ($^O eq "linux" || $TestLib::windows_os) ? qw(127.0.0.2 127.0.0.3 0.0.0.0) : ()) + { + if (!PostgresNode::can_bind($addr, $port)) + { + $found = 0; + last; + } + } + } + }; } } @@ -80,21 +130,41 @@ sub mm_get_free_port sub new { my ($class, $n_nodes, $referee) = @_; + my @nodes; + my $self; # ask PostgresNode to use tcp and listen on mm_listen_address - $PostgresNode::use_tcp = 1; - $PostgresNode::test_pghost = $mm_listen_address; - - my @nodes = map { get_new_node("node$_", ('port' => mm_get_free_port())) } (1..$n_nodes); - - my $self = { - nodes => \@nodes, - recv_timeout => 6 - }; - if (defined $referee && $referee) + eval { - $self->{referee} = get_new_node("referee", ( 'port' => mm_get_free_port() )); - } + if ($pg_15_modules) + { + $PostgreSQL::Test::Cluster::use_tcp = 1; + $PostgreSQL::Test::Cluster::test_pghost = $mm_listen_address; + @nodes = map { PostgreSQL::Test::Cluster->new("node$_", ('port' => mm_get_free_port())) } (1..$n_nodes); + $self = { + nodes => \@nodes, + recv_timeout => 6 + }; + if (defined $referee && $referee) + { + $self->{referee} = PostgreSQL::Test::Cluster->new("referee", ( 'port' => mm_get_free_port() )); + } + } + else + { + $PostgresNode::use_tcp = 1; + $PostgresNode::test_pghost = $mm_listen_address; + @nodes = map { PostgresNode::get_new_node("node$_", ('port' => mm_get_free_port())) } (1..$n_nodes); + $self = { + nodes => \@nodes, + recv_timeout => 6 + }; + if (defined $referee && $referee) + { + $self->{referee} = PostgresNode::get_new_node("referee", ( 'port' => mm_get_free_port() )); + } + } + }; bless $self, $class; return $self; @@ -106,7 +176,17 @@ sub init my $nodes = $self->{nodes}; # use port range different to ordinary TAP tests - $PostgresNode::last_port_assigned = int(rand() * 16384) + 32767; + eval + { + if ($pg_15_modules) + { + $PostgreSQL::Test::Cluster::last_port_assigned = int(rand() * 16384) + 32767; + } + else + { + $PostgresNode::last_port_assigned = int(rand() * 16384) + 32767; + } + }; if (defined $self->{referee}) { @@ -122,7 +202,19 @@ sub init # everywhere but on arm (which is the only live arch which might be strict # here) my $binary_basetypes = 0; - if (!$TestLib::windows_os) + my $is_windows_os; + eval + { + if ($pg_15_modules) + { + $is_windows_os = $PostgreSQL::Test::Utils::windows_os; + } + else + { + $is_windows_os = $TestLib::windows_os; + } + }; + if (!$is_windows_os) { my $uname_arch = `uname -m`; if ($? != 0) { @@ -182,14 +274,52 @@ sub init # multimaster.CoordinatorTrace_log_level = LOG + # multimaster.DmqStateIntermediate_log_level = LOG + # multimaster.DmqStateFinal_log_level = LOG + # multimaster.DmqTraceOutgoing_log_level = LOG + # multimaster.DmqTraceIncoming_log_level = LOG + # multimaster.DmqTraceShmMq_log_level = LOG + # multimaster.DmqPqTiming_log_level = LOG + + # multimaster.ResolverState_log_level = LOG + # multimaster.ResolverTx_log_level = LOG + # multimaster.ResolverTasks_log_level = LOG + + # multimaster.StatusRequest_log_level = LOG + + # multimaster.BgwPoolEvent_log_level = LOG # multimaster.BgwPoolEventDebug_log_level = LOG + # multimaster.DeadlockCheck_log_level = LOG + # multimaster.DeadlockUpdate_log_level = LOG + # multimaster.DeadlockSerialize_log_level = LOG + + # multimaster.DDLStmtOutgoing_log_level = LOG + # multimaster.DDLStmtIncoming_log_level = LOG + # multimaster.DDLProcessingTrace_log_level = LOG + + # multimaster.ProtoTraceFilter_log_level = LOG + # multimaster.ProtoTraceSender_log_level = LOG + # multimaster.ProtoTraceMessage_log_level = LOG + # multimaster.ProtoTraceState_log_level = LOG + + # multimaster.ReceiverState_log_level = LOG # multimaster.ReceiverStateDebug_log_level = LOG + # multimaster.ReceiverFilter_log_level = LOG # multimaster.ApplyMessage_log_level = LOG # multimaster.ApplyTrace_log_level = LOG + # multimaster.ApplyError_log_level = LOG + # multimaster.ApplyBgwFinish_log_level = LOG # multimaster.ReceiverFeedback_log_level = LOG + # multimaster.StateMessage_log_level = LOG + # multimaster.StateSwitch_log_level = LOG multimaster.StateDebug_log_level = LOG + + # multimaster.SyncpointCreated_log_level = LOG + # multimaster.SyncpointApply_log_level = LOG + + # multimaster.NodeMgmt_log_level = LOG }); $node->append_conf('pg_hba.conf', $hba); @@ -339,9 +469,21 @@ sub connstr sub add_node() { my ($self) = @_; + my $new_node; - my $new_node = get_new_node("node@{[$#{$self->{nodes}} + 2]}", - (port => mm_get_free_port())); + eval + { + if ($pg_15_modules) + { + $new_node = PostgreSQL::Test::Cluster->new("node@{[$#{$self->{nodes}} + 2]}", + (port => mm_get_free_port())); + } + else + { + $new_node = PostgresNode::get_new_node("node@{[$#{$self->{nodes}} + 2]}", + (port => mm_get_free_port())); + } + }; push(@{$self->{nodes}}, $new_node); return $#{$self->{nodes}}; diff --git a/Makefile b/Makefile index 994e04ff8a..19171ffacc 100644 --- a/Makefile +++ b/Makefile @@ -69,7 +69,6 @@ all: multimaster.so submake-regress: $(MAKE) -C $(top_builddir)/src/test/regress all - $(MAKE) -C $(top_builddir)/src/test/regress tablespace-setup # all .pl tests should pass now, but let's see what the buildfarm says # ifndef MTM_ALL diff --git a/expected/regression_ee.diff b/expected/regression_ee.diff index ebc60ab969..4814bbea27 100644 --- a/expected/regression_ee.diff +++ b/expected/regression_ee.diff @@ -1,7 +1,7 @@ diff ../../../src/test/regress/expected/create_table.out ../tmp_check/regress_outdir/results/create_table.out --- ../../../src/test/regress/expected/create_table.out CENSORED +++ ../tmp_check/regress_outdir/results/create_table.out CENSORED -@@ -263,17 +263,17 @@ +@@ -58,17 +58,17 @@ DROP TABLE as_select1; PREPARE select1 AS SELECT 1 as a; CREATE TABLE as_select1 AS EXECUTE select1; @@ -29,7 +29,7 @@ diff ../../../src/test/regress/expected/create_table.out ../tmp_check/regress_ou diff ../../../src/test/regress/expected/create_index.out ../tmp_check/regress_outdir/results/create_index.out --- ../../../src/test/regress/expected/create_index.out CENSORED +++ ../tmp_check/regress_outdir/results/create_index.out CENSORED -@@ -1394,31 +1394,33 @@ +@@ -1389,31 +1389,33 @@ CREATE TABLE concur_heap (f1 text, f2 text); -- empty table CREATE INDEX CONCURRENTLY concur_index1 ON concur_heap(f2,f1); @@ -70,7 +70,7 @@ diff ../../../src/test/regress/expected/create_index.out ../tmp_check/regress_ou COMMIT; -- test where predicate is able to do a transactional update during -- a concurrent build before switching pg_index state flags. -@@ -1430,7 +1432,9 @@ +@@ -1425,7 +1427,9 @@ END; $$; CREATE INDEX CONCURRENTLY concur_index8 ON concur_heap (f1) WHERE predicate_stable(); @@ -80,7 +80,7 @@ diff ../../../src/test/regress/expected/create_index.out ../tmp_check/regress_ou DROP FUNCTION predicate_stable(); -- But you can do a regular index build in a transaction BEGIN; -@@ -1439,8 +1443,6 @@ +@@ -1434,8 +1438,6 @@ -- Failed builds are left invalid by VACUUM FULL, fixed by REINDEX VACUUM FULL concur_heap; REINDEX TABLE concur_heap; @@ -89,7 +89,7 @@ diff ../../../src/test/regress/expected/create_index.out ../tmp_check/regress_ou DELETE FROM concur_heap WHERE f1 = 'b'; VACUUM FULL concur_heap; \d concur_heap -@@ -1450,12 +1452,6 @@ +@@ -1445,12 +1447,6 @@ f1 | text | | | f2 | text | | | Indexes: @@ -102,7 +102,7 @@ diff ../../../src/test/regress/expected/create_index.out ../tmp_check/regress_ou "std_index" btree (f2) REINDEX TABLE concur_heap; -@@ -1466,12 +1462,6 @@ +@@ -1461,12 +1457,6 @@ f1 | text | | | f2 | text | | | Indexes: @@ -115,7 +115,7 @@ diff ../../../src/test/regress/expected/create_index.out ../tmp_check/regress_ou "std_index" btree (f2) -- Temporary tables with concurrent builds and on-commit actions -@@ -1481,7 +1471,9 @@ +@@ -1476,7 +1466,9 @@ ON COMMIT PRESERVE ROWS; INSERT INTO concur_temp VALUES (1, 'foo'), (2, 'bar'); CREATE INDEX CONCURRENTLY concur_temp_ind ON concur_temp(f1); @@ -125,7 +125,7 @@ diff ../../../src/test/regress/expected/create_index.out ../tmp_check/regress_ou DROP TABLE concur_temp; -- ON COMMIT DROP BEGIN; -@@ -1490,34 +1482,42 @@ +@@ -1485,34 +1477,42 @@ INSERT INTO concur_temp VALUES (1, 'foo'), (2, 'bar'); -- Fails when running in a transaction. CREATE INDEX CONCURRENTLY concur_temp_ind ON concur_temp(f1); @@ -172,7 +172,7 @@ diff ../../../src/test/regress/expected/create_index.out ../tmp_check/regress_ou \d concur_heap Table "public.concur_heap" Column | Type | Collation | Nullable | Default -@@ -2474,46 +2474,38 @@ +@@ -2600,46 +2600,38 @@ INSERT INTO concur_reindex_tab4 VALUES (1), (1), (2); -- This trick creates an invalid index. CREATE UNIQUE INDEX CONCURRENTLY concur_reindex_ind5 ON concur_reindex_tab4 (c1); @@ -260,71 +260,62 @@ diff ../../../src/test/regress/expected/index_including_gist.out ../tmp_check/re DROP TABLE tbl_gist; /* -diff ../../../src/test/regress/expected/sanity_check.out ../tmp_check/regress_outdir/results/sanity_check.out ---- ../../../src/test/regress/expected/sanity_check.out CENSORED -+++ ../tmp_check/regress_outdir/results/sanity_check.out CENSORED -@@ -11,6 +11,8 @@ - FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace - WHERE relkind IN ('r', 'p') AND (nspname ~ '^pg_temp_') IS NOT TRUE - ORDER BY relname; -+_pg_publication|t -+_pg_subscription|t - a|f - a_star|f - aggtest|f -@@ -32,6 +34,8 @@ - check_tbl|f - circle_tbl|t - city|f -+cluster_nodes|t -+config|t - copy_tbl|f - d|f - d_star|f -@@ -67,6 +71,7 @@ - jtbl|t - kd_point_tbl|t - line_tbl|f -+local_tables|t - log_table|f - lseg_tbl|f - main_table|f -@@ -83,6 +88,7 @@ - mlparted_defd|f - money_data|f - mytable|t -+nodes_init_done|t - num_data|f - num_exp_add|t - num_exp_div|t -@@ -140,7 +146,6 @@ - pg_policy|t - pg_proc|t - pg_profile|t --pg_publication|t - pg_publication_rel|t - pg_range|t - pg_replication_origin|t -@@ -154,7 +159,6 @@ - pg_statistic|t - pg_statistic_ext|t - pg_statistic_ext_data|t --pg_subscription|t - pg_subscription_rel|t - pg_tablespace|t - pg_transform|t -@@ -185,6 +189,7 @@ - sql_sizing|f - stud_emp|f - student|f -+syncpoints|t - tab_core_types|f - tableam_parted_a_heap2|f - tableam_parted_b_heap2|f +diff ../../../src/test/regress/expected/select_into.out ../tmp_check/regress_outdir/results/select_into.out +--- ../../../src/test/regress/expected/select_into.out CENSORED ++++ ../tmp_check/regress_outdir/results/select_into.out CENSORED +@@ -50,27 +50,19 @@ + PREPARE data_sel AS SELECT generate_series(1,3); + CREATE TABLE selinto_schema.tbl_withdata3 (a) AS + EXECUTE data_sel WITH DATA; ++ERROR: [MTM] failed to prepare transaction at peer node + EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + CREATE TABLE selinto_schema.tbl_withdata4 (a) AS + EXECUTE data_sel WITH DATA; +- QUERY PLAN +--------------------------------------- +- ProjectSet (actual rows=3 loops=1) +- -> Result (actual rows=1 loops=1) +-(2 rows) +- ++ERROR: [MTM] failed to prepare transaction at peer node + -- EXECUTE and WITH NO DATA, passes. + CREATE TABLE selinto_schema.tbl_nodata3 (a) AS + EXECUTE data_sel WITH NO DATA; ++ERROR: [MTM] failed to prepare transaction at peer node + EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + CREATE TABLE selinto_schema.tbl_nodata4 (a) AS + EXECUTE data_sel WITH NO DATA; +- QUERY PLAN +-------------------------------- +- ProjectSet (never executed) +- -> Result (never executed) +-(2 rows) +- ++ERROR: [MTM] failed to prepare transaction at peer node + RESET SESSION AUTHORIZATION; + ALTER DEFAULT PRIVILEGES FOR ROLE regress_selinto_user + GRANT INSERT ON TABLES TO regress_selinto_user; +@@ -78,15 +70,11 @@ + RESET SESSION AUTHORIZATION; + DEALLOCATE data_sel; + DROP SCHEMA selinto_schema CASCADE; +-NOTICE: drop cascades to 8 other objects ++NOTICE: drop cascades to 4 other objects + DETAIL: drop cascades to table selinto_schema.tbl_withdata1 + drop cascades to table selinto_schema.tbl_withdata2 + drop cascades to table selinto_schema.tbl_nodata1 + drop cascades to table selinto_schema.tbl_nodata2 +-drop cascades to table selinto_schema.tbl_withdata3 +-drop cascades to table selinto_schema.tbl_withdata4 +-drop cascades to table selinto_schema.tbl_nodata3 +-drop cascades to table selinto_schema.tbl_nodata4 + DROP USER regress_selinto_user; + -- Tests for WITH NO DATA and column name consistency + CREATE TABLE ctas_base (i int, j int); diff ../../../src/test/regress/expected/transactions.out ../tmp_check/regress_outdir/results/transactions.out --- ../../../src/test/regress/expected/transactions.out CENSORED +++ ../tmp_check/regress_outdir/results/transactions.out CENSORED -@@ -685,50 +685,38 @@ +@@ -689,50 +689,38 @@ INSERT INTO abc VALUES (1); INSERT INTO abc VALUES (2); COMMIT AND CHAIN; -- TBLOCK_END @@ -384,7 +375,7 @@ diff ../../../src/test/regress/expected/transactions.out ../tmp_check/regress_ou COMMIT; START TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE, DEFERRABLE; SHOW transaction_isolation; -@@ -796,24 +784,13 @@ +@@ -800,24 +788,13 @@ SAVEPOINT x; COMMIT AND CHAIN; -- TBLOCK_SUBCOMMIT @@ -413,7 +404,7 @@ diff ../../../src/test/regress/expected/transactions.out ../tmp_check/regress_ou COMMIT; -- different mix of options just for fun START TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ WRITE, NOT DEFERRABLE; -@@ -881,17 +858,14 @@ +@@ -885,17 +862,14 @@ ROLLBACK; -- not allowed outside a transaction block COMMIT AND CHAIN; -- error @@ -433,8 +424,8 @@ diff ../../../src/test/regress/expected/transactions.out ../tmp_check/regress_ou RESET default_transaction_read_only; DROP TABLE abc; -@@ -981,7 +955,7 @@ - SELECT 1\; BEGIN\; SAVEPOINT sp\; ROLLBACK TO SAVEPOINT sp\; COMMIT; +@@ -1041,7 +1015,7 @@ + -- Tests for AND CHAIN in implicit transaction blocks SET TRANSACTION READ ONLY\; COMMIT AND CHAIN; -- error -ERROR: COMMIT AND CHAIN can only be used in transaction blocks @@ -442,7 +433,7 @@ diff ../../../src/test/regress/expected/transactions.out ../tmp_check/regress_ou SHOW transaction_read_only; transaction_read_only ----------------------- -@@ -1000,23 +974,20 @@ +@@ -1060,23 +1034,20 @@ -- COMMIT/ROLLBACK + COMMIT/ROLLBACK AND CHAIN INSERT INTO abc VALUES (7)\; COMMIT\; INSERT INTO abc VALUES (8)\; COMMIT AND CHAIN; -- 7 commit, 8 error WARNING: there is no transaction in progress @@ -470,8 +461,8 @@ diff ../../../src/test/regress/expected/transactions.out ../tmp_check/regress_ou COMMIT; START TRANSACTION ISOLATION LEVEL REPEATABLE READ\; INSERT INTO abc VALUES (16)\; ROLLBACK AND CHAIN; -- 16 ok SHOW transaction_isolation; -- transaction is active at this point -@@ -1028,7 +999,7 @@ - ROLLBACK; +@@ -1089,7 +1060,7 @@ + SET default_transaction_isolation = 'read committed'; -- START TRANSACTION + COMMIT/ROLLBACK + COMMIT/ROLLBACK AND CHAIN START TRANSACTION ISOLATION LEVEL REPEATABLE READ\; INSERT INTO abc VALUES (17)\; COMMIT\; INSERT INTO abc VALUES (18)\; COMMIT AND CHAIN; -- 17 commit, 18 error -ERROR: COMMIT AND CHAIN can only be used in transaction blocks @@ -479,7 +470,7 @@ diff ../../../src/test/regress/expected/transactions.out ../tmp_check/regress_ou SHOW transaction_isolation; -- out of transaction block transaction_isolation ----------------------- -@@ -1047,9 +1018,8 @@ +@@ -1109,9 +1080,8 @@ a ---- 7 @@ -490,6 +481,24 @@ diff ../../../src/test/regress/expected/transactions.out ../tmp_check/regress_ou DROP TABLE abc; -- Test for successful cleanup of an aborted transaction at session exit. +diff ../../../src/test/regress/expected/portals.out ../tmp_check/regress_outdir/results/portals.out +--- ../../../src/test/regress/expected/portals.out CENSORED ++++ ../tmp_check/regress_outdir/results/portals.out CENSORED +@@ -1553,11 +1553,9 @@ + + declare held_portal cursor with hold for select * from toasted_data; + commit; ++ERROR: cannot PREPARE a transaction that has created a cursor WITH HOLD + drop table toasted_data; ++ERROR: table "toasted_data" does not exist + fetch all in held_portal; +- f1 +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +- {12345678,12345679,12345680,12345681,12345682,12345683,12345684,12345685,12345686,12345687,12345688,12345689,12345690,12345691,12345692,12345693,12345694,12345695,12345696,12345697,12345698,12345699,12345700,12345701,12345702,12345703,12345704,12345705,12345706,12345707,12345708,12345709,12345710,12345711,12345712,12345713,12345714,12345715,12345716,12345717,12345718,12345719,12345720,12345721,12345722,12345723,12345724,12345725,12345726,12345727,12345728,12345729,12345730,12345731,12345732,12345733,12345734,12345735,12345736,12345737,12345738,12345739,12345740,12345741,12345742,12345743,12345744,12345745,12345746,12345747,12345748,12345749,12345750,12345751,12345752,12345753,12345754,12345755,12345756,12345757,12345758,12345759,12345760,12345761,12345762,12345763,12345764,12345765,12345766,12345767,12345768,12345769,12345770,12345771,12345772,12345773,12345774,12345775,12345776,12345777,12345778,12345779,12345780,12345781,12345782,12345783,12345784,12345785,12345786,12345787,12345788,12345789,12345790,12345791,12345792,12345793,12345794,12345795,12345796,12345797,12345798,12345799,12345800,12345801,12345802,12345803,12345804,12345805,12345806,12345807,12345808,12345809,12345810,12345811,12345812,12345813,12345814,12345815,12345816,12345817,12345818,12345819,12345820,12345821,12345822,12345823,12345824,12345825,12345826,12345827,12345828,12345829,12345830,12345831,12345832,12345833,12345834,12345835,12345836,12345837,12345838,12345839,12345840,12345841,12345842,12345843,12345844,12345845,12345846,12345847,12345848,12345849,12345850,12345851,12345852,12345853,12345854,12345855,12345856,12345857,12345858,12345859,12345860,12345861,12345862,12345863,12345864,12345865,12345866,12345867,12345868,12345869,12345870,12345871,12345872,12345873,12345874,12345875,12345876,12345877,12345878,12345879,12345880,12345881,12345882,12345883,12345884,12345885,12345886,12345887,12345888,12345889,12345890,12345891,12345892,12345893,12345894,12345895,12345896,12345897,12345898,12345899,12345900,12345901,12345902,12345903,12345904,12345905,12345906,12345907,12345908,12345909,12345910,12345911,12345912,12345913,12345914,12345915,12345916,12345917,12345918,12345919,12345920,12345921,12345922,12345923,12345924,12345925,12345926,12345927,12345928,12345929,12345930,12345931,12345932,12345933,12345934,12345935,12345936,12345937,12345938,12345939,12345940,12345941,12345942,12345943,12345944,12345945,12345946,12345947,12345948,12345949,12345950,12345951,12345952,12345953,12345954,12345955,12345956,12345957,12345958,12345959,12345960,12345961,12345962,12345963,12345964,12345965,12345966,12345967,12345968,12345969,12345970,12345971,12345972,12345973,12345974,12345975,12345976,12345977,12345978,12345979,12345980,12345981,12345982,12345983,12345984,12345985,12345986,12345987,12345988,12345989,12345990,12345991,12345992,12345993,12345994,12345995,12345996,12345997,12345998,12345999,12346000,12346001,12346002,12346003,12346004,12346005,12346006,12346007,12346008,12346009,12346010,12346011,12346012,12346013,12346014,12346015,12346016,12346017,12346018,12346019,12346020,12346021,12346022,12346023,12346024,12346025,12346026,12346027,12346028,12346029,12346030,12346031,12346032,12346033,12346034,12346035,12346036,12346037,12346038,12346039,12346040,12346041,12346042,12346043,12346044,12346045,12346046,12346047,12346048,12346049,12346050,12346051,12346052,12346053,12346054,12346055,12346056,12346057,12346058,12346059,12346060,12346061,12346062,12346063,12346064,12346065,12346066,12346067,12346068,12346069,12346070,12346071,12346072,12346073,12346074,12346075,12346076,12346077,12346078,12346079,12346080,12346081,12346082,12346083,12346084,12346085,12346086,12346087,12346088,12346089,12346090,12346091,12346092,12346093,12346094,12346095,12346096,12346097,12346098,12346099,12346100,12346101,12346102,12346103,12346104,12346105,12346106,12346107,12346108,12346109,12346110,12346111,12346112,12346113,12346114,12346115,12346116,12346117,12346118,12346119,12346120,12346121,12346122,12346123,12346124,12346125,12346126,12346127,12346128,12346129,12346130,12346131,12346132,12346133,12346134,12346135,12346136,12346137,12346138,12346139,12346140,12346141,12346142,12346143,12346144,12346145,12346146,12346147,12346148,12346149,12346150,12346151,12346152,12346153,12346154,12346155,12346156,12346157,12346158,12346159,12346160,12346161,12346162,12346163,12346164,12346165,12346166,12346167,12346168,12346169,12346170,12346171,12346172,12346173,12346174,12346175,12346176,12346177,12346178,12346179,12346180,12346181,12346182,12346183,12346184,12346185,12346186,12346187,12346188,12346189,12346190,12346191,12346192,12346193,12346194,12346195,12346196,12346197,12346198,12346199,12346200,12346201,12346202,12346203,12346204,12346205,12346206,12346207,12346208,12346209,12346210,12346211,12346212,12346213,12346214,12346215,12346216,12346217,12346218,12346219,12346220,12346221,12346222,12346223,12346224,12346225,12346226,12346227,12346228,12346229,12346230,12346231,12346232,12346233,12346234,12346235,12346236,12346237,12346238,12346239,12346240,12346241,12346242,12346243,12346244,12346245,12346246,12346247,12346248,12346249,12346250,12346251,12346252,12346253,12346254,12346255,12346256,12346257,12346258,12346259,12346260,12346261,12346262,12346263,12346264,12346265,12346266,12346267,12346268,12346269,12346270,12346271,12346272,12346273,12346274,12346275,12346276,12346277,12346278,12346279,12346280,12346281,12346282,12346283,12346284,12346285,12346286,12346287,12346288,12346289,12346290,12346291,12346292,12346293,12346294,12346295,12346296,12346297,12346298,12346299,12346300,12346301,12346302,12346303,12346304,12346305,12346306,12346307,12346308,12346309,12346310,12346311,12346312,12346313,12346314,12346315,12346316,12346317,12346318,12346319,12346320,12346321,12346322,12346323,12346324,12346325,12346326,12346327,12346328,12346329,12346330,12346331,12346332,12346333,12346334,12346335,12346336,12346337,12346338,12346339,12346340,12346341,12346342,12346343,12346344,12346345,12346346,12346347,12346348,12346349,12346350,12346351,12346352,12346353,12346354,12346355,12346356,12346357,12346358,12346359,12346360,12346361,12346362,12346363,12346364,12346365,12346366,12346367,12346368,12346369,12346370,12346371,12346372,12346373,12346374,12346375,12346376,12346377,12346378,12346379,12346380,12346381,12346382,12346383,12346384,12346385,12346386,12346387,12346388,12346389,12346390,12346391,12346392,12346393,12346394,12346395,12346396,12346397,12346398,12346399,12346400,12346401,12346402,12346403,12346404,12346405,12346406,12346407,12346408,12346409,12346410,12346411,12346412,12346413,12346414,12346415,12346416,12346417,12346418,12346419,12346420,12346421,12346422,12346423,12346424,12346425,12346426,12346427,12346428,12346429,12346430,12346431,12346432,12346433,12346434,12346435,12346436,12346437,12346438,12346439,12346440,12346441,12346442,12346443,12346444,12346445,12346446,12346447,12346448,12346449,12346450,12346451,12346452,12346453,12346454,12346455,12346456,12346457,12346458,12346459,12346460,12346461,12346462,12346463,12346464,12346465,12346466,12346467,12346468,12346469,12346470,12346471,12346472,12346473,12346474,12346475,12346476,12346477,12346478,12346479,12346480,12346481,12346482,12346483,12346484,12346485,12346486,12346487,12346488,12346489,12346490,12346491,12346492,12346493,12346494,12346495,12346496,12346497,12346498,12346499,12346500,12346501,12346502,12346503,12346504,12346505,12346506,12346507,12346508,12346509,12346510,12346511,12346512,12346513,12346514,12346515,12346516,12346517,12346518,12346519,12346520,12346521,12346522,12346523,12346524,12346525,12346526,12346527,12346528,12346529,12346530,12346531,12346532,12346533,12346534,12346535,12346536,12346537,12346538,12346539,12346540,12346541,12346542,12346543,12346544,12346545,12346546,12346547,12346548,12346549,12346550,12346551,12346552,12346553,12346554,12346555,12346556,12346557,12346558,12346559,12346560,12346561,12346562,12346563,12346564,12346565,12346566,12346567,12346568,12346569,12346570,12346571,12346572,12346573,12346574,12346575,12346576,12346577,12346578,12346579,12346580,12346581,12346582,12346583,12346584,12346585,12346586,12346587,12346588,12346589,12346590,12346591,12346592,12346593,12346594,12346595,12346596,12346597,12346598,12346599,12346600,12346601,12346602,12346603,12346604,12346605,12346606,12346607,12346608,12346609,12346610,12346611,12346612,12346613,12346614,12346615,12346616,12346617,12346618,12346619,12346620,12346621,12346622,12346623,12346624,12346625,12346626,12346627,12346628,12346629,12346630,12346631,12346632,12346633,12346634,12346635,12346636,12346637,12346638,12346639,12346640,12346641,12346642,12346643,12346644,12346645,12346646,12346647,12346648,12346649,12346650,12346651,12346652,12346653,12346654,12346655,12346656,12346657,12346658,12346659,12346660,12346661,12346662,12346663,12346664,12346665,12346666,12346667,12346668,12346669,12346670,12346671,12346672,12346673,12346674,12346675,12346676,12346677,12346678} +-(1 row) +- ++ERROR: cursor "held_portal" does not exist + reset default_toast_compression; diff ../../../src/test/regress/expected/brin.out ../tmp_check/regress_outdir/results/brin.out --- ../../../src/test/regress/expected/brin.out CENSORED +++ ../tmp_check/regress_outdir/results/brin.out CENSORED @@ -503,112 +512,30 @@ diff ../../../src/test/regress/expected/brin.out ../tmp_check/regress_outdir/res -- vacuum the table, to discard TOAST data VACUUM brintest_3; -- retry insert with a different random-looking (but deterministic) value -diff ../../../src/test/regress/expected/rowsecurity.out ../tmp_check/regress_outdir/results/rowsecurity.out ---- ../../../src/test/regress/expected/rowsecurity.out CENSORED -+++ ../tmp_check/regress_outdir/results/rowsecurity.out CENSORED -@@ -113,30 +113,7 @@ - (3 rows) - - \d document -- Table "regress_rls_schema.document" -- Column | Type | Collation | Nullable | Default -----------+---------+-----------+----------+--------- -- did | integer | | not null | -- cid | integer | | | -- dlevel | integer | | not null | -- dauthor | name | | | -- dtitle | text | | | --Indexes: -- "document_pkey" PRIMARY KEY, btree (did) --Foreign-key constraints: -- "document_cid_fkey" FOREIGN KEY (cid) REFERENCES category(cid) --Policies: -- POLICY "p1" -- USING ((dlevel <= ( SELECT uaccount.seclv -- FROM uaccount -- WHERE (uaccount.pguser = CURRENT_USER)))) -- POLICY "p1r" AS RESTRICTIVE -- TO regress_rls_dave -- USING ((cid <> 44)) -- POLICY "p2r" AS RESTRICTIVE -- TO regress_rls_dave -- USING (((cid <> 44) AND (cid < 50))) -- -+ERROR: permission denied for view pg_publication - SELECT * FROM pg_policies WHERE schemaname = 'regress_rls_schema' AND tablename = 'document' ORDER BY policyname; - schemaname | tablename | policyname | permissive | roles | cmd | qual | with_check - --------------------+-----------+------------+-------------+--------------------+-----+--------------------------------------------+------------ -@@ -938,27 +915,7 @@ - CREATE POLICY pp1r ON part_document AS RESTRICTIVE TO regress_rls_dave - USING (cid < 55); - \d+ part_document -- Partitioned table "regress_rls_schema.part_document" -- Column | Type | Collation | Nullable | Default | Storage | Stats target | Description -----------+---------+-----------+----------+---------+----------+--------------+------------- -- did | integer | | | | plain | | -- cid | integer | | | | plain | | -- dlevel | integer | | not null | | plain | | -- dauthor | name | | | | plain | | -- dtitle | text | | | | extended | | --Partition key: RANGE (cid) --Policies: -- POLICY "pp1" -- USING ((dlevel <= ( SELECT uaccount.seclv -- FROM uaccount -- WHERE (uaccount.pguser = CURRENT_USER)))) -- POLICY "pp1r" AS RESTRICTIVE -- TO regress_rls_dave -- USING ((cid < 55)) --Partitions: part_document_fiction FOR VALUES FROM (11) TO (12), -- part_document_nonfiction FOR VALUES FROM (99) TO (100), -- part_document_satire FOR VALUES FROM (55) TO (56) -- -+ERROR: permission denied for view pg_publication - SELECT * FROM pg_policies WHERE schemaname = 'regress_rls_schema' AND tablename like '%part_document%' ORDER BY policyname; - schemaname | tablename | policyname | permissive | roles | cmd | qual | with_check - --------------------+---------------+------------+-------------+--------------------+-----+--------------------------------------------+------------ -diff ../../../src/test/regress/expected/atx.out ../tmp_check/regress_outdir/results/atx.out ---- ../../../src/test/regress/expected/atx.out CENSORED -+++ ../tmp_check/regress_outdir/results/atx.out CENSORED -@@ -851,6 +851,7 @@ - declare c2 cursor with hold for select count_tt1_v(), count_tt1_s(); - insert into atx_tt1 values(2); - commit; -+ERROR: cannot PREPARE a transaction that has created a cursor WITH HOLD - commit; - begin; - begin autonomous; -@@ -866,6 +867,7 @@ - drop function count_tt1_s(); - drop table if exists atx_tt1; - close c2; -+ERROR: cursor "c2" does not exist - -- 13 - create table atx_13_t(i int); - begin; -@@ -985,9 +987,7 @@ - insert into atx_tt2 values(1); - declare c2 cursor with hold for select error_function(); - commit; --NOTICE: other exception 22012, division by zero --ERROR: control reached end of function without RETURN --CONTEXT: PL/pgSQL function error_function() -+ERROR: cannot PREPARE a transaction that has created a cursor WITH HOLD - commit; - drop function if exists error_function(); - drop table if exists atx_tt2; -@@ -1074,6 +1074,7 @@ - RESET client_min_messages; - create database regression_atx_test_database; - ALTER DATABASE "regression_atx_test_database" SET lc_messages TO 'C'; -+ERROR: [MTM] failed to prepare transaction at peer node - \c regression_atx_test_database - create table atx_test as select 1 as id; - begin; -diff ../../../src/test/regress/expected/atx5.out ../tmp_check/regress_outdir/results/atx5.out ---- ../../../src/test/regress/expected/atx5.out CENSORED -+++ ../tmp_check/regress_outdir/results/atx5.out CENSORED -@@ -24,10 +24,7 @@ +diff ../../../src/test/regress/expected/privileges.out ../tmp_check/regress_outdir/results/privileges.out +--- ../../../src/test/regress/expected/privileges.out CENSORED ++++ ../tmp_check/regress_outdir/results/privileges.out CENSORED +@@ -1613,11 +1613,16 @@ + -- Do the same concurrently + CREATE INDEX CONCURRENTLY sro_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0))) + WHERE sro_ifun(a + 10) > sro_ifun(10); ++ERROR: multimaster doesn't support CREATE INDEX CONCURRENTLY + -- REINDEX + REINDEX TABLE sro_tab; ++NOTICE: table "sro_tab" has no indexes to reindex + REINDEX INDEX sro_idx; ++ERROR: relation "sro_idx" does not exist + REINDEX TABLE CONCURRENTLY sro_tab; ++NOTICE: table "sro_tab" has no indexes that can be reindexed concurrently + DROP INDEX sro_idx; ++ERROR: index "sro_idx" does not exist + -- CLUSTER + CREATE INDEX sro_cluster_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0))); + CLUSTER sro_tab USING sro_cluster_idx; +diff ../../../src/test/regress/expected/atx3.out ../tmp_check/regress_outdir/results/atx3.out +--- ../../../src/test/regress/expected/atx3.out CENSORED ++++ ../tmp_check/regress_outdir/results/atx3.out CENSORED +@@ -115,10 +115,7 @@ NOTICE: function atx_test_30_one() does not exist, skipping NOTICE: function atx_test_30_one() does not exist, skipping NOTICE: function atx_test_30_one() does not exist, skipping @@ -620,10 +547,7 @@ diff ../../../src/test/regress/expected/atx5.out ../tmp_check/regress_outdir/res SET client_min_messages = 'warning'; DROP FUNCTION IF EXISTS atx_test_30_one(); DROP FUNCTION IF EXISTS atx_test_30_two(); -diff ../../../src/test/regress/expected/atx9.out ../tmp_check/regress_outdir/results/atx9.out ---- ../../../src/test/regress/expected/atx9.out CENSORED -+++ ../tmp_check/regress_outdir/results/atx9.out CENSORED -@@ -29,50 +29,38 @@ +@@ -547,50 +544,38 @@ INSERT INTO abc VALUES (1); INSERT INTO abc VALUES (2); COMMIT AND CHAIN; -- TBLOCK_END @@ -683,7 +607,7 @@ diff ../../../src/test/regress/expected/atx9.out ../tmp_check/regress_outdir/res COMMIT; ROLLBACK; BEGIN; -@@ -144,24 +132,13 @@ +@@ -662,24 +647,13 @@ SAVEPOINT x; COMMIT AND CHAIN; -- TBLOCK_SUBCOMMIT @@ -712,7 +636,7 @@ diff ../../../src/test/regress/expected/atx9.out ../tmp_check/regress_outdir/res COMMIT; ROLLBACK; -- different mix of options just for fun -@@ -232,17 +209,14 @@ +@@ -750,17 +724,14 @@ COMMIT; -- not allowed outside a transaction block COMMIT AUTONOMOUS AND CHAIN; -- error @@ -737,7 +661,7 @@ diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/re +++ ../tmp_check/regress_outdir/results/rules.out CENSORED @@ -1285,6 +1285,15 @@ SELECT viewname, definition FROM pg_views - WHERE schemaname IN ('pg_catalog', 'public') + WHERE schemaname = 'pg_catalog' ORDER BY viewname; +_pg_prepared_xacts| SELECT p.transaction, + p.gid, @@ -748,13 +672,13 @@ diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/re + FROM ((pg_prepared_xact() p(transaction, gid, prepared, ownerid, dbid, state3pc) + LEFT JOIN pg_authid u ON ((p.ownerid = u.oid))) + LEFT JOIN pg_database d ON ((p.dbid = d.oid))); - iexit| SELECT ih.name, - ih.thepath, - interpt_pp(ih.thepath, r.thepath) AS exit -@@ -1452,19 +1461,30 @@ - p.parameter_types, - p.from_sql - FROM pg_prepared_statement() p(name, statement, prepare_time, parameter_types, from_sql); + pg_available_extension_versions| SELECT e.name, + e.version, + (x.extname IS NOT NULL) AS installed, +@@ -1427,15 +1436,6 @@ + p.generic_plans, + p.custom_plans + FROM pg_prepared_statement() p(name, statement, prepare_time, parameter_types, from_sql, generic_plans, custom_plans); -pg_prepared_xacts| SELECT p.transaction, - p.gid, - p.prepared, @@ -764,111 +688,334 @@ diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/re - FROM ((pg_prepared_xact() p(transaction, gid, prepared, ownerid, dbid, state3pc) - LEFT JOIN pg_authid u ON ((p.ownerid = u.oid))) - LEFT JOIN pg_database d ON ((p.dbid = d.oid))); -+pg_prepared_xacts| SELECT _pg_prepared_xacts.transaction, -+ _pg_prepared_xacts.gid, -+ _pg_prepared_xacts.prepared, -+ _pg_prepared_xacts.owner, -+ _pg_prepared_xacts.database, -+ _pg_prepared_xacts.state3pc -+ FROM _pg_prepared_xacts -+ WHERE (_pg_prepared_xacts.gid !~~ 'MTM-%'::text) -+ ORDER BY ((_pg_prepared_xacts.transaction)::text)::bigint; -+pg_publication| SELECT _pg_publication.oid, -+ _pg_publication.pubname, -+ _pg_publication.pubowner, -+ _pg_publication.puballtables, -+ _pg_publication.pubinsert, -+ _pg_publication.pubupdate, -+ _pg_publication.pubdelete, -+ _pg_publication.pubtruncate, -+ _pg_publication.pubviaroot -+ FROM _pg_publication -+ WHERE (_pg_publication.pubname <> 'multimaster'::name); pg_publication_tables| SELECT p.pubname, n.nspname AS schemaname, - c.relname AS tablename -- FROM pg_publication p, -+ FROM _pg_publication p, - LATERAL pg_get_publication_tables((p.pubname)::text) gpt(relid), - (pg_class c - JOIN pg_namespace n ON ((n.oid = c.relnamespace))) -@@ -1659,7 +1679,7 @@ - l.provider, - l.label - FROM (pg_seclabel l -- JOIN pg_publication p ON (((l.classoid = p.tableoid) AND (l.objoid = p.oid)))) -+ JOIN _pg_publication p ON (((l.classoid = p.tableoid) AND (l.objoid = p.oid)))) - WHERE (l.objsubid = 0) - UNION ALL - SELECT l.objoid, -@@ -1671,7 +1691,7 @@ - l.provider, - l.label - FROM (pg_shseclabel l -- JOIN pg_subscription s ON (((l.classoid = s.tableoid) AND (l.objoid = s.oid)))) -+ JOIN _pg_subscription s ON (((l.classoid = s.tableoid) AND (l.objoid = s.oid)))) - UNION ALL - SELECT l.objoid, - l.classoid, -@@ -2066,7 +2086,7 @@ - st.last_msg_receipt_time, - st.latest_end_lsn, - st.latest_end_time -- FROM (pg_subscription su -+ FROM (_pg_subscription su - LEFT JOIN pg_stat_get_subscription(NULL::oid) st(subid, relid, pid, received_lsn, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time) ON ((st.subid = su.oid))); - pg_stat_sys_indexes| SELECT pg_stat_all_indexes.relid, - pg_stat_all_indexes.indexrelid, -@@ -2408,6 +2428,17 @@ - FROM (unnest(s.stxkeys) k(k) - JOIN pg_attribute a ON (((a.attrelid = s.stxrelid) AND (a.attnum = k.k)))) - WHERE (NOT has_column_privilege(c.oid, a.attnum, 'select'::text))))) AND ((c.relrowsecurity = false) OR (NOT row_security_active(c.oid)))); -+pg_subscription| SELECT _pg_subscription.oid, -+ _pg_subscription.subdbid, -+ _pg_subscription.subname, -+ _pg_subscription.subowner, -+ _pg_subscription.subenabled, -+ _pg_subscription.subconninfo, -+ _pg_subscription.subslotname, -+ _pg_subscription.subsynccommit, -+ _pg_subscription.subpublications -+ FROM _pg_subscription -+ WHERE (_pg_subscription.subname !~~ 'mtm_sub_%'::text); - pg_tables| SELECT n.nspname AS schemaname, c.relname AS tablename, - pg_get_userbyid(c.relowner) AS tableowner, +diff ../../../src/test/regress/expected/psql.out ../tmp_check/regress_outdir/results/psql.out +--- ../../../src/test/regress/expected/psql.out CENSORED ++++ ../tmp_check/regress_outdir/results/psql.out CENSORED +@@ -5292,6 +5292,7 @@ + BEGIN; + INSERT INTO oer_test VALUES (5); + COMMIT AND CHAIN; ++ERROR: [MTM] COMMIT AND CHAIN is not supported + INSERT INTO oer_test VALUES (6); + COMMIT; + SELECT * FROM oer_test; diff ../../../src/test/regress/expected/publication.out ../tmp_check/regress_outdir/results/publication.out --- ../../../src/test/regress/expected/publication.out CENSORED +++ ../tmp_check/regress_outdir/results/publication.out CENSORED -@@ -11,9 +11,9 @@ - RESET client_min_messages; - COMMENT ON PUBLICATION testpub_default IS 'test publication'; +@@ -13,8 +13,9 @@ SELECT obj_description(p.oid, 'pg_publication') FROM pg_publication p; -- obj_description -------------------- -- test publication -+ obj_description -+----------------- + obj_description + ------------------ + - (1 row) + test publication +-(1 row) ++(2 rows) SET client_min_messages = 'ERROR'; + CREATE PUBLICATION testpib_ins_trunct WITH (publish = insert); +@@ -33,18 +34,20 @@ + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root + --------------------+--------------------------+------------+---------+---------+---------+-----------+---------- + testpib_ins_trunct | regress_publication_user | f | t | f | f | f | f + testpub_default | regress_publication_user | f | f | t | f | f | f +-(2 rows) ++(3 rows) + + ALTER PUBLICATION testpub_default SET (publish = 'insert, update, delete'); + \dRp + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root + --------------------+--------------------------+------------+---------+---------+---------+-----------+---------- + testpib_ins_trunct | regress_publication_user | f | t | f | f | f | f + testpub_default | regress_publication_user | f | t | t | t | f | f +-(2 rows) ++(3 rows) + + --- adding tables + CREATE SCHEMA pub_test; diff ../../../src/test/regress/expected/subscription.out ../tmp_check/regress_outdir/results/subscription.out --- ../../../src/test/regress/expected/subscription.out CENSORED +++ ../tmp_check/regress_outdir/results/subscription.out CENSORED -@@ -32,9 +32,9 @@ - WARNING: tables were not subscribed, you will have to run ALTER SUBSCRIPTION ... REFRESH PUBLICATION to subscribe the tables - COMMENT ON SUBSCRIPTION regress_testsub IS 'test subscription'; +@@ -34,8 +34,10 @@ SELECT obj_description(s.oid, 'pg_subscription') FROM pg_subscription s; -- obj_description --------------------- -- test subscription -+ obj_description -+----------------- + obj_description + ------------------- + - (1 row) ++ + test subscription +-(1 row) ++(3 rows) -- fail - name already exists + CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false); +@@ -76,11 +78,13 @@ + ERROR: invalid connection string syntax: missing "=" after "foobar" in connection info string + + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------------------+-----------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | f | d | f | off | dbname=regress_doesnotexist | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | f | d | f | off | dbname=regress_doesnotexist | 0/0 ++(3 rows) + + ALTER SUBSCRIPTION regress_testsub SET PUBLICATION testpub2, testpub3 WITH (refresh = false); + ALTER SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist2'; +@@ -96,11 +100,13 @@ + -- ok + ALTER SUBSCRIPTION regress_testsub SKIP (lsn = '0/12345'); + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------------------+------------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | f | d | f | off | dbname=regress_doesnotexist2 | 0/12345 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | f | d | f | off | dbname=regress_doesnotexist2 | 0/12345 ++(3 rows) + + -- ok - with lsn = NONE + ALTER SUBSCRIPTION regress_testsub SKIP (lsn = NONE); +@@ -108,11 +114,13 @@ + ALTER SUBSCRIPTION regress_testsub SKIP (lsn = '0/0'); + ERROR: invalid WAL location (LSN): 0/0 + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------------------+------------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | f | d | f | off | dbname=regress_doesnotexist2 | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | f | d | f | off | dbname=regress_doesnotexist2 | 0/0 ++(3 rows) + + BEGIN; + ALTER SUBSCRIPTION regress_testsub ENABLE; +@@ -120,16 +128,20 @@ + List of subscriptions + Name | Owner | Enabled | Publication + -----------------+---------------------------+---------+--------------------- + regress_testsub | regress_subscription_user | t | {testpub2,testpub3} +-(1 row) ++(3 rows) + + ALTER SUBSCRIPTION regress_testsub DISABLE; + \dRs + List of subscriptions + Name | Owner | Enabled | Publication + -----------------+---------------------------+---------+--------------------- + regress_testsub | regress_subscription_user | f | {testpub2,testpub3} +-(1 row) ++(3 rows) + + COMMIT; + -- fail - must be owner of subscription +@@ -143,11 +155,13 @@ + ERROR: invalid value for parameter "synchronous_commit": "foobar" + HINT: Available values: local, remote_write, remote_apply, on, off. + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +----------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------------------+------------------------------+---------- +- regress_testsub_foo | regress_subscription_user | f | {testpub2,testpub3} | f | f | d | f | local | dbname=regress_doesnotexist2 | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++---------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub_foo | regress_subscription_user | f | {testpub2,testpub3} | f | f | d | f | local | dbname=regress_doesnotexist2 | 0/0 ++(3 rows) + + -- rename back to keep the rest simple + ALTER SUBSCRIPTION regress_testsub_foo RENAME TO regress_testsub; +@@ -179,20 +193,24 @@ + CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, binary = true); + WARNING: tables were not subscribed, you will have to run ALTER SUBSCRIPTION ... REFRESH PUBLICATION to subscribe the tables + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------------------+-----------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub} | t | f | d | f | off | dbname=regress_doesnotexist | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub} | t | f | d | f | off | dbname=regress_doesnotexist | 0/0 ++(3 rows) + + ALTER SUBSCRIPTION regress_testsub SET (binary = false); + ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE); + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------------------+-----------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | f | d | f | off | dbname=regress_doesnotexist | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | f | d | f | off | dbname=regress_doesnotexist | 0/0 ++(3 rows) + + DROP SUBSCRIPTION regress_testsub; + -- fail - streaming must be boolean +@@ -202,20 +220,24 @@ + CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, streaming = true); + WARNING: tables were not subscribed, you will have to run ALTER SUBSCRIPTION ... REFRESH PUBLICATION to subscribe the tables + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------------------+-----------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | t | d | f | off | dbname=regress_doesnotexist | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | t | d | f | off | dbname=regress_doesnotexist | 0/0 ++(3 rows) + + ALTER SUBSCRIPTION regress_testsub SET (streaming = false); + ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE); + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------------------+-----------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | f | d | f | off | dbname=regress_doesnotexist | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | f | d | f | off | dbname=regress_doesnotexist | 0/0 ++(3 rows) + + -- fail - publication already exists + ALTER SUBSCRIPTION regress_testsub ADD PUBLICATION testpub WITH (refresh = false); +@@ -229,11 +251,13 @@ + ALTER SUBSCRIPTION regress_testsub ADD PUBLICATION testpub1, testpub2 WITH (refresh = false); + ERROR: publication "testpub1" is already in subscription "regress_testsub" + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+-----------------------------+--------+-----------+------------------+------------------+--------------------+-----------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub,testpub1,testpub2} | f | f | d | f | off | dbname=regress_doesnotexist | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+-----------------------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub,testpub1,testpub2} | f | f | d | f | off | dbname=regress_doesnotexist | 0/0 ++(3 rows) + + -- fail - publication used more then once + ALTER SUBSCRIPTION regress_testsub DROP PUBLICATION testpub1, testpub1 WITH (refresh = false); +@@ -247,11 +271,13 @@ + -- ok - delete publications + ALTER SUBSCRIPTION regress_testsub DROP PUBLICATION testpub1, testpub2 WITH (refresh = false); + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------------------+-----------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | f | d | f | off | dbname=regress_doesnotexist | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | f | d | f | off | dbname=regress_doesnotexist | 0/0 ++(3 rows) + + DROP SUBSCRIPTION regress_testsub; + CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION mypub +@@ -284,11 +310,13 @@ + CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, two_phase = true); + WARNING: tables were not subscribed, you will have to run ALTER SUBSCRIPTION ... REFRESH PUBLICATION to subscribe the tables + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------------------+-----------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | f | p | f | off | dbname=regress_doesnotexist | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | f | p | f | off | dbname=regress_doesnotexist | 0/0 ++(3 rows) + + --fail - alter of two_phase option not supported. + ALTER SUBSCRIPTION regress_testsub SET (two_phase = false); +@@ -296,11 +324,13 @@ + -- but can alter streaming when two_phase enabled + ALTER SUBSCRIPTION regress_testsub SET (streaming = true); + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------------------+-----------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | t | p | f | off | dbname=regress_doesnotexist | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | t | p | f | off | dbname=regress_doesnotexist | 0/0 ++(3 rows) + + ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE); + DROP SUBSCRIPTION regress_testsub; +@@ -308,11 +338,13 @@ + CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, streaming = true, two_phase = true); + WARNING: tables were not subscribed, you will have to run ALTER SUBSCRIPTION ... REFRESH PUBLICATION to subscribe the tables + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------------------+-----------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | t | p | f | off | dbname=regress_doesnotexist | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | t | p | f | off | dbname=regress_doesnotexist | 0/0 ++(3 rows) + + ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE); + DROP SUBSCRIPTION regress_testsub; +@@ -323,19 +355,23 @@ + CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, disable_on_error = false); + WARNING: tables were not subscribed, you will have to run ALTER SUBSCRIPTION ... REFRESH PUBLICATION to subscribe the tables + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------------------+-----------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | f | d | f | off | dbname=regress_doesnotexist | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | f | d | f | off | dbname=regress_doesnotexist | 0/0 ++(3 rows) + + ALTER SUBSCRIPTION regress_testsub SET (disable_on_error = true); + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN +------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------------------+-----------------------------+---------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | f | d | t | off | dbname=regress_doesnotexist | 0/0 +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Synchronous commit | Conninfo | Skip LSN ++-----------------+---------------------------+---------+---------------+--------+-----------+------------------+------------------+--------------------+-----------------------------------------------+---------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | f | d | t | off | dbname=regress_doesnotexist | 0/0 ++(3 rows) + + ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE); + DROP SUBSCRIPTION regress_testsub; diff ../../../src/test/regress/expected/prepare.out ../tmp_check/regress_outdir/results/prepare.out --- ../../../src/test/regress/expected/prepare.out CENSORED +++ ../tmp_check/regress_outdir/results/prepare.out CENSORED @@ -927,7 +1074,7 @@ diff ../../../src/test/regress/expected/indexing.out ../tmp_check/regress_outdir drop table idxpart; -- Verify bugfix with query on indexed partitioned table with no partitions -- https://postgr.es/m/20180124162006.pmapfiznhgngwtjf@alvherre.pgsql -@@ -175,7 +175,7 @@ +@@ -176,7 +176,7 @@ ERROR: cannot drop index idxpart1_a_idx because index idxpart_a_idx requires it HINT: You can drop index idxpart_a_idx instead. drop index concurrently idxpart_a_idx; -- unsupported @@ -936,7 +1083,7 @@ diff ../../../src/test/regress/expected/indexing.out ../tmp_check/regress_outdir drop index idxpart_a_idx; -- both indexes go away select relname, relkind from pg_class where relname like 'idxpart%' order by relname; -@@ -206,12 +206,14 @@ +@@ -207,12 +207,14 @@ HINT: You can drop index idxpart_temp_a_idx instead. -- non-concurrent drop is enforced here, so it is a valid case. drop index concurrently idxpart_temp_a_idx; diff --git a/run.pl b/run.pl index de4b018891..f3a13d945e 100755 --- a/run.pl +++ b/run.pl @@ -27,17 +27,44 @@ $cluster->create_mm('regression'); # prevent PostgresNode.pm from shutting down nodes on exit in END {} - @PostgresNode::all_nodes = (); + eval + { + if ($Cluster::pg_15_modules) + { + @PostgreSQL::Test::Cluster::all_nodes = (); + } + else + { + @PostgresNode::all_nodes = (); + } + }; } elsif ($action eq "stop") { - my @datas = <$TestLib::tmp_check/*data>; - foreach my $data (@datas) { - TestLib::system_log('pg_ctl', - '-D', "$data/pgdata", - '-m', 'fast', - 'stop'); - } + eval + { + if ($Cluster::pg_15_modules) + { + my @datas = <$PostgreSQL::Test::Utils::tmp_check/*data>; + foreach my $data (@datas) { + PostgreSQL::Test::Utils::system_log('pg_ctl', + '-D', "$data/pgdata", + '-m', 'fast', + 'stop'); + } + @PostgreSQL::Test::Cluster::all_nodes = (); + } + else + { + my @datas = <$TestLib::tmp_check/*data>; + foreach my $data (@datas) { + TestLib::system_log('pg_ctl', + '-D', "$data/pgdata", + '-m', 'fast', + 'stop'); + } + } + }; } else { diff --git a/src/commit.c b/src/commit.c index 0018c0b467..4e9d3c5505 100644 --- a/src/commit.c +++ b/src/commit.c @@ -135,14 +135,39 @@ mtm_commit_cleanup(int status, Datum arg) /* there was no precommit, we can abort */ PG_TRY(); { - AbortOutOfAnyTransaction(); - StartTransactionCommand(); +#ifdef PGPRO_EE + int atxLevel = DatumGetInt32(arg); + + /* + * If we are inside ATX transaction, we can not call + * AbortOutOfAnyTransaction() because this call will abort + * ALL transactions and we will have problems if the + * calling code is not designed for this case. + */ + if (atxLevel) + { + /* Abort (current ATX transaction only): */ + AbortCurrentTransaction(); + /* Restart ATX transaction if it was resumed: */ + if (atxLevel > getNestLevelATX()) + SuspendTransaction(); + } + else +#endif + { + AbortOutOfAnyTransaction(); + StartTransactionCommand(); + } FinishPreparedTransaction(mtm_commit_state.gid, false, false); mtm_commit_state.gtx->state.status = GTXAborted; mtm_log(MtmTxFinish, "%s aborted as own orphaned not precomitted", mtm_commit_state.gid); CommitTransactionCommand(); - +#ifdef PGPRO_EE + /* Restart ATX transaction if it was resumed: */ + if (atxLevel > getNestLevelATX()) + SuspendTransaction(); +#endif } /* * this should be extremely unlikely, but if we fail, don't @@ -218,7 +243,7 @@ MtmBeginTransaction() * register gtx hook first (it will be called last) */ GlobalTxEnsureBeforeShmemExitHook(); - before_shmem_exit(mtm_commit_cleanup, Int32GetDatum(1)); + before_shmem_exit(mtm_commit_cleanup, Int32GetDatum(0)); mtm_commit_state.mctx = AllocSetContextCreate(TopMemoryContext, "MtmCommitContext", ALLOCSET_DEFAULT_SIZES); @@ -373,6 +398,9 @@ MtmTwoPhaseCommit(void) MtmGeneration xact_gen; char dmq_stream_name[DMQ_STREAM_NAME_MAXLEN]; GTxState gtx_state; +#ifdef PGPRO_EE + int atxLevel = getNestLevelATX(); +#endif if (MtmNo3PC) { @@ -714,7 +742,11 @@ MtmTwoPhaseCommit(void) } PG_CATCH(); { +#ifdef PGPRO_EE + mtm_commit_cleanup(0, Int32GetDatum(atxLevel)); +#else mtm_commit_cleanup(0, Int32GetDatum(0)); +#endif PG_RE_THROW(); } diff --git a/src/ddl.c b/src/ddl.c index 49ccc2d0c4..39955dae6c 100644 --- a/src/ddl.c +++ b/src/ddl.c @@ -119,19 +119,21 @@ static void MtmSeqNextvalHook(Oid seqid, int64 next); static void MtmExecutorStart(QueryDesc *queryDesc, int eflags); static void MtmExecutorFinish(QueryDesc *queryDesc); -static void MtmProcessUtility(PlannedStmt *pstmt, const char *queryString, +static void MtmProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc); static void MtmProcessUtilityReceiver(PlannedStmt *pstmt, const char *queryString, + bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc); static void MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString, + bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc); @@ -139,6 +141,7 @@ static void MtmProcessUtilitySender(PlannedStmt *pstmt, static void MtmGucUpdate(const char *key); static void MtmInitializeRemoteFunctionsMap(void); static char *MtmGucSerialize(void); +static void MtmGucSync(const char *prefix); static void MtmMakeRelationLocal(Oid relid, bool locked); static List *AdjustCreateSequence(List *options); @@ -148,6 +151,11 @@ static void MtmFinishDDLCommand(void); PG_FUNCTION_INFO_V1(mtm_make_table_local); +#if PG_VERSION_NUM >= 150000 +static shmem_request_hook_type prev_shmem_request_hook = NULL; +static void mtm_ddl_shmem_request(void); +#endif + /***************************************************************************** * * Init @@ -157,6 +165,10 @@ PG_FUNCTION_INFO_V1(mtm_make_table_local); void MtmDDLReplicationInit() { +#if PG_VERSION_NUM >= 150000 + prev_shmem_request_hook = shmem_request_hook; + shmem_request_hook = mtm_ddl_shmem_request; +#else Size size = 0; size = add_size(size, sizeof(struct DDLSharedState)); @@ -167,6 +179,7 @@ MtmDDLReplicationInit() RequestAddinShmemSpace(size); RequestNamedLWLockTranche("mtm-ddl", 1); +#endif PreviousExecutorStartHook = ExecutorStart_hook; ExecutorStart_hook = MtmExecutorStart; @@ -181,6 +194,25 @@ MtmDDLReplicationInit() SeqNextvalHook = MtmSeqNextvalHook; } +#if PG_VERSION_NUM >= 150000 +static void +mtm_ddl_shmem_request(void) +{ + Size size = 0; + + if (prev_shmem_request_hook) + prev_shmem_request_hook(); + + size = add_size(size, sizeof(struct DDLSharedState)); + size = add_size(size, hash_estimate_size(MULTIMASTER_MAX_LOCAL_TABLES, + sizeof(Oid))); + size = MAXALIGN(size); + + RequestAddinShmemSpace(size); + RequestNamedLWLockTranche("mtm-ddl", 1); +} +#endif + void MtmDDLReplicationShmemStartup(void) { @@ -359,7 +391,7 @@ MtmGucInit(void) MtmGucHash = hash_create("MtmGucHash", MTM_GUC_HASHSIZE, &hash_ctl, - HASH_ELEM | HASH_CONTEXT); + HASH_ELEM | HASH_CONTEXT | HASH_STRINGS); /* * If current role is not equal to MtmDatabaseUser, than set it before any @@ -614,6 +646,71 @@ MtmGucSerialize(void) return serialized_gucs->data; } +/* + * Any loaded extension can set ist own parameters + * replacing existing placeholders if needed + * and reserve its own parameter pefix. + * Then all remaining placeholders with this prefix are deleted. + * Multimaster guc list MtmGucEntry should be updated also. + * This version just removes parameters which: + * - have reserved prefixes, + * - are not in guc variables list now. + * + * XXX: Can module name be used as a reserved prefix? + * + * XXX: Is it better to store placeholder flag in MtmGucEntry? + * + */ +void +MtmGucSync(const char *prefix) +{ + dlist_mutable_iter iter; + + if (!MtmGucHash) + MtmGucInit(); + + dlist_foreach_modify(iter, &MtmGucList) + { + MtmGucEntry *cur_entry = dlist_container(MtmGucEntry, list_node, iter.cur); + struct config_generic *gconf; + bool is_reserved_class = false; + const char *sep = strchr(cur_entry->key, GUC_QUALIFIER_SEPARATOR); + size_t classLen; + ListCell *lc; + + if (sep == NULL) + /* leave if is not prefixed */ + continue; + + classLen = sep - cur_entry->key; + foreach(lc, reserved_class_prefix) + { + const char *rcprefix = lfirst(lc); + + if (strlen(rcprefix) == classLen && + strncmp(cur_entry->key, rcprefix, classLen) == 0) + { + elog(LOG, "----> MtmGucSerialize: invalid configuration parameter name \"%s\": " + "\"%s\" is a reserved prefix.", + cur_entry->key, rcprefix); + is_reserved_class = true; + break; + } + } + + if (!is_reserved_class) + /* leave if prefix is not rerserved */ + continue; + + gconf = fing_guc_conf(cur_entry->key); + if (gconf) + /* leave if is in guc variable list */ + continue; + + dlist_delete(iter.cur); + hash_search(MtmGucHash, cur_entry->key, HASH_REMOVE, NULL); + } +} /***************************************************************************** @@ -656,12 +753,13 @@ MtmProcessDDLCommand(char const *queryString, bool transactional, static void MtmFinishDDLCommand() { - LogLogicalMessage("E", "", 1, true); + const char *msg = "MTM Finish DDL Command"; + LogLogicalMessage("E", msg, strlen(msg) + 1, true); } static void -MtmProcessUtility(PlannedStmt *pstmt, const char *queryString, +MtmProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc) @@ -676,13 +774,13 @@ MtmProcessUtility(PlannedStmt *pstmt, const char *queryString, { if (PreviousProcessUtilityHook != NULL) { - PreviousProcessUtilityHook(pstmt, queryString, + PreviousProcessUtilityHook(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc); } else { - standard_ProcessUtility(pstmt, queryString, + standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc); } @@ -691,12 +789,12 @@ MtmProcessUtility(PlannedStmt *pstmt, const char *queryString, if (MtmIsLogicalReceiver) { - MtmProcessUtilityReceiver(pstmt, queryString, context, params, + MtmProcessUtilityReceiver(pstmt, queryString, context, readOnlyTree, params, queryEnv, dest, qc); } else { - MtmProcessUtilitySender(pstmt, queryString, context, params, + MtmProcessUtilitySender(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc); } @@ -718,7 +816,7 @@ MtmProcessUtility(PlannedStmt *pstmt, const char *queryString, * receiver (e.g calling DDL from trigger) this hook does nothing. */ static void -MtmProcessUtilityReceiver(PlannedStmt *pstmt, const char *queryString, +MtmProcessUtilityReceiver(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc) @@ -839,22 +937,18 @@ MtmProcessUtilityReceiver(PlannedStmt *pstmt, const char *queryString, } if (PreviousProcessUtilityHook != NULL) - { - PreviousProcessUtilityHook(pstmt, queryString, + PreviousProcessUtilityHook(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc); - } else - { - standard_ProcessUtility(pstmt, queryString, + standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc); - } } static void -MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString, +MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc) @@ -938,6 +1032,10 @@ MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString, MtmExplicitFinishPrepared(isTopLevel, stmt->gid, false); return; + case TRANS_STMT_ROLLBACK_TO: + MtmDDLResetStatement(); + break; + default: break; } @@ -1186,17 +1284,13 @@ MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString, stmt_string, skipCommand, MtmDDLStatement != NULL); if (PreviousProcessUtilityHook != NULL) - { - PreviousProcessUtilityHook(pstmt, queryString, + PreviousProcessUtilityHook(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc); - } else - { - standard_ProcessUtility(pstmt, queryString, + standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc); - } /* Catch GUC assignment */ if (nodeTag(parsetree) == T_VariableSetStmt) @@ -1209,6 +1303,14 @@ MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString, } } + /* Catch GUC changes after LOAD */ + if (nodeTag(parsetree) == T_LoadStmt) + { + LoadStmt *stmt = (LoadStmt *) parsetree; + + MtmGucSync(stmt->filename); + } + if (executed) { MtmFinishDDLCommand(); @@ -1311,11 +1413,12 @@ MtmExecutorFinish(QueryDesc *queryDesc) if (operation == CMD_INSERT || operation == CMD_UPDATE || operation == CMD_DELETE || pstmt->hasModifyingCTE) { - int i; + ListCell *l; - for (i = 0; i < estate->es_num_result_relations; i++) + foreach(l, estate->es_opened_result_relations) { - Relation rel = estate->es_result_relations[i].ri_RelationDesc; + ResultRelInfo *resultRelInfo = lfirst(l); + Relation rel = resultRelInfo->ri_RelationDesc; /* * Don't run 3pc unless we modified at least one non-local table. @@ -1526,7 +1629,7 @@ MtmDDLResetApplyState() DDLApplyInProgress = false; /* the memory it points to is about to go away */ debug_query_string = NULL; - pgstat_report_activity(STATE_RUNNING, NULL); + pgstat_report_activity(STATE_IDLE, ""); } @@ -1709,7 +1812,7 @@ MtmInitializeRemoteFunctionsMap() if (q != NULL) *q++ = '\0'; - clist = FuncnameGetCandidates(stringToQualifiedNameList(p), -1, NIL, false, false, true); + clist = FuncnameGetCandidates(stringToQualifiedNameList(p), -1, NIL, false, false, true, true); if (clist == NULL) mtm_log(DEBUG1, "Can't resolve function '%s', postponing that", p); else @@ -1724,7 +1827,7 @@ MtmInitializeRemoteFunctionsMap() p = q; } while (p != NULL); - clist = FuncnameGetCandidates(stringToQualifiedNameList("mtm.alter_sequences"), -1, NIL, false, false, true); + clist = FuncnameGetCandidates(stringToQualifiedNameList("mtm.alter_sequences"), -1, NIL, false, false, true, true); if (clist != NULL) hash_search(MtmRemoteFunctions, &clist->oid, HASH_ENTER, NULL); diff --git a/src/dmq.c b/src/dmq.c index c2d14fae28..48fe1430a5 100644 --- a/src/dmq.c +++ b/src/dmq.c @@ -44,7 +44,9 @@ #include "utils/builtins.h" #include "utils/timestamp.h" #include "storage/shm_toc.h" +#include "postmaster/autovacuum.h" #include "postmaster/interrupt.h" +#include "replication/walsender.h" #include "storage/shm_mq.h" #include "storage/ipc.h" #include "tcop/tcopprot.h" @@ -238,6 +240,11 @@ static volatile sig_atomic_t got_SIGHUP = false; static shmem_startup_hook_type PreviousShmemStartupHook; +#if PG_VERSION_NUM >= 150000 +static shmem_request_hook_type prev_shmem_request_hook = NULL; +static void mtm_dmq_shmem_request(void); +#endif + void *(*dmq_receiver_start_hook)(char *sender_name); dmq_hook_type dmq_receiver_stop_hook; dmq_hook_type dmq_sender_connect_hook; @@ -353,7 +360,7 @@ dmq_shmem_startup_hook(void) DMQ_MAX_SUBS_PER_BACKEND * MaxBackends, DMQ_MAX_SUBS_PER_BACKEND * MaxBackends, &hash_info, - HASH_ELEM); + HASH_ELEM | HASH_STRINGS); LWLockRelease(AddinShmemInitLock); } @@ -362,10 +369,19 @@ static Size dmq_shmem_size(void) { Size size = 0; +#if PG_VERSION_NUM < 150000 + int maxbackends = MaxConnections + autovacuum_max_workers + + max_worker_processes + max_wal_senders + 1; +#endif size = add_size(size, sizeof(struct DmqSharedState)); +#if PG_VERSION_NUM >= 150000 size = add_size(size, hash_estimate_size(DMQ_MAX_SUBS_PER_BACKEND * MaxBackends, sizeof(DmqStreamSubscription))); +#else + size = add_size(size, hash_estimate_size(DMQ_MAX_SUBS_PER_BACKEND * maxbackends, + sizeof(DmqStreamSubscription))); +#endif return MAXALIGN(size); } @@ -378,9 +394,14 @@ dmq_init(int send_timeout, int connect_timeout) return; /* Reserve area for our shared state */ +#if PG_VERSION_NUM >= 150000 + prev_shmem_request_hook = shmem_request_hook; + shmem_request_hook = mtm_dmq_shmem_request; +#else RequestAddinShmemSpace(dmq_shmem_size()); RequestNamedLWLockTranche("dmq", 1); +#endif /* Set up common data for all our workers */ memset(&worker, 0, sizeof(worker)); @@ -402,6 +423,18 @@ dmq_init(int send_timeout, int connect_timeout) shmem_startup_hook = dmq_shmem_startup_hook; } +#if PG_VERSION_NUM >= 150000 +static void +mtm_dmq_shmem_request(void) +{ + if (prev_shmem_request_hook) + prev_shmem_request_hook(); + + RequestAddinShmemSpace(dmq_shmem_size()); + RequestNamedLWLockTranche("dmq", 1); +} +#endif + static Size dmq_toc_size() { @@ -776,7 +809,7 @@ dmq_sender_main(Datum main_arg) switch (conns[conn_id].state) { case Idle: - Assert(false); +// Assert(false); break; /* @@ -875,10 +908,23 @@ dmq_sender_main(Datum main_arg) if (!PQisBusy(conns[conn_id].pgconn)) { int8 mask_pos = conns[conn_id].mask_pos; + PGresult *result = PQgetResult(conns[conn_id].pgconn); - /* - * XXX check here that dmq_receiver_loop not failed? - */ + if (!result) { + mtm_log(ERROR, "[DMQ] PQgetResult returned NULL"); + } + + mtm_log(DmqStateIntermediate, "PQgetResult status: %d", PQresultStatus(result)); + + if (PQresultStatus(result) != PGRES_COPY_BOTH) { + mtm_log(DmqStateFinal, "[DMQ] wrong response from dmq receiver '%s': '%s'; '%s'", + conns[conn_id].receiver_name, + PQresStatus(PQresultStatus(result)), + PQerrorMessage(conns[conn_id].pgconn)); + conns[conn_id].state = Idle; + dmq_state->sconn_cnt[conns[conn_id].mask_pos] = DMQSCONN_DEAD; + break; + } conns[conn_id].state = Active; DeleteWaitEvent(set, event.pos); @@ -1119,7 +1165,11 @@ dmq_handle_message(StringInfo msg, DmqReceiverSlot *my_slot, } else { +#if PG_VERSION_NUM < 150000 res = shm_mq_send(mq_handles[sub.procno], body_len, body, false); +#else + res = shm_mq_send(mq_handles[sub.procno], body_len, body, false, true); +#endif if (res == SHM_MQ_DETACHED) mtm_log(COMMERROR, "[DMQ] queue %d is detached, dropping message (stream=%s)", sub.procno, stream_name); @@ -1443,7 +1493,13 @@ dmq_receiver_loop(PG_FUNCTION_ARGS) extra = dmq_receiver_start_hook(sender_name); /* do not hold globalxmin. XXX: try to carefully release snaps */ - MyPgXact->xmin = InvalidTransactionId; +#if PG_VERSION_NUM < 150000 + MyProc->xmin = InvalidTransactionId; +#else + pg_atomic_write_u64(&MyProc->xmin, InvalidTransactionId); +#endif + dmq_receiver_recreate_mqs(&dmq_state->receivers[receiver_id], + segs, mq_handles); for (;;) { @@ -1623,7 +1679,11 @@ dmq_push(DmqDestinationId dest_id, char *stream_name, char *msg) buf.len, buf.len, buf.data); /* XXX: use sendv instead */ +#if PG_VERSION_NUM < 150000 res = shm_mq_send(dmq_local.mq_outh, buf.len, buf.data, false); +#else + res = shm_mq_send(dmq_local.mq_outh, buf.len, buf.data, false, true); +#endif pfree(buf.data); if (res != SHM_MQ_SUCCESS) mtm_log(ERROR, "[DMQ] dmq_push: can't send to queue"); @@ -1648,7 +1708,11 @@ dmq_push_buffer(DmqDestinationId dest_id, char *stream_name, const void *payload buf.len, buf.len, buf.data); /* XXX: use sendv instead */ +#if PG_VERSION_NUM < 150000 res = shm_mq_send(dmq_local.mq_outh, buf.len, buf.data, false); +#else + res = shm_mq_send(dmq_local.mq_outh, buf.len, buf.data, false, true); +#endif pfree(buf.data); if (res != SHM_MQ_SUCCESS) mtm_log(ERROR, "[DMQ] dmq_push: can't send to queue, status = %d", res); diff --git a/src/global_tx.c b/src/global_tx.c index fff4921515..e5cc6d197f 100644 --- a/src/global_tx.c +++ b/src/global_tx.c @@ -47,6 +47,11 @@ char const *const GlobalTxStatusMnem[] = "GTXAborted" }; +#if PG_VERSION_NUM >= 150000 +static shmem_request_hook_type prev_shmem_request_hook = NULL; +static void mtm_gtx_shmem_request(void); +#endif + int term_cmp(GlobalTxTerm t1, GlobalTxTerm t2) { @@ -153,9 +158,32 @@ GlobalTxAtExit(int code, Datum arg) void MtmGlobalTxInit() +{ +#if PG_VERSION_NUM >= 150000 + prev_shmem_request_hook = shmem_request_hook; + shmem_request_hook = mtm_gtx_shmem_request; +#else + Size size = 0; + + size = add_size(size, sizeof(gtx_shared_data)); + size = add_size(size, hash_estimate_size(2*MaxConnections, + sizeof(GlobalTx))); + size = MAXALIGN(size); + + RequestAddinShmemSpace(size); + RequestNamedLWLockTranche("mtm-gtx-lock", 1); +#endif +} + +#if PG_VERSION_NUM >= 150000 +static void +mtm_gtx_shmem_request(void) { Size size = 0; + if (prev_shmem_request_hook) + prev_shmem_request_hook(); + size = add_size(size, sizeof(gtx_shared_data)); size = add_size(size, hash_estimate_size(2*MaxConnections, sizeof(GlobalTx))); @@ -164,6 +192,7 @@ MtmGlobalTxInit() RequestAddinShmemSpace(size); RequestNamedLWLockTranche("mtm-gtx-lock", 1); } +#endif void MtmGlobalTxShmemStartup(void) @@ -185,7 +214,7 @@ MtmGlobalTxShmemStartup(void) gtx_shared->lock = &(GetNamedLWLockTranche("mtm-gtx-lock"))->lock; gtx_shared->gid2gtx = ShmemInitHash("gid2gtx", 2*MaxConnections, 2*MaxConnections, - &info, HASH_ELEM); + &info, HASH_ELEM | HASH_STRINGS); LWLockRelease(AddinShmemInitLock); } diff --git a/src/include/compat.h b/src/include/compat.h index a6ffaaa248..349617ebb9 100644 --- a/src/include/compat.h +++ b/src/include/compat.h @@ -1,12 +1,16 @@ #ifndef MTMCOMPAT_H #define MTMCOMPAT_H +#if 0 /* built-in connection pool ported */ /* EE pooler gets rid of static variable */ #ifdef PGPRO_EE #define FeBeWaitSetCompat() (MyProcPort->pqcomm_waitset) #else #define FeBeWaitSetCompat() (FeBeWaitSet) #endif +#else +#define FeBeWaitSetCompat() (FeBeWaitSet) +#endif #ifdef PGPRO_EE /* atx */ #define BeginTransactionBlockCompat() (BeginTransactionBlock(false, NIL)) @@ -16,11 +20,6 @@ #define UserAbortTransactionBlockCompat(chain) (UserAbortTransactionBlock(chain)) #endif -/* atx renames this for some reason */ -#ifdef PGPRO_EE -#define on_commits_compat() (pg_on_commit_actions) -#else #define on_commits_compat() (on_commits) -#endif #endif /* MTMCOMPAT_H */ diff --git a/src/multimaster.c b/src/multimaster.c index 9165492afc..ff6fc73e77 100644 --- a/src/multimaster.c +++ b/src/multimaster.c @@ -52,6 +52,8 @@ #include "compat.h" +#include "time.h" + typedef enum { MTM_STATE_LOCK_ID @@ -220,6 +222,10 @@ bool mtm_config_valid; static shmem_startup_hook_type PreviousShmemStartupHook; +#if PG_VERSION_NUM >= 150000 +static shmem_request_hook_type prev_shmem_request_hook = NULL; +static void mtm_shmem_request(void); +#endif /* * If you get really bored one day, you may try hardware-accelerated popcount @@ -711,13 +717,20 @@ NULL); NULL); } + MarkGUCPrefixReserved("multimaster"); + /* * Request additional shared resources. (These are no-ops if we're not in * the postmaster process.) We'll allocate or attach to the shared * resources in mtm_shmem_startup(). */ +#if PG_VERSION_NUM >= 150000 + prev_shmem_request_hook = shmem_request_hook; + shmem_request_hook = mtm_shmem_request; +#else RequestAddinShmemSpace(MTM_SHMEM_SIZE + sizeof(MtmTime)); RequestNamedLWLockTranche(MULTIMASTER_NAME, 2); +#endif dmq_init(MtmHeartbeatSendTimeout, MtmConnectTimeout); dmq_receiver_start_hook = MtmOnDmqReceiverConnect; @@ -748,6 +761,18 @@ NULL); #endif } +#if PG_VERSION_NUM >= 150000 +static void +mtm_shmem_request(void) +{ + if (prev_shmem_request_hook) + prev_shmem_request_hook(); + + RequestAddinShmemSpace(MTM_SHMEM_SIZE + sizeof(MtmTime)); + RequestNamedLWLockTranche(MULTIMASTER_NAME, 2); +} +#endif + /* * Module unload callback * @@ -1095,6 +1120,9 @@ mtm_after_node_create(PG_FUNCTION_ARGS) bool conninfo_isnull; int n_nodes; int rc; +#if PG_VERSION_NUM >= 150000 + ParseState *pstate; +#endif Assert(CALLED_AS_TRIGGER(fcinfo)); Assert(TRIGGER_FIRED_FOR_ROW(trigdata->tg_event)); @@ -1135,6 +1163,10 @@ mtm_after_node_create(PG_FUNCTION_ARGS) mtm_log(NodeMgmt, "mtm_after_node_create %d", node_id); +#if PG_VERSION_NUM >= 150000 + pstate = make_parsestate(NULL); +#endif + if (is_self) { /* @@ -1143,11 +1175,19 @@ mtm_after_node_create(PG_FUNCTION_ARGS) */ pub_stmt->pubname = MULTIMASTER_NAME; pub_stmt->for_all_tables = false; +#if PG_VERSION_NUM < 150000 pub_stmt->tables = NIL; +#else + pub_stmt->pubobjects = NIL; +#endif pub_stmt->options = list_make1( makeDefElem("publish", (Node *) makeString(pstrdup("insert, truncate")), -1) ); +#if PG_VERSION_NUM < 150000 CreatePublication(pub_stmt); +#else + CreatePublication(pstate, pub_stmt); +#endif /* liftoff */ MtmMonitorStart(MyDatabaseId, GetUserId()); @@ -1186,7 +1226,11 @@ mtm_after_node_create(PG_FUNCTION_ARGS) client_min_messages = ERROR; log_min_messages = ERROR; +#if PG_VERSION_NUM < 150000 CreateSubscription(cs_stmt, true); +#else + CreateSubscription(pstate, cs_stmt, true); +#endif /* restore log_level's */ client_min_messages = saved_client_min_messages; @@ -1204,6 +1248,9 @@ mtm_after_node_create(PG_FUNCTION_ARGS) origin_name = psprintf(MULTIMASTER_SLOT_PATTERN, node_id); replorigin_create(origin_name); } +#if PG_VERSION_NUM >= 150000 + free_parsestate(pstate); +#endif PG_RETURN_VOID(); } @@ -1344,6 +1391,7 @@ mtm_join_node(PG_FUNCTION_ARGS) /* Await for workers finish and create syncpoints */ PG_TRY(); { + const char *logmsg = "MTM Syncpoint in join_node"; while (!MtmAllApplyWorkersFinished()) MtmSleep(USECS_PER_SEC / 10); @@ -1370,7 +1418,7 @@ mtm_join_node(PG_FUNCTION_ARGS) LogLogicalMessage("S", msg, strlen(msg) + 1, false); replorigin_session_origin = InvalidRepOriginId; } - LogLogicalMessage("S", "", 1, false); + LogLogicalMessage("S", logmsg, strlen(logmsg) + 1, false); } PG_CATCH(); { @@ -1524,7 +1572,11 @@ mtm_ping(PG_FUNCTION_ARGS) "Failed to query mtm.cluster_status on '%s': %s", peer_connstr, msg); } +#if PG_VERSION_NUM < 150000 peer_gen_num = pg_strtouint64(PQgetvalue(res, 0, 0), NULL, 10); +#else + peer_gen_num = strtou64(PQgetvalue(res, 0, 0), NULL, 10); +#endif PQclear(res); PQfinish(conn); if (curr_gen.num != peer_gen_num) @@ -1993,7 +2045,13 @@ gather(nodemask_t participants, gather_hook_t msg_ok, Datum msg_ok_arg, int *sendconn_cnt, uint64 gen_num) { + time_t start; + bool to = false; *msg_count = 0; + + start = time(NULL); + + //elog(LOG, "----> gather 1"); while (participants != 0) { bool ret; @@ -2001,6 +2059,15 @@ gather(nodemask_t participants, StringInfoData msg; int rc; bool wait; + time_t current; + + current = time(NULL); + + if (current - start > 3) { + elog(LOG, "----> gather timeout"); + to = true; +// return false; + } ret = dmq_pop_nb(&sender_mask_pos, &msg, participants, &wait); if (ret) @@ -2055,6 +2122,8 @@ gather(nodemask_t participants, } } + if (to) + elog(LOG, "----> gather end"); return true; } diff --git a/src/pglogical_apply.c b/src/pglogical_apply.c index 566d5acb97..3f9c27c2d9 100644 --- a/src/pglogical_apply.c +++ b/src/pglogical_apply.c @@ -172,11 +172,6 @@ create_rel_estate(Relation rel) resultRelInfo = makeNode(ResultRelInfo); InitResultRelInfo(resultRelInfo, rel, 1, NULL, 0); - estate->es_result_relations = resultRelInfo; - estate->es_num_result_relations = 1; - estate->es_result_relation_info = resultRelInfo; - estate->es_output_cid = GetCurrentCommandId(true); - rte = makeNode(RangeTblEntry); rte->rtekind = RTE_RELATION; rte->relid = RelationGetRelid(rel); @@ -184,6 +179,9 @@ create_rel_estate(Relation rel) rte->rellockmode = AccessShareLock; ExecInitRangeTable(estate, list_make1(rte)); + estate->es_result_relation_info = resultRelInfo; + estate->es_output_cid = GetCurrentCommandId(true); + /* Prepare to catch AFTER triggers. */ AfterTriggerBeginQuery(); @@ -387,7 +385,7 @@ process_remote_message(StringInfo s, MtmReceiverWorkerContext *rwctx) MtmApplyDDLMessage(messageBody, false); CommitTransactionCommand(); - pgstat_report_activity(STATE_RUNNING, NULL); + pgstat_report_activity(STATE_IDLE, ""); standalone = true; break; } @@ -398,7 +396,7 @@ process_remote_message(StringInfo s, MtmReceiverWorkerContext *rwctx) pfree(activity); mtm_log(MtmApplyMessage, "executing tx DDL message %s", messageBody); MtmApplyDDLMessage(messageBody, true); - pgstat_report_activity(STATE_RUNNING, NULL); + pgstat_report_activity(STATE_IDLE, ""); break; } case 'L': @@ -1238,9 +1236,10 @@ process_remote_insert(StringInfo s, Relation rel) if (relinfo->ri_NumIndices > 0) { List *recheckIndexes; + ResultRelInfo *resultRelInfo = estate->es_result_relation_info; - recheckIndexes = ExecInsertIndexTuples(bufferedSlots[i], - estate, false, NULL, NIL); + recheckIndexes = ExecInsertIndexTuples(resultRelInfo, bufferedSlots[i], + estate, false, false, NULL, NIL); /* AFTER ROW INSERT Triggers */ ExecARInsertTriggers(estate, relinfo, bufferedSlots[i], @@ -1267,11 +1266,12 @@ process_remote_insert(StringInfo s, Relation rel) else { TupleTableSlot *newslot; + ResultRelInfo *resultRelInfo = estate->es_result_relation_info; newslot = ExecInitExtraTupleSlot(estate, tupDesc, &TTSOpsHeapTuple); tuple_to_slot(estate, rel, &new_tuple, newslot); - ExecSimpleRelationInsert(estate, newslot); + ExecSimpleRelationInsert(resultRelInfo, estate, newslot); } ExecCloseIndices(estate->es_result_relation_info); if (ActiveSnapshotSet()) @@ -1367,6 +1367,7 @@ process_remote_update(StringInfo s, Relation rel) if (found) { HeapTuple remote_tuple = NULL; + ResultRelInfo *resultRelInfo = estate->es_result_relation_info; remote_tuple = heap_modify_tuple(ExecFetchSlotHeapTuple(localslot, true, NULL), tupDesc, @@ -1376,7 +1377,7 @@ process_remote_update(StringInfo s, Relation rel) ExecStoreHeapTuple(remote_tuple, remoteslot, false); EvalPlanQualSetSlot(&epqstate, remoteslot); - ExecSimpleRelationUpdate(estate, &epqstate, localslot, remoteslot); + ExecSimpleRelationUpdate(resultRelInfo, estate, &epqstate, localslot, remoteslot); } else { @@ -1444,8 +1445,10 @@ process_remote_delete(StringInfo s, Relation rel) if (found) { + ResultRelInfo *resultRelInfo = estate->es_result_relation_info; + EvalPlanQualSetSlot(&epqstate, localslot); - ExecSimpleRelationDelete(estate, &epqstate, localslot); + ExecSimpleRelationDelete(resultRelInfo, estate, &epqstate, localslot); } else { diff --git a/src/pglogical_config.c b/src/pglogical_config.c index 0c06660aca..192ef14625 100644 --- a/src/pglogical_config.c +++ b/src/pglogical_config.c @@ -24,7 +24,9 @@ #include "nodes/makefuncs.h" #include "utils/builtins.h" +#if PG_VERSION_NUM < 150000 #include "utils/int8.h" +#endif #include "utils/inval.h" #include "utils/varlena.h" #include "utils/lsyscache.h" @@ -378,6 +380,7 @@ parse_param_bool(DefElem *elem) static uint32 parse_param_uint32(DefElem *elem) { +#if PG_VERSION_NUM < 150000 int64 res; if (!scanint8(strVal(elem->arg), true, &res)) @@ -385,6 +388,18 @@ parse_param_uint32(DefElem *elem) (errcode(ERRCODE_INVALID_PARAMETER_VALUE), MTM_ERRMSG("could not parse integer value \"%s\" for parameter \"%s\"", strVal(elem->arg), elem->defname))); +#else + unsigned long res; + char *endptr; + + errno = 0; + res = strtoul(strVal(elem->arg), &endptr, 10); + if (errno != 0 || *endptr != '\0') + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + MTM_ERRMSG("could not parse integer value \"%s\" for parameter \"%s\"", + strVal(elem->arg), elem->defname))); +#endif if (res > PG_UINT32_MAX || res < 0) ereport(ERROR, diff --git a/src/pglogical_output.c b/src/pglogical_output.c index 95bfa00540..14bd49130b 100644 --- a/src/pglogical_output.c +++ b/src/pglogical_output.c @@ -44,7 +44,9 @@ #include "utils/builtins.h" #include "utils/catcache.h" #include "utils/guc.h" +#if PG_VERSION_NUM < 150000 #include "utils/int8.h" +#endif #include "utils/inval.h" #include "utils/lsyscache.h" #include "utils/memutils.h" @@ -70,12 +72,13 @@ static void pg_decode_begin_txn(LogicalDecodingContext *ctx, static void pg_decode_commit_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr commit_lsn); +static void pg_decode_begin_prepare_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn); static void pg_decode_prepare_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr lsn); static void pg_decode_commit_prepared_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr lsn); static void pg_decode_abort_prepared_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, - XLogRecPtr lsn); + XLogRecPtr lsn, TimestampTz prepare_time); static bool pg_filter_prepare(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, TransactionId xid, const char *gid); @@ -136,9 +139,10 @@ _PG_output_plugin_init(OutputPluginCallbacks *cb) cb->abort_cb = pg_decode_abort_txn; cb->filter_prepare_cb = pg_filter_prepare; + cb->begin_prepare_cb = pg_decode_begin_prepare_txn; cb->prepare_cb = pg_decode_prepare_txn; cb->commit_prepared_cb = pg_decode_commit_prepared_txn; - cb->abort_prepared_cb = pg_decode_abort_prepared_txn; + cb->rollback_prepared_cb = pg_decode_abort_prepared_txn; cb->filter_by_origin_cb = pg_decode_origin_filter; cb->shutdown_cb = pg_decode_shutdown; @@ -485,6 +489,46 @@ pg_decode_commit_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, } } +void +pg_decode_begin_prepare_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn) +{ + PGLogicalOutputData *data = (PGLogicalOutputData *) ctx->output_plugin_private; + bool send_replication_origin = data->forward_changeset_origins; + + if (!startup_message_sent) + send_startup_message(ctx, data, false /* can't be last message */ ); + + /* If the record didn't originate locally, send origin info */ + send_replication_origin &= txn->origin_id != InvalidRepOriginId; + + if (data->api) + { + MtmOutputPluginPrepareWrite(ctx, !send_replication_origin, true); + data->api->write_begin(ctx->out, data, txn); + + if (send_replication_origin) + { + char *origin; + + /* Message boundary */ + MtmOutputPluginWrite(ctx, false, false); + MtmOutputPluginPrepareWrite(ctx, true, false); + + /* + * XXX: which behaviour we want here? + * + * Alternatives: - don't send origin message if origin name not + * found (that's what we do now) - throw error - that will break + * replication, not good - send some special "unknown" origin + */ + if (data->api->write_origin && + replorigin_by_oid(txn->origin_id, true, &origin)) + data->api->write_origin(ctx->out, origin, txn->origin_lsn); + } + MtmOutputPluginWrite(ctx, true, false); + } +} + void pg_decode_prepare_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr lsn) @@ -509,7 +553,7 @@ pg_decode_commit_prepared_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn void pg_decode_abort_prepared_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, - XLogRecPtr lsn) + XLogRecPtr lsn, TimestampTz prepare_time) { PGLogicalOutputData *data = (PGLogicalOutputData *) ctx->output_plugin_private; diff --git a/src/pglogical_proto.c b/src/pglogical_proto.c index 1c1367fdd4..766f965ae8 100644 --- a/src/pglogical_proto.c +++ b/src/pglogical_proto.c @@ -175,6 +175,7 @@ pglogical_write_begin(StringInfo out, PGLogicalOutputData *data, MtmLastRelId = InvalidOid; MtmCurrentXid = txn->xid; DDLInProgress = false; + elog(LOG, "---> pglogical_write_begin: false"); pq_sendbyte(out, 'B'); /* BEGIN */ pq_sendint(out, hooks_data->cfg->my_node_id, 4); @@ -253,6 +254,7 @@ pglogical_write_message(StringInfo out, LogicalDecodingContext *ctx, case 'D': DDLInProgress = true; + elog(LOG, "---> pglogical_write_message: true %d: %s",hooks_data->receiver_node_id, message); mtm_log(ProtoTraceMessage, "Sent tx DDL message to node %d: %s", hooks_data->receiver_node_id, message); break; @@ -266,6 +268,7 @@ pglogical_write_message(StringInfo out, LogicalDecodingContext *ctx, case 'E': DDLInProgress = false; + elog(LOG, "---> pglogical_write_message: false"); /* * we use End message only as indicator of DDL transaction finish, @@ -468,7 +471,11 @@ pglogical_write_prepare(StringInfo out, PGLogicalOutputData *data, /* send fixed fields */ pq_sendint64(out, lsn); pq_sendint64(out, txn->end_lsn); +#if PG_VERSION_NUM < 150000 pq_sendint64(out, txn->commit_time); +#else + pq_sendint64(out, txn->xact_time.commit_time); +#endif send_node_id(out, txn, hooks_data); pq_sendint64(out, txn->origin_lsn); @@ -499,7 +506,11 @@ pglogical_write_commit_prepared(StringInfo out, PGLogicalOutputData *data, /* send fixed fields */ pq_sendint64(out, lsn); pq_sendint64(out, txn->end_lsn); +#if PG_VERSION_NUM < 150000 pq_sendint64(out, txn->commit_time); +#else + pq_sendint64(out, txn->xact_time.commit_time); +#endif send_node_id(out, txn, hooks_data); pq_sendint64(out, txn->origin_lsn); @@ -532,7 +543,11 @@ pglogical_write_abort_prepared(StringInfo out, PGLogicalOutputData *data, /* send fixed fields */ pq_sendint64(out, lsn); pq_sendint64(out, txn->end_lsn); +#if PG_VERSION_NUM < 150000 pq_sendint64(out, txn->commit_time); +#else + pq_sendint64(out, txn->xact_time.commit_time); +#endif send_node_id(out, txn, hooks_data); pq_sendint64(out, txn->origin_lsn); @@ -560,7 +575,11 @@ pglogical_write_commit(StringInfo out, PGLogicalOutputData *data, /* send fixed fields */ pq_sendint64(out, lsn); pq_sendint64(out, txn->end_lsn); +#if PG_VERSION_NUM < 150000 pq_sendint64(out, txn->commit_time); +#else + pq_sendint64(out, txn->xact_time.commit_time); +#endif send_node_id(out, txn, hooks_data); pq_sendint64(out, txn->origin_lsn); @@ -583,7 +602,11 @@ pglogical_write_abort(StringInfo out, PGLogicalOutputData *data, /* send fixed fields */ pq_sendint64(out, lsn); pq_sendint64(out, txn->end_lsn); +#if PG_VERSION_NUM < 150000 pq_sendint64(out, txn->commit_time); +#else + pq_sendint64(out, txn->xact_time.commit_time); +#endif send_node_id(out, txn, hooks_data); pq_sendint64(out, txn->origin_lsn); diff --git a/src/resolver.c b/src/resolver.c index 2c9933ff51..659e9a2276 100644 --- a/src/resolver.c +++ b/src/resolver.c @@ -450,7 +450,7 @@ handle_response(MtmConfig *mtm_cfg, MtmMessage *raw_msg) else if (raw_msg->tag == T_Mtm2AResponse) gid = ((Mtm2AResponse *) raw_msg)->gid; else - Assert(false); + mtm_log(ERROR, "Illegal message tag %d", raw_msg->tag); mtm_log(ResolverTx, "handle_response: got '%s'", MtmMesageToString(raw_msg)); diff --git a/src/state.c b/src/state.c index 01b502b775..a05eb55a74 100644 --- a/src/state.c +++ b/src/state.c @@ -12,6 +12,9 @@ #include #include +#if PG_VERSION_NUM >= 150000 +#include "common/pg_prng.h" +#endif #include "access/twophase.h" #include "access/xlogutils.h" #include "access/xlog_internal.h" @@ -243,6 +246,11 @@ static PrepareBarrierMode pb_acquired_in_mode; static bool campaign_requested; +#if PG_VERSION_NUM >= 150000 +static shmem_request_hook_type prev_shmem_request_hook = NULL; +static void mtm_state_shmem_request(void); +#endif + /* * ----------------------------------- * Startup @@ -252,9 +260,26 @@ static bool campaign_requested; void MtmStateInit() { +#if PG_VERSION_NUM >= 150000 + prev_shmem_request_hook = shmem_request_hook; + shmem_request_hook = mtm_state_shmem_request; +#else + RequestAddinShmemSpace(sizeof(struct MtmState)); + RequestNamedLWLockTranche("mtm_state_locks", 3); +#endif +} + +#if PG_VERSION_NUM >= 150000 +static void +mtm_state_shmem_request(void) +{ + if (prev_shmem_request_hook) + prev_shmem_request_hook(); + RequestAddinShmemSpace(sizeof(struct MtmState)); RequestNamedLWLockTranche("mtm_state_locks", 3); } +#endif void MtmStateShmemStartup() @@ -1677,7 +1702,11 @@ CampaignerMain(Datum main_arg) MemoryContext campaigner_ctx = AllocSetContextCreate(TopMemoryContext, "CampaignerContext", ALLOCSET_DEFAULT_SIZES); +#if PG_VERSION_NUM < 150000 static unsigned short drandom_seed[3] = {0, 0, 0}; +#else + static pg_prng_state drandom_seed = {0, 0}; +#endif TimestampTz last_campaign_at = 0; int rc = WL_TIMEOUT; @@ -1719,9 +1748,13 @@ CampaignerMain(Datum main_arg) /* Mix the PID with the most predictable bits of the timestamp */ iseed = (uint64) now ^ ((uint64) MyProcPid << 32); +#if PG_VERSION_NUM < 150000 drandom_seed[0] = (unsigned short) iseed; drandom_seed[1] = (unsigned short) (iseed >> 16); drandom_seed[2] = (unsigned short) (iseed >> 32); +#else + pg_prng_seed(&drandom_seed, iseed); +#endif } /* @@ -1801,10 +1834,17 @@ CampaignerMain(Datum main_arg) * here nodes will mostly propose the same set of candidates, * supporting each other) */ +#if PG_VERSION_NUM < 150000 rc = WaitLatch(MyLatch, WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, campaign_retry_interval * pg_erand48(drandom_seed), PG_WAIT_EXTENSION); +#else + rc = WaitLatch(MyLatch, + WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + campaign_retry_interval * pg_prng_double(&drandom_seed), + PG_WAIT_EXTENSION); +#endif if (rc & WL_LATCH_SET) ResetLatch(MyLatch); @@ -3286,7 +3326,7 @@ check_status_requests(MtmConfig *mtm_cfg, bool *job_pending) txset_hash_ctl.entrysize = sizeof(txset_entry); txset_hash_ctl.hcxt = CurrentMemoryContext; txset = hash_create("txset", max_batch_size, &txset_hash_ctl, - HASH_ELEM | HASH_CONTEXT); + HASH_ELEM | HASH_CONTEXT | HASH_STRINGS); while (dmq_pop_nb(&sender_mask_pos, &packed_msg, MtmGetDmqReceiversMask(), &wait)) { @@ -3729,17 +3769,20 @@ start_node_workers(int node_id, MtmConfig *new_cfg, Datum arg) if (!MtmNodeById(new_cfg, node_id)->init_done) { + ReplicationSlot *s; + /* * Create filter slot to filter out already applied changes since the * last syncpoint during replication start */ /* slot might be already created if we failed before setting init_done */ - int acq = ReplicationSlotAcquire(filter_slot, SAB_Inquire); - if (acq == 0) - ReplicationSlotRelease(); - else if (acq == -1) + + s = SearchNamedReplicationSlot(filter_slot, true); + if (s == NULL) { - ReplicationSlotCreate(filter_slot, false, RS_PERSISTENT); + bool two_phase = true; + + ReplicationSlotCreate(filter_slot, false, RS_PERSISTENT, two_phase); ReplicationSlotReserveWal(); /* Write this slot to disk */ ReplicationSlotMarkDirty(); @@ -3776,17 +3819,18 @@ start_node_workers(int node_id, MtmConfig *new_cfg, Datum arg) if (!MtmNodeById(new_cfg, node_id)->init_done) { + ReplicationSlot *s; char *query; int rc; /* Create logical slot for our publication to this neighbour */ /* slot might be already created if we failed before setting init_done */ - int acq = ReplicationSlotAcquire(slot, SAB_Inquire); - if (acq == 0) - ReplicationSlotRelease(); - else if (acq == -1) - { - ReplicationSlotCreate(slot, true, RS_EPHEMERAL); + + s = SearchNamedReplicationSlot(slot, true); + if (s == NULL) { + bool two_phase = true; + + ReplicationSlotCreate(slot, true, RS_EPHEMERAL, two_phase); ctx = CreateInitDecodingContext(MULTIMASTER_NAME, NIL, false, /* do not build snapshot */ InvalidXLogRecPtr, @@ -3874,7 +3918,7 @@ stop_node_workers(int node_id, MtmConfig *new_cfg, Datum arg) ReplicationSlotDrop(filter_slot_name, true); /* delete replication origin, was acquired by receiver */ - replorigin_drop(replorigin_by_name(logical_slot, false), true); + replorigin_drop_by_name(logical_slot, false, true); /* * Delete logical slot. It is aquired by walsender, so call with nowait = @@ -4236,7 +4280,11 @@ GetLoggedPreparedXactState(HTAB *txset) XLogRecPtr start_lsn; XLogRecPtr lsn; TimeLineID timeline; +#if PG_VERSION_NUM < 150000 XLogRecPtr end_wal_lsn = GetFlushRecPtr(); +#else + XLogRecPtr end_wal_lsn = GetFlushRecPtr(NULL); +#endif XLogRecPtr end_lsn = end_wal_lsn; int n_trans = hash_get_num_entries(txset); @@ -4414,7 +4462,7 @@ mtm_get_logged_prepared_xact_state(PG_FUNCTION_ARGS) txset_hash_ctl.entrysize = sizeof(txset_entry); txset_hash_ctl.hcxt = CurrentMemoryContext; txset = hash_create("txset", 1, &txset_hash_ctl, - HASH_ELEM | HASH_CONTEXT); + HASH_ELEM | HASH_CONTEXT | HASH_STRINGS); txse = hash_search(txset, gid, HASH_ENTER, NULL); txse->resp.state.status = GTXInvalid; diff --git a/src/syncpoint.c b/src/syncpoint.c index a70ffc36e9..064e707cd6 100644 --- a/src/syncpoint.c +++ b/src/syncpoint.c @@ -103,8 +103,9 @@ MaybeLogSyncpoint(void) (GetInsertRecPtr() - Mtm->latestSyncpoint >= MtmSyncpointInterval * 1024)) { XLogRecPtr syncpoint_lsn; + const char *msg = "MTM syncpoint in MaybeLogsyncpoint"; - syncpoint_lsn = LogLogicalMessage("S", "", 1, false); + syncpoint_lsn = LogLogicalMessage("S", msg, strlen(msg) + 1, false); Mtm->latestSyncpoint = syncpoint_lsn; mtm_log(SyncpointCreated, @@ -144,6 +145,7 @@ SyncpointRegister(int origin_node_id, XLogRecPtr origin_lsn, { char *sql; int rc; + const char *msg = "MTM Syncpoint in SyncpointRegister"; /* Start tx */ StartTransactionCommand(); @@ -156,7 +158,7 @@ SyncpointRegister(int origin_node_id, XLogRecPtr origin_lsn, * performed instead of 3PC and so receiver is not allowed to fail * applying this transaction and go ahead even in normal mode. */ - LogLogicalMessage("B", "", 1, true); + LogLogicalMessage("B", msg, strlen(msg) + 1, true); /* Save syncpoint */ sql = psprintf("insert into mtm.syncpoints values " @@ -477,7 +479,11 @@ RecoveryFilterLoad(int filter_node_id, Syncpoint *spvector, MtmConfig *mtm_cfg) /* ensure we will scan everything written up to this point, just in case */ XLogFlush(GetXLogWriteRecPtr()); +#if PG_VERSION_NUM < 150000 current_last_lsn = GetFlushRecPtr(); +#else + current_last_lsn = GetFlushRecPtr(NULL); +#endif Assert(current_last_lsn != InvalidXLogRecPtr); @@ -490,7 +496,11 @@ RecoveryFilterLoad(int filter_node_id, Syncpoint *spvector, MtmConfig *mtm_cfg) } /* create hash */ +#if PG_VERSION_NUM < 150000 estimate_size = (GetFlushRecPtr() - start_lsn) / 100; +#else + estimate_size = (GetFlushRecPtr(NULL) - start_lsn) / 100; +#endif estimate_size = Min(Max(estimate_size, 1000), 100000); MemSet(&hash_ctl, 0, sizeof(hash_ctl)); hash_ctl.keysize = hash_ctl.entrysize = sizeof(FilterEntry); diff --git a/t/000_deadlock.pl b/t/000_deadlock.pl index d22c562baa..78c324961c 100644 --- a/t/000_deadlock.pl +++ b/t/000_deadlock.pl @@ -4,7 +4,6 @@ use warnings; use Cluster; -use TestLib; # Test whether we have both DBI and DBD::pg my $dbdpg_rc = eval diff --git a/t/001_regress.pl b/t/001_regress.pl index cbe1feaaa0..e9d4541e77 100644 --- a/t/001_regress.pl +++ b/t/001_regress.pl @@ -34,7 +34,14 @@ } # determenistic ports for expected files -$PostgresNode::last_port_assigned = 55431; +if ($Cluster::pg_15_modules) +{ + $PostgreSQL::Test::Cluster::last_port_assigned = 55431; +} +else +{ + $PostgresNode::last_port_assigned = 55431; +} my $cluster = new Cluster(3); $cluster->init(q{ @@ -68,10 +75,6 @@ CREATE VIEW pg_prepared_xacts AS select * from _pg_prepared_xacts where gid not like 'MTM-%' ORDER BY transaction::text::bigint; - ALTER TABLE pg_publication RENAME TO _pg_publication; - CREATE VIEW pg_catalog.pg_publication AS SELECT * FROM pg_catalog._pg_publication WHERE pubname<>'multimaster'; - ALTER TABLE pg_subscription RENAME TO _pg_subscription; - CREATE VIEW pg_catalog.pg_subscription AS SELECT * FROM pg_catalog._pg_subscription WHERE subname NOT LIKE 'mtm_sub_%'; }); $cluster->{nodes}->[0]->safe_psql('regression', q{ @@ -84,13 +87,30 @@ # load schedule without tablespace test which is not expected # to work with several postgreses on a single node -my $schedule = TestLib::slurp_file('../../src/test/regress/parallel_schedule'); +my $schedule; +if ($Cluster::pg_15_modules) +{ + $schedule = PostgreSQL::Test::Utils::slurp_file('../../src/test/regress/parallel_schedule'); +} +else +{ + $schedule = TestLib::slurp_file('../../src/test/regress/parallel_schedule'); +} $schedule =~ s/test: tablespace/#test: tablespace/g; $schedule =~ s/test: cfs/#test: cfs/g; $schedule =~ s/test: largeobject//; # serial schedule $schedule =~ s/largeobject//; # parallel schedule +$schedule =~ s/atx0//; # parallel schedule +$schedule =~ s/atx2//; # parallel schedule unlink('parallel_schedule'); -TestLib::append_to_file('parallel_schedule', $schedule); +if ($Cluster::pg_15_modules) +{ + PostgreSQL::Test::Utils::append_to_file('parallel_schedule', $schedule); +} +else +{ + TestLib::append_to_file('parallel_schedule', $schedule); +} my $regress_shlib = $ENV{REGRESS_SHLIB}; my $regress_libdir = dirname($regress_shlib); @@ -99,13 +119,26 @@ # REMOVEME: not needed in 14+, pg_regress fixed in upstream mkdir("${regress_outdir}/sql"); mkdir("${regress_outdir}/expected"); -TestLib::system_log($ENV{'PG_REGRESS'}, - '--host=' . $cluster->{nodes}->[0]->host, '--port=' . $cluster->{nodes}->[0]->port, - '--use-existing', '--bindir=', - '--schedule=parallel_schedule', - "--dlpath=${regress_libdir}", - '--inputdir=../../src/test/regress', - "--outputdir=${regress_outdir}"); +if ($Cluster::pg_15_modules) +{ + PostgreSQL::Test::Utils::system_log($ENV{'PG_REGRESS'}, + '--host=' . $cluster->{nodes}->[0]->host, '--port=' . $cluster->{nodes}->[0]->port, + '--use-existing', '--bindir=', + '--schedule=parallel_schedule', + "--dlpath=${regress_libdir}", + '--inputdir=../../src/test/regress', + "--outputdir=${regress_outdir}"); +} +else +{ + TestLib::system_log($ENV{'PG_REGRESS'}, + '--host=' . $cluster->{nodes}->[0]->host, '--port=' . $cluster->{nodes}->[0]->port, + '--use-existing', '--bindir=', + '--schedule=parallel_schedule', + "--dlpath=${regress_libdir}", + '--inputdir=../../src/test/regress', + "--outputdir=${regress_outdir}"); +} unlink('parallel_schedule'); # rename s/diffs/diff as some upper level testing systems are searching for all @@ -114,7 +147,15 @@ or die "cannot rename file: $!"; # strip absolute paths and dates out of resulted regression.diffs -my $res_diff = TestLib::slurp_file("${regress_outdir}/regression.diff"); +my $res_diff; +if ($Cluster::pg_15_modules) +{ + $res_diff = PostgreSQL::Test::Utils::slurp_file("${regress_outdir}/regression.diff"); +} +else +{ + $res_diff = TestLib::slurp_file("${regress_outdir}/regression.diff"); +} # In <= 11 default diff format was context, since 12 unified; handing lines # starting with ---|+++|*** covers both. # To make someone's life easier, we prepend .. to make relative paths correct. @@ -125,6 +166,9 @@ # diff -U3 /blabla/contrib/mmts/../../src/test/regress/expected/opr_sanity.out /blabla/mmts/../../src/test/regress/results/opr_sanity.out # was added to each file diff $res_diff =~ s/(diff ).+contrib\/mmts(.+\.out).+contrib\/mmts(.+\.out\n)/$1..$2 ..$3/g; +# Since 15 paths are more canonicalized removing '..' if possible +$res_diff =~ s/(--- |\+\+\+ |\*\*\* ).+(\/src\/test\/regress\/expected\/.+\.out)\t.+\n/$1..\/..\/..$2\tCENSORED\n/g; +$res_diff =~ s/(diff ).+(\/src\/test\/regress\/expected\/.+\.out).+contrib\/mmts(.+\.out\n)/$1..\/..\/..$2 ..$3/g; $res_diff =~ s/(lo_import[ \(]')\/[^']+\//$1\/CENSORED\//g; #SELECT lo_export(loid, '/home/alex/projects/ppro/postgrespro/contrib/mmts/../../src/test/regress/results/lotest.txt') FROM lotest_stash_values; $res_diff =~ s/(lo_export.*\'\/).+\//$1CENSORED\//g; @@ -134,7 +178,14 @@ # finally compare regression.diffs with our version # Do not use diffs extension as some upper level testing systems are searching for all # *.diffs files. -TestLib::append_to_file("$ENV{TESTDIR}/results/regression.diff", $res_diff); +if ($Cluster::pg_15_modules) +{ + PostgreSQL::Test::Utils::append_to_file("$ENV{TESTDIR}/results/regression.diff", $res_diff); +} +else +{ + TestLib::append_to_file("$ENV{TESTDIR}/results/regression.diff", $res_diff); +} # TODO: work with diffs on per-test basis my $expected_file; if (Cluster::is_ee()) @@ -145,7 +196,19 @@ { $expected_file = "expected/regression_vanilla.diff" } -$diff = TestLib::system_log("diff -U3 ${expected_file} $ENV{TESTDIR}/results/regression.diff"); +# Remove lines which contains random data (like ports, users, etc) from output file +# Remove line which starts with '+ mtm_sub_' from output file because it contains random user +run [ "sed", "-i.bak.000", "/+ mtm_sub_/d", "$ENV{TESTDIR}/results/regression.diff" ]; +# Remove line which starts from '+ multimaster' from output file because it contains random port number +run [ "sed", "-i.bak.001", "/+ multimaster/d", "$ENV{TESTDIR}/results/regression.diff" ]; +if ($Cluster::pg_15_modules) +{ + $diff = PostgreSQL::Test::Utils::system_log("diff -U3 ${expected_file} $ENV{TESTDIR}/results/regression.diff"); +} +else +{ + $diff = TestLib::system_log("diff -U3 ${expected_file} $ENV{TESTDIR}/results/regression.diff"); +} run [ "diff", "-U3", "${expected_file}", "$ENV{TESTDIR}/results/regression.diff" ], ">", "$ENV{TESTDIR}/regression.diff.diff"; my $res = $?; diff --git a/t/002_regressmm.pl b/t/002_regressmm.pl index 43af034318..f02286feda 100644 --- a/t/002_regressmm.pl +++ b/t/002_regressmm.pl @@ -3,7 +3,14 @@ use Test::More tests => 1; # determenistic ports for expected files -$PostgresNode::last_port_assigned = 55431; +if ($Cluster::pg_15_modules) +{ + $PostgreSQL::Test::Cluster::last_port_assigned = 55431; +} +else +{ + $PostgresNode::last_port_assigned = 55431; +} my $cluster = new Cluster(3); $cluster->init(q{ @@ -23,11 +30,25 @@ push @tests, 'atx'; } -my $ret = TestLib::system_log($ENV{'PG_REGRESS'}, - '--host=' . $cluster->{nodes}->[0]->host, '--port=' . $cluster->{nodes}->[0]->port, - '--use-existing', '--bindir=', @tests); -if ($ret != 0) +my $ret; +if ($Cluster::pg_15_modules) +{ + $ret = PostgreSQL::Test::Utils::system_log($ENV{'PG_REGRESS'}, + '--host=' . $cluster->{nodes}->[0]->host, '--port=' . $cluster->{nodes}->[0]->port, + '--use-existing', '--bindir=', @tests); + if ($ret != 0) + { + print "### Got regression! \n", PostgreSQL::Test::Utils::slurp_file('regression.diffs'); + } +} +else { - print "### Got regression! \n", TestLib::slurp_file('regression.diffs'); + $ret = TestLib::system_log($ENV{'PG_REGRESS'}, + '--host=' . $cluster->{nodes}->[0]->host, '--port=' . $cluster->{nodes}->[0]->port, + '--use-existing', '--bindir=', @tests); + if ($ret != 0) + { + print "### Got regression! \n", TestLib::slurp_file('regression.diffs'); + } } is($ret, 0, "multimaster regress"); diff --git a/t/003_basic_recovery.pl b/t/003_basic_recovery.pl index ea8fb37e1f..7826984e5f 100644 --- a/t/003_basic_recovery.pl +++ b/t/003_basic_recovery.pl @@ -4,7 +4,6 @@ use strict; use warnings; use Cluster; -use TestLib; use Test::More tests => 4; my $cluster = new Cluster(3); diff --git a/t/004_recovery.pl b/t/004_recovery.pl index e551e25ea8..b7268c1dc9 100644 --- a/t/004_recovery.pl +++ b/t/004_recovery.pl @@ -2,7 +2,6 @@ use warnings; use Cluster; -use TestLib; use Test::More tests => 6; my $cluster = new Cluster(3); diff --git a/t/005_pgbench.pl b/t/005_pgbench.pl index 18f8d777e0..0704d4b537 100644 --- a/t/005_pgbench.pl +++ b/t/005_pgbench.pl @@ -5,7 +5,6 @@ use warnings; use Cluster; -use TestLib; use Test::More tests => 2; my $cluster = new Cluster(2); diff --git a/t/006_pgbenchdl.pl b/t/006_pgbenchdl.pl index 4f51d1c4c7..1b2cfe1bf8 100644 --- a/t/006_pgbenchdl.pl +++ b/t/006_pgbenchdl.pl @@ -5,7 +5,6 @@ use warnings; use Cluster; -use TestLib; use Test::More tests => 1; use Data::Dumper; diff --git a/t/007_add_stop_node.pl b/t/007_add_stop_node.pl index 97dbbf677a..4c896fd73d 100644 --- a/t/007_add_stop_node.pl +++ b/t/007_add_stop_node.pl @@ -2,9 +2,7 @@ use warnings; use Carp; -use PostgresNode; use Cluster; -use TestLib; use Test::More tests => 8; # Generally add node with concurrent load (and failures) is not supported diff --git a/t/008_bugfixes.pl b/t/008_bugfixes.pl index 21824abc47..e0a8252e9f 100644 --- a/t/008_bugfixes.pl +++ b/t/008_bugfixes.pl @@ -2,11 +2,9 @@ use POSIX; use strict; use Test::More; -use TestLib; use Time::HiRes qw(usleep); use warnings; -use PostgresNode; use Cluster; use Test::More tests => Cluster::is_ee() ? 6 : 5; diff --git a/t/009_identity_func.pl b/t/009_identity_func.pl index 7d159c3aed..b15b78acff 100644 --- a/t/009_identity_func.pl +++ b/t/009_identity_func.pl @@ -1,8 +1,6 @@ use strict; use warnings; -use PostgresNode; use Cluster; -use TestLib; use Test::More tests => 29; my $cluster = new Cluster(3);