From 1b59ad0ace80b04220da1ea7aa6a349a5a17b930 Mon Sep 17 00:00:00 2001 From: Mikhail Rutman Date: Tue, 26 Apr 2022 13:53:37 +0700 Subject: [PATCH 01/32] Porting multimaster to postgres 14 This commit ports multimaster to Postgres 14: - removed tablespace-setup from mmts/Makefile (according to commit 6c788d9f6aadb41d76a72d56149268371a7895ee); - add readOnlyTree flag to MtmProcessUtility() (according to commit 7c337b6b527b7052e6a751f966d5734c56f668b5); - explicitly specify the hash function HASH_STRING (according to commit b3817f5f774663d55931dd4fab9c5a94a15ae7ab); - refactor the use of EState (according to commit 1375422c7826a2bf387be29895e961614f69de4b); - add 'include_out_arguments' to the function FuncnameGetCandidates() (caccording to commit e56bce5d43789cce95d099554ae9593ada92b3b7); - use MyProc->xmin instead of MyPgXact->xmin in dmq.c (according to commit 73487a60fc1063ba4b5178b69aee4ee210c182c4); - remove EE pooler support; - use SearchNamedReplicationSlot() instead of ReplicationSlotAcquire() --- Cluster.pm | 1 + Makefile | 1 - expected/regression_ee.diff | 1887 +++++++++++++++++++++++++++++++++-- src/ddl.c | 47 +- src/dmq.c | 4 +- src/global_tx.c | 2 +- src/include/compat.h | 10 - src/pglogical_apply.c | 28 +- src/pglogical_output.c | 48 +- src/state.c | 32 +- 10 files changed, 1923 insertions(+), 137 deletions(-) diff --git a/Cluster.pm b/Cluster.pm index ea7860f695..5b68eb23c1 100644 --- a/Cluster.pm +++ b/Cluster.pm @@ -141,6 +141,7 @@ sub init { $node->init(allows_streaming => 'logical'); $node->append_conf('postgresql.conf', qq{ + enable_self_join_removal = off max_connections = 50 log_line_prefix = '%m [%p] [xid%x] %i ' log_statement = all 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..24c5d720fb 100644 --- a/expected/regression_ee.diff +++ b/expected/regression_ee.diff @@ -1,3 +1,17 @@ +diff ../../../src/test/regress/expected/type_sanity.out ../tmp_check/regress_outdir/results/type_sanity.out +--- ../../../src/test/regress/expected/type_sanity.out CENSORED ++++ ../tmp_check/regress_outdir/results/type_sanity.out CENSORED +@@ -77,7 +77,9 @@ + 5017 | pg_mcv_list + 13374 | abstime + 13375 | reltime +-(8 rows) ++ 16514 | pg_publication ++ 16518 | pg_subscription ++(10 rows) + + -- Make sure typarray points to a "true" array type of our own base + SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype, 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 @@ -29,7 +43,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 @@ +@@ -1371,31 +1371,33 @@ CREATE TABLE concur_heap (f1 text, f2 text); -- empty table CREATE INDEX CONCURRENTLY concur_index1 ON concur_heap(f2,f1); @@ -70,7 +84,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 @@ +@@ -1407,7 +1409,9 @@ END; $$; CREATE INDEX CONCURRENTLY concur_index8 ON concur_heap (f1) WHERE predicate_stable(); @@ -80,7 +94,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 @@ +@@ -1416,8 +1420,6 @@ -- Failed builds are left invalid by VACUUM FULL, fixed by REINDEX VACUUM FULL concur_heap; REINDEX TABLE concur_heap; @@ -89,7 +103,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 @@ +@@ -1427,12 +1429,6 @@ f1 | text | | | f2 | text | | | Indexes: @@ -102,7 +116,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 @@ +@@ -1443,12 +1439,6 @@ f1 | text | | | f2 | text | | | Indexes: @@ -115,7 +129,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 @@ +@@ -1458,7 +1448,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 +139,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 @@ +@@ -1467,34 +1459,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 +186,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 @@ +@@ -2583,46 +2583,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,6 +274,687 @@ diff ../../../src/test/regress/expected/index_including_gist.out ../tmp_check/re DROP TABLE tbl_gist; /* +diff ../../../src/test/regress/expected/profiles.out ../tmp_check/regress_outdir/results/profiles.out +--- ../../../src/test/regress/expected/profiles.out CENSORED ++++ ../tmp_check/regress_outdir/results/profiles.out CENSORED +@@ -21,16 +21,15 @@ + PASSWORD_REUSE_TIME 1 + PASSWORD_REUSE_MAX 1 + PASSWORD_GRACE_TIME 1; ++ERROR: [MTM] failed to prepare transaction at peer node + ALTER ROLE regress_profile_role PROFILE regress_test_profile; ++ERROR: profile "regress_test_profile" does not exist + DROP PROFILE regress_test_profile; -- error +-ERROR: profile "regress_test_profile" cannot be dropped because some objects depend on it +-DETAIL: profile of role regress_profile_role ++ERROR: profile "regress_test_profile" does not exist + -- Test profile parameters + ALTER PROFILE regress_test_profile LIMIT + FAILED_LOGIN_ATTEMPTS 0; -- error +-ERROR: invalid resource limit +-LINE 2: FAILED_LOGIN_ATTEMPTS 0; +- ^ ++ERROR: profile "regress_test_profile" does not exist + ALTER PROFILE regress_test_profile LIMIT + FAILED_LOGIN_ATTEMPTS 1.1; -- error + ERROR: syntax error at or near "1.1" +@@ -38,9 +37,7 @@ + ^ + ALTER PROFILE regress_test_profile LIMIT + PASSWORD_REUSE_TIME -2; -- error +-ERROR: invalid resource limit +-LINE 2: PASSWORD_REUSE_TIME -2; +- ^ ++ERROR: profile "regress_test_profile" does not exist + ALTER PROFILE regress_test_profile LIMIT + PASSWORD_REUSE_MAX -1; -- error + ERROR: syntax error at or near "-" +@@ -48,12 +45,16 @@ + ^ + ALTER PROFILE regress_test_profile LIMIT + PASSWORD_LIFE_TIME 0.1; ++ERROR: profile "regress_test_profile" does not exist + ALTER PROFILE regress_test_profile LIMIT + PASSWORD_GRACE_TIME default; ++ERROR: profile "regress_test_profile" does not exist + ALTER PROFILE regress_test_profile LIMIT + FAILED_LOGIN_ATTEMPTS unlimited; ++ERROR: profile "regress_test_profile" does not exist + ALTER PROFILE regress_test_profile LIMIT + PASSWORD_REUSE_TIME 1; ++ERROR: profile "regress_test_profile" does not exist + -- Use ORDER BY pflname in order to make test results not dependable on possible + -- changes in records restoring order + SELECT +@@ -69,15 +70,15 @@ + pflpasswordminlen, + pflpasswordrequirecomplex + FROM pg_profile ORDER BY pflname; +- pflname | pflfailedloginattempts | pflfailedauthkeeptime | pfluserinactivetime | pflpasswordreusetime | pflpasswordreusemax | pflpasswordlifetime | pflpasswordgracetime | pflpasswordminuniqchars | pflpasswordminlen | pflpasswordrequirecomplex +-----------------------+------------------------+-----------------------+---------------------+----------------------+---------------------+---------------------+----------------------+-------------------------+-------------------+--------------------------- +- default | -1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | 0 +- regress_test_profile | -1 | -2 | -2 | 86400 | 1 | 8640 | -2 | -2 | -2 | -2 +-(2 rows) ++ pflname | pflfailedloginattempts | pflfailedauthkeeptime | pfluserinactivetime | pflpasswordreusetime | pflpasswordreusemax | pflpasswordlifetime | pflpasswordgracetime | pflpasswordminuniqchars | pflpasswordminlen | pflpasswordrequirecomplex ++---------+------------------------+-----------------------+---------------------+----------------------+---------------------+---------------------+----------------------+-------------------------+-------------------+--------------------------- ++ default | -1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | 0 ++(1 row) + + -- Cleanup + ALTER ROLE regress_profile_role PROFILE DEFAULT; + DROP PROFILE regress_test_profile; ++ERROR: profile "regress_test_profile" does not exist + DROP ROLE regress_profile_role; + -- Check that the parameters USER_INACTIVE_TIME, FAILED_AUTH_KEEP_TIME and + -- PASSWORD_LIFE_TIME can't take value 0. Test both cases when these parameters +@@ -101,22 +102,18 @@ + USER_INACTIVE_TIME 1 + FAILED_AUTH_KEEP_TIME 1 + PASSWORD_LIFE_TIME 1; ++ERROR: [MTM] failed to prepare transaction at peer node + -- error, USER_INACTIVE_TIME can't take zero value + ALTER PROFILE regress_test_profile LIMIT USER_INACTIVE_TIME 0; +-ERROR: invalid resource limit +-LINE 1: ALTER PROFILE regress_test_profile LIMIT USER_INACTIVE_TIME ... +- ^ ++ERROR: profile "regress_test_profile" does not exist + -- error, FAILED_AUTH_KEEP_TIME can't take zero value + ALTER PROFILE regress_test_profile LIMIT FAILED_AUTH_KEEP_TIME 0; +-ERROR: invalid resource limit +-LINE 1: ALTER PROFILE regress_test_profile LIMIT FAILED_AUTH_KEEP_TI... +- ^ ++ERROR: profile "regress_test_profile" does not exist + -- error, PASSWORD_LIFE_TIME can't take zero value + ALTER PROFILE regress_test_profile LIMIT PASSWORD_LIFE_TIME 0; +-ERROR: invalid resource limit +-LINE 1: ALTER PROFILE regress_test_profile LIMIT PASSWORD_LIFE_TIME ... +- ^ ++ERROR: profile "regress_test_profile" does not exist + DROP PROFILE regress_test_profile; ++ERROR: profile "regress_test_profile" does not exist + -- + -- Test cases added within the task #PGPRO-3656 (Merge extra features of + -- passwordcheck under control of new passoword policy) +@@ -130,45 +127,54 @@ + PASSWORD_MIN_UNIQUE_CHARS 3 + PASSWORD_MIN_LEN 3 + PASSWORD_REQUIRE_COMPLEX 1; ++ERROR: [MTM] failed to prepare transaction at peer node + CREATE USER u1 PROFILE pfl1; ++ERROR: profile "pfl1" does not exist + -- ok, password string satisfies the limits PASSWORD_MIN_LEN, + -- PASSWORD_REQUIRE_COMPLEX and PASSWORD_MIN_UNIQUE_CHARS + ALTER USER u1 PASSWORD 'foo1'; ++ERROR: role "u1" does not exist + -- error, password string breaks the limit PASSWORD_MIN_LEN. + ALTER USER u1 PASSWORD 'fo'; +-ERROR: password must be at least 3 characters long ++ERROR: role "u1" does not exist + -- error, password string breaks the limit PASSWORD_REQUIRE_COMPLEX. + ALTER USER u1 PASSWORD 'fooo'; +-ERROR: password must contain both letters and nonletters ++ERROR: role "u1" does not exist + -- error, password string breaks the limit PASSWORD_MIN_UNIQUE_CHARS. + ALTER USER u1 PASSWORD 'f000'; +-ERROR: password must contain at least 3 unique characters ++ERROR: role "u1" does not exist + --error, password string contains a user name + ALTER USER u1 PASSWORD '123u1__'; +-ERROR: password must not contain user name ++ERROR: role "u1" does not exist + -- Turn off PASSWORD_REQUIRE_COMPLEX in order to allow acceptance of password + -- string containing only letters or digits + ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX 0; ++ERROR: profile "pfl1" does not exist + ALTER USER u1 PASSWORD 'foobar'; -- ok, password containing only letter is ++ERROR: role "u1" does not exist + -- now acceptable since the limit + -- PASSWORD_REQUIRE_COMPLEX was set to + -- false. + ALTER USER u1 PASSWORD '1234'; -- ok, by the same reason as for the password ++ERROR: role "u1" does not exist + -- string 'foobar' + -- Check that the limits PASSWORD_MIN_LEN, PASSWORD_MIN_UNIQUE_CHARS are still + -- followed when the limit PASSWORD_REQUIRE_COMPLEX is off + -- error, password string breaks the limit PASSWORD_MIN_LEN. + ALTER USER u1 PASSWORD 'fo'; +-ERROR: password must be at least 3 characters long ++ERROR: role "u1" does not exist + -- error, password string breaks the limit PASSWORD_MIN_UNIQUE_CHARS. + ALTER USER u1 PASSWORD 'foo'; +-ERROR: password must contain at least 3 unique characters ++ERROR: role "u1" does not exist + -- Check that a user name can be specified as a part of password phrase + ALTER USER u1 PASSWORD '123u1__'; --ok, it is allowed to specify a password ++ERROR: role "u1" does not exist + -- string containing a user name + -- Clean up + DROP USER u1; ++ERROR: role "u1" does not exist + DROP PROFILE pfl1; ++ERROR: profile "pfl1" does not exist + -- Check that a value for clauses PASSWORD_MIN_UNIQUE_CHARS and PASSWORD_MIN_LEN + -- is positive integer + -- error, value of PASSWORD_MIN_UNIQUE_CHARS must be > 0 +@@ -192,16 +198,13 @@ + LINE 1: CREATE PROFILE pfl1 LIMIT PASSWORD_MIN_LEN 1.2; + ^ + CREATE PROFILE pfl1; ++ERROR: [MTM] failed to prepare transaction at peer node + -- error, value of PASSWORD_MIN_UNIQUE_CHARS must be > 0 + ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_UNIQUE_CHARS 0; +-ERROR: invalid resource limit +-LINE 1: ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_UNIQUE_CHARS 0; +- ^ ++ERROR: profile "pfl1" does not exist + -- error, value of PASSWORD_MIN_LEN must be > 0 + ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_LEN 0; +-ERROR: invalid resource limit +-LINE 1: ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_LEN 0; +- ^ ++ERROR: profile "pfl1" does not exist + -- error, value of PASSWORD_MIN_UNIQUE_CHARS must be integer + ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_UNIQUE_CHARS 1.2; + ERROR: syntax error at or near "1.2" +@@ -214,17 +217,26 @@ + ^ + -- Clean up + DROP PROFILE pfl1; ++ERROR: profile "pfl1" does not exist + -- Check that boolean value for the clause PASSWORD_REQUIRE_COMPLEX can take any + -- of the following values: ON, OFF, TRUE, FALSE, 1, 0 + CREATE PROFILE pfl1; ++ERROR: [MTM] failed to prepare transaction at peer node + ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX 0; -- ok ++ERROR: profile "pfl1" does not exist + ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX 1; -- ok ++ERROR: profile "pfl1" does not exist + ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX false; -- ok ++ERROR: profile "pfl1" does not exist + ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX true; -- ok ++ERROR: profile "pfl1" does not exist + ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX on; -- ok ++ERROR: profile "pfl1" does not exist + ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX off; -- ok ++ERROR: profile "pfl1" does not exist + -- Clean up + DROP PROFILE pfl1; ++ERROR: profile "pfl1" does not exist + -- Check that the error "ERROR: conflicting or redundant resource" is emitted + -- in case one of the options PASSWORD_MIN_UNIQUE_CHARS, PASSWORD_MIN_LEN, + -- PASSWORD_REQUIRE_COMPLEX repeated twice. +@@ -244,20 +256,15 @@ + ^ + -- The same test for ALTER PROFILE + CREATE PROFILE pfl1; ++ERROR: [MTM] failed to prepare transaction at peer node + ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_LEN 2 PASSWORD_MIN_LEN 1; -- error +-ERROR: conflicting or redundant resource +-LINE 1: ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_LEN 2 PASSWORD_MIN_LEN... +- ^ ++ERROR: profile "pfl1" does not exist + ALTER PROFILE pfl1 + LIMIT PASSWORD_MIN_UNIQUE_CHARS 2 PASSWORD_MIN_UNIQUE_CHARS 1; -- error +-ERROR: conflicting or redundant resource +-LINE 2: LIMIT PASSWORD_MIN_UNIQUE_CHARS 2 PASSWORD_MIN_UNIQUE_CHARS ... +- ^ ++ERROR: profile "pfl1" does not exist + ALTER PROFILE pfl1 + LIMIT PASSWORD_REQUIRE_COMPLEX off PASSWORD_REQUIRE_COMPLEX on; -- error +-ERROR: conflicting or redundant resource +-LINE 2: LIMIT PASSWORD_REQUIRE_COMPLEX off PASSWORD_REQUIRE_COMPLEX ... +- ^ ++ERROR: profile "pfl1" does not exist + -- Unlike other profile options, PASSWORD_REQUIRE_COMPLEX cannot be set to + -- UNLIMITED. + ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX UNLIMITED; +@@ -266,56 +273,58 @@ + ^ + -- Clean up + DROP PROFILE pfl1; ++ERROR: profile "pfl1" does not exist + -- Begin of tests that were added within implementation of the task PGPRO-4309 + -- Check that ALTER PROFILE RENAME does work as expected. + CREATE PROFILE profile_test; ++ERROR: [MTM] failed to prepare transaction at peer node + -- Query what profiles are currently stored in the system catalog table 'pg_profile'. + -- Use ORDER BY pflname in order to make test results not dependable on possible + -- changes in records restoring order + SELECT pflname FROM pg_profile ORDER BY pflname; +- pflname +--------------- ++ pflname ++--------- + default +- profile_test +-(2 rows) ++(1 row) + + -- Rename profile 'profile_test' to 'profile_test_new' + ALTER PROFILE profile_test RENAME TO profile_test_new; ++ERROR: profile "profile_test" does not exist + -- and check that the new profile name is stored in + -- the system catalog table pg_profile + SELECT pflname FROM pg_profile ORDER BY pflname; +- pflname +------------------- ++ pflname ++--------- + default +- profile_test_new +-(2 rows) ++(1 row) + + -- Clean up + DROP PROFILE profile_test_new; ++ERROR: profile "profile_test_new" does not exist + -- Check that rounding of a time value is correct + CREATE PROFILE test_profile LIMIT PASSWORD_LIFE_TIME 0.00001; ++ERROR: [MTM] failed to prepare transaction at peer node + ALTER PROFILE test_profile LIMIT PASSWORD_LIFE_TIME 0.0000000000000000000000000000000001; +-ERROR: invalid resource limit +-LINE 1: ALTER PROFILE test_profile LIMIT PASSWORD_LIFE_TIME 0.000000... +- ^ ++ERROR: profile "test_profile" does not exist + SELECT pflpasswordlifetime FROM pg_profile WHERE pflname = 'test_profile'; + pflpasswordlifetime + --------------------- +- 1 +-(1 row) ++(0 rows) + + -- Check that PASSWORD_GRACE_TIME can be assigned the value 0; + ALTER PROFILE test_profile LIMIT PASSWORD_GRACE_TIME 0 PASSWORD_LIFE_TIME 1; ++ERROR: profile "test_profile" does not exist + SELECT pflpasswordgracetime, pflpasswordlifetime FROM pg_profile WHERE pflname = 'test_profile'; + pflpasswordgracetime | pflpasswordlifetime + ----------------------+--------------------- +- 0 | 86400 +-(1 row) ++(0 rows) + + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist + -- Check that a value of interval type can be supplied for time-related profile options in + -- the statement CREATE PROFILE + CREATE PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '1' DAY PASSWORD_GRACE_TIME INTERVAL '2' HOUR PASSWORD_REUSE_TIME INTERVAL '30' MINUTE USER_INACTIVE_TIME INTERVAL '75' SECOND ; ++ERROR: [MTM] failed to prepare transaction at peer node + SELECT + pflpasswordlifetime, + pflpasswordgracetime, +@@ -324,13 +333,14 @@ + FROM pg_profile WHERE pflname='test_profile'; + pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime + ---------------------+----------------------+----------------------+--------------------- +- 86400 | 7200 | 1800 | 75 +-(1 row) ++(0 rows) + + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist + -- Check that a value of interval type can be supplied in all supported formats + -- the statement CREATE PROFILE + CREATE PROFILE test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '1 YEAR 2 MONTHS 3 DAYS 4 HOURS 5 MINUTES 6.123 SECONDS' PASSWORD_LIFE_TIME INTERVAL '1 MINUTE' MINUTE PASSWORD_GRACE_TIME INTERVAL '1 SECOND' MINUTE PASSWORD_REUSE_TIME INTERVAL '1 MINUTE 1 SECOND' SECOND USER_INACTIVE_TIME INTERVAL '1 MINUTE 1 SECOND' MINUTE; ++ERROR: [MTM] failed to prepare transaction at peer node + SELECT + pflfailedauthkeeptime, + pflpasswordlifetime, +@@ -340,11 +350,12 @@ + FROM pg_profile WHERE pflname='test_profile'; + pflfailedauthkeeptime | pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime + -----------------------+---------------------+----------------------+----------------------+--------------------- +- 37015506 | 60 | 0 | 61 | 60 +-(1 row) ++(0 rows) + + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist + CREATE PROFILE test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '1 YEAR 2 MONTHS 3 DAYS 4 HOURS 5 MINUTES 6.523 SECONDS' PASSWORD_LIFE_TIME INTERVAL '1 MINUTE' SECOND PASSWORD_GRACE_TIME INTERVAL '1 MINUTE' PASSWORD_REUSE_TIME INTERVAL '1-2' SECOND USER_INACTIVE_TIME INTERVAL '3 4:05:06' SECOND; ++ERROR: [MTM] failed to prepare transaction at peer node + SELECT + pflfailedauthkeeptime, + pflpasswordlifetime, +@@ -354,21 +365,22 @@ + FROM pg_profile WHERE pflname='test_profile'; + pflfailedauthkeeptime | pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime + -----------------------+---------------------+----------------------+----------------------+--------------------- +- 37015507 | 60 | 60 | 36741600 | 273906 +-(1 row) ++(0 rows) + + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist + CREATE PROFILE test_profile LIMIT PASSWORD_REUSE_TIME INTERVAL 'P2Y3M4DT5H6M7S' USER_INACTIVE_TIME INTERVAL 'P0003-04-05T06:07:08'; ++ERROR: [MTM] failed to prepare transaction at peer node + SELECT + pflpasswordreusetime, + pfluserinactivetime + FROM pg_profile WHERE pflname='test_profile'; + pflpasswordreusetime | pfluserinactivetime + ----------------------+--------------------- +- 71255167 | 105494828 +-(1 row) ++(0 rows) + + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist + -- Invalid interval type values + -- the statement CREATE PROFILE + --FAILED_AUTH_KEEP_TIME value must be from 1 to 2147483647 seconds +@@ -419,6 +431,7 @@ + -- Check that an interval type value and a real type value can intermixed + -- in the same CREATE PROFILE statement. + CREATE PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '1' DAY PASSWORD_GRACE_TIME 0.01 PASSWORD_REUSE_TIME INTERVAL '30' MINUTE USER_INACTIVE_TIME 1; ++ERROR: [MTM] failed to prepare transaction at peer node + SELECT + pflpasswordlifetime, + pflpasswordgracetime, +@@ -427,14 +440,16 @@ + FROM pg_profile WHERE pflname='test_profile'; + pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime + ---------------------+----------------------+----------------------+--------------------- +- 86400 | 864 | 1800 | 86400 +-(1 row) ++(0 rows) + + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist + CREATE PROFILE test_profile; ++ERROR: [MTM] failed to prepare transaction at peer node + -- Check that a value of interval type can be supplied for time-related profile options in + -- the statement ALTER PROFILE + ALTER PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '1' DAY PASSWORD_GRACE_TIME INTERVAL '2' HOUR PASSWORD_REUSE_TIME INTERVAL '30' MINUTE USER_INACTIVE_TIME INTERVAL '75' SECOND ; ++ERROR: profile "test_profile" does not exist + SELECT + pflpasswordlifetime, + pflpasswordgracetime, +@@ -443,12 +458,12 @@ + FROM pg_profile WHERE pflname='test_profile'; + pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime + ---------------------+----------------------+----------------------+--------------------- +- 86400 | 7200 | 1800 | 75 +-(1 row) ++(0 rows) + + -- Check that a value of interval type can be supplied in all supported formats + -- the statement ALTER PROFILE + ALTER PROFILE test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '1 YEAR 2 MONTHS 3 DAYS 4 HOURS 5 MINUTES 6.123 SECONDS' PASSWORD_LIFE_TIME INTERVAL '1 MINUTE' MINUTE PASSWORD_GRACE_TIME INTERVAL '1 SECOND' MINUTE PASSWORD_REUSE_TIME INTERVAL '1 MINUTE 1 SECOND' SECOND USER_INACTIVE_TIME INTERVAL '1 MINUTE 1 SECOND' MINUTE; ++ERROR: profile "test_profile" does not exist + SELECT + pflfailedauthkeeptime, + pflpasswordlifetime, +@@ -458,10 +473,10 @@ + FROM pg_profile WHERE pflname='test_profile'; + pflfailedauthkeeptime | pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime + -----------------------+---------------------+----------------------+----------------------+--------------------- +- 37015506 | 60 | 0 | 61 | 60 +-(1 row) ++(0 rows) + + ALTER PROFILE test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '1 YEAR 2 MONTHS 3 DAYS 4 HOURS 5 MINUTES 6.523 SECONDS' PASSWORD_LIFE_TIME INTERVAL '1 MINUTE' SECOND PASSWORD_GRACE_TIME INTERVAL '1 MINUTE' PASSWORD_REUSE_TIME INTERVAL '1-2' SECOND USER_INACTIVE_TIME INTERVAL '3 4:05:06' SECOND; ++ERROR: profile "test_profile" does not exist + SELECT + pflfailedauthkeeptime, + pflpasswordlifetime, +@@ -471,69 +486,49 @@ + FROM pg_profile WHERE pflname='test_profile'; + pflfailedauthkeeptime | pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime + -----------------------+---------------------+----------------------+----------------------+--------------------- +- 37015507 | 60 | 60 | 36741600 | 273906 +-(1 row) ++(0 rows) + + ALTER PROFILE test_profile LIMIT PASSWORD_REUSE_TIME INTERVAL 'P2Y3M4DT5H6M7S' USER_INACTIVE_TIME INTERVAL 'P0003-04-05T06:07:08'; ++ERROR: profile "test_profile" does not exist + SELECT + pflpasswordreusetime, + pfluserinactivetime + FROM pg_profile WHERE pflname='test_profile'; + pflpasswordreusetime | pfluserinactivetime + ----------------------+--------------------- +- 71255167 | 105494828 +-(1 row) ++(0 rows) + + -- Invalid interval type values + -- the statement ALTER PROFILE + --FAILED_AUTH_KEEP_TIME value must be from 1 to 2147483647 seconds + ALTER PROFILE test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '100' YEAR; --error +-ERROR: interval must be in range 1..2147483647 seconds +-LINE 1: ...test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '100' YEAR... +- ^ ++ERROR: profile "test_profile" does not exist + ALTER PROFILE test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '1 MINUTE' DAY; --error +-ERROR: interval must be in range 1..2147483647 seconds +-LINE 1: ...test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '1 MINUTE'... +- ^ ++ERROR: profile "test_profile" does not exist + --PASSWORD_LIFE_TIME value must be from 1 to 2147483647 seconds + ALTER PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '100' YEAR; --error +-ERROR: interval must be in range 1..2147483647 seconds +-LINE 1: ...LE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '100' YEAR... +- ^ ++ERROR: profile "test_profile" does not exist + ALTER PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '1 MINUTE' HOUR; --error +-ERROR: interval must be in range 1..2147483647 seconds +-LINE 1: ...LE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '1 MINUTE'... +- ^ ++ERROR: profile "test_profile" does not exist + --PASSWORD_GRACE_TIME value must be from 0 to 2147483647 seconds + ALTER PROFILE test_profile LIMIT PASSWORD_GRACE_TIME INTERVAL '100' YEAR; --error +-ERROR: interval must be in range 0..2147483647 seconds +-LINE 1: ...E test_profile LIMIT PASSWORD_GRACE_TIME INTERVAL '100' YEAR... +- ^ ++ERROR: profile "test_profile" does not exist + ALTER PROFILE test_profile LIMIT PASSWORD_GRACE_TIME INTERVAL '-1 SECOND'; --error +-ERROR: interval must be in range 0..2147483647 seconds +-LINE 1: ...E test_profile LIMIT PASSWORD_GRACE_TIME INTERVAL '-1 SECOND... +- ^ ++ERROR: profile "test_profile" does not exist + --PASSWORD_REUSE_TIME value must be from 0 to 2147483647 seconds + ALTER PROFILE test_profile LIMIT PASSWORD_REUSE_TIME INTERVAL '100' YEAR; --error +-ERROR: interval must be in range 0..2147483647 seconds +-LINE 1: ...E test_profile LIMIT PASSWORD_REUSE_TIME INTERVAL '100' YEAR... +- ^ ++ERROR: profile "test_profile" does not exist + ALTER PROFILE test_profile LIMIT PASSWORD_REUSE_TIME INTERVAL '-1 SECOND'; --error +-ERROR: interval must be in range 0..2147483647 seconds +-LINE 1: ...E test_profile LIMIT PASSWORD_REUSE_TIME INTERVAL '-1 SECOND... +- ^ ++ERROR: profile "test_profile" does not exist + --USER_INACTIVE_TIME value must be from 1 to 2147483647 seconds + ALTER PROFILE test_profile LIMIT USER_INACTIVE_TIME INTERVAL '100' YEAR; --error +-ERROR: interval must be in range 1..2147483647 seconds +-LINE 1: ...LE test_profile LIMIT USER_INACTIVE_TIME INTERVAL '100' YEAR... +- ^ ++ERROR: profile "test_profile" does not exist + ALTER PROFILE test_profile LIMIT USER_INACTIVE_TIME INTERVAL '1 SECOND' YEAR; --error +-ERROR: interval must be in range 1..2147483647 seconds +-LINE 1: ...LE test_profile LIMIT USER_INACTIVE_TIME INTERVAL '1 SECOND'... +- ^ ++ERROR: profile "test_profile" does not exist + -- Check that an interval type value and a real type value can intermixed + -- in the same ALTER PROFILE statement. + ALTER PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '5' DAY PASSWORD_GRACE_TIME 0.01 PASSWORD_REUSE_TIME INTERVAL '70' MINUTE USER_INACTIVE_TIME 1; ++ERROR: profile "test_profile" does not exist + SELECT + pflpasswordlifetime, + pflpasswordgracetime, +@@ -542,36 +537,40 @@ + FROM pg_profile WHERE pflname='test_profile'; + pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime + ---------------------+----------------------+----------------------+--------------------- +- 432000 | 864 | 4200 | 86400 +-(1 row) ++(0 rows) + + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist + -- Check support of statement CREATE PROFILE IF NOT EXISTS + CREATE PROFILE IF NOT EXISTS test_profile; ++ERROR: [MTM] failed to prepare transaction at peer node + -- Check that the profile test_profile was created + SELECT 1 FROM pg_profile WHERE pflname='test_profile'; + ?column? + ---------- +- 1 +-(1 row) ++(0 rows) + + -- Re-execute the same CREATE PROFILE statement and check it doesn't fail + CREATE PROFILE IF NOT EXISTS test_profile; ++ERROR: [MTM] failed to prepare transaction at peer node + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist + -- Check support of statement CREATE PROFILE FROM + CREATE PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '10' HOUR FAILED_LOGIN_ATTEMPTS 7; ++ERROR: [MTM] failed to prepare transaction at peer node + CREATE PROFILE test_profile_copy FROM test_profile; ++ERROR: profile "test_profile" does not exist + -- Use ORDER BY pflname in order to make test results not dependable on possible + -- changes in records restoring order + SELECT pflname, pflfailedloginattempts, pflfailedauthkeeptime, pfluserinactivetime, pflpasswordreusetime, pflpasswordreusemax, pflpasswordlifetime, pflpasswordgracetime, pflpasswordminuniqchars, pflpasswordminlen, pflpasswordrequirecomplex FROM pg_profile WHERE pflname IN ('test_profile', 'test_profile_copy') ORDER BY pflname; +- pflname | pflfailedloginattempts | pflfailedauthkeeptime | pfluserinactivetime | pflpasswordreusetime | pflpasswordreusemax | pflpasswordlifetime | pflpasswordgracetime | pflpasswordminuniqchars | pflpasswordminlen | pflpasswordrequirecomplex +--------------------+------------------------+-----------------------+---------------------+----------------------+---------------------+---------------------+----------------------+-------------------------+-------------------+--------------------------- +- test_profile | 7 | -2 | -2 | -2 | -2 | 36000 | -2 | -2 | -2 | -2 +- test_profile_copy | 7 | -2 | -2 | -2 | -2 | 36000 | -2 | -2 | -2 | -2 +-(2 rows) ++ pflname | pflfailedloginattempts | pflfailedauthkeeptime | pfluserinactivetime | pflpasswordreusetime | pflpasswordreusemax | pflpasswordlifetime | pflpasswordgracetime | pflpasswordminuniqchars | pflpasswordminlen | pflpasswordrequirecomplex ++---------+------------------------+-----------------------+---------------------+----------------------+---------------------+---------------------+----------------------+-------------------------+-------------------+--------------------------- ++(0 rows) + + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist + DROP PROFILE test_profile_copy; ++ERROR: profile "test_profile_copy" does not exist + -- Check that all profile options support the value DEFAULT. + CREATE PROFILE test_profile LIMIT + FAILED_LOGIN_ATTEMPTS DEFAULT +@@ -584,6 +583,7 @@ + PASSWORD_MIN_UNIQUE_CHARS DEFAULT + PASSWORD_MIN_LEN DEFAULT + PASSWORD_REQUIRE_COMPLEX DEFAULT; ++ERROR: [MTM] failed to prepare transaction at peer node + \x + SELECT + pflfailedloginattempts, +@@ -597,21 +597,13 @@ + pflpasswordminlen, + pflpasswordrequirecomplex + FROM pg_profile WHERE pflname = 'test_profile'; +--[ RECORD 1 ]-------------+--- +-pflfailedloginattempts | -2 +-pflfailedauthkeeptime | -2 +-pfluserinactivetime | -2 +-pflpasswordreusetime | -2 +-pflpasswordreusemax | -2 +-pflpasswordlifetime | -2 +-pflpasswordgracetime | -2 +-pflpasswordminuniqchars | -2 +-pflpasswordminlen | -2 +-pflpasswordrequirecomplex | -2 ++(0 rows) + + \x + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist + CREATE PROFILE test_profile; ++ERROR: [MTM] failed to prepare transaction at peer node + ALTER PROFILE test_profile LIMIT + FAILED_LOGIN_ATTEMPTS DEFAULT + FAILED_AUTH_KEEP_TIME DEFAULT +@@ -623,6 +615,7 @@ + PASSWORD_MIN_UNIQUE_CHARS DEFAULT + PASSWORD_MIN_LEN DEFAULT + PASSWORD_REQUIRE_COMPLEX DEFAULT; ++ERROR: profile "test_profile" does not exist + \x + SELECT + pflfailedloginattempts, +@@ -636,20 +629,11 @@ + pflpasswordminlen, + pflpasswordrequirecomplex + FROM pg_profile WHERE pflname = 'test_profile'; +--[ RECORD 1 ]-------------+--- +-pflfailedloginattempts | -2 +-pflfailedauthkeeptime | -2 +-pfluserinactivetime | -2 +-pflpasswordreusetime | -2 +-pflpasswordreusemax | -2 +-pflpasswordlifetime | -2 +-pflpasswordgracetime | -2 +-pflpasswordminuniqchars | -2 +-pflpasswordminlen | -2 +-pflpasswordrequirecomplex | -2 ++(0 rows) + + \x + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist + -- Check that almost all profile options (except for PASSWORD_REQUIRE_COMPLEX) + -- support the value UNLIMITED. + CREATE PROFILE test_profile LIMIT +@@ -662,6 +646,7 @@ + PASSWORD_GRACE_TIME UNLIMITED + PASSWORD_MIN_UNIQUE_CHARS UNLIMITED + PASSWORD_MIN_LEN UNLIMITED; ++ERROR: [MTM] failed to prepare transaction at peer node + \x + SELECT + pflfailedloginattempts, +@@ -675,21 +660,13 @@ + pflpasswordminlen, + pflpasswordrequirecomplex + FROM pg_profile WHERE pflname = 'test_profile'; +--[ RECORD 1 ]-------------+--- +-pflfailedloginattempts | -1 +-pflfailedauthkeeptime | -1 +-pfluserinactivetime | -1 +-pflpasswordreusetime | -1 +-pflpasswordreusemax | -1 +-pflpasswordlifetime | -1 +-pflpasswordgracetime | -1 +-pflpasswordminuniqchars | -1 +-pflpasswordminlen | -1 +-pflpasswordrequirecomplex | -2 ++(0 rows) + + \x + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist + CREATE PROFILE test_profile; ++ERROR: [MTM] failed to prepare transaction at peer node + ALTER PROFILE test_profile LIMIT + FAILED_LOGIN_ATTEMPTS UNLIMITED + FAILED_AUTH_KEEP_TIME UNLIMITED +@@ -700,6 +677,7 @@ + PASSWORD_GRACE_TIME UNLIMITED + PASSWORD_MIN_UNIQUE_CHARS UNLIMITED + PASSWORD_MIN_LEN UNLIMITED; ++ERROR: profile "test_profile" does not exist + \x + SELECT + pflfailedloginattempts, +@@ -713,17 +691,8 @@ + pflpasswordminlen, + pflpasswordrequirecomplex + FROM pg_profile WHERE pflname = 'test_profile'; +--[ RECORD 1 ]-------------+--- +-pflfailedloginattempts | -1 +-pflfailedauthkeeptime | -1 +-pfluserinactivetime | -1 +-pflpasswordreusetime | -1 +-pflpasswordreusemax | -1 +-pflpasswordlifetime | -1 +-pflpasswordgracetime | -1 +-pflpasswordminuniqchars | -1 +-pflpasswordminlen | -1 +-pflpasswordrequirecomplex | -2 ++(0 rows) + + \x + DROP PROFILE test_profile; ++ERROR: profile "test_profile" does not exist 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 @@ -297,7 +992,7 @@ diff ../../../src/test/regress/expected/sanity_check.out ../tmp_check/regress_ou num_data|f num_exp_add|t num_exp_div|t -@@ -140,7 +146,6 @@ +@@ -141,7 +147,6 @@ pg_policy|t pg_proc|t pg_profile|t @@ -305,7 +1000,7 @@ diff ../../../src/test/regress/expected/sanity_check.out ../tmp_check/regress_ou pg_publication_rel|t pg_range|t pg_replication_origin|t -@@ -154,7 +159,6 @@ +@@ -155,7 +160,6 @@ pg_statistic|t pg_statistic_ext|t pg_statistic_ext_data|t @@ -313,7 +1008,7 @@ diff ../../../src/test/regress/expected/sanity_check.out ../tmp_check/regress_ou pg_subscription_rel|t pg_tablespace|t pg_transform|t -@@ -185,6 +189,7 @@ +@@ -187,6 +191,7 @@ sql_sizing|f stud_emp|f student|f @@ -321,6 +1016,473 @@ diff ../../../src/test/regress/expected/sanity_check.out ../tmp_check/regress_ou 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/join.out ../tmp_check/regress_outdir/results/join.out +--- ../../../src/test/regress/expected/join.out CENSORED ++++ ../tmp_check/regress_outdir/results/join.out CENSORED +@@ -4936,11 +4936,14 @@ + -- Trivial self-join case. + explain (costs off) + select p.* from sj p, sj q where q.a = p.a and q.b = q.a - 1; +- QUERY PLAN +------------------------------------------------ +- Seq Scan on sj q +- Filter: ((a IS NOT NULL) AND (b = (a - 1))) +-(2 rows) ++ QUERY PLAN ++------------------------------- ++ Nested Loop ++ Join Filter: (p.a = q.a) ++ -> Seq Scan on sj q ++ Filter: (b = (a - 1)) ++ -> Seq Scan on sj p ++(5 rows) + + select p.* from sj p, sj q where q.a = p.a and q.b = q.a - 1; + a | b | c +@@ -4954,11 +4957,15 @@ + select * from sj p + where exists (select * from sj q + where q.a = p.a and q.b < 10); +- QUERY PLAN +------------------------------------------- +- Seq Scan on sj q +- Filter: ((a IS NOT NULL) AND (b < 10)) +-(2 rows) ++ QUERY PLAN ++-------------------------------- ++ Nested Loop ++ Join Filter: (p.a = q.a) ++ -> Seq Scan on sj p ++ -> Materialize ++ -> Seq Scan on sj q ++ Filter: (b < 10) ++(6 rows) + + select * from sj p where exists (select * from sj q where q.a = p.a and q.b < 10); + a | b | c +@@ -4985,13 +4992,11 @@ + (select a as x from sj where false) as q1, + (select a as y from sj where false) as q2 + where q1.x = q2.y; +- QUERY PLAN +---------------------------------- ++ QUERY PLAN ++-------------------------- + Result + One-Time Filter: false +- -> Seq Scan on sj +- Filter: (a IS NOT NULL) +-(4 rows) ++(2 rows) + + -- We can't use a cross-EC generated self join qual because of current logic of + -- the generate_join_implied_equalities routine. +@@ -5032,11 +5037,18 @@ + explain (costs off) + select * from sj t1 join sj t2 on t1.a = t2.a and t1.b = t2.b + join sj t3 on t2.a = t3.a and t2.b + 1 = t3.b + 1; +- QUERY PLAN +---------------------------------------------------------------------------- +- Seq Scan on sj t3 +- Filter: ((a IS NOT NULL) AND (b IS NOT NULL) AND ((b + 1) IS NOT NULL)) +-(2 rows) ++ QUERY PLAN ++-------------------------------------------------------------------------------- ++ Nested Loop ++ Join Filter: ((t1.a = t2.a) AND (t1.b = t2.b) AND ((t3.b + 1) = (t2.b + 1))) ++ -> Seq Scan on sj t2 ++ -> Materialize ++ -> Nested Loop ++ Join Filter: (t1.a = t3.a) ++ -> Seq Scan on sj t1 ++ -> Materialize ++ -> Seq Scan on sj t3 ++(9 rows) + + -- subselect that references the removed relation + explain (costs off) +@@ -5045,14 +5057,17 @@ + where t1.a = t2.a; + QUERY PLAN + ------------------------------------------ +- Seq Scan on sj t2 +- Filter: (a IS NOT NULL) ++ Nested Loop ++ Join Filter: (t1.a = t2.a) ++ -> Seq Scan on sj t1 ++ -> Materialize ++ -> Seq Scan on sj t2 + SubPlan 1 + -> Result +- One-Time Filter: (t2.a = t2.a) ++ One-Time Filter: (t2.a = t1.a) + -> Seq Scan on sj +- Filter: (a = t2.a) +-(7 rows) ++ Filter: (a = t1.a) ++(10 rows) + + -- self-join under outer join + explain (costs off) +@@ -5061,12 +5076,15 @@ + QUERY PLAN + ------------------------------------ + Nested Loop Left Join +- Join Filter: (y.a = z.q1) +- -> Seq Scan on sj y +- Filter: (a IS NOT NULL) ++ Join Filter: (x.a = z.q1) ++ -> Nested Loop ++ Join Filter: (x.a = y.a) ++ -> Seq Scan on sj x ++ -> Materialize ++ -> Seq Scan on sj y + -> Materialize + -> Seq Scan on int8_tbl z +-(6 rows) ++(9 rows) + + explain (costs off) + select * from sj x join sj y on x.a = y.a +@@ -5075,11 +5093,14 @@ + ------------------------------------ + Nested Loop Left Join + Join Filter: (y.a = z.q1) +- -> Seq Scan on sj y +- Filter: (a IS NOT NULL) ++ -> Nested Loop ++ Join Filter: (x.a = y.a) ++ -> Seq Scan on sj x ++ -> Materialize ++ -> Seq Scan on sj y + -> Materialize + -> Seq Scan on int8_tbl z +-(6 rows) ++(9 rows) + + -- Test that placeholders are updated correctly after join removal + explain (costs off) +@@ -5088,44 +5109,56 @@ + right join sj j1 inner join sj j2 on j1.a = j2.a + on true) z + on true; +- QUERY PLAN +------------------------------------------- ++ QUERY PLAN ++------------------------------------------- + Nested Loop Left Join + -> Result + -> Nested Loop Left Join +- -> Seq Scan on sj j2 +- Filter: (a IS NOT NULL) ++ -> Nested Loop ++ Join Filter: (j1.a = j2.a) ++ -> Seq Scan on sj j1 ++ -> Materialize ++ -> Seq Scan on sj j2 + -> Materialize + -> Seq Scan on int8_tbl y +-(7 rows) ++(10 rows) + + -- Test that OR predicated are updated correctly after join removal + CREATE TABLE tab_with_flag ( id INT PRIMARY KEY, is_flag SMALLINT); + CREATE INDEX idx_test_is_flag ON tab_with_flag (is_flag); + explain (costs off) + SELECT COUNT(*) FROM tab_with_flag WHERE (is_flag IS NULL OR is_flag = 0) AND id IN (SELECT id FROM tab_with_flag WHERE id IN (2, 3)); +- QUERY PLAN +----------------------------------------------------------------------------------- ++ QUERY PLAN ++------------------------------------------------------------------------ + Aggregate +- -> Bitmap Heap Scan on tab_with_flag +- Recheck Cond: ((id = ANY ('{2,3}'::integer[])) AND (id IS NOT NULL)) +- Filter: ((is_flag IS NULL) OR (is_flag = 0)) +- -> Bitmap Index Scan on tab_with_flag_pkey +- Index Cond: ((id = ANY ('{2,3}'::integer[])) AND (id IS NOT NULL)) +-(6 rows) ++ -> Nested Loop ++ -> Bitmap Heap Scan on tab_with_flag tab_with_flag_1 ++ Recheck Cond: (id = ANY ('{2,3}'::integer[])) ++ -> Bitmap Index Scan on tab_with_flag_pkey ++ Index Cond: (id = ANY ('{2,3}'::integer[])) ++ -> Memoize ++ Cache Key: tab_with_flag_1.id ++ Cache Mode: logical ++ -> Index Scan using tab_with_flag_pkey on tab_with_flag ++ Index Cond: (id = tab_with_flag_1.id) ++ Filter: ((is_flag IS NULL) OR (is_flag = 0)) ++(12 rows) + + DROP TABLE tab_with_flag; + -- HAVING clause + explain (costs off) + select p.b from sj p join sj q on p.a = q.a group by p.b having sum(p.a) = 1; +- QUERY PLAN +---------------------------------- ++ QUERY PLAN ++------------------------------------ + HashAggregate +- Group Key: q.b +- Filter: (sum(q.a) = 1) +- -> Seq Scan on sj q +- Filter: (a IS NOT NULL) +-(5 rows) ++ Group Key: p.b ++ Filter: (sum(p.a) = 1) ++ -> Nested Loop ++ Join Filter: (p.a = q.a) ++ -> Seq Scan on sj p ++ -> Materialize ++ -> Seq Scan on sj q ++(8 rows) + + -- update lateral references and range table entry reference + explain (verbose, costs off) +@@ -5135,13 +5168,20 @@ + ------------------------------------------------------ + Nested Loop + Output: 1 +- -> Seq Scan on public.sj y +- Output: y.a, y.b, y.c +- Filter: (y.a IS NOT NULL) ++ -> Nested Loop ++ Output: x.a ++ Inner Unique: true ++ Join Filter: (x.a = y.a) ++ -> Seq Scan on public.sj x ++ Output: x.a, x.b, x.c ++ -> Materialize ++ Output: y.a ++ -> Seq Scan on public.sj y ++ Output: y.a + -> Function Scan on pg_catalog.generate_series gs + Output: gs.i +- Function Call: generate_series(1, y.a) +-(8 rows) ++ Function Call: generate_series(1, x.a) ++(15 rows) + + explain (verbose, costs off) + select 1 from (select y.* from sj x, sj y where x.a = y.a) q, +@@ -5150,13 +5190,20 @@ + ------------------------------------------------------ + Nested Loop + Output: 1 +- -> Seq Scan on public.sj y +- Output: y.a, y.b, y.c +- Filter: (y.a IS NOT NULL) ++ -> Nested Loop ++ Output: y.a ++ Inner Unique: true ++ Join Filter: (x.a = y.a) ++ -> Seq Scan on public.sj x ++ Output: x.a, x.b, x.c ++ -> Materialize ++ Output: y.a ++ -> Seq Scan on public.sj y ++ Output: y.a + -> Function Scan on pg_catalog.generate_series gs + Output: gs.i + Function Call: generate_series(1, y.a) +-(8 rows) ++(15 rows) + + -- Test that a non-EC-derived join clause is processed correctly. Use an + -- outer join so that we can't form an EC. +@@ -5165,22 +5212,29 @@ + QUERY PLAN + ------------------------------------ + Nested Loop Left Join +- Join Filter: ((q.a + q.a) = r.a) +- -> Seq Scan on sj q +- Filter: (a IS NOT NULL) ++ Join Filter: ((p.a + q.a) = r.a) ++ -> Nested Loop ++ Join Filter: (p.a = q.a) ++ -> Seq Scan on sj p ++ -> Materialize ++ -> Seq Scan on sj q + -> Materialize + -> Seq Scan on sj r +-(6 rows) ++(9 rows) + + -- FIXME this constant false filter doesn't look good. Should we merge + -- equivalence classes? + explain (costs off) + select * from sj p, sj q where p.a = q.a and p.b = 1 and q.b = 2; +- QUERY PLAN +------------------------------------------------------ +- Seq Scan on sj q +- Filter: ((a IS NOT NULL) AND (b = 2) AND (b = 1)) +-(2 rows) ++ QUERY PLAN ++---------------------------- ++ Nested Loop ++ Join Filter: (p.a = q.a) ++ -> Seq Scan on sj p ++ Filter: (b = 1) ++ -> Seq Scan on sj q ++ Filter: (b = 2) ++(6 rows) + + -- Check that attr_needed is updated correctly after self-join removal. In this + -- test, the join of j1 with j2 is removed. k1.b is required at either j1 or j2. +@@ -5195,24 +5249,29 @@ + explain (costs off) select 1 from + (sk k1 join sk k2 on k1.a = k2.a) + join (sj j1 join sj j2 on j1.a = j2.a) on j1.b = k1.b; +- QUERY PLAN +------------------------------------------------------ ++ QUERY PLAN ++----------------------------------------------------------------- + Nested Loop +- Join Filter: (k1.b = j2.b) ++ Join Filter: (k1.b = j1.b) + -> Nested Loop + -> Index Scan using sk_a_idx on sk k1 + -> Index Only Scan using sk_a_idx on sk k2 + Index Cond: (a = k1.a) + -> Materialize +- -> Index Scan using sj_a_key on sj j2 +- Index Cond: (a IS NOT NULL) +-(9 rows) ++ -> Nested Loop ++ -> Index Scan using sj_a_key on sj j1 ++ -> Memoize ++ Cache Key: j1.a ++ Cache Mode: logical ++ -> Index Only Scan using sj_a_key on sj j2 ++ Index Cond: (a = j1.a) ++(14 rows) + + explain (costs off) select 1 from + (sk k1 join sk k2 on k1.a = k2.a) + join (sj j1 join sj j2 on j1.a = j2.a) on j2.b = k1.b; +- QUERY PLAN +------------------------------------------------------ ++ QUERY PLAN ++------------------------------------------------------------ + Nested Loop + Join Filter: (k1.b = j2.b) + -> Nested Loop +@@ -5220,9 +5279,14 @@ + -> Index Only Scan using sk_a_idx on sk k2 + Index Cond: (a = k1.a) + -> Materialize +- -> Index Scan using sj_a_key on sj j2 +- Index Cond: (a IS NOT NULL) +-(9 rows) ++ -> Nested Loop ++ -> Index Only Scan using sj_a_key on sj j1 ++ -> Memoize ++ Cache Key: j1.a ++ Cache Mode: logical ++ -> Index Scan using sj_a_key on sj j2 ++ Index Cond: (a = j1.a) ++(14 rows) + + reset join_collapse_limit; + reset enable_seqscan; +@@ -5230,12 +5294,18 @@ + CREATE TABLE emp1 ( id SERIAL PRIMARY KEY NOT NULL, code int); + explain (verbose, costs off) + SELECT * FROM emp1 e1, emp1 e2 WHERE e1.id = e2.id AND e2.code <> e1.code; +- QUERY PLAN +----------------------------------------------------------- +- Seq Scan on public.emp1 e2 +- Output: e2.id, e2.code, e2.id, e2.code +- Filter: ((e2.id IS NOT NULL) AND (e2.code <> e2.code)) +-(3 rows) ++ QUERY PLAN ++---------------------------------------------------- ++ Nested Loop ++ Output: e1.id, e1.code, e2.id, e2.code ++ Inner Unique: true ++ -> Seq Scan on public.emp1 e1 ++ Output: e1.id, e1.code ++ -> Index Scan using emp1_pkey on public.emp1 e2 ++ Output: e2.id, e2.code ++ Index Cond: (e2.id = e1.id) ++ Filter: (e2.code <> e1.code) ++(9 rows) + + -- We can remove the join even if we find the join can't duplicate rows and + -- the base quals of each side are different. In the following case we end up +@@ -5246,11 +5316,15 @@ + -- Both sides are unique, but base quals are different + explain (costs off) + select * from sl t1, sl t2 where t1.a = t2.a and t1.b = 1 and t2.b = 2; +- QUERY PLAN +------------------------------------------------------ +- Seq Scan on sl t2 +- Filter: ((a IS NOT NULL) AND (b = 2) AND (b = 1)) +-(2 rows) ++ QUERY PLAN ++------------------------------ ++ Nested Loop ++ Join Filter: (t1.a = t2.a) ++ -> Seq Scan on sl t1 ++ Filter: (b = 1) ++ -> Seq Scan on sl t2 ++ Filter: (b = 2) ++(6 rows) + + -- + ---- Only one side is unqiue 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 @@ -470,8 +1632,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; +@@ -1029,7 +1000,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 +1641,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 @@ +@@ -1049,9 +1020,8 @@ a ---- 7 @@ -567,48 +1729,431 @@ diff ../../../src/test/regress/expected/rowsecurity.out ../tmp_check/regress_out 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; +diff ../../../src/test/regress/expected/object_address.out ../tmp_check/regress_outdir/results/object_address.out +--- ../../../src/test/regress/expected/object_address.out CENSORED ++++ ../tmp_check/regress_outdir/results/object_address.out CENSORED +@@ -580,44 +580,6 @@ + AS descr + FROM objects + ORDER BY objects.classid, objects.objid, objects.objsubid; +-("(""default acl"",,,)")|("(""default acl"",,)")|NULL +-("(tablespace,,,)")|("(tablespace,,)")|NULL +-("(type,,,)")|("(type,,)")|NULL +-("(routine,,,)")|("(routine,,)")|NULL +-("(relation,,,)")|("(relation,,)")|NULL +-("(""table column"",,,)")|("(""table column"",,)")|NULL +-("(role,,,)")|("(role,,)")|NULL +-("(database,,,)")|("(database,,)")|NULL +-("(server,,,)")|("(server,,)")|NULL +-("(""user mapping"",,,)")|("(""user mapping"",,)")|NULL +-("(""foreign-data wrapper"",,,)")|("(""foreign-data wrapper"",,)")|NULL +-("(""access method"",,,)")|("(""access method"",,)")|NULL +-("(""operator of access method"",,,)")|("(""operator of access method"",,)")|NULL +-("(""function of access method"",,,)")|("(""function of access method"",,)")|NULL +-("(""default value"",,,)")|("(""default value"",,)")|NULL +-("(cast,,,)")|("(cast,,)")|NULL +-("(constraint,,,)")|("(constraint,,)")|NULL +-("(conversion,,,)")|("(conversion,,)")|NULL +-("(language,,,)")|("(language,,)")|NULL +-("(""large object"",,,)")|("(""large object"",,)")|NULL +-("(schema,,,)")|("(schema,,)")|NULL +-("(""operator class"",,,)")|("(""operator class"",,)")|NULL +-("(operator,,,)")|("(operator,,)")|NULL +-("(rule,,,)")|("(rule,,)")|NULL +-("(trigger,,,)")|("(trigger,,)")|NULL +-("(""operator family"",,,)")|("(""operator family"",,)")|NULL +-("(extension,,,)")|("(extension,,)")|NULL +-("(policy,,,)")|("(policy,,)")|NULL +-("(""statistics object"",,,)")|("(""statistics object"",,)")|NULL +-("(collation,,,)")|("(collation,,)")|NULL +-("(""event trigger"",,,)")|("(""event trigger"",,)")|NULL +-("(transform,,,)")|("(transform,,)")|NULL +-("(""text search dictionary"",,,)")|("(""text search dictionary"",,)")|NULL +-("(""text search parser"",,,)")|("(""text search parser"",,)")|NULL +-("(""text search configuration"",,,)")|("(""text search configuration"",,)")|NULL +-("(""text search template"",,,)")|("(""text search template"",,)")|NULL +-("(subscription,,,)")|("(subscription,,)")|NULL +-("(publication,,,)")|("(publication,,)")|NULL +-("(""publication relation"",,,)")|("(""publication relation"",,)")|NULL ++ERROR: unrecognized object class: 16512 + -- restore normal output mode + \a\t +diff ../../../src/test/regress/expected/atx2.out ../tmp_check/regress_outdir/results/atx2.out +--- ../../../src/test/regress/expected/atx2.out CENSORED ++++ ../tmp_check/regress_outdir/results/atx2.out CENSORED +@@ -287,362 +287,9 @@ + return 1; + end$$; + select atx_lo_test10(:my_loid); +- atx_lo_test10 +---------------- +- 1 +-(1 row) +- +-select lo_unlink(:my_loid); +- lo_unlink +------------ +- 1 +-(1 row) +- +--- put some initial data +-select lo_creat(-1) as my_loid \gset +-select lo_put( :my_loid, 0, 'lo test' ); +- lo_put +--------- +- +-(1 row) +- +--- This function should not fail +-select * from lo_test_func( :my_loid ); +- lo_test_func +--------------- +- 0 +-(1 row) +- +--- Read something +-select convert_from(data, 'UTF8') from pg_largeobject where loid = :my_loid; +- convert_from +------------------ +- My mega lo test +-(1 row) +- +--- 11 +-DO $body$ +-begin +- begin +- begin autonomous +- set datestyle = 'euro'; +- end; +- exception +- when others then +- raise notice 'exception %, %', SQLSTATE, SQLERRM; +- end; +-end; +-$body$ language plpgsql; +--- 12 +-create table if not exists atx_tt1(f1 int); +-create function count_tt1_v() returns int8 as 'select count(*) from atx_tt1' language sql volatile; +-create function count_tt1_s() returns int8 as 'select count(*) from atx_tt1' language sql stable; +-begin; +- begin autonomous; +- insert into atx_tt1 values(1); +- declare c1 cursor for select count_tt1_v(), count_tt1_s(); +- insert into atx_tt1 values(2); +- fetch all from c1; +- count_tt1_v | count_tt1_s +--------------+------------- +- 2 | 1 +-(1 row) +- +- rollback; +-rollback; +-begin; +- begin autonomous; +- insert into atx_tt1 values(1); +- declare c2 cursor with hold for select count_tt1_v(), count_tt1_s(); +- insert into atx_tt1 values(2); +- commit; +-commit; +-begin; +- begin autonomous; +- insert into atx_tt1 values(1); +- declare c1 cursor for select count_tt1_v(), count_tt1_s(); +- begin autonomous; +- fetch all from c1; +-ERROR: cursor "c1" does not exist +- rollback; +- rollback; +-rollback; +-drop function count_tt1_v(); +-drop function count_tt1_s(); +-drop table if exists atx_tt1; +-close c2; +--- 13 +-create table atx_13_t(i int); +-begin; +- begin autonomous; +- update atx_13_t set i = 1; +- rollback; +- begin autonomous; +- update atx_13_t set i = 2; +- rollback; +- drop table if exists atx_13_t; +- begin autonomous; +- update atx_13_t set i = 3 where i in (select i from atx_13_t); +-ERROR: lockmode RowExclusiveLock conflicts with lock AccessExclusiveLock of parent transaction, acquiring this lock in an autonomous transaction will lead to a sure deadlock +-LINE 1: update atx_13_t set i = 3 where i in (select i from atx_13_t... +- ^ +- rollback; +-commit; +--- 14 +-create or replace function atx_14_trigger_func() returns trigger as $body$ +-begin +- return null; +-end; +-$body$ language plpgsql; +-create table atx_14_test(a text, b text); +-create trigger atx_14_test_audit +-after insert on atx_14_test +-for each row execute procedure atx_14_trigger_func(); +-begin; +- insert into atx_14_test values (125); +- begin autonomous transaction; +- commit; +- insert into atx_14_test values (1); +-commit; +-drop table if exists atx_14_test; +-drop function atx_14_trigger_func(); +--- 15 +-create or replace function atx_15_dummy() returns text as $$ +-declare +- x text; +-begin +- x := 'one'; +- begin autonomous +- x := 'two'; +- end; +- return x; +-end; $$ language plpgsql; +-create table atx_15_test as select 1 as int, NULL as name; +-update atx_15_test set name = atx_15_dummy() returning *; +- int | name +------+------ +- 1 | two +-(1 row) +- +-drop table if exists atx_15_test; +-drop function if exists atx_15_dummy(); +--- 16 +-create table test(i int); +-begin; +- begin autonomous; +- insert into test values(1); +- declare c cursor for select * from test; +- begin autonomous; +- commit; +- rollback; +-rollback; +-drop table if exists test; +--- 17 +-create table test(f1 int); +-begin; +- begin autonomous; +- insert into test values(1); +- declare c1 cursor for select * from test; +- begin autonomous; +- fetch all from c1; +-ERROR: cursor "c1" does not exist +- rollback; +- rollback; +-rollback; +-drop table if exists test; +--- 19 +-create or replace function error_func() returns int as $body$ +-begin +- return 0/0; +-end; +-$body$ language plpgsql; +-DO $body$ +-begin +- begin +- begin autonomous +- select error_func(); +- end; +- exception +- when others then +- raise notice 'exception %, %', SQLSTATE, SQLERRM; +- end; +-end; +-$body$ language plpgsql; +-NOTICE: exception 22012, division by zero +-drop function if exists error_func(); +--- 21 +-CREATE OR REPLACE FUNCTION error_function() +- RETURNS integer AS +-$BODY$ +-begin +- begin autonomous +- SELECT 0/0; +- end; +- return 1; +-exception +- when others then +- raise notice 'other exception %, %', SQLSTATE, SQLERRM; +-end; +-$BODY$ LANGUAGE plpgsql; +-create table if not exists atx_tt2(f1 int); +-begin; +- begin autonomous; +- 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 @@ +-commit; +-drop function if exists error_function(); +-drop table if exists atx_tt2; +--- 22 +-create or replace function if_modified_func_22() returns trigger as $body$ +-declare +- v_new_data text; +-begin +- v_new_data := row(new.*); +- begin autonomous +- return new; +- end; +-end; +-$body$ language plpgsql; +-create table atx_test_22(a text, b text); +-create trigger atx_test_22_audit +-after insert on atx_test_22 +-for each row execute procedure if_modified_func_22(); +-begin; +- insert into atx_test_22 values (1); +- begin autonomous transaction; +- commit; +- insert into atx_test_22 values (2); +-commit; +-drop table if exists atx_test_22; +-drop function if exists if_modified_func_22(); +--- 23 +-CREATE OR REPLACE FUNCTION error_function3() +- RETURNS integer AS +-$BODY$ +-begin +- begin autonomous +- SELECT 0/0; +- end; +- return 1; +-exception +- when others then +- raise notice 'other exception %, %', SQLSTATE, SQLERRM; +-end; +-$BODY$ LANGUAGE plpgsql; +-begin; +- begin autonomous; +- declare c2 cursor with hold for select error_function3(); +- commit; +-NOTICE: other exception 22012, division by zero +-ERROR: control reached end of function without RETURN +-CONTEXT: PL/pgSQL function error_function3() +-commit; +-drop function if exists error_function3(); +-close c2; +-ERROR: cursor "c2" does not exist +--- 24 +-CREATE OR REPLACE FUNCTION error_function3() +- RETURNS integer AS +-$BODY$ +-begin +- begin autonomous +- SELECT 0/0; +- end; +- return 1; +-exception +- when others then +- raise notice 'other exception %, %', SQLSTATE, SQLERRM; +- return 0; +-end; +-$BODY$ LANGUAGE plpgsql; +-begin; +- begin autonomous; +- declare c3 cursor with hold for select error_function3(); +- commit; +-NOTICE: other exception 22012, division by zero +-commit; +-drop function if exists error_function3(); +-close c3; +--- 25 +-select count(*) * 0 as dummy_res from ( select pg_terminate_backend(pid) from pg_stat_activity where datname = 'regression_atx_test_database' ) as foo; +- dummy_res +------------ +- 0 +-(1 row) +- +-SET client_min_messages TO 'warning'; +-drop database if exists regression_atx_test_database; +-RESET client_min_messages; +-create database regression_atx_test_database; +-ALTER DATABASE "regression_atx_test_database" SET lc_messages TO 'C'; +-\c regression_atx_test_database +-create table atx_test as select 1 as id; +-begin; +- begin autonomous; +- create table tmp1 as select id from atx_test; +- delete from atx_test where id in ( select id from unknown ); +-ERROR: relation "unknown" does not exist +-LINE 1: delete from atx_test where id in ( select id from unknown ); +- ^ +- rollback; +- begin autonomous; +- drop table atx_test; +-\c regression +--- PGPRO-5052 +-BEGIN TRANSACTION; BEGIN AUTONOMOUS TRANSACTION; +-CREATE FUNCTION atx_srf_test_func() RETURNS setof text AS +-$$ SELECT 'foo'::varchar $$ +-LANGUAGE SQL; +-SELECT atx_srf_test_func(); +- atx_srf_test_func +-------------------- +- foo +-(1 row) +- +-COMMIT AUTONOMOUS; COMMIT; +-DROP FUNCTION atx_srf_test_func(); +--- PGPRO-5860 +-create table mmm5860(i int); +-create or replace function crash_func5860() returns int language plpgsql as $$ +-declare +-begin +- create table if not exists mmm5860(i int); +- begin autonomous +- begin +- create table if not exists mmm5860(i int); +- exception +- when others then +- raise notice 'other exception %, %', SQLSTATE, SQLERRM; +- end; +- end; +- return 1; +-end$$; +-select * from crash_func5860(); +-NOTICE: relation "mmm5860" already exists, skipping +-NOTICE: relation "mmm5860" already exists, skipping +- crash_func5860 +----------------- +- 1 +-(1 row) +- +-drop function crash_func5860(); +-drop table mmm5860; +--- PGPRO-6207 +-BEGIN; +-COMMIT AUTONOMOUS; +-WARNING: there is no autonomous transaction in progress +-BEGIN; +-ABORT AUTONOMOUS; +-WARNING: there is no autonomous transaction in progress +-BEGIN; +- SAVEPOINT sp; +-COMMIT AUTONOMOUS; +-WARNING: there is no autonomous transaction in progress +-BEGIN; +- SAVEPOINT sp; +-ABORT AUTONOMOUS; +-WARNING: there is no autonomous transaction in progress ++FATAL: RollbackAndReleaseCurrentSubTransaction: unexpected state DEFAULT ++CONTEXT: PL/pgSQL function atx_lo_test10(oid) line 9 during exception cleanup ++server closed the connection unexpectedly ++ This probably means the server terminated abnormally ++ before or while processing the request. ++connection to server was lost +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 +2165,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 @@ +@@ -383,50 +380,38 @@ INSERT INTO abc VALUES (1); INSERT INTO abc VALUES (2); COMMIT AND CHAIN; -- TBLOCK_END @@ -683,7 +2225,7 @@ diff ../../../src/test/regress/expected/atx9.out ../tmp_check/regress_outdir/res COMMIT; ROLLBACK; BEGIN; -@@ -144,24 +132,13 @@ +@@ -498,24 +483,13 @@ SAVEPOINT x; COMMIT AND CHAIN; -- TBLOCK_SUBCOMMIT @@ -712,7 +2254,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 @@ +@@ -586,17 +560,14 @@ COMMIT; -- not allowed outside a transaction block COMMIT AUTONOMOUS AND CHAIN; -- error @@ -732,6 +2274,18 @@ diff ../../../src/test/regress/expected/atx9.out ../tmp_check/regress_outdir/res RESET default_transaction_read_only; DROP TABLE abc; +diff ../../../src/test/regress/expected/sysviews.out ../tmp_check/regress_outdir/results/sysviews.out +--- ../../../src/test/regress/expected/sysviews.out CENSORED ++++ ../tmp_check/regress_outdir/results/sysviews.out CENSORED +@@ -119,7 +119,7 @@ + enable_partition_pruning | on + enable_partitionwise_aggregate | off + enable_partitionwise_join | off +- enable_self_join_removal | on ++ enable_self_join_removal | off + enable_seqscan | on + enable_sort | on + enable_tidscan | on diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/results/rules.out --- ../../../src/test/regress/expected/rules.out CENSORED +++ ../tmp_check/regress_outdir/results/rules.out CENSORED @@ -751,10 +2305,10 @@ diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/re 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); +@@ -1443,19 +1452,30 @@ + 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, @@ -792,7 +2346,7 @@ diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/re 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 @@ +@@ -1651,7 +1671,7 @@ l.provider, l.label FROM (pg_seclabel l @@ -801,7 +2355,7 @@ diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/re WHERE (l.objsubid = 0) UNION ALL SELECT l.objoid, -@@ -1671,7 +1691,7 @@ +@@ -1663,7 +1683,7 @@ l.provider, l.label FROM (pg_shseclabel l @@ -810,7 +2364,7 @@ diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/re UNION ALL SELECT l.objoid, l.classoid, -@@ -2066,7 +2086,7 @@ +@@ -2099,7 +2119,7 @@ st.last_msg_receipt_time, st.latest_end_lsn, st.latest_end_time @@ -819,15 +2373,17 @@ diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/re 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)))); +@@ -2524,6 +2544,19 @@ + LEFT JOIN pg_namespace sn ON ((sn.oid = s.stxnamespace))) + JOIN LATERAL ( SELECT unnest(pg_get_statisticsobjdef_expressions(s.oid)) AS expr, + unnest(sd.stxdexpr) AS a) stat ON ((stat.expr IS NOT NULL))); +pg_subscription| SELECT _pg_subscription.oid, + _pg_subscription.subdbid, + _pg_subscription.subname, + _pg_subscription.subowner, + _pg_subscription.subenabled, ++ _pg_subscription.subbinary, ++ _pg_subscription.substream, + _pg_subscription.subconninfo, + _pg_subscription.subslotname, + _pg_subscription.subsynccommit, @@ -837,6 +2393,50 @@ diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/re 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 +@@ -2813,36 +2813,14 @@ + CREATE VIEW view_heap_psql AS SELECT f1 from tbl_heap_psql; + CREATE MATERIALIZED VIEW mat_view_heap_psql USING heap_psql AS SELECT f1 from tbl_heap_psql; + \d+ tbl_heap_psql +- Table "tableam_display.tbl_heap_psql" +- Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +---------+----------------+-----------+----------+---------+----------+--------------+------------- +- f1 | integer | | | | plain | | +- f2 | character(100) | | | | extended | | +- ++ERROR: permission denied for view pg_publication + \d+ tbl_heap +- Table "tableam_display.tbl_heap" +- Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +---------+----------------+-----------+----------+---------+----------+--------------+------------- +- f1 | integer | | | | plain | | +- f2 | character(100) | | | | extended | | +- ++ERROR: permission denied for view pg_publication + \set HIDE_TABLEAM off + \d+ tbl_heap_psql +- Table "tableam_display.tbl_heap_psql" +- Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +---------+----------------+-----------+----------+---------+----------+--------------+------------- +- f1 | integer | | | | plain | | +- f2 | character(100) | | | | extended | | +-Access method: heap_psql +- ++ERROR: permission denied for view pg_publication + \d+ tbl_heap +- Table "tableam_display.tbl_heap" +- Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +---------+----------------+-----------+----------+---------+----------+--------------+------------- +- f1 | integer | | | | plain | | +- f2 | character(100) | | | | extended | | +-Access method: heap +- ++ERROR: permission denied for view pg_publication + -- AM is displayed for tables, indexes and materialized views. + \d+ + List of relations 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 @@ -869,6 +2469,104 @@ diff ../../../src/test/regress/expected/subscription.out ../tmp_check/regress_ou (1 row) -- fail - name already exists +diff ../../../src/test/regress/expected/equivclass.out ../tmp_check/regress_outdir/results/equivclass.out +--- ../../../src/test/regress/expected/equivclass.out CENSORED ++++ ../tmp_check/regress_outdir/results/equivclass.out CENSORED +@@ -438,15 +438,17 @@ + explain (costs off) + select * from ec0 m join ec0 n on m.ff = n.ff + join ec1 p on m.ff + n.ff = p.f1; +- QUERY PLAN +----------------------------------------- ++ QUERY PLAN ++------------------------------------------------ + Nested Loop +- Join Filter: ((n.ff + n.ff) = p.f1) +- -> Seq Scan on ec1 p ++ Join Filter: ((m.ff + n.ff) = p.f1) ++ -> Nested Loop ++ -> Seq Scan on ec0 m ++ -> Index Scan using ec0_pkey on ec0 n ++ Index Cond: (ff = m.ff) + -> Materialize +- -> Seq Scan on ec0 n +- Filter: (ff IS NOT NULL) +-(6 rows) ++ -> Seq Scan on ec1 p ++(8 rows) + + explain (costs off) + select * from ec0 m join ec0 n on m.ff = n.ff +@@ -454,12 +456,14 @@ + QUERY PLAN + --------------------------------------------------------------- + Nested Loop +- Join Filter: ((p.f1)::bigint = ((n.ff + n.ff))::int8alias1) +- -> Seq Scan on ec1 p ++ Join Filter: ((p.f1)::bigint = ((m.ff + n.ff))::int8alias1) ++ -> Nested Loop ++ -> Seq Scan on ec0 m ++ -> Index Scan using ec0_pkey on ec0 n ++ Index Cond: (ff = m.ff) + -> Materialize +- -> Seq Scan on ec0 n +- Filter: (ff IS NOT NULL) +-(6 rows) ++ -> Seq Scan on ec1 p ++(8 rows) + + reset enable_mergejoin; + -- this could be converted, but isn't at present +diff ../../../src/test/regress/expected/copy2.out ../tmp_check/regress_outdir/results/copy2.out +--- ../../../src/test/regress/expected/copy2.out CENSORED ++++ ../tmp_check/regress_outdir/results/copy2.out CENSORED +@@ -359,11 +359,12 @@ + (2 rows) + + COMMIT; ++ERROR: [MTM] failed to prepare transaction at peer node + SELECT * FROM vistest; + a + ---- +- d1 +- e ++ a0 ++ b + (2 rows) + + BEGIN; +@@ -387,11 +388,12 @@ + (2 rows) + + COMMIT; ++ERROR: [MTM] failed to prepare transaction at peer node + SELECT * FROM vistest; + a + ---- +- d2 +- e ++ a0 ++ b + (2 rows) + + BEGIN; +@@ -448,12 +450,11 @@ + (2 rows) + + COMMIT; ++ERROR: [MTM] failed to prepare transaction at peer node + SELECT * FROM vistest; +- a +----- +- d4 +- e +-(2 rows) ++ a ++--- ++(0 rows) + + -- Test FORCE_NOT_NULL and FORCE_NULL options + CREATE TEMP TABLE forcetest ( 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 @@ -955,3 +2653,52 @@ diff ../../../src/test/regress/expected/indexing.out ../tmp_check/regress_outdir drop table idxpart_temp; -- ALTER INDEX .. ATTACH, error cases +diff ../../../src/test/regress/expected/oidjoins.out ../tmp_check/regress_outdir/results/oidjoins.out +--- ../../../src/test/regress/expected/oidjoins.out CENSORED ++++ ../tmp_check/regress_outdir/results/oidjoins.out CENSORED +@@ -257,10 +257,10 @@ + NOTICE: checking pg_transform {trftosql} => pg_proc {oid} + NOTICE: checking pg_sequence {seqrelid} => pg_class {oid} + NOTICE: checking pg_sequence {seqtypid} => pg_type {oid} +-NOTICE: checking pg_publication {pubowner} => pg_authid {oid} +-NOTICE: checking pg_publication_rel {prpubid} => pg_publication {oid} ++NOTICE: checking _pg_publication {pubowner} => pg_authid {oid} ++NOTICE: checking pg_publication_rel {prpubid} => _pg_publication {oid} + NOTICE: checking pg_publication_rel {prrelid} => pg_class {oid} +-NOTICE: checking pg_subscription {subdbid} => pg_database {oid} +-NOTICE: checking pg_subscription {subowner} => pg_authid {oid} +-NOTICE: checking pg_subscription_rel {srsubid} => pg_subscription {oid} ++NOTICE: checking _pg_subscription {subdbid} => pg_database {oid} ++NOTICE: checking _pg_subscription {subowner} => pg_authid {oid} ++NOTICE: checking pg_subscription_rel {srsubid} => _pg_subscription {oid} + NOTICE: checking pg_subscription_rel {srrelid} => pg_class {oid} +diff ../../../src/test/regress/expected/stats.out ../tmp_check/regress_outdir/results/stats.out +--- ../../../src/test/regress/expected/stats.out CENSORED ++++ ../tmp_check/regress_outdir/results/stats.out CENSORED +@@ -99,6 +99,7 @@ + TRUNCATE trunc_stats_test1; + INSERT INTO trunc_stats_test1 DEFAULT VALUES; + COMMIT; ++ERROR: [MTM] failed to prepare transaction at peer node + -- use a savepoint: 1 insert, 1 live + BEGIN; + INSERT INTO trunc_stats_test2 DEFAULT VALUES; +@@ -109,6 +110,7 @@ + INSERT INTO trunc_stats_test2 DEFAULT VALUES; + RELEASE SAVEPOINT p1; + COMMIT; ++ERROR: [MTM] failed to prepare transaction at peer node + -- rollback a savepoint: this should count 4 inserts and have 2 + -- live tuples after commit (and 2 dead ones due to aborted subxact) + BEGIN; +@@ -166,8 +168,8 @@ + relname | n_tup_ins | n_tup_upd | n_tup_del | n_live_tup | n_dead_tup + -------------------+-----------+-----------+-----------+------------+------------ + trunc_stats_test | 3 | 0 | 0 | 0 | 0 +- trunc_stats_test1 | 4 | 2 | 1 | 1 | 0 +- trunc_stats_test2 | 1 | 0 | 0 | 1 | 0 ++ trunc_stats_test1 | 3 | 4 | 1 | 2 | 5 ++ trunc_stats_test2 | 2 | 0 | 0 | 0 | 2 + trunc_stats_test3 | 4 | 0 | 0 | 2 | 2 + trunc_stats_test4 | 2 | 0 | 0 | 0 | 2 + (5 rows) diff --git a/src/ddl.c b/src/ddl.c index 49ccc2d0c4..e0aec3a4e0 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); @@ -359,7 +361,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 @@ -661,7 +663,7 @@ MtmFinishDDLCommand() 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 +678,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 +693,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 +720,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 +841,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) @@ -1186,17 +1184,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) @@ -1311,11 +1305,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. @@ -1709,7 +1704,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 +1719,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..5f2c0f0458 100644 --- a/src/dmq.c +++ b/src/dmq.c @@ -353,7 +353,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); } @@ -1443,7 +1443,7 @@ 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; + MyProc->xmin = InvalidTransactionId; for (;;) { diff --git a/src/global_tx.c b/src/global_tx.c index fff4921515..4e1a940982 100644 --- a/src/global_tx.c +++ b/src/global_tx.c @@ -185,7 +185,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..45a88550d4 100644 --- a/src/include/compat.h +++ b/src/include/compat.h @@ -1,12 +1,7 @@ #ifndef MTMCOMPAT_H #define MTMCOMPAT_H -/* EE pooler gets rid of static variable */ -#ifdef PGPRO_EE -#define FeBeWaitSetCompat() (MyProcPort->pqcomm_waitset) -#else #define FeBeWaitSetCompat() (FeBeWaitSet) -#endif #ifdef PGPRO_EE /* atx */ #define BeginTransactionBlockCompat() (BeginTransactionBlock(false, NIL)) @@ -16,11 +11,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/pglogical_apply.c b/src/pglogical_apply.c index 566d5acb97..f359e51d36 100644 --- a/src/pglogical_apply.c +++ b/src/pglogical_apply.c @@ -166,24 +166,27 @@ create_rel_estate(Relation rel) EState *estate; ResultRelInfo *resultRelInfo; RangeTblEntry *rte; + List *rangeTable; estate = CreateExecutorState(); 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); rte->relkind = rel->rd_rel->relkind; rte->rellockmode = AccessShareLock; + rangeTable = list_make1(rte); ExecInitRangeTable(estate, list_make1(rte)); + ExecInitRangeTable(estate, rangeTable); + ExecInitResultRelation(estate, resultRelInfo, 1); + + estate->es_result_relation_info = resultRelInfo; + estate->es_output_cid = GetCurrentCommandId(true); + /* Prepare to catch AFTER triggers. */ AfterTriggerBeginQuery(); @@ -1238,9 +1241,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 +1271,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 +1372,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 +1382,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 +1450,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_output.c b/src/pglogical_output.c index 95bfa00540..b4efe4231a 100644 --- a/src/pglogical_output.c +++ b/src/pglogical_output.c @@ -70,12 +70,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 +137,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 +487,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 +551,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/state.c b/src/state.c index 01b502b775..34496abb3a 100644 --- a/src/state.c +++ b/src/state.c @@ -3286,7 +3286,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 +3729,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 +3779,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 +3878,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_by_name(logical_slot, false); /* * Delete logical slot. It is aquired by walsender, so call with nowait = @@ -4414,7 +4418,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; From 59786baa4cdd678c3b8c6c0a1a8432b865f4a8f6 Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Tue, 31 May 2022 10:12:00 +0500 Subject: [PATCH 02/32] Code compatibility with Postgres 15 --- Cluster.pm | 158 ++++++++++++++++++++++++++++++++++-------- run.pl | 43 +++++++++--- src/dmq.c | 6 +- src/multimaster.c | 12 +++- src/pglogical_proto.c | 10 +-- src/state.c | 11 ++- src/syncpoint.c | 4 +- 7 files changed, 190 insertions(+), 54 deletions(-) diff --git a/Cluster.pm b/Cluster.pm index 5b68eb23c1..0a2ee8999a 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) { @@ -340,9 +432,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/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/dmq.c b/src/dmq.c index 5f2c0f0458..f328f8de50 100644 --- a/src/dmq.c +++ b/src/dmq.c @@ -1119,7 +1119,7 @@ dmq_handle_message(StringInfo msg, DmqReceiverSlot *my_slot, } else { - res = shm_mq_send(mq_handles[sub.procno], body_len, body, false); + res = shm_mq_send(mq_handles[sub.procno], body_len, body, false, true); if (res == SHM_MQ_DETACHED) mtm_log(COMMERROR, "[DMQ] queue %d is detached, dropping message (stream=%s)", sub.procno, stream_name); @@ -1623,7 +1623,7 @@ dmq_push(DmqDestinationId dest_id, char *stream_name, char *msg) buf.len, buf.len, buf.data); /* XXX: use sendv instead */ - res = shm_mq_send(dmq_local.mq_outh, buf.len, buf.data, false); + res = shm_mq_send(dmq_local.mq_outh, buf.len, buf.data, false, true); pfree(buf.data); if (res != SHM_MQ_SUCCESS) mtm_log(ERROR, "[DMQ] dmq_push: can't send to queue"); @@ -1648,7 +1648,7 @@ dmq_push_buffer(DmqDestinationId dest_id, char *stream_name, const void *payload buf.len, buf.len, buf.data); /* XXX: use sendv instead */ - res = shm_mq_send(dmq_local.mq_outh, buf.len, buf.data, false); + res = shm_mq_send(dmq_local.mq_outh, buf.len, buf.data, false, true); 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/multimaster.c b/src/multimaster.c index 9165492afc..2d52039f64 100644 --- a/src/multimaster.c +++ b/src/multimaster.c @@ -742,10 +742,12 @@ NULL); DetectGlobalDeadLock = MtmDetectGlobalDeadLock; +#if 0 #ifdef PGPRO_EE SuspendTransactionHook = MtmSuspendTransaction; ResumeTransactionHook = MtmResumeTransaction; #endif +#endif } /* @@ -1095,6 +1097,7 @@ mtm_after_node_create(PG_FUNCTION_ARGS) bool conninfo_isnull; int n_nodes; int rc; + ParseState *pstate; Assert(CALLED_AS_TRIGGER(fcinfo)); Assert(TRIGGER_FIRED_FOR_ROW(trigdata->tg_event)); @@ -1135,6 +1138,8 @@ mtm_after_node_create(PG_FUNCTION_ARGS) mtm_log(NodeMgmt, "mtm_after_node_create %d", node_id); + pstate = make_parsestate(NULL); + if (is_self) { /* @@ -1143,11 +1148,11 @@ mtm_after_node_create(PG_FUNCTION_ARGS) */ pub_stmt->pubname = MULTIMASTER_NAME; pub_stmt->for_all_tables = false; - pub_stmt->tables = NIL; + pub_stmt->pubobjects = NIL; pub_stmt->options = list_make1( makeDefElem("publish", (Node *) makeString(pstrdup("insert, truncate")), -1) ); - CreatePublication(pub_stmt); + CreatePublication(pstate, pub_stmt); /* liftoff */ MtmMonitorStart(MyDatabaseId, GetUserId()); @@ -1186,7 +1191,7 @@ mtm_after_node_create(PG_FUNCTION_ARGS) client_min_messages = ERROR; log_min_messages = ERROR; - CreateSubscription(cs_stmt, true); + CreateSubscription(pstate, cs_stmt, true); /* restore log_level's */ client_min_messages = saved_client_min_messages; @@ -1204,6 +1209,7 @@ mtm_after_node_create(PG_FUNCTION_ARGS) origin_name = psprintf(MULTIMASTER_SLOT_PATTERN, node_id); replorigin_create(origin_name); } + free_parsestate(pstate); PG_RETURN_VOID(); } diff --git a/src/pglogical_proto.c b/src/pglogical_proto.c index 1c1367fdd4..93fe60516a 100644 --- a/src/pglogical_proto.c +++ b/src/pglogical_proto.c @@ -468,7 +468,7 @@ pglogical_write_prepare(StringInfo out, PGLogicalOutputData *data, /* send fixed fields */ pq_sendint64(out, lsn); pq_sendint64(out, txn->end_lsn); - pq_sendint64(out, txn->commit_time); + pq_sendint64(out, txn->xact_time.commit_time); send_node_id(out, txn, hooks_data); pq_sendint64(out, txn->origin_lsn); @@ -499,7 +499,7 @@ pglogical_write_commit_prepared(StringInfo out, PGLogicalOutputData *data, /* send fixed fields */ pq_sendint64(out, lsn); pq_sendint64(out, txn->end_lsn); - pq_sendint64(out, txn->commit_time); + pq_sendint64(out, txn->xact_time.commit_time); send_node_id(out, txn, hooks_data); pq_sendint64(out, txn->origin_lsn); @@ -532,7 +532,7 @@ pglogical_write_abort_prepared(StringInfo out, PGLogicalOutputData *data, /* send fixed fields */ pq_sendint64(out, lsn); pq_sendint64(out, txn->end_lsn); - pq_sendint64(out, txn->commit_time); + pq_sendint64(out, txn->xact_time.commit_time); send_node_id(out, txn, hooks_data); pq_sendint64(out, txn->origin_lsn); @@ -560,7 +560,7 @@ pglogical_write_commit(StringInfo out, PGLogicalOutputData *data, /* send fixed fields */ pq_sendint64(out, lsn); pq_sendint64(out, txn->end_lsn); - pq_sendint64(out, txn->commit_time); + pq_sendint64(out, txn->xact_time.commit_time); send_node_id(out, txn, hooks_data); pq_sendint64(out, txn->origin_lsn); @@ -583,7 +583,7 @@ pglogical_write_abort(StringInfo out, PGLogicalOutputData *data, /* send fixed fields */ pq_sendint64(out, lsn); pq_sendint64(out, txn->end_lsn); - pq_sendint64(out, txn->commit_time); + pq_sendint64(out, txn->xact_time.commit_time); send_node_id(out, txn, hooks_data); pq_sendint64(out, txn->origin_lsn); diff --git a/src/state.c b/src/state.c index 34496abb3a..6d8e9e331f 100644 --- a/src/state.c +++ b/src/state.c @@ -12,6 +12,7 @@ #include #include +#include "common/pg_prng.h" #include "access/twophase.h" #include "access/xlogutils.h" #include "access/xlog_internal.h" @@ -1677,7 +1678,7 @@ CampaignerMain(Datum main_arg) MemoryContext campaigner_ctx = AllocSetContextCreate(TopMemoryContext, "CampaignerContext", ALLOCSET_DEFAULT_SIZES); - static unsigned short drandom_seed[3] = {0, 0, 0}; + static pg_prng_state drandom_seed = {0, 0}; TimestampTz last_campaign_at = 0; int rc = WL_TIMEOUT; @@ -1719,9 +1720,7 @@ CampaignerMain(Datum main_arg) /* Mix the PID with the most predictable bits of the timestamp */ iseed = (uint64) now ^ ((uint64) MyProcPid << 32); - drandom_seed[0] = (unsigned short) iseed; - drandom_seed[1] = (unsigned short) (iseed >> 16); - drandom_seed[2] = (unsigned short) (iseed >> 32); + pg_prng_seed(&drandom_seed, iseed); } /* @@ -1803,7 +1802,7 @@ CampaignerMain(Datum main_arg) */ rc = WaitLatch(MyLatch, WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, - campaign_retry_interval * pg_erand48(drandom_seed), + campaign_retry_interval * pg_prng_double(&drandom_seed), PG_WAIT_EXTENSION); if (rc & WL_LATCH_SET) @@ -4240,7 +4239,7 @@ GetLoggedPreparedXactState(HTAB *txset) XLogRecPtr start_lsn; XLogRecPtr lsn; TimeLineID timeline; - XLogRecPtr end_wal_lsn = GetFlushRecPtr(); + XLogRecPtr end_wal_lsn = GetFlushRecPtr(NULL); XLogRecPtr end_lsn = end_wal_lsn; int n_trans = hash_get_num_entries(txset); diff --git a/src/syncpoint.c b/src/syncpoint.c index a70ffc36e9..abde143ef3 100644 --- a/src/syncpoint.c +++ b/src/syncpoint.c @@ -477,7 +477,7 @@ 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()); - current_last_lsn = GetFlushRecPtr(); + current_last_lsn = GetFlushRecPtr(NULL); Assert(current_last_lsn != InvalidXLogRecPtr); @@ -490,7 +490,7 @@ RecoveryFilterLoad(int filter_node_id, Syncpoint *spvector, MtmConfig *mtm_cfg) } /* create hash */ - estimate_size = (GetFlushRecPtr() - start_lsn) / 100; + estimate_size = (GetFlushRecPtr(NULL) - start_lsn) / 100; estimate_size = Min(Max(estimate_size, 1000), 100000); MemSet(&hash_ctl, 0, sizeof(hash_ctl)); hash_ctl.keysize = hash_ctl.entrysize = sizeof(FilterEntry); From b6fcf8cc28cdf45fa08d6875a89d4d641d634072 Mon Sep 17 00:00:00 2001 From: Mikhail Rutman Date: Wed, 27 Apr 2022 16:25:01 +0700 Subject: [PATCH 03/32] fix multimaster build due to connpool changes --- src/include/compat.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/include/compat.h b/src/include/compat.h index 45a88550d4..dbf96c510f 100644 --- a/src/include/compat.h +++ b/src/include/compat.h @@ -1,7 +1,12 @@ #ifndef MTMCOMPAT_H #define MTMCOMPAT_H +/* EE pooler gets rid of static variable */ +#ifdef PGPRO_EE +#define FeBeWaitSetCompat() (MyProcPort->pqcomm_waitset) +#else #define FeBeWaitSetCompat() (FeBeWaitSet) +#endif #ifdef PGPRO_EE /* atx */ #define BeginTransactionBlockCompat() (BeginTransactionBlock(false, NIL)) From ddc54d42131daf662138da658b9db11f16252ff1 Mon Sep 17 00:00:00 2001 From: Koval Dmitry Date: Tue, 30 Nov 2021 22:34:48 +0300 Subject: [PATCH 04/32] Fixed processing of error for DDL-queries in PgPlSQL block Tags: atx, multimaster --- src/commit.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/commit.c b/src/commit.c index 0018c0b467..877d64215a 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,7 @@ MtmTwoPhaseCommit(void) } PG_CATCH(); { - mtm_commit_cleanup(0, Int32GetDatum(0)); + mtm_commit_cleanup(0, Int32GetDatum(atxLevel)); PG_RE_THROW(); } From ef470aedb722f57b9d7d3e83a61e62a246147b53 Mon Sep 17 00:00:00 2001 From: Mikhail Rutman Date: Tue, 31 May 2022 15:29:37 +0700 Subject: [PATCH 05/32] remove 'enable_self_join_removal=off' from Cluster.pm Tags: Multimaster --- Cluster.pm | 1 - 1 file changed, 1 deletion(-) diff --git a/Cluster.pm b/Cluster.pm index 5b68eb23c1..ea7860f695 100644 --- a/Cluster.pm +++ b/Cluster.pm @@ -141,7 +141,6 @@ sub init { $node->init(allows_streaming => 'logical'); $node->append_conf('postgresql.conf', qq{ - enable_self_join_removal = off max_connections = 50 log_line_prefix = '%m [%p] [xid%x] %i ' log_statement = all From 40251489ffd714ec5d2dbb086f3be8b65b18f72b Mon Sep 17 00:00:00 2001 From: Mikhail Rutman Date: Tue, 31 May 2022 17:10:45 +0700 Subject: [PATCH 06/32] fix EState initialization Tags: Multimaster --- src/pglogical_apply.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/pglogical_apply.c b/src/pglogical_apply.c index f359e51d36..14bcf8d8f6 100644 --- a/src/pglogical_apply.c +++ b/src/pglogical_apply.c @@ -166,7 +166,6 @@ create_rel_estate(Relation rel) EState *estate; ResultRelInfo *resultRelInfo; RangeTblEntry *rte; - List *rangeTable; estate = CreateExecutorState(); @@ -178,12 +177,8 @@ create_rel_estate(Relation rel) rte->relid = RelationGetRelid(rel); rte->relkind = rel->rd_rel->relkind; rte->rellockmode = AccessShareLock; - rangeTable = list_make1(rte); ExecInitRangeTable(estate, list_make1(rte)); - ExecInitRangeTable(estate, rangeTable); - ExecInitResultRelation(estate, resultRelInfo, 1); - estate->es_result_relation_info = resultRelInfo; estate->es_output_cid = GetCurrentCommandId(true); From 8dd4cd09f87e32119102b6c7d00794ba978630c3 Mon Sep 17 00:00:00 2001 From: Mikhail Rutman Date: Tue, 31 May 2022 17:11:34 +0700 Subject: [PATCH 07/32] fix test 001_regress - removed test atx0 from regression; - removed the replacing of tables pg_publication and pg_subscription with views, because some regression tests (object_address.sql) failed. - add removing multimaster output lines from regression.diff by pattern 'mtm_sub_'. These lines contain floating port numbers, which prevents the comparison of diff files. - update regression_ee.diff Tags: Multimaster --- expected/regression_ee.diff | 2169 +++++------------------------------ t/001_regress.pl | 6 +- 2 files changed, 274 insertions(+), 1901 deletions(-) diff --git a/expected/regression_ee.diff b/expected/regression_ee.diff index 24c5d720fb..c37becee73 100644 --- a/expected/regression_ee.diff +++ b/expected/regression_ee.diff @@ -1,17 +1,3 @@ -diff ../../../src/test/regress/expected/type_sanity.out ../tmp_check/regress_outdir/results/type_sanity.out ---- ../../../src/test/regress/expected/type_sanity.out CENSORED -+++ ../tmp_check/regress_outdir/results/type_sanity.out CENSORED -@@ -77,7 +77,9 @@ - 5017 | pg_mcv_list - 13374 | abstime - 13375 | reltime --(8 rows) -+ 16514 | pg_publication -+ 16518 | pg_subscription -+(10 rows) - - -- Make sure typarray points to a "true" array type of our own base - SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype, 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 @@ -43,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 -@@ -1371,31 +1371,33 @@ +@@ -1398,31 +1398,33 @@ CREATE TABLE concur_heap (f1 text, f2 text); -- empty table CREATE INDEX CONCURRENTLY concur_index1 ON concur_heap(f2,f1); @@ -84,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. -@@ -1407,7 +1409,9 @@ +@@ -1434,7 +1436,9 @@ END; $$; CREATE INDEX CONCURRENTLY concur_index8 ON concur_heap (f1) WHERE predicate_stable(); @@ -94,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; -@@ -1416,8 +1420,6 @@ +@@ -1443,8 +1447,6 @@ -- Failed builds are left invalid by VACUUM FULL, fixed by REINDEX VACUUM FULL concur_heap; REINDEX TABLE concur_heap; @@ -103,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 -@@ -1427,12 +1429,6 @@ +@@ -1454,12 +1456,6 @@ f1 | text | | | f2 | text | | | Indexes: @@ -116,7 +102,7 @@ diff ../../../src/test/regress/expected/create_index.out ../tmp_check/regress_ou "std_index" btree (f2) REINDEX TABLE concur_heap; -@@ -1443,12 +1439,6 @@ +@@ -1470,12 +1466,6 @@ f1 | text | | | f2 | text | | | Indexes: @@ -129,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 -@@ -1458,7 +1448,9 @@ +@@ -1485,7 +1475,9 @@ ON COMMIT PRESERVE ROWS; INSERT INTO concur_temp VALUES (1, 'foo'), (2, 'bar'); CREATE INDEX CONCURRENTLY concur_temp_ind ON concur_temp(f1); @@ -139,7 +125,7 @@ diff ../../../src/test/regress/expected/create_index.out ../tmp_check/regress_ou DROP TABLE concur_temp; -- ON COMMIT DROP BEGIN; -@@ -1467,34 +1459,42 @@ +@@ -1494,34 +1486,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); @@ -186,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 -@@ -2583,46 +2583,38 @@ +@@ -2610,46 +2610,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); @@ -274,700 +260,10 @@ diff ../../../src/test/regress/expected/index_including_gist.out ../tmp_check/re DROP TABLE tbl_gist; /* -diff ../../../src/test/regress/expected/profiles.out ../tmp_check/regress_outdir/results/profiles.out ---- ../../../src/test/regress/expected/profiles.out CENSORED -+++ ../tmp_check/regress_outdir/results/profiles.out CENSORED -@@ -21,16 +21,15 @@ - PASSWORD_REUSE_TIME 1 - PASSWORD_REUSE_MAX 1 - PASSWORD_GRACE_TIME 1; -+ERROR: [MTM] failed to prepare transaction at peer node - ALTER ROLE regress_profile_role PROFILE regress_test_profile; -+ERROR: profile "regress_test_profile" does not exist - DROP PROFILE regress_test_profile; -- error --ERROR: profile "regress_test_profile" cannot be dropped because some objects depend on it --DETAIL: profile of role regress_profile_role -+ERROR: profile "regress_test_profile" does not exist - -- Test profile parameters - ALTER PROFILE regress_test_profile LIMIT - FAILED_LOGIN_ATTEMPTS 0; -- error --ERROR: invalid resource limit --LINE 2: FAILED_LOGIN_ATTEMPTS 0; -- ^ -+ERROR: profile "regress_test_profile" does not exist - ALTER PROFILE regress_test_profile LIMIT - FAILED_LOGIN_ATTEMPTS 1.1; -- error - ERROR: syntax error at or near "1.1" -@@ -38,9 +37,7 @@ - ^ - ALTER PROFILE regress_test_profile LIMIT - PASSWORD_REUSE_TIME -2; -- error --ERROR: invalid resource limit --LINE 2: PASSWORD_REUSE_TIME -2; -- ^ -+ERROR: profile "regress_test_profile" does not exist - ALTER PROFILE regress_test_profile LIMIT - PASSWORD_REUSE_MAX -1; -- error - ERROR: syntax error at or near "-" -@@ -48,12 +45,16 @@ - ^ - ALTER PROFILE regress_test_profile LIMIT - PASSWORD_LIFE_TIME 0.1; -+ERROR: profile "regress_test_profile" does not exist - ALTER PROFILE regress_test_profile LIMIT - PASSWORD_GRACE_TIME default; -+ERROR: profile "regress_test_profile" does not exist - ALTER PROFILE regress_test_profile LIMIT - FAILED_LOGIN_ATTEMPTS unlimited; -+ERROR: profile "regress_test_profile" does not exist - ALTER PROFILE regress_test_profile LIMIT - PASSWORD_REUSE_TIME 1; -+ERROR: profile "regress_test_profile" does not exist - -- Use ORDER BY pflname in order to make test results not dependable on possible - -- changes in records restoring order - SELECT -@@ -69,15 +70,15 @@ - pflpasswordminlen, - pflpasswordrequirecomplex - FROM pg_profile ORDER BY pflname; -- pflname | pflfailedloginattempts | pflfailedauthkeeptime | pfluserinactivetime | pflpasswordreusetime | pflpasswordreusemax | pflpasswordlifetime | pflpasswordgracetime | pflpasswordminuniqchars | pflpasswordminlen | pflpasswordrequirecomplex ------------------------+------------------------+-----------------------+---------------------+----------------------+---------------------+---------------------+----------------------+-------------------------+-------------------+--------------------------- -- default | -1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | 0 -- regress_test_profile | -1 | -2 | -2 | 86400 | 1 | 8640 | -2 | -2 | -2 | -2 --(2 rows) -+ pflname | pflfailedloginattempts | pflfailedauthkeeptime | pfluserinactivetime | pflpasswordreusetime | pflpasswordreusemax | pflpasswordlifetime | pflpasswordgracetime | pflpasswordminuniqchars | pflpasswordminlen | pflpasswordrequirecomplex -+---------+------------------------+-----------------------+---------------------+----------------------+---------------------+---------------------+----------------------+-------------------------+-------------------+--------------------------- -+ default | -1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | 0 -+(1 row) - - -- Cleanup - ALTER ROLE regress_profile_role PROFILE DEFAULT; - DROP PROFILE regress_test_profile; -+ERROR: profile "regress_test_profile" does not exist - DROP ROLE regress_profile_role; - -- Check that the parameters USER_INACTIVE_TIME, FAILED_AUTH_KEEP_TIME and - -- PASSWORD_LIFE_TIME can't take value 0. Test both cases when these parameters -@@ -101,22 +102,18 @@ - USER_INACTIVE_TIME 1 - FAILED_AUTH_KEEP_TIME 1 - PASSWORD_LIFE_TIME 1; -+ERROR: [MTM] failed to prepare transaction at peer node - -- error, USER_INACTIVE_TIME can't take zero value - ALTER PROFILE regress_test_profile LIMIT USER_INACTIVE_TIME 0; --ERROR: invalid resource limit --LINE 1: ALTER PROFILE regress_test_profile LIMIT USER_INACTIVE_TIME ... -- ^ -+ERROR: profile "regress_test_profile" does not exist - -- error, FAILED_AUTH_KEEP_TIME can't take zero value - ALTER PROFILE regress_test_profile LIMIT FAILED_AUTH_KEEP_TIME 0; --ERROR: invalid resource limit --LINE 1: ALTER PROFILE regress_test_profile LIMIT FAILED_AUTH_KEEP_TI... -- ^ -+ERROR: profile "regress_test_profile" does not exist - -- error, PASSWORD_LIFE_TIME can't take zero value - ALTER PROFILE regress_test_profile LIMIT PASSWORD_LIFE_TIME 0; --ERROR: invalid resource limit --LINE 1: ALTER PROFILE regress_test_profile LIMIT PASSWORD_LIFE_TIME ... -- ^ -+ERROR: profile "regress_test_profile" does not exist - DROP PROFILE regress_test_profile; -+ERROR: profile "regress_test_profile" does not exist - -- - -- Test cases added within the task #PGPRO-3656 (Merge extra features of - -- passwordcheck under control of new passoword policy) -@@ -130,45 +127,54 @@ - PASSWORD_MIN_UNIQUE_CHARS 3 - PASSWORD_MIN_LEN 3 - PASSWORD_REQUIRE_COMPLEX 1; -+ERROR: [MTM] failed to prepare transaction at peer node - CREATE USER u1 PROFILE pfl1; -+ERROR: profile "pfl1" does not exist - -- ok, password string satisfies the limits PASSWORD_MIN_LEN, - -- PASSWORD_REQUIRE_COMPLEX and PASSWORD_MIN_UNIQUE_CHARS - ALTER USER u1 PASSWORD 'foo1'; -+ERROR: role "u1" does not exist - -- error, password string breaks the limit PASSWORD_MIN_LEN. - ALTER USER u1 PASSWORD 'fo'; --ERROR: password must be at least 3 characters long -+ERROR: role "u1" does not exist - -- error, password string breaks the limit PASSWORD_REQUIRE_COMPLEX. - ALTER USER u1 PASSWORD 'fooo'; --ERROR: password must contain both letters and nonletters -+ERROR: role "u1" does not exist - -- error, password string breaks the limit PASSWORD_MIN_UNIQUE_CHARS. - ALTER USER u1 PASSWORD 'f000'; --ERROR: password must contain at least 3 unique characters -+ERROR: role "u1" does not exist - --error, password string contains a user name - ALTER USER u1 PASSWORD '123u1__'; --ERROR: password must not contain user name -+ERROR: role "u1" does not exist - -- Turn off PASSWORD_REQUIRE_COMPLEX in order to allow acceptance of password - -- string containing only letters or digits - ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX 0; -+ERROR: profile "pfl1" does not exist - ALTER USER u1 PASSWORD 'foobar'; -- ok, password containing only letter is -+ERROR: role "u1" does not exist - -- now acceptable since the limit - -- PASSWORD_REQUIRE_COMPLEX was set to - -- false. - ALTER USER u1 PASSWORD '1234'; -- ok, by the same reason as for the password -+ERROR: role "u1" does not exist - -- string 'foobar' - -- Check that the limits PASSWORD_MIN_LEN, PASSWORD_MIN_UNIQUE_CHARS are still - -- followed when the limit PASSWORD_REQUIRE_COMPLEX is off - -- error, password string breaks the limit PASSWORD_MIN_LEN. - ALTER USER u1 PASSWORD 'fo'; --ERROR: password must be at least 3 characters long -+ERROR: role "u1" does not exist - -- error, password string breaks the limit PASSWORD_MIN_UNIQUE_CHARS. - ALTER USER u1 PASSWORD 'foo'; --ERROR: password must contain at least 3 unique characters -+ERROR: role "u1" does not exist - -- Check that a user name can be specified as a part of password phrase - ALTER USER u1 PASSWORD '123u1__'; --ok, it is allowed to specify a password -+ERROR: role "u1" does not exist - -- string containing a user name - -- Clean up - DROP USER u1; -+ERROR: role "u1" does not exist - DROP PROFILE pfl1; -+ERROR: profile "pfl1" does not exist - -- Check that a value for clauses PASSWORD_MIN_UNIQUE_CHARS and PASSWORD_MIN_LEN - -- is positive integer - -- error, value of PASSWORD_MIN_UNIQUE_CHARS must be > 0 -@@ -192,16 +198,13 @@ - LINE 1: CREATE PROFILE pfl1 LIMIT PASSWORD_MIN_LEN 1.2; - ^ - CREATE PROFILE pfl1; -+ERROR: [MTM] failed to prepare transaction at peer node - -- error, value of PASSWORD_MIN_UNIQUE_CHARS must be > 0 - ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_UNIQUE_CHARS 0; --ERROR: invalid resource limit --LINE 1: ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_UNIQUE_CHARS 0; -- ^ -+ERROR: profile "pfl1" does not exist - -- error, value of PASSWORD_MIN_LEN must be > 0 - ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_LEN 0; --ERROR: invalid resource limit --LINE 1: ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_LEN 0; -- ^ -+ERROR: profile "pfl1" does not exist - -- error, value of PASSWORD_MIN_UNIQUE_CHARS must be integer - ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_UNIQUE_CHARS 1.2; - ERROR: syntax error at or near "1.2" -@@ -214,17 +217,26 @@ - ^ - -- Clean up - DROP PROFILE pfl1; -+ERROR: profile "pfl1" does not exist - -- Check that boolean value for the clause PASSWORD_REQUIRE_COMPLEX can take any - -- of the following values: ON, OFF, TRUE, FALSE, 1, 0 - CREATE PROFILE pfl1; -+ERROR: [MTM] failed to prepare transaction at peer node - ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX 0; -- ok -+ERROR: profile "pfl1" does not exist - ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX 1; -- ok -+ERROR: profile "pfl1" does not exist - ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX false; -- ok -+ERROR: profile "pfl1" does not exist - ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX true; -- ok -+ERROR: profile "pfl1" does not exist - ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX on; -- ok -+ERROR: profile "pfl1" does not exist - ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX off; -- ok -+ERROR: profile "pfl1" does not exist - -- Clean up - DROP PROFILE pfl1; -+ERROR: profile "pfl1" does not exist - -- Check that the error "ERROR: conflicting or redundant resource" is emitted - -- in case one of the options PASSWORD_MIN_UNIQUE_CHARS, PASSWORD_MIN_LEN, - -- PASSWORD_REQUIRE_COMPLEX repeated twice. -@@ -244,20 +256,15 @@ - ^ - -- The same test for ALTER PROFILE - CREATE PROFILE pfl1; -+ERROR: [MTM] failed to prepare transaction at peer node - ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_LEN 2 PASSWORD_MIN_LEN 1; -- error --ERROR: conflicting or redundant resource --LINE 1: ALTER PROFILE pfl1 LIMIT PASSWORD_MIN_LEN 2 PASSWORD_MIN_LEN... -- ^ -+ERROR: profile "pfl1" does not exist - ALTER PROFILE pfl1 - LIMIT PASSWORD_MIN_UNIQUE_CHARS 2 PASSWORD_MIN_UNIQUE_CHARS 1; -- error --ERROR: conflicting or redundant resource --LINE 2: LIMIT PASSWORD_MIN_UNIQUE_CHARS 2 PASSWORD_MIN_UNIQUE_CHARS ... -- ^ -+ERROR: profile "pfl1" does not exist - ALTER PROFILE pfl1 - LIMIT PASSWORD_REQUIRE_COMPLEX off PASSWORD_REQUIRE_COMPLEX on; -- error --ERROR: conflicting or redundant resource --LINE 2: LIMIT PASSWORD_REQUIRE_COMPLEX off PASSWORD_REQUIRE_COMPLEX ... -- ^ -+ERROR: profile "pfl1" does not exist - -- Unlike other profile options, PASSWORD_REQUIRE_COMPLEX cannot be set to - -- UNLIMITED. - ALTER PROFILE pfl1 LIMIT PASSWORD_REQUIRE_COMPLEX UNLIMITED; -@@ -266,56 +273,58 @@ - ^ - -- Clean up - DROP PROFILE pfl1; -+ERROR: profile "pfl1" does not exist - -- Begin of tests that were added within implementation of the task PGPRO-4309 - -- Check that ALTER PROFILE RENAME does work as expected. - CREATE PROFILE profile_test; -+ERROR: [MTM] failed to prepare transaction at peer node - -- Query what profiles are currently stored in the system catalog table 'pg_profile'. - -- Use ORDER BY pflname in order to make test results not dependable on possible - -- changes in records restoring order - SELECT pflname FROM pg_profile ORDER BY pflname; -- pflname ---------------- -+ pflname -+--------- - default -- profile_test --(2 rows) -+(1 row) - - -- Rename profile 'profile_test' to 'profile_test_new' - ALTER PROFILE profile_test RENAME TO profile_test_new; -+ERROR: profile "profile_test" does not exist - -- and check that the new profile name is stored in - -- the system catalog table pg_profile - SELECT pflname FROM pg_profile ORDER BY pflname; -- pflname -------------------- -+ pflname -+--------- - default -- profile_test_new --(2 rows) -+(1 row) - - -- Clean up - DROP PROFILE profile_test_new; -+ERROR: profile "profile_test_new" does not exist - -- Check that rounding of a time value is correct - CREATE PROFILE test_profile LIMIT PASSWORD_LIFE_TIME 0.00001; -+ERROR: [MTM] failed to prepare transaction at peer node - ALTER PROFILE test_profile LIMIT PASSWORD_LIFE_TIME 0.0000000000000000000000000000000001; --ERROR: invalid resource limit --LINE 1: ALTER PROFILE test_profile LIMIT PASSWORD_LIFE_TIME 0.000000... -- ^ -+ERROR: profile "test_profile" does not exist - SELECT pflpasswordlifetime FROM pg_profile WHERE pflname = 'test_profile'; - pflpasswordlifetime - --------------------- -- 1 --(1 row) -+(0 rows) - - -- Check that PASSWORD_GRACE_TIME can be assigned the value 0; - ALTER PROFILE test_profile LIMIT PASSWORD_GRACE_TIME 0 PASSWORD_LIFE_TIME 1; -+ERROR: profile "test_profile" does not exist - SELECT pflpasswordgracetime, pflpasswordlifetime FROM pg_profile WHERE pflname = 'test_profile'; - pflpasswordgracetime | pflpasswordlifetime - ----------------------+--------------------- -- 0 | 86400 --(1 row) -+(0 rows) - - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist - -- Check that a value of interval type can be supplied for time-related profile options in - -- the statement CREATE PROFILE - CREATE PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '1' DAY PASSWORD_GRACE_TIME INTERVAL '2' HOUR PASSWORD_REUSE_TIME INTERVAL '30' MINUTE USER_INACTIVE_TIME INTERVAL '75' SECOND ; -+ERROR: [MTM] failed to prepare transaction at peer node - SELECT - pflpasswordlifetime, - pflpasswordgracetime, -@@ -324,13 +333,14 @@ - FROM pg_profile WHERE pflname='test_profile'; - pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime - ---------------------+----------------------+----------------------+--------------------- -- 86400 | 7200 | 1800 | 75 --(1 row) -+(0 rows) - - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist - -- Check that a value of interval type can be supplied in all supported formats - -- the statement CREATE PROFILE - CREATE PROFILE test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '1 YEAR 2 MONTHS 3 DAYS 4 HOURS 5 MINUTES 6.123 SECONDS' PASSWORD_LIFE_TIME INTERVAL '1 MINUTE' MINUTE PASSWORD_GRACE_TIME INTERVAL '1 SECOND' MINUTE PASSWORD_REUSE_TIME INTERVAL '1 MINUTE 1 SECOND' SECOND USER_INACTIVE_TIME INTERVAL '1 MINUTE 1 SECOND' MINUTE; -+ERROR: [MTM] failed to prepare transaction at peer node - SELECT - pflfailedauthkeeptime, - pflpasswordlifetime, -@@ -340,11 +350,12 @@ - FROM pg_profile WHERE pflname='test_profile'; - pflfailedauthkeeptime | pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime - -----------------------+---------------------+----------------------+----------------------+--------------------- -- 37015506 | 60 | 0 | 61 | 60 --(1 row) -+(0 rows) - - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist - CREATE PROFILE test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '1 YEAR 2 MONTHS 3 DAYS 4 HOURS 5 MINUTES 6.523 SECONDS' PASSWORD_LIFE_TIME INTERVAL '1 MINUTE' SECOND PASSWORD_GRACE_TIME INTERVAL '1 MINUTE' PASSWORD_REUSE_TIME INTERVAL '1-2' SECOND USER_INACTIVE_TIME INTERVAL '3 4:05:06' SECOND; -+ERROR: [MTM] failed to prepare transaction at peer node - SELECT - pflfailedauthkeeptime, - pflpasswordlifetime, -@@ -354,21 +365,22 @@ - FROM pg_profile WHERE pflname='test_profile'; - pflfailedauthkeeptime | pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime - -----------------------+---------------------+----------------------+----------------------+--------------------- -- 37015507 | 60 | 60 | 36741600 | 273906 --(1 row) -+(0 rows) - - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist - CREATE PROFILE test_profile LIMIT PASSWORD_REUSE_TIME INTERVAL 'P2Y3M4DT5H6M7S' USER_INACTIVE_TIME INTERVAL 'P0003-04-05T06:07:08'; -+ERROR: [MTM] failed to prepare transaction at peer node - SELECT - pflpasswordreusetime, - pfluserinactivetime - FROM pg_profile WHERE pflname='test_profile'; - pflpasswordreusetime | pfluserinactivetime - ----------------------+--------------------- -- 71255167 | 105494828 --(1 row) -+(0 rows) - - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist - -- Invalid interval type values - -- the statement CREATE PROFILE - --FAILED_AUTH_KEEP_TIME value must be from 1 to 2147483647 seconds -@@ -419,6 +431,7 @@ - -- Check that an interval type value and a real type value can intermixed - -- in the same CREATE PROFILE statement. - CREATE PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '1' DAY PASSWORD_GRACE_TIME 0.01 PASSWORD_REUSE_TIME INTERVAL '30' MINUTE USER_INACTIVE_TIME 1; -+ERROR: [MTM] failed to prepare transaction at peer node - SELECT - pflpasswordlifetime, - pflpasswordgracetime, -@@ -427,14 +440,16 @@ - FROM pg_profile WHERE pflname='test_profile'; - pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime - ---------------------+----------------------+----------------------+--------------------- -- 86400 | 864 | 1800 | 86400 --(1 row) -+(0 rows) - - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist - CREATE PROFILE test_profile; -+ERROR: [MTM] failed to prepare transaction at peer node - -- Check that a value of interval type can be supplied for time-related profile options in - -- the statement ALTER PROFILE - ALTER PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '1' DAY PASSWORD_GRACE_TIME INTERVAL '2' HOUR PASSWORD_REUSE_TIME INTERVAL '30' MINUTE USER_INACTIVE_TIME INTERVAL '75' SECOND ; -+ERROR: profile "test_profile" does not exist - SELECT - pflpasswordlifetime, - pflpasswordgracetime, -@@ -443,12 +458,12 @@ - FROM pg_profile WHERE pflname='test_profile'; - pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime - ---------------------+----------------------+----------------------+--------------------- -- 86400 | 7200 | 1800 | 75 --(1 row) -+(0 rows) - - -- Check that a value of interval type can be supplied in all supported formats - -- the statement ALTER PROFILE - ALTER PROFILE test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '1 YEAR 2 MONTHS 3 DAYS 4 HOURS 5 MINUTES 6.123 SECONDS' PASSWORD_LIFE_TIME INTERVAL '1 MINUTE' MINUTE PASSWORD_GRACE_TIME INTERVAL '1 SECOND' MINUTE PASSWORD_REUSE_TIME INTERVAL '1 MINUTE 1 SECOND' SECOND USER_INACTIVE_TIME INTERVAL '1 MINUTE 1 SECOND' MINUTE; -+ERROR: profile "test_profile" does not exist - SELECT - pflfailedauthkeeptime, - pflpasswordlifetime, -@@ -458,10 +473,10 @@ - FROM pg_profile WHERE pflname='test_profile'; - pflfailedauthkeeptime | pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime - -----------------------+---------------------+----------------------+----------------------+--------------------- -- 37015506 | 60 | 0 | 61 | 60 --(1 row) -+(0 rows) - - ALTER PROFILE test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '1 YEAR 2 MONTHS 3 DAYS 4 HOURS 5 MINUTES 6.523 SECONDS' PASSWORD_LIFE_TIME INTERVAL '1 MINUTE' SECOND PASSWORD_GRACE_TIME INTERVAL '1 MINUTE' PASSWORD_REUSE_TIME INTERVAL '1-2' SECOND USER_INACTIVE_TIME INTERVAL '3 4:05:06' SECOND; -+ERROR: profile "test_profile" does not exist - SELECT - pflfailedauthkeeptime, - pflpasswordlifetime, -@@ -471,69 +486,49 @@ - FROM pg_profile WHERE pflname='test_profile'; - pflfailedauthkeeptime | pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime - -----------------------+---------------------+----------------------+----------------------+--------------------- -- 37015507 | 60 | 60 | 36741600 | 273906 --(1 row) -+(0 rows) - - ALTER PROFILE test_profile LIMIT PASSWORD_REUSE_TIME INTERVAL 'P2Y3M4DT5H6M7S' USER_INACTIVE_TIME INTERVAL 'P0003-04-05T06:07:08'; -+ERROR: profile "test_profile" does not exist - SELECT - pflpasswordreusetime, - pfluserinactivetime - FROM pg_profile WHERE pflname='test_profile'; - pflpasswordreusetime | pfluserinactivetime - ----------------------+--------------------- -- 71255167 | 105494828 --(1 row) -+(0 rows) - - -- Invalid interval type values - -- the statement ALTER PROFILE - --FAILED_AUTH_KEEP_TIME value must be from 1 to 2147483647 seconds - ALTER PROFILE test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '100' YEAR; --error --ERROR: interval must be in range 1..2147483647 seconds --LINE 1: ...test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '100' YEAR... -- ^ -+ERROR: profile "test_profile" does not exist - ALTER PROFILE test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '1 MINUTE' DAY; --error --ERROR: interval must be in range 1..2147483647 seconds --LINE 1: ...test_profile LIMIT FAILED_AUTH_KEEP_TIME INTERVAL '1 MINUTE'... -- ^ -+ERROR: profile "test_profile" does not exist - --PASSWORD_LIFE_TIME value must be from 1 to 2147483647 seconds - ALTER PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '100' YEAR; --error --ERROR: interval must be in range 1..2147483647 seconds --LINE 1: ...LE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '100' YEAR... -- ^ -+ERROR: profile "test_profile" does not exist - ALTER PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '1 MINUTE' HOUR; --error --ERROR: interval must be in range 1..2147483647 seconds --LINE 1: ...LE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '1 MINUTE'... -- ^ -+ERROR: profile "test_profile" does not exist - --PASSWORD_GRACE_TIME value must be from 0 to 2147483647 seconds - ALTER PROFILE test_profile LIMIT PASSWORD_GRACE_TIME INTERVAL '100' YEAR; --error --ERROR: interval must be in range 0..2147483647 seconds --LINE 1: ...E test_profile LIMIT PASSWORD_GRACE_TIME INTERVAL '100' YEAR... -- ^ -+ERROR: profile "test_profile" does not exist - ALTER PROFILE test_profile LIMIT PASSWORD_GRACE_TIME INTERVAL '-1 SECOND'; --error --ERROR: interval must be in range 0..2147483647 seconds --LINE 1: ...E test_profile LIMIT PASSWORD_GRACE_TIME INTERVAL '-1 SECOND... -- ^ -+ERROR: profile "test_profile" does not exist - --PASSWORD_REUSE_TIME value must be from 0 to 2147483647 seconds - ALTER PROFILE test_profile LIMIT PASSWORD_REUSE_TIME INTERVAL '100' YEAR; --error --ERROR: interval must be in range 0..2147483647 seconds --LINE 1: ...E test_profile LIMIT PASSWORD_REUSE_TIME INTERVAL '100' YEAR... -- ^ -+ERROR: profile "test_profile" does not exist - ALTER PROFILE test_profile LIMIT PASSWORD_REUSE_TIME INTERVAL '-1 SECOND'; --error --ERROR: interval must be in range 0..2147483647 seconds --LINE 1: ...E test_profile LIMIT PASSWORD_REUSE_TIME INTERVAL '-1 SECOND... -- ^ -+ERROR: profile "test_profile" does not exist - --USER_INACTIVE_TIME value must be from 1 to 2147483647 seconds - ALTER PROFILE test_profile LIMIT USER_INACTIVE_TIME INTERVAL '100' YEAR; --error --ERROR: interval must be in range 1..2147483647 seconds --LINE 1: ...LE test_profile LIMIT USER_INACTIVE_TIME INTERVAL '100' YEAR... -- ^ -+ERROR: profile "test_profile" does not exist - ALTER PROFILE test_profile LIMIT USER_INACTIVE_TIME INTERVAL '1 SECOND' YEAR; --error --ERROR: interval must be in range 1..2147483647 seconds --LINE 1: ...LE test_profile LIMIT USER_INACTIVE_TIME INTERVAL '1 SECOND'... -- ^ -+ERROR: profile "test_profile" does not exist - -- Check that an interval type value and a real type value can intermixed - -- in the same ALTER PROFILE statement. - ALTER PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '5' DAY PASSWORD_GRACE_TIME 0.01 PASSWORD_REUSE_TIME INTERVAL '70' MINUTE USER_INACTIVE_TIME 1; -+ERROR: profile "test_profile" does not exist - SELECT - pflpasswordlifetime, - pflpasswordgracetime, -@@ -542,36 +537,40 @@ - FROM pg_profile WHERE pflname='test_profile'; - pflpasswordlifetime | pflpasswordgracetime | pflpasswordreusetime | pfluserinactivetime - ---------------------+----------------------+----------------------+--------------------- -- 432000 | 864 | 4200 | 86400 --(1 row) -+(0 rows) - - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist - -- Check support of statement CREATE PROFILE IF NOT EXISTS - CREATE PROFILE IF NOT EXISTS test_profile; -+ERROR: [MTM] failed to prepare transaction at peer node - -- Check that the profile test_profile was created - SELECT 1 FROM pg_profile WHERE pflname='test_profile'; - ?column? - ---------- -- 1 --(1 row) -+(0 rows) - - -- Re-execute the same CREATE PROFILE statement and check it doesn't fail - CREATE PROFILE IF NOT EXISTS test_profile; -+ERROR: [MTM] failed to prepare transaction at peer node - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist - -- Check support of statement CREATE PROFILE FROM - CREATE PROFILE test_profile LIMIT PASSWORD_LIFE_TIME INTERVAL '10' HOUR FAILED_LOGIN_ATTEMPTS 7; -+ERROR: [MTM] failed to prepare transaction at peer node - CREATE PROFILE test_profile_copy FROM test_profile; -+ERROR: profile "test_profile" does not exist - -- Use ORDER BY pflname in order to make test results not dependable on possible - -- changes in records restoring order - SELECT pflname, pflfailedloginattempts, pflfailedauthkeeptime, pfluserinactivetime, pflpasswordreusetime, pflpasswordreusemax, pflpasswordlifetime, pflpasswordgracetime, pflpasswordminuniqchars, pflpasswordminlen, pflpasswordrequirecomplex FROM pg_profile WHERE pflname IN ('test_profile', 'test_profile_copy') ORDER BY pflname; -- pflname | pflfailedloginattempts | pflfailedauthkeeptime | pfluserinactivetime | pflpasswordreusetime | pflpasswordreusemax | pflpasswordlifetime | pflpasswordgracetime | pflpasswordminuniqchars | pflpasswordminlen | pflpasswordrequirecomplex ---------------------+------------------------+-----------------------+---------------------+----------------------+---------------------+---------------------+----------------------+-------------------------+-------------------+--------------------------- -- test_profile | 7 | -2 | -2 | -2 | -2 | 36000 | -2 | -2 | -2 | -2 -- test_profile_copy | 7 | -2 | -2 | -2 | -2 | 36000 | -2 | -2 | -2 | -2 --(2 rows) -+ pflname | pflfailedloginattempts | pflfailedauthkeeptime | pfluserinactivetime | pflpasswordreusetime | pflpasswordreusemax | pflpasswordlifetime | pflpasswordgracetime | pflpasswordminuniqchars | pflpasswordminlen | pflpasswordrequirecomplex -+---------+------------------------+-----------------------+---------------------+----------------------+---------------------+---------------------+----------------------+-------------------------+-------------------+--------------------------- -+(0 rows) - - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist - DROP PROFILE test_profile_copy; -+ERROR: profile "test_profile_copy" does not exist - -- Check that all profile options support the value DEFAULT. - CREATE PROFILE test_profile LIMIT - FAILED_LOGIN_ATTEMPTS DEFAULT -@@ -584,6 +583,7 @@ - PASSWORD_MIN_UNIQUE_CHARS DEFAULT - PASSWORD_MIN_LEN DEFAULT - PASSWORD_REQUIRE_COMPLEX DEFAULT; -+ERROR: [MTM] failed to prepare transaction at peer node - \x - SELECT - pflfailedloginattempts, -@@ -597,21 +597,13 @@ - pflpasswordminlen, - pflpasswordrequirecomplex - FROM pg_profile WHERE pflname = 'test_profile'; ---[ RECORD 1 ]-------------+--- --pflfailedloginattempts | -2 --pflfailedauthkeeptime | -2 --pfluserinactivetime | -2 --pflpasswordreusetime | -2 --pflpasswordreusemax | -2 --pflpasswordlifetime | -2 --pflpasswordgracetime | -2 --pflpasswordminuniqchars | -2 --pflpasswordminlen | -2 --pflpasswordrequirecomplex | -2 -+(0 rows) - - \x - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist - CREATE PROFILE test_profile; -+ERROR: [MTM] failed to prepare transaction at peer node - ALTER PROFILE test_profile LIMIT - FAILED_LOGIN_ATTEMPTS DEFAULT - FAILED_AUTH_KEEP_TIME DEFAULT -@@ -623,6 +615,7 @@ - PASSWORD_MIN_UNIQUE_CHARS DEFAULT - PASSWORD_MIN_LEN DEFAULT - PASSWORD_REQUIRE_COMPLEX DEFAULT; -+ERROR: profile "test_profile" does not exist - \x - SELECT - pflfailedloginattempts, -@@ -636,20 +629,11 @@ - pflpasswordminlen, - pflpasswordrequirecomplex - FROM pg_profile WHERE pflname = 'test_profile'; ---[ RECORD 1 ]-------------+--- --pflfailedloginattempts | -2 --pflfailedauthkeeptime | -2 --pfluserinactivetime | -2 --pflpasswordreusetime | -2 --pflpasswordreusemax | -2 --pflpasswordlifetime | -2 --pflpasswordgracetime | -2 --pflpasswordminuniqchars | -2 --pflpasswordminlen | -2 --pflpasswordrequirecomplex | -2 -+(0 rows) - - \x - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist - -- Check that almost all profile options (except for PASSWORD_REQUIRE_COMPLEX) - -- support the value UNLIMITED. - CREATE PROFILE test_profile LIMIT -@@ -662,6 +646,7 @@ - PASSWORD_GRACE_TIME UNLIMITED - PASSWORD_MIN_UNIQUE_CHARS UNLIMITED - PASSWORD_MIN_LEN UNLIMITED; -+ERROR: [MTM] failed to prepare transaction at peer node - \x - SELECT - pflfailedloginattempts, -@@ -675,21 +660,13 @@ - pflpasswordminlen, - pflpasswordrequirecomplex - FROM pg_profile WHERE pflname = 'test_profile'; ---[ RECORD 1 ]-------------+--- --pflfailedloginattempts | -1 --pflfailedauthkeeptime | -1 --pfluserinactivetime | -1 --pflpasswordreusetime | -1 --pflpasswordreusemax | -1 --pflpasswordlifetime | -1 --pflpasswordgracetime | -1 --pflpasswordminuniqchars | -1 --pflpasswordminlen | -1 --pflpasswordrequirecomplex | -2 -+(0 rows) - - \x - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist - CREATE PROFILE test_profile; -+ERROR: [MTM] failed to prepare transaction at peer node - ALTER PROFILE test_profile LIMIT - FAILED_LOGIN_ATTEMPTS UNLIMITED - FAILED_AUTH_KEEP_TIME UNLIMITED -@@ -700,6 +677,7 @@ - PASSWORD_GRACE_TIME UNLIMITED - PASSWORD_MIN_UNIQUE_CHARS UNLIMITED - PASSWORD_MIN_LEN UNLIMITED; -+ERROR: profile "test_profile" does not exist - \x - SELECT - pflfailedloginattempts, -@@ -713,17 +691,8 @@ - pflpasswordminlen, - pflpasswordrequirecomplex - FROM pg_profile WHERE pflname = 'test_profile'; ---[ RECORD 1 ]-------------+--- --pflfailedloginattempts | -1 --pflfailedauthkeeptime | -1 --pfluserinactivetime | -1 --pflpasswordreusetime | -1 --pflpasswordreusemax | -1 --pflpasswordlifetime | -1 --pflpasswordgracetime | -1 --pflpasswordminuniqchars | -1 --pflpasswordminlen | -1 --pflpasswordrequirecomplex | -2 -+(0 rows) - - \x - DROP PROFILE test_profile; -+ERROR: profile "test_profile" does not exist 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 @@ +@@ -32,6 +32,8 @@ check_tbl|f circle_tbl|t city|f @@ -976,7 +272,7 @@ diff ../../../src/test/regress/expected/sanity_check.out ../tmp_check/regress_ou copy_tbl|f d|f d_star|f -@@ -67,6 +71,7 @@ +@@ -67,6 +69,7 @@ jtbl|t kd_point_tbl|t line_tbl|f @@ -984,7 +280,7 @@ diff ../../../src/test/regress/expected/sanity_check.out ../tmp_check/regress_ou log_table|f lseg_tbl|f main_table|f -@@ -83,6 +88,7 @@ +@@ -83,6 +86,7 @@ mlparted_defd|f money_data|f mytable|t @@ -992,22 +288,6 @@ diff ../../../src/test/regress/expected/sanity_check.out ../tmp_check/regress_ou num_data|f num_exp_add|t num_exp_div|t -@@ -141,7 +147,6 @@ - pg_policy|t - pg_proc|t - pg_profile|t --pg_publication|t - pg_publication_rel|t - pg_range|t - pg_replication_origin|t -@@ -155,7 +160,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 @@ -187,6 +191,7 @@ sql_sizing|f stud_emp|f @@ -1068,421 +348,6 @@ diff ../../../src/test/regress/expected/select_into.out ../tmp_check/regress_out 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/join.out ../tmp_check/regress_outdir/results/join.out ---- ../../../src/test/regress/expected/join.out CENSORED -+++ ../tmp_check/regress_outdir/results/join.out CENSORED -@@ -4936,11 +4936,14 @@ - -- Trivial self-join case. - explain (costs off) - select p.* from sj p, sj q where q.a = p.a and q.b = q.a - 1; -- QUERY PLAN ------------------------------------------------- -- Seq Scan on sj q -- Filter: ((a IS NOT NULL) AND (b = (a - 1))) --(2 rows) -+ QUERY PLAN -+------------------------------- -+ Nested Loop -+ Join Filter: (p.a = q.a) -+ -> Seq Scan on sj q -+ Filter: (b = (a - 1)) -+ -> Seq Scan on sj p -+(5 rows) - - select p.* from sj p, sj q where q.a = p.a and q.b = q.a - 1; - a | b | c -@@ -4954,11 +4957,15 @@ - select * from sj p - where exists (select * from sj q - where q.a = p.a and q.b < 10); -- QUERY PLAN -------------------------------------------- -- Seq Scan on sj q -- Filter: ((a IS NOT NULL) AND (b < 10)) --(2 rows) -+ QUERY PLAN -+-------------------------------- -+ Nested Loop -+ Join Filter: (p.a = q.a) -+ -> Seq Scan on sj p -+ -> Materialize -+ -> Seq Scan on sj q -+ Filter: (b < 10) -+(6 rows) - - select * from sj p where exists (select * from sj q where q.a = p.a and q.b < 10); - a | b | c -@@ -4985,13 +4992,11 @@ - (select a as x from sj where false) as q1, - (select a as y from sj where false) as q2 - where q1.x = q2.y; -- QUERY PLAN ----------------------------------- -+ QUERY PLAN -+-------------------------- - Result - One-Time Filter: false -- -> Seq Scan on sj -- Filter: (a IS NOT NULL) --(4 rows) -+(2 rows) - - -- We can't use a cross-EC generated self join qual because of current logic of - -- the generate_join_implied_equalities routine. -@@ -5032,11 +5037,18 @@ - explain (costs off) - select * from sj t1 join sj t2 on t1.a = t2.a and t1.b = t2.b - join sj t3 on t2.a = t3.a and t2.b + 1 = t3.b + 1; -- QUERY PLAN ----------------------------------------------------------------------------- -- Seq Scan on sj t3 -- Filter: ((a IS NOT NULL) AND (b IS NOT NULL) AND ((b + 1) IS NOT NULL)) --(2 rows) -+ QUERY PLAN -+-------------------------------------------------------------------------------- -+ Nested Loop -+ Join Filter: ((t1.a = t2.a) AND (t1.b = t2.b) AND ((t3.b + 1) = (t2.b + 1))) -+ -> Seq Scan on sj t2 -+ -> Materialize -+ -> Nested Loop -+ Join Filter: (t1.a = t3.a) -+ -> Seq Scan on sj t1 -+ -> Materialize -+ -> Seq Scan on sj t3 -+(9 rows) - - -- subselect that references the removed relation - explain (costs off) -@@ -5045,14 +5057,17 @@ - where t1.a = t2.a; - QUERY PLAN - ------------------------------------------ -- Seq Scan on sj t2 -- Filter: (a IS NOT NULL) -+ Nested Loop -+ Join Filter: (t1.a = t2.a) -+ -> Seq Scan on sj t1 -+ -> Materialize -+ -> Seq Scan on sj t2 - SubPlan 1 - -> Result -- One-Time Filter: (t2.a = t2.a) -+ One-Time Filter: (t2.a = t1.a) - -> Seq Scan on sj -- Filter: (a = t2.a) --(7 rows) -+ Filter: (a = t1.a) -+(10 rows) - - -- self-join under outer join - explain (costs off) -@@ -5061,12 +5076,15 @@ - QUERY PLAN - ------------------------------------ - Nested Loop Left Join -- Join Filter: (y.a = z.q1) -- -> Seq Scan on sj y -- Filter: (a IS NOT NULL) -+ Join Filter: (x.a = z.q1) -+ -> Nested Loop -+ Join Filter: (x.a = y.a) -+ -> Seq Scan on sj x -+ -> Materialize -+ -> Seq Scan on sj y - -> Materialize - -> Seq Scan on int8_tbl z --(6 rows) -+(9 rows) - - explain (costs off) - select * from sj x join sj y on x.a = y.a -@@ -5075,11 +5093,14 @@ - ------------------------------------ - Nested Loop Left Join - Join Filter: (y.a = z.q1) -- -> Seq Scan on sj y -- Filter: (a IS NOT NULL) -+ -> Nested Loop -+ Join Filter: (x.a = y.a) -+ -> Seq Scan on sj x -+ -> Materialize -+ -> Seq Scan on sj y - -> Materialize - -> Seq Scan on int8_tbl z --(6 rows) -+(9 rows) - - -- Test that placeholders are updated correctly after join removal - explain (costs off) -@@ -5088,44 +5109,56 @@ - right join sj j1 inner join sj j2 on j1.a = j2.a - on true) z - on true; -- QUERY PLAN -------------------------------------------- -+ QUERY PLAN -+------------------------------------------- - Nested Loop Left Join - -> Result - -> Nested Loop Left Join -- -> Seq Scan on sj j2 -- Filter: (a IS NOT NULL) -+ -> Nested Loop -+ Join Filter: (j1.a = j2.a) -+ -> Seq Scan on sj j1 -+ -> Materialize -+ -> Seq Scan on sj j2 - -> Materialize - -> Seq Scan on int8_tbl y --(7 rows) -+(10 rows) - - -- Test that OR predicated are updated correctly after join removal - CREATE TABLE tab_with_flag ( id INT PRIMARY KEY, is_flag SMALLINT); - CREATE INDEX idx_test_is_flag ON tab_with_flag (is_flag); - explain (costs off) - SELECT COUNT(*) FROM tab_with_flag WHERE (is_flag IS NULL OR is_flag = 0) AND id IN (SELECT id FROM tab_with_flag WHERE id IN (2, 3)); -- QUERY PLAN ------------------------------------------------------------------------------------ -+ QUERY PLAN -+------------------------------------------------------------------------ - Aggregate -- -> Bitmap Heap Scan on tab_with_flag -- Recheck Cond: ((id = ANY ('{2,3}'::integer[])) AND (id IS NOT NULL)) -- Filter: ((is_flag IS NULL) OR (is_flag = 0)) -- -> Bitmap Index Scan on tab_with_flag_pkey -- Index Cond: ((id = ANY ('{2,3}'::integer[])) AND (id IS NOT NULL)) --(6 rows) -+ -> Nested Loop -+ -> Bitmap Heap Scan on tab_with_flag tab_with_flag_1 -+ Recheck Cond: (id = ANY ('{2,3}'::integer[])) -+ -> Bitmap Index Scan on tab_with_flag_pkey -+ Index Cond: (id = ANY ('{2,3}'::integer[])) -+ -> Memoize -+ Cache Key: tab_with_flag_1.id -+ Cache Mode: logical -+ -> Index Scan using tab_with_flag_pkey on tab_with_flag -+ Index Cond: (id = tab_with_flag_1.id) -+ Filter: ((is_flag IS NULL) OR (is_flag = 0)) -+(12 rows) - - DROP TABLE tab_with_flag; - -- HAVING clause - explain (costs off) - select p.b from sj p join sj q on p.a = q.a group by p.b having sum(p.a) = 1; -- QUERY PLAN ----------------------------------- -+ QUERY PLAN -+------------------------------------ - HashAggregate -- Group Key: q.b -- Filter: (sum(q.a) = 1) -- -> Seq Scan on sj q -- Filter: (a IS NOT NULL) --(5 rows) -+ Group Key: p.b -+ Filter: (sum(p.a) = 1) -+ -> Nested Loop -+ Join Filter: (p.a = q.a) -+ -> Seq Scan on sj p -+ -> Materialize -+ -> Seq Scan on sj q -+(8 rows) - - -- update lateral references and range table entry reference - explain (verbose, costs off) -@@ -5135,13 +5168,20 @@ - ------------------------------------------------------ - Nested Loop - Output: 1 -- -> Seq Scan on public.sj y -- Output: y.a, y.b, y.c -- Filter: (y.a IS NOT NULL) -+ -> Nested Loop -+ Output: x.a -+ Inner Unique: true -+ Join Filter: (x.a = y.a) -+ -> Seq Scan on public.sj x -+ Output: x.a, x.b, x.c -+ -> Materialize -+ Output: y.a -+ -> Seq Scan on public.sj y -+ Output: y.a - -> Function Scan on pg_catalog.generate_series gs - Output: gs.i -- Function Call: generate_series(1, y.a) --(8 rows) -+ Function Call: generate_series(1, x.a) -+(15 rows) - - explain (verbose, costs off) - select 1 from (select y.* from sj x, sj y where x.a = y.a) q, -@@ -5150,13 +5190,20 @@ - ------------------------------------------------------ - Nested Loop - Output: 1 -- -> Seq Scan on public.sj y -- Output: y.a, y.b, y.c -- Filter: (y.a IS NOT NULL) -+ -> Nested Loop -+ Output: y.a -+ Inner Unique: true -+ Join Filter: (x.a = y.a) -+ -> Seq Scan on public.sj x -+ Output: x.a, x.b, x.c -+ -> Materialize -+ Output: y.a -+ -> Seq Scan on public.sj y -+ Output: y.a - -> Function Scan on pg_catalog.generate_series gs - Output: gs.i - Function Call: generate_series(1, y.a) --(8 rows) -+(15 rows) - - -- Test that a non-EC-derived join clause is processed correctly. Use an - -- outer join so that we can't form an EC. -@@ -5165,22 +5212,29 @@ - QUERY PLAN - ------------------------------------ - Nested Loop Left Join -- Join Filter: ((q.a + q.a) = r.a) -- -> Seq Scan on sj q -- Filter: (a IS NOT NULL) -+ Join Filter: ((p.a + q.a) = r.a) -+ -> Nested Loop -+ Join Filter: (p.a = q.a) -+ -> Seq Scan on sj p -+ -> Materialize -+ -> Seq Scan on sj q - -> Materialize - -> Seq Scan on sj r --(6 rows) -+(9 rows) - - -- FIXME this constant false filter doesn't look good. Should we merge - -- equivalence classes? - explain (costs off) - select * from sj p, sj q where p.a = q.a and p.b = 1 and q.b = 2; -- QUERY PLAN ------------------------------------------------------- -- Seq Scan on sj q -- Filter: ((a IS NOT NULL) AND (b = 2) AND (b = 1)) --(2 rows) -+ QUERY PLAN -+---------------------------- -+ Nested Loop -+ Join Filter: (p.a = q.a) -+ -> Seq Scan on sj p -+ Filter: (b = 1) -+ -> Seq Scan on sj q -+ Filter: (b = 2) -+(6 rows) - - -- Check that attr_needed is updated correctly after self-join removal. In this - -- test, the join of j1 with j2 is removed. k1.b is required at either j1 or j2. -@@ -5195,24 +5249,29 @@ - explain (costs off) select 1 from - (sk k1 join sk k2 on k1.a = k2.a) - join (sj j1 join sj j2 on j1.a = j2.a) on j1.b = k1.b; -- QUERY PLAN ------------------------------------------------------- -+ QUERY PLAN -+----------------------------------------------------------------- - Nested Loop -- Join Filter: (k1.b = j2.b) -+ Join Filter: (k1.b = j1.b) - -> Nested Loop - -> Index Scan using sk_a_idx on sk k1 - -> Index Only Scan using sk_a_idx on sk k2 - Index Cond: (a = k1.a) - -> Materialize -- -> Index Scan using sj_a_key on sj j2 -- Index Cond: (a IS NOT NULL) --(9 rows) -+ -> Nested Loop -+ -> Index Scan using sj_a_key on sj j1 -+ -> Memoize -+ Cache Key: j1.a -+ Cache Mode: logical -+ -> Index Only Scan using sj_a_key on sj j2 -+ Index Cond: (a = j1.a) -+(14 rows) - - explain (costs off) select 1 from - (sk k1 join sk k2 on k1.a = k2.a) - join (sj j1 join sj j2 on j1.a = j2.a) on j2.b = k1.b; -- QUERY PLAN ------------------------------------------------------- -+ QUERY PLAN -+------------------------------------------------------------ - Nested Loop - Join Filter: (k1.b = j2.b) - -> Nested Loop -@@ -5220,9 +5279,14 @@ - -> Index Only Scan using sk_a_idx on sk k2 - Index Cond: (a = k1.a) - -> Materialize -- -> Index Scan using sj_a_key on sj j2 -- Index Cond: (a IS NOT NULL) --(9 rows) -+ -> Nested Loop -+ -> Index Only Scan using sj_a_key on sj j1 -+ -> Memoize -+ Cache Key: j1.a -+ Cache Mode: logical -+ -> Index Scan using sj_a_key on sj j2 -+ Index Cond: (a = j1.a) -+(14 rows) - - reset join_collapse_limit; - reset enable_seqscan; -@@ -5230,12 +5294,18 @@ - CREATE TABLE emp1 ( id SERIAL PRIMARY KEY NOT NULL, code int); - explain (verbose, costs off) - SELECT * FROM emp1 e1, emp1 e2 WHERE e1.id = e2.id AND e2.code <> e1.code; -- QUERY PLAN ------------------------------------------------------------ -- Seq Scan on public.emp1 e2 -- Output: e2.id, e2.code, e2.id, e2.code -- Filter: ((e2.id IS NOT NULL) AND (e2.code <> e2.code)) --(3 rows) -+ QUERY PLAN -+---------------------------------------------------- -+ Nested Loop -+ Output: e1.id, e1.code, e2.id, e2.code -+ Inner Unique: true -+ -> Seq Scan on public.emp1 e1 -+ Output: e1.id, e1.code -+ -> Index Scan using emp1_pkey on public.emp1 e2 -+ Output: e2.id, e2.code -+ Index Cond: (e2.id = e1.id) -+ Filter: (e2.code <> e1.code) -+(9 rows) - - -- We can remove the join even if we find the join can't duplicate rows and - -- the base quals of each side are different. In the following case we end up -@@ -5246,11 +5316,15 @@ - -- Both sides are unique, but base quals are different - explain (costs off) - select * from sl t1, sl t2 where t1.a = t2.a and t1.b = 1 and t2.b = 2; -- QUERY PLAN ------------------------------------------------------- -- Seq Scan on sl t2 -- Filter: ((a IS NOT NULL) AND (b = 2) AND (b = 1)) --(2 rows) -+ QUERY PLAN -+------------------------------ -+ Nested Loop -+ Join Filter: (t1.a = t2.a) -+ -> Seq Scan on sl t1 -+ Filter: (b = 1) -+ -> Seq Scan on sl t2 -+ Filter: (b = 2) -+(6 rows) - - -- - ---- Only one side is unqiue 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 @@ -1665,491 +530,84 @@ 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/object_address.out ../tmp_check/regress_outdir/results/object_address.out ---- ../../../src/test/regress/expected/object_address.out CENSORED -+++ ../tmp_check/regress_outdir/results/object_address.out CENSORED -@@ -580,44 +580,6 @@ - AS descr - FROM objects - ORDER BY objects.classid, objects.objid, objects.objsubid; --("(""default acl"",,,)")|("(""default acl"",,)")|NULL --("(tablespace,,,)")|("(tablespace,,)")|NULL --("(type,,,)")|("(type,,)")|NULL --("(routine,,,)")|("(routine,,)")|NULL --("(relation,,,)")|("(relation,,)")|NULL --("(""table column"",,,)")|("(""table column"",,)")|NULL --("(role,,,)")|("(role,,)")|NULL --("(database,,,)")|("(database,,)")|NULL --("(server,,,)")|("(server,,)")|NULL --("(""user mapping"",,,)")|("(""user mapping"",,)")|NULL --("(""foreign-data wrapper"",,,)")|("(""foreign-data wrapper"",,)")|NULL --("(""access method"",,,)")|("(""access method"",,)")|NULL --("(""operator of access method"",,,)")|("(""operator of access method"",,)")|NULL --("(""function of access method"",,,)")|("(""function of access method"",,)")|NULL --("(""default value"",,,)")|("(""default value"",,)")|NULL --("(cast,,,)")|("(cast,,)")|NULL --("(constraint,,,)")|("(constraint,,)")|NULL --("(conversion,,,)")|("(conversion,,)")|NULL --("(language,,,)")|("(language,,)")|NULL --("(""large object"",,,)")|("(""large object"",,)")|NULL --("(schema,,,)")|("(schema,,)")|NULL --("(""operator class"",,,)")|("(""operator class"",,)")|NULL --("(operator,,,)")|("(operator,,)")|NULL --("(rule,,,)")|("(rule,,)")|NULL --("(trigger,,,)")|("(trigger,,)")|NULL --("(""operator family"",,,)")|("(""operator family"",,)")|NULL --("(extension,,,)")|("(extension,,)")|NULL --("(policy,,,)")|("(policy,,)")|NULL --("(""statistics object"",,,)")|("(""statistics object"",,)")|NULL --("(collation,,,)")|("(collation,,)")|NULL --("(""event trigger"",,,)")|("(""event trigger"",,)")|NULL --("(transform,,,)")|("(transform,,)")|NULL --("(""text search dictionary"",,,)")|("(""text search dictionary"",,)")|NULL --("(""text search parser"",,,)")|("(""text search parser"",,)")|NULL --("(""text search configuration"",,,)")|("(""text search configuration"",,)")|NULL --("(""text search template"",,,)")|("(""text search template"",,)")|NULL --("(subscription,,,)")|("(subscription,,)")|NULL --("(publication,,,)")|("(publication,,)")|NULL --("(""publication relation"",,,)")|("(""publication relation"",,)")|NULL -+ERROR: unrecognized object class: 16512 - -- restore normal output mode - \a\t +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 +@@ -1493,11 +1493,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/atx2.out ../tmp_check/regress_outdir/results/atx2.out --- ../../../src/test/regress/expected/atx2.out CENSORED +++ ../tmp_check/regress_outdir/results/atx2.out CENSORED -@@ -287,362 +287,9 @@ +@@ -287,17 +287,14 @@ return 1; end$$; select atx_lo_test10(:my_loid); -- atx_lo_test10 ----------------- -- 1 --(1 row) -- --select lo_unlink(:my_loid); ++NOTICE: other exception 42703, [MTM] failed to prepare transaction at peer node + atx_lo_test10 + --------------- + 1 + (1 row) + + select lo_unlink(:my_loid); - lo_unlink ------------ - 1 -(1 row) - ---- put some initial data --select lo_creat(-1) as my_loid \gset --select lo_put( :my_loid, 0, 'lo test' ); -- lo_put ---------- -- --(1 row) -- ---- This function should not fail --select * from lo_test_func( :my_loid ); -- lo_test_func ---------------- -- 0 --(1 row) -- ---- Read something --select convert_from(data, 'UTF8') from pg_largeobject where loid = :my_loid; -- convert_from ------------------- -- My mega lo test --(1 row) -- ---- 11 --DO $body$ --begin -- begin -- begin autonomous -- set datestyle = 'euro'; -- end; -- exception -- when others then -- raise notice 'exception %, %', SQLSTATE, SQLERRM; -- end; --end; --$body$ language plpgsql; ---- 12 --create table if not exists atx_tt1(f1 int); --create function count_tt1_v() returns int8 as 'select count(*) from atx_tt1' language sql volatile; --create function count_tt1_s() returns int8 as 'select count(*) from atx_tt1' language sql stable; --begin; -- begin autonomous; -- insert into atx_tt1 values(1); -- declare c1 cursor for select count_tt1_v(), count_tt1_s(); -- insert into atx_tt1 values(2); -- fetch all from c1; -- count_tt1_v | count_tt1_s ---------------+------------- -- 2 | 1 --(1 row) -- -- rollback; --rollback; --begin; -- begin autonomous; -- insert into atx_tt1 values(1); -- declare c2 cursor with hold for select count_tt1_v(), count_tt1_s(); -- insert into atx_tt1 values(2); -- commit; --commit; --begin; -- begin autonomous; -- insert into atx_tt1 values(1); -- declare c1 cursor for select count_tt1_v(), count_tt1_s(); -- begin autonomous; -- fetch all from c1; --ERROR: cursor "c1" does not exist -- rollback; -- rollback; --rollback; --drop function count_tt1_v(); --drop function count_tt1_s(); --drop table if exists atx_tt1; --close c2; ---- 13 --create table atx_13_t(i int); --begin; -- begin autonomous; -- update atx_13_t set i = 1; -- rollback; -- begin autonomous; -- update atx_13_t set i = 2; -- rollback; -- drop table if exists atx_13_t; -- begin autonomous; -- update atx_13_t set i = 3 where i in (select i from atx_13_t); --ERROR: lockmode RowExclusiveLock conflicts with lock AccessExclusiveLock of parent transaction, acquiring this lock in an autonomous transaction will lead to a sure deadlock --LINE 1: update atx_13_t set i = 3 where i in (select i from atx_13_t... -- ^ -- rollback; --commit; ---- 14 --create or replace function atx_14_trigger_func() returns trigger as $body$ --begin -- return null; --end; --$body$ language plpgsql; --create table atx_14_test(a text, b text); --create trigger atx_14_test_audit --after insert on atx_14_test --for each row execute procedure atx_14_trigger_func(); --begin; -- insert into atx_14_test values (125); -- begin autonomous transaction; -- commit; -- insert into atx_14_test values (1); --commit; --drop table if exists atx_14_test; --drop function atx_14_trigger_func(); ---- 15 --create or replace function atx_15_dummy() returns text as $$ --declare -- x text; --begin -- x := 'one'; -- begin autonomous -- x := 'two'; -- end; -- return x; --end; $$ language plpgsql; --create table atx_15_test as select 1 as int, NULL as name; --update atx_15_test set name = atx_15_dummy() returning *; -- int | name -------+------ -- 1 | two --(1 row) -- --drop table if exists atx_15_test; --drop function if exists atx_15_dummy(); ---- 16 --create table test(i int); --begin; -- begin autonomous; -- insert into test values(1); -- declare c cursor for select * from test; -- begin autonomous; -- commit; -- rollback; --rollback; --drop table if exists test; ---- 17 --create table test(f1 int); --begin; -- begin autonomous; -- insert into test values(1); -- declare c1 cursor for select * from test; -- begin autonomous; -- fetch all from c1; --ERROR: cursor "c1" does not exist -- rollback; -- rollback; --rollback; --drop table if exists test; ---- 19 --create or replace function error_func() returns int as $body$ --begin -- return 0/0; --end; --$body$ language plpgsql; --DO $body$ --begin -- begin -- begin autonomous -- select error_func(); -- end; -- exception -- when others then -- raise notice 'exception %, %', SQLSTATE, SQLERRM; -- end; --end; --$body$ language plpgsql; --NOTICE: exception 22012, division by zero --drop function if exists error_func(); ---- 21 --CREATE OR REPLACE FUNCTION error_function() -- RETURNS integer AS --$BODY$ --begin -- begin autonomous -- SELECT 0/0; -- end; -- return 1; --exception -- when others then -- raise notice 'other exception %, %', SQLSTATE, SQLERRM; --end; --$BODY$ LANGUAGE plpgsql; --create table if not exists atx_tt2(f1 int); --begin; -- begin autonomous; -- insert into atx_tt2 values(1); -- declare c2 cursor with hold for select error_function(); -- commit; ++ERROR: [MTM] failed to prepare transaction at peer node + -- put some initial data + select lo_creat(-1) as my_loid \gset + select lo_put( :my_loid, 0, 'lo test' ); +@@ -356,6 +353,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; +@@ -371,6 +369,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; +@@ -490,9 +489,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() --commit; --drop function if exists error_function(); --drop table if exists atx_tt2; ---- 22 --create or replace function if_modified_func_22() returns trigger as $body$ --declare -- v_new_data text; --begin -- v_new_data := row(new.*); -- begin autonomous -- return new; -- end; --end; --$body$ language plpgsql; --create table atx_test_22(a text, b text); --create trigger atx_test_22_audit --after insert on atx_test_22 --for each row execute procedure if_modified_func_22(); --begin; -- insert into atx_test_22 values (1); -- begin autonomous transaction; -- commit; -- insert into atx_test_22 values (2); --commit; --drop table if exists atx_test_22; --drop function if exists if_modified_func_22(); ---- 23 --CREATE OR REPLACE FUNCTION error_function3() -- RETURNS integer AS --$BODY$ --begin -- begin autonomous -- SELECT 0/0; -- end; -- return 1; --exception -- when others then -- raise notice 'other exception %, %', SQLSTATE, SQLERRM; --end; --$BODY$ LANGUAGE plpgsql; --begin; -- begin autonomous; -- declare c2 cursor with hold for select error_function3(); -- commit; --NOTICE: other exception 22012, division by zero --ERROR: control reached end of function without RETURN --CONTEXT: PL/pgSQL function error_function3() --commit; --drop function if exists error_function3(); --close c2; --ERROR: cursor "c2" does not exist ---- 24 --CREATE OR REPLACE FUNCTION error_function3() -- RETURNS integer AS --$BODY$ --begin -- begin autonomous -- SELECT 0/0; -- end; -- return 1; --exception -- when others then -- raise notice 'other exception %, %', SQLSTATE, SQLERRM; -- return 0; --end; --$BODY$ LANGUAGE plpgsql; --begin; -- begin autonomous; -- declare c3 cursor with hold for select error_function3(); -- commit; --NOTICE: other exception 22012, division by zero --commit; --drop function if exists error_function3(); --close c3; ---- 25 --select count(*) * 0 as dummy_res from ( select pg_terminate_backend(pid) from pg_stat_activity where datname = 'regression_atx_test_database' ) as foo; -- dummy_res ------------- -- 0 --(1 row) -- --SET client_min_messages TO 'warning'; --drop database if exists regression_atx_test_database; --RESET client_min_messages; --create database regression_atx_test_database; --ALTER DATABASE "regression_atx_test_database" SET lc_messages TO 'C'; --\c regression_atx_test_database --create table atx_test as select 1 as id; --begin; -- begin autonomous; -- create table tmp1 as select id from atx_test; -- delete from atx_test where id in ( select id from unknown ); --ERROR: relation "unknown" does not exist --LINE 1: delete from atx_test where id in ( select id from unknown ); -- ^ -- rollback; -- begin autonomous; -- drop table atx_test; --\c regression ---- PGPRO-5052 --BEGIN TRANSACTION; BEGIN AUTONOMOUS TRANSACTION; --CREATE FUNCTION atx_srf_test_func() RETURNS setof text AS --$$ SELECT 'foo'::varchar $$ --LANGUAGE SQL; --SELECT atx_srf_test_func(); -- atx_srf_test_func --------------------- -- foo --(1 row) -- --COMMIT AUTONOMOUS; COMMIT; --DROP FUNCTION atx_srf_test_func(); ---- PGPRO-5860 --create table mmm5860(i int); --create or replace function crash_func5860() returns int language plpgsql as $$ --declare --begin -- create table if not exists mmm5860(i int); -- begin autonomous -- begin -- create table if not exists mmm5860(i int); -- exception -- when others then -- raise notice 'other exception %, %', SQLSTATE, SQLERRM; -- end; -- end; -- return 1; --end$$; --select * from crash_func5860(); --NOTICE: relation "mmm5860" already exists, skipping --NOTICE: relation "mmm5860" already exists, skipping -- crash_func5860 ------------------ -- 1 --(1 row) -- --drop function crash_func5860(); --drop table mmm5860; ---- PGPRO-6207 --BEGIN; --COMMIT AUTONOMOUS; --WARNING: there is no autonomous transaction in progress --BEGIN; --ABORT AUTONOMOUS; --WARNING: there is no autonomous transaction in progress --BEGIN; -- SAVEPOINT sp; --COMMIT AUTONOMOUS; --WARNING: there is no autonomous transaction in progress --BEGIN; -- SAVEPOINT sp; --ABORT AUTONOMOUS; --WARNING: there is no autonomous transaction in progress -+FATAL: RollbackAndReleaseCurrentSubTransaction: unexpected state DEFAULT -+CONTEXT: PL/pgSQL function atx_lo_test10(oid) line 9 during exception cleanup -+server closed the connection unexpectedly -+ This probably means the server terminated abnormally -+ before or while processing the request. -+connection to server was lost ++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; +@@ -582,6 +579,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/atx3.out ../tmp_check/regress_outdir/results/atx3.out --- ../../../src/test/regress/expected/atx3.out CENSORED +++ ../tmp_check/regress_outdir/results/atx3.out CENSORED @@ -2274,18 +732,6 @@ diff ../../../src/test/regress/expected/atx3.out ../tmp_check/regress_outdir/res RESET default_transaction_read_only; DROP TABLE abc; -diff ../../../src/test/regress/expected/sysviews.out ../tmp_check/regress_outdir/results/sysviews.out ---- ../../../src/test/regress/expected/sysviews.out CENSORED -+++ ../tmp_check/regress_outdir/results/sysviews.out CENSORED -@@ -119,7 +119,7 @@ - enable_partition_pruning | on - enable_partitionwise_aggregate | off - enable_partitionwise_join | off -- enable_self_join_removal | on -+ enable_self_join_removal | off - enable_seqscan | on - enable_sort | on - enable_tidscan | on diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/results/rules.out --- ../../../src/test/regress/expected/rules.out CENSORED +++ ../tmp_check/regress_outdir/results/rules.out CENSORED @@ -2305,7 +751,7 @@ diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/re iexit| SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit -@@ -1443,19 +1452,30 @@ +@@ -1465,15 +1474,15 @@ p.generic_plans, p.custom_plans FROM pg_prepared_statement() p(name, statement, prepare_time, parameter_types, from_sql, generic_plans, custom_plans); @@ -2327,246 +773,224 @@ diff ../../../src/test/regress/expected/rules.out ../tmp_check/regress_outdir/re + 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))) -@@ -1651,7 +1671,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, -@@ -1663,7 +1683,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, -@@ -2099,7 +2119,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, -@@ -2524,6 +2544,19 @@ - LEFT JOIN pg_namespace sn ON ((sn.oid = s.stxnamespace))) - JOIN LATERAL ( SELECT unnest(pg_get_statisticsobjdef_expressions(s.oid)) AS expr, - unnest(sd.stxdexpr) AS a) stat ON ((stat.expr IS NOT NULL))); -+pg_subscription| SELECT _pg_subscription.oid, -+ _pg_subscription.subdbid, -+ _pg_subscription.subname, -+ _pg_subscription.subowner, -+ _pg_subscription.subenabled, -+ _pg_subscription.subbinary, -+ _pg_subscription.substream, -+ _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 -@@ -2813,36 +2813,14 @@ - CREATE VIEW view_heap_psql AS SELECT f1 from tbl_heap_psql; - CREATE MATERIALIZED VIEW mat_view_heap_psql USING heap_psql AS SELECT f1 from tbl_heap_psql; - \d+ tbl_heap_psql -- Table "tableam_display.tbl_heap_psql" -- Column | Type | Collation | Nullable | Default | Storage | Stats target | Description ----------+----------------+-----------+----------+---------+----------+--------------+------------- -- f1 | integer | | | | plain | | -- f2 | character(100) | | | | extended | | -- -+ERROR: permission denied for view pg_publication - \d+ tbl_heap -- Table "tableam_display.tbl_heap" -- Column | Type | Collation | Nullable | Default | Storage | Stats target | Description ----------+----------------+-----------+----------+---------+----------+--------------+------------- -- f1 | integer | | | | plain | | -- f2 | character(100) | | | | extended | | -- -+ERROR: permission denied for view pg_publication - \set HIDE_TABLEAM off - \d+ tbl_heap_psql -- Table "tableam_display.tbl_heap_psql" -- Column | Type | Collation | Nullable | Default | Storage | Stats target | Description ----------+----------------+-----------+----------+---------+----------+--------------+------------- -- f1 | integer | | | | plain | | -- f2 | character(100) | | | | extended | | --Access method: heap_psql -- -+ERROR: permission denied for view pg_publication - \d+ tbl_heap -- Table "tableam_display.tbl_heap" -- Column | Type | Collation | Nullable | Default | Storage | Stats target | Description ----------+----------------+-----------+----------+---------+----------+--------------+------------- -- f1 | integer | | | | plain | | -- f2 | character(100) | | | | extended | | --Access method: heap -- -+ERROR: permission denied for view pg_publication - -- AM is displayed for tables, indexes and materialized views. - \d+ - List of relations 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); +@@ -31,18 +32,20 @@ + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root + --------------------+--------------------------+------------+---------+---------+---------+-----------+---------- ++ multimaster | miker | f | t | f | f | t | f + 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 + --------------------+--------------------------+------------+---------+---------+---------+-----------+---------- ++ multimaster | miker | f | t | f | f | t | f + 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 -diff ../../../src/test/regress/expected/equivclass.out ../tmp_check/regress_outdir/results/equivclass.out ---- ../../../src/test/regress/expected/equivclass.out CENSORED -+++ ../tmp_check/regress_outdir/results/equivclass.out CENSORED -@@ -438,15 +438,17 @@ - explain (costs off) - select * from ec0 m join ec0 n on m.ff = n.ff - join ec1 p on m.ff + n.ff = p.f1; -- QUERY PLAN ------------------------------------------ -+ QUERY PLAN -+------------------------------------------------ - Nested Loop -- Join Filter: ((n.ff + n.ff) = p.f1) -- -> Seq Scan on ec1 p -+ Join Filter: ((m.ff + n.ff) = p.f1) -+ -> Nested Loop -+ -> Seq Scan on ec0 m -+ -> Index Scan using ec0_pkey on ec0 n -+ Index Cond: (ff = m.ff) - -> Materialize -- -> Seq Scan on ec0 n -- Filter: (ff IS NOT NULL) --(6 rows) -+ -> Seq Scan on ec1 p -+(8 rows) - - explain (costs off) - select * from ec0 m join ec0 n on m.ff = n.ff -@@ -454,12 +456,14 @@ - QUERY PLAN - --------------------------------------------------------------- - Nested Loop -- Join Filter: ((p.f1)::bigint = ((n.ff + n.ff))::int8alias1) -- -> Seq Scan on ec1 p -+ Join Filter: ((p.f1)::bigint = ((m.ff + n.ff))::int8alias1) -+ -> Nested Loop -+ -> Seq Scan on ec0 m -+ -> Index Scan using ec0_pkey on ec0 n -+ Index Cond: (ff = m.ff) - -> Materialize -- -> Seq Scan on ec0 n -- Filter: (ff IS NOT NULL) --(6 rows) -+ -> Seq Scan on ec1 p -+(8 rows) - - reset enable_mergejoin; - -- this could be converted, but isn't at present -diff ../../../src/test/regress/expected/copy2.out ../tmp_check/regress_outdir/results/copy2.out ---- ../../../src/test/regress/expected/copy2.out CENSORED -+++ ../tmp_check/regress_outdir/results/copy2.out CENSORED -@@ -359,11 +359,12 @@ - (2 rows) - - COMMIT; -+ERROR: [MTM] failed to prepare transaction at peer node - SELECT * FROM vistest; - a - ---- -- d1 -- e -+ a0 -+ b - (2 rows) - - BEGIN; -@@ -387,11 +388,12 @@ - (2 rows) - - COMMIT; -+ERROR: [MTM] failed to prepare transaction at peer node - SELECT * FROM vistest; - a - ---- -- d2 -- e -+ a0 -+ b - (2 rows) + 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 | Synchronous commit | Conninfo +------------------+---------------------------+---------+-------------+--------+-----------+--------------------+----------------------------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo ++-----------------+---------------------------+---------+---------------+--------+-----------+--------------------+----------------------------------------------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist ++(3 rows) + + ALTER SUBSCRIPTION regress_testsub SET PUBLICATION testpub2, testpub3 WITH (refresh = false); + ALTER SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist2'; +@@ -94,11 +98,13 @@ + ALTER SUBSCRIPTION regress_testsub SET (create_slot = false); + ERROR: unrecognized subscription parameter: "create_slot" + \dRs+ +- List of subscriptions +- Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo +------------------+---------------------------+---------+---------------------+--------+-----------+--------------------+------------------------------ ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo ++-----------------+---------------------------+---------+---------------------+--------+-----------+--------------------+----------------------------------------------- + regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | f | off | dbname=regress_doesnotexist2 +-(1 row) ++(3 rows) BEGIN; -@@ -448,12 +450,11 @@ - (2 rows) + ALTER SUBSCRIPTION regress_testsub ENABLE; +@@ -106,16 +112,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; -+ERROR: [MTM] failed to prepare transaction at peer node - SELECT * FROM vistest; -- a ------ -- d4 -- e --(2 rows) -+ a -+--- -+(0 rows) + -- fail - must be owner of subscription +@@ -129,11 +139,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 | Synchronous commit | Conninfo +----------------------+---------------------------+---------+---------------------+--------+-----------+--------------------+------------------------------ ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo ++---------------------+---------------------------+---------+---------------------+--------+-----------+--------------------+----------------------------------------------- + regress_testsub_foo | regress_subscription_user | f | {testpub2,testpub3} | f | f | local | dbname=regress_doesnotexist2 +-(1 row) ++(3 rows) - -- Test FORCE_NOT_NULL and FORCE_NULL options - CREATE TEMP TABLE forcetest ( + -- rename back to keep the rest simple + ALTER SUBSCRIPTION regress_testsub_foo RENAME TO regress_testsub; +@@ -165,20 +177,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 | Synchronous commit | Conninfo +------------------+---------------------------+---------+-------------+--------+-----------+--------------------+----------------------------- +- regress_testsub | regress_subscription_user | f | {testpub} | t | f | off | dbname=regress_doesnotexist +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo ++-----------------+---------------------------+---------+---------------+--------+-----------+--------------------+----------------------------------------------- ++ regress_testsub | regress_subscription_user | f | {testpub} | t | f | off | dbname=regress_doesnotexist ++(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 | Synchronous commit | Conninfo +------------------+---------------------------+---------+-------------+--------+-----------+--------------------+----------------------------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo ++-----------------+---------------------------+---------+---------------+--------+-----------+--------------------+----------------------------------------------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist ++(3 rows) + + DROP SUBSCRIPTION regress_testsub; + -- fail - streaming must be boolean +@@ -188,20 +204,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 | Synchronous commit | Conninfo +------------------+---------------------------+---------+-------------+--------+-----------+--------------------+----------------------------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | t | off | dbname=regress_doesnotexist +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo ++-----------------+---------------------------+---------+---------------+--------+-----------+--------------------+----------------------------------------------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | t | off | dbname=regress_doesnotexist ++(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 | Synchronous commit | Conninfo +------------------+---------------------------+---------+-------------+--------+-----------+--------------------+----------------------------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo ++-----------------+---------------------------+---------+---------------+--------+-----------+--------------------+----------------------------------------------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist ++(3 rows) + + -- fail - publication already exists + ALTER SUBSCRIPTION regress_testsub ADD PUBLICATION testpub WITH (refresh = false); +@@ -215,11 +235,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 | Synchronous commit | Conninfo +------------------+---------------------------+---------+-----------------------------+--------+-----------+--------------------+----------------------------- ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo ++-----------------+---------------------------+---------+-----------------------------+--------+-----------+--------------------+----------------------------------------------- + regress_testsub | regress_subscription_user | f | {testpub,testpub1,testpub2} | f | f | off | dbname=regress_doesnotexist +-(1 row) ++(3 rows) + + -- fail - publication used more then once + ALTER SUBSCRIPTION regress_testsub DROP PUBLICATION testpub1, testpub1 WITH (refresh = false); +@@ -233,11 +255,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 | Synchronous commit | Conninfo +------------------+---------------------------+---------+-------------+--------+-----------+--------------------+----------------------------- +- regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist +-(1 row) ++ List of subscriptions ++ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo ++-----------------+---------------------------+---------+---------------+--------+-----------+--------------------+----------------------------------------------- ++ regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist ++(3 rows) + + DROP SUBSCRIPTION regress_testsub; + CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION mypub 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 @@ -2653,52 +1077,3 @@ diff ../../../src/test/regress/expected/indexing.out ../tmp_check/regress_outdir drop table idxpart_temp; -- ALTER INDEX .. ATTACH, error cases -diff ../../../src/test/regress/expected/oidjoins.out ../tmp_check/regress_outdir/results/oidjoins.out ---- ../../../src/test/regress/expected/oidjoins.out CENSORED -+++ ../tmp_check/regress_outdir/results/oidjoins.out CENSORED -@@ -257,10 +257,10 @@ - NOTICE: checking pg_transform {trftosql} => pg_proc {oid} - NOTICE: checking pg_sequence {seqrelid} => pg_class {oid} - NOTICE: checking pg_sequence {seqtypid} => pg_type {oid} --NOTICE: checking pg_publication {pubowner} => pg_authid {oid} --NOTICE: checking pg_publication_rel {prpubid} => pg_publication {oid} -+NOTICE: checking _pg_publication {pubowner} => pg_authid {oid} -+NOTICE: checking pg_publication_rel {prpubid} => _pg_publication {oid} - NOTICE: checking pg_publication_rel {prrelid} => pg_class {oid} --NOTICE: checking pg_subscription {subdbid} => pg_database {oid} --NOTICE: checking pg_subscription {subowner} => pg_authid {oid} --NOTICE: checking pg_subscription_rel {srsubid} => pg_subscription {oid} -+NOTICE: checking _pg_subscription {subdbid} => pg_database {oid} -+NOTICE: checking _pg_subscription {subowner} => pg_authid {oid} -+NOTICE: checking pg_subscription_rel {srsubid} => _pg_subscription {oid} - NOTICE: checking pg_subscription_rel {srrelid} => pg_class {oid} -diff ../../../src/test/regress/expected/stats.out ../tmp_check/regress_outdir/results/stats.out ---- ../../../src/test/regress/expected/stats.out CENSORED -+++ ../tmp_check/regress_outdir/results/stats.out CENSORED -@@ -99,6 +99,7 @@ - TRUNCATE trunc_stats_test1; - INSERT INTO trunc_stats_test1 DEFAULT VALUES; - COMMIT; -+ERROR: [MTM] failed to prepare transaction at peer node - -- use a savepoint: 1 insert, 1 live - BEGIN; - INSERT INTO trunc_stats_test2 DEFAULT VALUES; -@@ -109,6 +110,7 @@ - INSERT INTO trunc_stats_test2 DEFAULT VALUES; - RELEASE SAVEPOINT p1; - COMMIT; -+ERROR: [MTM] failed to prepare transaction at peer node - -- rollback a savepoint: this should count 4 inserts and have 2 - -- live tuples after commit (and 2 dead ones due to aborted subxact) - BEGIN; -@@ -166,8 +168,8 @@ - relname | n_tup_ins | n_tup_upd | n_tup_del | n_live_tup | n_dead_tup - -------------------+-----------+-----------+-----------+------------+------------ - trunc_stats_test | 3 | 0 | 0 | 0 | 0 -- trunc_stats_test1 | 4 | 2 | 1 | 1 | 0 -- trunc_stats_test2 | 1 | 0 | 0 | 1 | 0 -+ trunc_stats_test1 | 3 | 4 | 1 | 2 | 5 -+ trunc_stats_test2 | 2 | 0 | 0 | 0 | 2 - trunc_stats_test3 | 4 | 0 | 0 | 2 | 2 - trunc_stats_test4 | 2 | 0 | 0 | 0 | 2 - (5 rows) diff --git a/t/001_regress.pl b/t/001_regress.pl index cbe1feaaa0..bc36577842 100644 --- a/t/001_regress.pl +++ b/t/001_regress.pl @@ -68,10 +68,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{ @@ -89,6 +85,7 @@ $schedule =~ s/test: cfs/#test: cfs/g; $schedule =~ s/test: largeobject//; # serial schedule $schedule =~ s/largeobject//; # parallel schedule +$schedule =~ s/atx0//; # parallel schedule unlink('parallel_schedule'); TestLib::append_to_file('parallel_schedule', $schedule); @@ -146,6 +143,7 @@ $expected_file = "expected/regression_vanilla.diff" } $diff = TestLib::system_log("diff -U3 ${expected_file} $ENV{TESTDIR}/results/regression.diff"); +run [ "sed", "-i", "/mtm_sub_/d", "$ENV{TESTDIR}/results/regression.diff" ]; run [ "diff", "-U3", "${expected_file}", "$ENV{TESTDIR}/results/regression.diff" ], ">", "$ENV{TESTDIR}/regression.diff.diff"; my $res = $?; From afdeb79b02fe575aac2ea22ea915129b9bd2b78a Mon Sep 17 00:00:00 2001 From: Mikhail Rutman Date: Wed, 8 Jun 2022 17:40:46 +0700 Subject: [PATCH 08/32] Remove regression test atx2 and update regression_ee.diff Tag: Multimaster --- expected/regression_ee.diff | 60 ------------------------------------- t/001_regress.pl | 7 ++++- 2 files changed, 6 insertions(+), 61 deletions(-) diff --git a/expected/regression_ee.diff b/expected/regression_ee.diff index c37becee73..c77220b730 100644 --- a/expected/regression_ee.diff +++ b/expected/regression_ee.diff @@ -550,64 +550,6 @@ diff ../../../src/test/regress/expected/privileges.out ../tmp_check/regress_outd -- 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/atx2.out ../tmp_check/regress_outdir/results/atx2.out ---- ../../../src/test/regress/expected/atx2.out CENSORED -+++ ../tmp_check/regress_outdir/results/atx2.out CENSORED -@@ -287,17 +287,14 @@ - return 1; - end$$; - select atx_lo_test10(:my_loid); -+NOTICE: other exception 42703, [MTM] failed to prepare transaction at peer node - atx_lo_test10 - --------------- - 1 - (1 row) - - select lo_unlink(:my_loid); -- lo_unlink ------------- -- 1 --(1 row) -- -+ERROR: [MTM] failed to prepare transaction at peer node - -- put some initial data - select lo_creat(-1) as my_loid \gset - select lo_put( :my_loid, 0, 'lo test' ); -@@ -356,6 +353,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; -@@ -371,6 +369,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; -@@ -490,9 +489,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; -@@ -582,6 +579,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/atx3.out ../tmp_check/regress_outdir/results/atx3.out --- ../../../src/test/regress/expected/atx3.out CENSORED +++ ../tmp_check/regress_outdir/results/atx3.out CENSORED @@ -794,7 +736,6 @@ diff ../../../src/test/regress/expected/publication.out ../tmp_check/regress_out List of publications Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root --------------------+--------------------------+------------+---------+---------+---------+-----------+---------- -+ multimaster | miker | f | t | f | f | t | f 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) @@ -805,7 +746,6 @@ diff ../../../src/test/regress/expected/publication.out ../tmp_check/regress_out List of publications Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root --------------------+--------------------------+------------+---------+---------+---------+-----------+---------- -+ multimaster | miker | f | t | f | f | t | f 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) diff --git a/t/001_regress.pl b/t/001_regress.pl index bc36577842..47733ccadc 100644 --- a/t/001_regress.pl +++ b/t/001_regress.pl @@ -86,6 +86,7 @@ $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); @@ -142,8 +143,12 @@ { $expected_file = "expected/regression_vanilla.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", "/+ 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", "/+ multimaster/d", "$ENV{TESTDIR}/results/regression.diff" ]; $diff = TestLib::system_log("diff -U3 ${expected_file} $ENV{TESTDIR}/results/regression.diff"); -run [ "sed", "-i", "/mtm_sub_/d", "$ENV{TESTDIR}/results/regression.diff" ]; run [ "diff", "-U3", "${expected_file}", "$ENV{TESTDIR}/results/regression.diff" ], ">", "$ENV{TESTDIR}/regression.diff.diff"; my $res = $?; From 06ff4d0c21e2148cd9c31a415c1e69ff3a091e89 Mon Sep 17 00:00:00 2001 From: Mikhail Rutman Date: Thu, 9 Jun 2022 00:23:16 +0700 Subject: [PATCH 09/32] support BSD syntax of sed utility in t/001_regress.pl Tags: Multimaster --- t/001_regress.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/t/001_regress.pl b/t/001_regress.pl index 47733ccadc..9bbb3cd99a 100644 --- a/t/001_regress.pl +++ b/t/001_regress.pl @@ -145,9 +145,9 @@ } # 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", "/+ mtm_sub_/d", "$ENV{TESTDIR}/results/regression.diff" ]; +run [ "sed", "-i.bak", "/+ 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", "/+ multimaster/d", "$ENV{TESTDIR}/results/regression.diff" ]; +run [ "sed", "-i.bak", "/+ multimaster/d", "$ENV{TESTDIR}/results/regression.diff" ]; $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 = $?; From 54456baab67dd4c63af42a570ab01afab77831db Mon Sep 17 00:00:00 2001 From: Mikhail Rutman Date: Thu, 9 Jun 2022 23:32:50 +0700 Subject: [PATCH 10/32] Enable TAP test atx2 Tags: Multimaster --- expected/regression_ee.diff | 58 +++++++++++++++++++++++++++++++++++++ t/001_regress.pl | 1 - 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/expected/regression_ee.diff b/expected/regression_ee.diff index c77220b730..be28a270b6 100644 --- a/expected/regression_ee.diff +++ b/expected/regression_ee.diff @@ -550,6 +550,64 @@ diff ../../../src/test/regress/expected/privileges.out ../tmp_check/regress_outd -- 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/atx2.out ../tmp_check/regress_outdir/results/atx2.out +--- ../../../src/test/regress/expected/atx2.out CENSORED ++++ ../tmp_check/regress_outdir/results/atx2.out CENSORED +@@ -287,17 +287,14 @@ + return 1; + end$$; + select atx_lo_test10(:my_loid); ++NOTICE: other exception 42703, [MTM] failed to prepare transaction at peer node + atx_lo_test10 + --------------- + 1 + (1 row) + + select lo_unlink(:my_loid); +- lo_unlink +------------ +- 1 +-(1 row) +- ++ERROR: [MTM] failed to prepare transaction at peer node + -- put some initial data + select lo_creat(-1) as my_loid \gset + select lo_put( :my_loid, 0, 'lo test' ); +@@ -356,6 +353,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; +@@ -371,6 +369,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; +@@ -490,9 +489,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; +@@ -582,6 +579,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/atx3.out ../tmp_check/regress_outdir/results/atx3.out --- ../../../src/test/regress/expected/atx3.out CENSORED +++ ../tmp_check/regress_outdir/results/atx3.out CENSORED diff --git a/t/001_regress.pl b/t/001_regress.pl index 9bbb3cd99a..d614574247 100644 --- a/t/001_regress.pl +++ b/t/001_regress.pl @@ -86,7 +86,6 @@ $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); From 622a4858d21f18fb2f7e16a37808d2136b9a0823 Mon Sep 17 00:00:00 2001 From: Mikhail Rutman Date: Thu, 16 Jun 2022 15:17:13 +0700 Subject: [PATCH 11/32] Update regression_ee.diff --- expected/regression_ee.diff | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/expected/regression_ee.diff b/expected/regression_ee.diff index be28a270b6..d3ee87a940 100644 --- a/expected/regression_ee.diff +++ b/expected/regression_ee.diff @@ -586,7 +586,7 @@ diff ../../../src/test/regress/expected/atx2.out ../tmp_check/regress_outdir/res drop table if exists atx_tt1; close c2; +ERROR: cursor "c2" does not exist - -- 13 + -- create table atx_13_t(i int); begin; @@ -490,9 +489,7 @@ @@ -623,7 +623,7 @@ diff ../../../src/test/regress/expected/atx3.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(); -@@ -383,50 +380,38 @@ +@@ -547,50 +544,38 @@ INSERT INTO abc VALUES (1); INSERT INTO abc VALUES (2); COMMIT AND CHAIN; -- TBLOCK_END @@ -683,7 +683,7 @@ diff ../../../src/test/regress/expected/atx3.out ../tmp_check/regress_outdir/res COMMIT; ROLLBACK; BEGIN; -@@ -498,24 +483,13 @@ +@@ -662,24 +647,13 @@ SAVEPOINT x; COMMIT AND CHAIN; -- TBLOCK_SUBCOMMIT @@ -712,7 +712,7 @@ diff ../../../src/test/regress/expected/atx3.out ../tmp_check/regress_outdir/res COMMIT; ROLLBACK; -- different mix of options just for fun -@@ -586,17 +560,14 @@ +@@ -750,17 +724,14 @@ COMMIT; -- not allowed outside a transaction block COMMIT AUTONOMOUS AND CHAIN; -- error From 27702aff8caa4d80909060be38a64f1e22bc8ae3 Mon Sep 17 00:00:00 2001 From: "Anton A. Melnikov" Date: Mon, 11 Jul 2022 17:55:23 +0700 Subject: [PATCH 12/32] Fix zero MaxBackends --- src/dmq.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/dmq.c b/src/dmq.c index 5f2c0f0458..1cb82d961e 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" @@ -362,9 +364,13 @@ static Size dmq_shmem_size(void) { Size size = 0; + int maxbackends = 0; + + maxbackends = MaxConnections + autovacuum_max_workers + + max_worker_processes + max_wal_senders + 1; size = add_size(size, sizeof(struct DmqSharedState)); - size = add_size(size, hash_estimate_size(DMQ_MAX_SUBS_PER_BACKEND * MaxBackends, + size = add_size(size, hash_estimate_size(DMQ_MAX_SUBS_PER_BACKEND * maxbackends, sizeof(DmqStreamSubscription))); return MAXALIGN(size); } From 88afbdbeca23f9a01445d5000a5b5c529fd145f2 Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Tue, 2 Aug 2022 14:38:01 +0500 Subject: [PATCH 13/32] PG_VERSION_NUM test macro --- src/dmq.c | 12 ++++++++++++ src/multimaster.c | 18 ++++++++++++++++++ src/pglogical_proto.c | 20 ++++++++++++++++++++ src/state.c | 23 +++++++++++++++++++++++ src/syncpoint.c | 8 ++++++++ 5 files changed, 81 insertions(+) diff --git a/src/dmq.c b/src/dmq.c index f328f8de50..cede280449 100644 --- a/src/dmq.c +++ b/src/dmq.c @@ -1119,7 +1119,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); @@ -1623,7 +1627,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 +1656,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/multimaster.c b/src/multimaster.c index 2d52039f64..535f509244 100644 --- a/src/multimaster.c +++ b/src/multimaster.c @@ -1097,7 +1097,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)); @@ -1138,7 +1140,9 @@ 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) { @@ -1148,11 +1152,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()); @@ -1191,7 +1203,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; @@ -1209,7 +1225,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(); } diff --git a/src/pglogical_proto.c b/src/pglogical_proto.c index 93fe60516a..5afbbc5a7d 100644 --- a/src/pglogical_proto.c +++ b/src/pglogical_proto.c @@ -468,7 +468,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 +503,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 +540,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 +572,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 +599,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/state.c b/src/state.c index 6d8e9e331f..2848dfe61c 100644 --- a/src/state.c +++ b/src/state.c @@ -12,7 +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" @@ -1678,7 +1680,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; @@ -1720,7 +1726,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 } /* @@ -1800,10 +1812,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); @@ -4239,7 +4258,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); diff --git a/src/syncpoint.c b/src/syncpoint.c index abde143ef3..6a0dbf96f6 100644 --- a/src/syncpoint.c +++ b/src/syncpoint.c @@ -477,7 +477,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 +494,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); From 0b6494b65cbb82f844d8c8a084a044c7b0ac61d4 Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Tue, 2 Aug 2022 15:23:33 +0500 Subject: [PATCH 14/32] get rid of pg_strtouint64 according to 3c6f8c011f85df7b35c32f4ccaac5c86c9064a4a --- src/multimaster.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/multimaster.c b/src/multimaster.c index 535f509244..cbcaec05a9 100644 --- a/src/multimaster.c +++ b/src/multimaster.c @@ -1548,7 +1548,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) From a71db51b8e4d04f6381c7312ce43ceb7a6e8ddec Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Mon, 25 Jul 2022 13:47:04 +0500 Subject: [PATCH 15/32] fix test scripts for PostgreSQL 15 --- t/000_deadlock.pl | 1 - t/001_regress.pl | 83 ++++++++++++++++++++++++++++++++++------- t/002_regressmm.pl | 33 +++++++++++++--- t/003_basic_recovery.pl | 1 - t/004_recovery.pl | 1 - t/005_pgbench.pl | 1 - t/006_pgbenchdl.pl | 1 - t/007_add_stop_node.pl | 2 - t/008_bugfixes.pl | 2 - t/009_identity_func.pl | 2 - 10 files changed, 97 insertions(+), 30 deletions(-) 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..047cdda3f4 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{ @@ -84,13 +91,28 @@ # 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 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 +121,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 +149,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. @@ -134,7 +177,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 +195,14 @@ { $expected_file = "expected/regression_vanilla.diff" } -$diff = TestLib::system_log("diff -U3 ${expected_file} $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); From 8f063829de25e602053869e43a8ddb1e2e2f61f0 Mon Sep 17 00:00:00 2001 From: "Anton A. Melnikov" Date: Thu, 9 Jun 2022 16:24:15 +0300 Subject: [PATCH 16/32] Replace MaxBackends in dmq_shmem_size() with direct calculation. Cherry-pick of 9ebb737783b74f89024bf18aa528b599b9d32044 --- src/dmq.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/dmq.c b/src/dmq.c index cede280449..e4379c8dc7 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" @@ -362,9 +364,13 @@ static Size dmq_shmem_size(void) { Size size = 0; + int maxbackends = 0; + + maxbackends = MaxConnections + autovacuum_max_workers + + max_worker_processes + max_wal_senders + 1; size = add_size(size, sizeof(struct DmqSharedState)); - size = add_size(size, hash_estimate_size(DMQ_MAX_SUBS_PER_BACKEND * MaxBackends, + size = add_size(size, hash_estimate_size(DMQ_MAX_SUBS_PER_BACKEND * maxbackends, sizeof(DmqStreamSubscription))); return MAXALIGN(size); } From deb86e362548f75f50dae28a1527a6805ad87946 Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Tue, 4 Oct 2022 12:24:59 +0500 Subject: [PATCH 17/32] Accordance with core code changes after rebase The branch of changes in Postgres 15 core for multimaster was rebased after upstream updates. This commit brings multimaster code into line with code of this rebased branche. --- src/dmq.c | 4 ++++ src/pglogical_config.c | 15 +++++++++++++++ src/pglogical_output.c | 2 ++ 3 files changed, 21 insertions(+) diff --git a/src/dmq.c b/src/dmq.c index e4379c8dc7..c01d356c8d 100644 --- a/src/dmq.c +++ b/src/dmq.c @@ -1453,7 +1453,11 @@ dmq_receiver_loop(PG_FUNCTION_ARGS) extra = dmq_receiver_start_hook(sender_name); /* do not hold globalxmin. XXX: try to carefully release snaps */ +#if PG_VERSION_NUM < 150000 MyProc->xmin = InvalidTransactionId; +#else + pg_atomic_write_u64(&MyProc->xmin, InvalidTransactionId); +#endif for (;;) { 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 b4efe4231a..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" From 44623f2addbd58efc27b0687b7345a06b8b71ae8 Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Tue, 11 Oct 2022 16:22:00 +0500 Subject: [PATCH 18/32] PostgreSQL 15: all shared memory requests in shmem_request_hook() --- src/ddl.c | 36 +++++++++++++++++++++++++++++------- src/dmq.c | 35 +++++++++++++++++++++++++++++++---- src/global_tx.c | 22 ++++++++++++++++++++++ src/multimaster.c | 21 +++++++++++++++++++++ src/state.c | 22 ++++++++++++++++++++++ 5 files changed, 125 insertions(+), 11 deletions(-) diff --git a/src/ddl.c b/src/ddl.c index e0aec3a4e0..81070632c4 100644 --- a/src/ddl.c +++ b/src/ddl.c @@ -150,6 +150,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 @@ -159,16 +164,14 @@ PG_FUNCTION_INFO_V1(mtm_make_table_local); void MtmDDLReplicationInit() { - Size size = 0; - - size = add_size(size, sizeof(struct DDLSharedState)); - size = add_size(size, hash_estimate_size(MULTIMASTER_MAX_LOCAL_TABLES, - sizeof(Oid))); - size = MAXALIGN(size); - +#if PG_VERSION_NUM >= 150000 + prev_shmem_request_hook = shmem_request_hook; + shmem_request_hook = mtm_ddl_shmem_request; +#else RequestAddinShmemSpace(size); RequestNamedLWLockTranche("mtm-ddl", 1); +#endif PreviousExecutorStartHook = ExecutorStart_hook; ExecutorStart_hook = MtmExecutorStart; @@ -183,6 +186,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) { diff --git a/src/dmq.c b/src/dmq.c index c01d356c8d..99341a06bf 100644 --- a/src/dmq.c +++ b/src/dmq.c @@ -240,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; @@ -364,14 +369,19 @@ static Size dmq_shmem_size(void) { Size size = 0; - int maxbackends = 0; - - maxbackends = MaxConnections + autovacuum_max_workers + - max_worker_processes + max_wal_senders + 1; +#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); } @@ -384,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)); @@ -408,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() { diff --git a/src/global_tx.c b/src/global_tx.c index 4e1a940982..7473e1fd3c 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,25 @@ 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 + 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 +185,7 @@ MtmGlobalTxInit() RequestAddinShmemSpace(size); RequestNamedLWLockTranche("mtm-gtx-lock", 1); } +#endif void MtmGlobalTxShmemStartup(void) diff --git a/src/multimaster.c b/src/multimaster.c index cbcaec05a9..520658582a 100644 --- a/src/multimaster.c +++ b/src/multimaster.c @@ -220,6 +220,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 @@ -716,8 +720,13 @@ NULL); * 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; @@ -750,6 +759,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 * diff --git a/src/state.c b/src/state.c index 2848dfe61c..fae1868fd8 100644 --- a/src/state.c +++ b/src/state.c @@ -246,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 @@ -255,10 +260,27 @@ 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() { From 58d36b66b911a21d108176b008f60e57d1489e0e Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Fri, 14 Oct 2022 01:13:27 +0500 Subject: [PATCH 19/32] Fix for commit ddc54d42131daf662138da658b9db11f16252ff1 --- src/commit.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/commit.c b/src/commit.c index 877d64215a..4e9d3c5505 100644 --- a/src/commit.c +++ b/src/commit.c @@ -742,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(); } From e00f486fdbdd82a1a52f77e0e7c9104d42add754 Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Tue, 18 Oct 2022 23:29:06 +0500 Subject: [PATCH 20/32] Remove atx2 test from multimaster regression --- expected/regression_ee.diff | 58 ------------------------------------- t/001_regress.pl | 1 + 2 files changed, 1 insertion(+), 58 deletions(-) diff --git a/expected/regression_ee.diff b/expected/regression_ee.diff index d3ee87a940..fee9990e02 100644 --- a/expected/regression_ee.diff +++ b/expected/regression_ee.diff @@ -550,64 +550,6 @@ diff ../../../src/test/regress/expected/privileges.out ../tmp_check/regress_outd -- 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/atx2.out ../tmp_check/regress_outdir/results/atx2.out ---- ../../../src/test/regress/expected/atx2.out CENSORED -+++ ../tmp_check/regress_outdir/results/atx2.out CENSORED -@@ -287,17 +287,14 @@ - return 1; - end$$; - select atx_lo_test10(:my_loid); -+NOTICE: other exception 42703, [MTM] failed to prepare transaction at peer node - atx_lo_test10 - --------------- - 1 - (1 row) - - select lo_unlink(:my_loid); -- lo_unlink ------------- -- 1 --(1 row) -- -+ERROR: [MTM] failed to prepare transaction at peer node - -- put some initial data - select lo_creat(-1) as my_loid \gset - select lo_put( :my_loid, 0, 'lo test' ); -@@ -356,6 +353,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; -@@ -371,6 +369,7 @@ - drop function count_tt1_s(); - drop table if exists atx_tt1; - close c2; -+ERROR: cursor "c2" does not exist - -- - create table atx_13_t(i int); - begin; -@@ -490,9 +489,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; -@@ -582,6 +579,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/atx3.out ../tmp_check/regress_outdir/results/atx3.out --- ../../../src/test/regress/expected/atx3.out CENSORED +++ ../tmp_check/regress_outdir/results/atx3.out CENSORED diff --git a/t/001_regress.pl b/t/001_regress.pl index 4b73d1dd29..85ca458e0b 100644 --- a/t/001_regress.pl +++ b/t/001_regress.pl @@ -101,6 +101,7 @@ $schedule =~ s/test: largeobject//; # serial schedule $schedule =~ s/largeobject//; # parallel schedule $schedule =~ s/atx0//; # parallel schedule +$schedule =~ s/atx2//; # parallel schedule unlink('parallel_schedule'); if ($Cluster::pg_15_modules) { From 5fe8013782e2ee5e3c1d3eaf1d912bb264fffa52 Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Wed, 19 Oct 2022 12:15:30 +0500 Subject: [PATCH 21/32] Add some log and fix COPY BOTH mode --- src/dmq.c | 21 +++++++++++++++++---- src/multimaster.c | 16 ++++++++++++++++ src/pglogical_proto.c | 3 +++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/dmq.c b/src/dmq.c index 99341a06bf..9d565529e2 100644 --- a/src/dmq.c +++ b/src/dmq.c @@ -809,7 +809,7 @@ dmq_sender_main(Datum main_arg) switch (conns[conn_id].state) { case Idle: - Assert(false); +// Assert(false); break; /* @@ -908,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); diff --git a/src/multimaster.c b/src/multimaster.c index eb906b85b1..570e7fe6d4 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 @@ -2040,7 +2042,12 @@ gather(nodemask_t participants, gather_hook_t msg_ok, Datum msg_ok_arg, int *sendconn_cnt, uint64 gen_num) { + time_t start; *msg_count = 0; + + start = time(NULL); + + //elog(LOG, "----> gather 1"); while (participants != 0) { bool ret; @@ -2048,6 +2055,14 @@ gather(nodemask_t participants, StringInfoData msg; int rc; bool wait; + time_t current; + + current = time(NULL); + + if (current - start > 5) { + elog(LOG, "----> gather timeout"); +// return false; + } ret = dmq_pop_nb(&sender_mask_pos, &msg, participants, &wait); if (ret) @@ -2102,6 +2117,7 @@ gather(nodemask_t participants, } } + //elog(LOG, "----> gather 2"); return true; } diff --git a/src/pglogical_proto.c b/src/pglogical_proto.c index 5afbbc5a7d..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, From 946a0e3f62b75f29f9d41886e43b9d0a627a44bb Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Wed, 19 Oct 2022 13:28:27 +0500 Subject: [PATCH 22/32] extra logs for gather --- src/multimaster.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/multimaster.c b/src/multimaster.c index 570e7fe6d4..3adec28e1d 100644 --- a/src/multimaster.c +++ b/src/multimaster.c @@ -2043,6 +2043,7 @@ gather(nodemask_t participants, int *sendconn_cnt, uint64 gen_num) { time_t start; + bool to = false; *msg_count = 0; start = time(NULL); @@ -2059,8 +2060,9 @@ gather(nodemask_t participants, current = time(NULL); - if (current - start > 5) { + if (current - start > 3) { elog(LOG, "----> gather timeout"); + to = true; // return false; } @@ -2117,7 +2119,8 @@ gather(nodemask_t participants, } } - //elog(LOG, "----> gather 2"); + if (to) + elog(LOG, "----> gather end"); return true; } From f209c5b9a186c8b007d146f7b05251bf933d54cd Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Wed, 19 Oct 2022 13:37:29 +0500 Subject: [PATCH 23/32] connect backend before start receiver loop --- src/dmq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dmq.c b/src/dmq.c index 9d565529e2..48fe1430a5 100644 --- a/src/dmq.c +++ b/src/dmq.c @@ -1498,6 +1498,8 @@ dmq_receiver_loop(PG_FUNCTION_ARGS) #else pg_atomic_write_u64(&MyProc->xmin, InvalidTransactionId); #endif + dmq_receiver_recreate_mqs(&dmq_state->receivers[receiver_id], + segs, mq_handles); for (;;) { From b97727a63e4d9b222cb456dcc2b736c99b84d4bd Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Wed, 19 Oct 2022 13:46:23 +0500 Subject: [PATCH 24/32] fix LogLogicalMessage() in multimaster --- src/ddl.c | 3 ++- src/multimaster.c | 3 ++- src/syncpoint.c | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ddl.c b/src/ddl.c index 81070632c4..e9e199f428 100644 --- a/src/ddl.c +++ b/src/ddl.c @@ -680,7 +680,8 @@ 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); } diff --git a/src/multimaster.c b/src/multimaster.c index 3adec28e1d..0cd1d340b3 100644 --- a/src/multimaster.c +++ b/src/multimaster.c @@ -1389,6 +1389,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); @@ -1415,7 +1416,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(); { diff --git a/src/syncpoint.c b/src/syncpoint.c index 6a0dbf96f6..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 " From 1d03df8b0c4f67d7336bf25f5f3a3852444cfe00 Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Wed, 19 Oct 2022 14:11:42 +0500 Subject: [PATCH 25/32] Postgres 15 + multimaster regression DIFF New expected/regresssion_ee.diff, since the set and the content of regression tests were changed in Postgres 15. Additional filter for multimaster regression.diff, since core c10f830c511f0ba3e6f4c9d99f444d39e30440c8 makes paths more canonical (fewer '.'s and '..'s) Tags: Multimaster --- expected/regression_ee.diff | 1194 ++++++++++++++++++++++++++++++----- t/001_regress.pl | 7 +- 2 files changed, 1043 insertions(+), 158 deletions(-) diff --git a/expected/regression_ee.diff b/expected/regression_ee.diff index fee9990e02..78559855e8 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 -@@ -1398,31 +1398,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. -@@ -1434,7 +1436,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; -@@ -1443,8 +1447,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 -@@ -1454,12 +1456,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; -@@ -1470,12 +1466,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 -@@ -1485,7 +1475,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; -@@ -1494,34 +1486,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 -@@ -2610,46 +2610,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,42 +260,6 @@ 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 -@@ -32,6 +32,8 @@ - check_tbl|f - circle_tbl|t - city|f -+cluster_nodes|t -+config|t - copy_tbl|f - d|f - d_star|f -@@ -67,6 +69,7 @@ - jtbl|t - kd_point_tbl|t - line_tbl|f -+local_tables|t - log_table|f - lseg_tbl|f - main_table|f -@@ -83,6 +86,7 @@ - mlparted_defd|f - money_data|f - mytable|t -+nodes_init_done|t - num_data|f - num_exp_add|t - num_exp_div|t -@@ -187,6 +191,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 @@ -351,7 +315,7 @@ diff ../../../src/test/regress/expected/select_into.out ../tmp_check/regress_out 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 @@ -411,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 @@ -440,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 @@ -460,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 @@ -469,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 @@ -497,7 +461,7 @@ 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 -@@ -1029,7 +1000,7 @@ +@@ -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 @@ -506,7 +470,7 @@ diff ../../../src/test/regress/expected/transactions.out ../tmp_check/regress_ou SHOW transaction_isolation; -- out of transaction block transaction_isolation ----------------------- -@@ -1049,9 +1020,8 @@ +@@ -1109,9 +1080,8 @@ a ---- 7 @@ -517,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 @@ -533,7 +515,7 @@ diff ../../../src/test/regress/expected/brin.out ../tmp_check/regress_outdir/res 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 -@@ -1493,11 +1493,16 @@ +@@ -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); @@ -679,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, @@ -690,10 +672,10 @@ 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 -@@ -1465,15 +1474,15 @@ + 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); @@ -706,18 +688,759 @@ 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_tables| SELECT p.pubname, n.nspname AS schemaname, - c.relname AS tablename + c.relname AS tablename, +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; +@@ -5472,48 +5473,47 @@ + CONTEXT: PL/pgSQL function psql_error(text) line 3 at RAISE + INSERT INTO bla VALUES ('Calvin'), ('Hobbes'); + COMMIT; ++ERROR: [MTM] failed to prepare transaction at peer node + SELECT * FROM bla ORDER BY 1; +- s +--------- +- Calvin +- Hobbes +-(2 rows) +- ++ERROR: relation "bla" does not exist ++LINE 1: SELECT * FROM bla ORDER BY 1; ++ ^ + BEGIN; + INSERT INTO bla VALUES ('Susie'); -- succeeds ++ERROR: relation "bla" does not exist ++LINE 1: INSERT INTO bla VALUES ('Susie'); ++ ^ + -- now with combined queries + INSERT INTO bla VALUES ('Rosalyn') \; -- will rollback + SELECT 'before error' AS show \; -- will show nevertheless! + SELECT psql_error('boum!') \; -- failure + SELECT 'after error' AS noshow; -- hidden by preceding error +- show +--------------- +- before error +-(1 row) +- +-ERROR: error boum! +-CONTEXT: PL/pgSQL function psql_error(text) line 3 at RAISE ++ERROR: relation "bla" does not exist ++LINE 1: INSERT INTO bla VALUES ('Rosalyn') ; -- will rollback ++ ^ + INSERT INTO bla(s) VALUES ('Moe') \; -- will rollback + SELECT psql_error('bam!'); +-ERROR: error bam! +-CONTEXT: PL/pgSQL function psql_error(text) line 3 at RAISE ++ERROR: relation "bla" does not exist ++LINE 1: INSERT INTO bla(s) VALUES ('Moe') ; -- will rollback ++ ^ + INSERT INTO bla VALUES ('Miss Wormwood'); -- succeeds ++ERROR: relation "bla" does not exist ++LINE 1: INSERT INTO bla VALUES ('Miss Wormwood'); ++ ^ + COMMIT; + SELECT * FROM bla ORDER BY 1; +- s +---------------- +- Calvin +- Hobbes +- Miss Wormwood +- Susie +-(4 rows) +- ++ERROR: relation "bla" does not exist ++LINE 1: SELECT * FROM bla ORDER BY 1; ++ ^ + -- some with autocommit off + \set AUTOCOMMIT off + \echo '# AUTOCOMMIT:' :AUTOCOMMIT + # AUTOCOMMIT: off + -- implicit BEGIN + INSERT INTO bla VALUES ('Dad'); -- succeeds ++ERROR: relation "bla" does not exist ++LINE 1: INSERT INTO bla VALUES ('Dad'); ++ ^ + SELECT psql_error('bad!'); -- implicit partial rollback + ERROR: error bad! + CONTEXT: PL/pgSQL function psql_error(text) line 3 at RAISE +@@ -5521,38 +5521,25 @@ + SELECT COUNT(*) AS "#mum" + FROM bla WHERE s = 'Mum' \; -- but be counted here + SELECT psql_error('bad!'); -- implicit partial rollback +- #mum +------- +- 1 +-(1 row) +- +-ERROR: error bad! +-CONTEXT: PL/pgSQL function psql_error(text) line 3 at RAISE ++ERROR: relation "bla" does not exist ++LINE 1: INSERT INTO bla VALUES ('Mum') ; -- will rollback ++ ^ + COMMIT; + SELECT COUNT(*) AS "#mum" + FROM bla WHERE s = 'Mum' \; -- no mum here + SELECT * FROM bla ORDER BY 1; +- #mum +------- +- 0 +-(1 row) +- +- s +---------------- +- Calvin +- Dad +- Hobbes +- Miss Wormwood +- Susie +-(5 rows) +- ++ERROR: relation "bla" does not exist ++LINE 2: FROM bla WHERE s = 'Mum' ; -- no mum here ++ ^ + -- reset all + \set AUTOCOMMIT on + \set ON_ERROR_ROLLBACK off + \echo '# final ON_ERROR_ROLLBACK:' :ON_ERROR_ROLLBACK + # final ON_ERROR_ROLLBACK: off + DROP TABLE bla; ++ERROR: table "bla" does not exist + DROP FUNCTION psql_error; ++ERROR: current transaction is aborted, commands ignored until end of transaction block + -- check describing invalid multipart names + \dA regression.heap + improper qualified name (too many dotted names): regression.heap +@@ -5776,253 +5763,90 @@ + improper qualified name (too many dotted names): nonesuch.myevt + -- check that dots within quoted name segments are not counted + \dA "no.such.access.method" +-List of access methods +- Name | Type +-------+------ +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dt "no.such.table.relation" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \da "no.such.aggregate.function" +- List of aggregate functions +- Schema | Name | Result data type | Argument data types | Description +---------+------+------------------+---------------------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dAc "no.such.operator.class" +- List of operator classes +- AM | Input type | Storage type | Operator class | Default? +-----+------------+--------------+----------------+---------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dAf "no.such.operator.family" +- List of operator families +- AM | Operator family | Applicable types +-----+-----------------+------------------ +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dAo "no.such.operator.of.operator.family" +- List of operators of operator families +- AM | Operator family | Operator | Strategy | Purpose +-----+-----------------+----------+----------+--------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dAp "no.such.operator.support.function.of.operator.family" +- List of support functions of operator families +- AM | Operator family | Registered left type | Registered right type | Number | Function +-----+-----------------+----------------------+-----------------------+--------+---------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \db "no.such.tablespace" +- List of tablespaces +- Name | Owner | Location +-------+-------+---------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dc "no.such.conversion" +- List of conversions +- Schema | Name | Source | Destination | Default? +---------+------+--------+-------------+---------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dC "no.such.cast" +- List of casts +- Source type | Target type | Function | Implicit? +--------------+-------------+----------+----------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dd "no.such.object.description" +- Object descriptions +- Schema | Name | Object | Description +---------+------+--------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dD "no.such.domain" +- List of domains +- Schema | Name | Type | Collation | Nullable | Default | Check +---------+------+------+-----------+----------+---------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \ddp "no.such.default.access.privilege" +- Default access privileges +- Owner | Schema | Type | Access privileges +--------+--------+------+------------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \di "no.such.index.relation" +- List of relations +- Schema | Name | Type | Owner | Table +---------+------+------+-------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dm "no.such.materialized.view" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \ds "no.such.relation" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dt "no.such.relation" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dv "no.such.relation" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \des "no.such.foreign.server" +- List of foreign servers +- Name | Owner | Foreign-data wrapper +-------+-------+---------------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dew "no.such.foreign.data.wrapper" +- List of foreign-data wrappers +- Name | Owner | Handler | Validator +-------+-------+---------+----------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \df "no.such.function" +- List of functions +- Schema | Name | Result data type | Argument data types | Type +---------+------+------------------+---------------------+------ +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dF "no.such.text.search.configuration" +-List of text search configurations +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dFd "no.such.text.search.dictionary" +-List of text search dictionaries +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dFp "no.such.text.search.parser" +- List of text search parsers +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dFt "no.such.text.search.template" +-List of text search templates +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dg "no.such.role" +- List of roles +- Role name | Attributes | Member of +------------+------------+----------- +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dL "no.such.language" +- List of languages +- Name | Owner | Trusted | Description +-------+-------+---------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dn "no.such.schema" +-List of schemas +- Name | Owner +-------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \do "no.such.operator" +- List of operators +- Schema | Name | Left arg type | Right arg type | Result type | Description +---------+------+---------------+----------------+-------------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dO "no.such.collation" +- List of collations +- Schema | Name | Collate | Ctype | ICU Locale | Provider | Deterministic? +---------+------+---------+-------+------------+----------+---------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dp "no.such.access.privilege" +- Access privileges +- Schema | Name | Type | Access privileges | Column privileges | Policies +---------+------+------+-------------------+-------------------+---------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dP "no.such.partitioned.relation" +- List of partitioned relations +- Schema | Name | Owner | Type | Parent name | Table +---------+------+-------+------+-------------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \drds "no.such.setting" +- List of settings +- Role | Database | Settings +-------+----------+---------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dRp "no.such.publication" +- List of publications +- Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root +-------+-------+------------+---------+---------+---------+-----------+---------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dRs "no.such.subscription" +- List of subscriptions +- Name | Owner | Enabled | Publication +-------+-------+---------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dT "no.such.data.type" +- List of data types +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dx "no.such.installed.extension" +- List of installed extensions +- Name | Version | Schema | Description +-------+---------+--------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dX "no.such.extended.statistics" +- List of extended statistics +- Schema | Name | Definition | Ndistinct | Dependencies | MCV +---------+------+------------+-----------+--------------+----- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dy "no.such.event.trigger" +- List of event triggers +- Name | Event | Owner | Enabled | Function | Tags +-------+-------+-------+---------+----------+------ +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + -- again, but with dotted schema qualifications. + \dA "no.such.schema"."no.such.access.method" + improper qualified name (too many dotted names): "no.such.schema"."no.such.access.method" + \dt "no.such.schema"."no.such.table.relation" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \da "no.such.schema"."no.such.aggregate.function" +- List of aggregate functions +- Schema | Name | Result data type | Argument data types | Description +---------+------+------------------+---------------------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dAc "no.such.schema"."no.such.operator.class" + improper qualified name (too many dotted names): "no.such.schema"."no.such.operator.class" + \dAf "no.such.schema"."no.such.operator.family" +@@ -6034,127 +5858,51 @@ + \db "no.such.schema"."no.such.tablespace" + improper qualified name (too many dotted names): "no.such.schema"."no.such.tablespace" + \dc "no.such.schema"."no.such.conversion" +- List of conversions +- Schema | Name | Source | Destination | Default? +---------+------+--------+-------------+---------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dC "no.such.schema"."no.such.cast" +- List of casts +- Source type | Target type | Function | Implicit? +--------------+-------------+----------+----------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dd "no.such.schema"."no.such.object.description" +- Object descriptions +- Schema | Name | Object | Description +---------+------+--------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dD "no.such.schema"."no.such.domain" +- List of domains +- Schema | Name | Type | Collation | Nullable | Default | Check +---------+------+------+-----------+----------+---------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \ddp "no.such.schema"."no.such.default.access.privilege" +- Default access privileges +- Owner | Schema | Type | Access privileges +--------+--------+------+------------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \di "no.such.schema"."no.such.index.relation" +- List of relations +- Schema | Name | Type | Owner | Table +---------+------+------+-------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dm "no.such.schema"."no.such.materialized.view" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \ds "no.such.schema"."no.such.relation" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dt "no.such.schema"."no.such.relation" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dv "no.such.schema"."no.such.relation" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \des "no.such.schema"."no.such.foreign.server" + improper qualified name (too many dotted names): "no.such.schema"."no.such.foreign.server" + \dew "no.such.schema"."no.such.foreign.data.wrapper" + improper qualified name (too many dotted names): "no.such.schema"."no.such.foreign.data.wrapper" + \df "no.such.schema"."no.such.function" +- List of functions +- Schema | Name | Result data type | Argument data types | Type +---------+------+------------------+---------------------+------ +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dF "no.such.schema"."no.such.text.search.configuration" +-List of text search configurations +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dFd "no.such.schema"."no.such.text.search.dictionary" +-List of text search dictionaries +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dFp "no.such.schema"."no.such.text.search.parser" +- List of text search parsers +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dFt "no.such.schema"."no.such.text.search.template" +-List of text search templates +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dg "no.such.schema"."no.such.role" + improper qualified name (too many dotted names): "no.such.schema"."no.such.role" + \dL "no.such.schema"."no.such.language" + cross-database references are not implemented: "no.such.schema"."no.such.language" + \do "no.such.schema"."no.such.operator" +- List of operators +- Schema | Name | Left arg type | Right arg type | Result type | Description +---------+------+---------------+----------------+-------------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dO "no.such.schema"."no.such.collation" +- List of collations +- Schema | Name | Collate | Ctype | ICU Locale | Provider | Deterministic? +---------+------+---------+-------+------------+----------+---------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dp "no.such.schema"."no.such.access.privilege" +- Access privileges +- Schema | Name | Type | Access privileges | Column privileges | Policies +---------+------+------+-------------------+-------------------+---------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dP "no.such.schema"."no.such.partitioned.relation" +- List of partitioned relations +- Schema | Name | Owner | Type | Parent name | Table +---------+------+-------+------+-------------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \drds "no.such.schema"."no.such.setting" + improper qualified name (too many dotted names): "no.such.schema"."no.such.setting" + \dRp "no.such.schema"."no.such.publication" +@@ -6162,154 +5910,58 @@ + \dRs "no.such.schema"."no.such.subscription" + improper qualified name (too many dotted names): "no.such.schema"."no.such.subscription" + \dT "no.such.schema"."no.such.data.type" +- List of data types +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dx "no.such.schema"."no.such.installed.extension" + improper qualified name (too many dotted names): "no.such.schema"."no.such.installed.extension" + \dX "no.such.schema"."no.such.extended.statistics" +- List of extended statistics +- Schema | Name | Definition | Ndistinct | Dependencies | MCV +---------+------+------------+-----------+--------------+----- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dy "no.such.schema"."no.such.event.trigger" + improper qualified name (too many dotted names): "no.such.schema"."no.such.event.trigger" + -- again, but with current database and dotted schema qualifications. + \dt regression."no.such.schema"."no.such.table.relation" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \da regression."no.such.schema"."no.such.aggregate.function" +- List of aggregate functions +- Schema | Name | Result data type | Argument data types | Description +---------+------+------------------+---------------------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dc regression."no.such.schema"."no.such.conversion" +- List of conversions +- Schema | Name | Source | Destination | Default? +---------+------+--------+-------------+---------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dC regression."no.such.schema"."no.such.cast" +- List of casts +- Source type | Target type | Function | Implicit? +--------------+-------------+----------+----------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dd regression."no.such.schema"."no.such.object.description" +- Object descriptions +- Schema | Name | Object | Description +---------+------+--------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dD regression."no.such.schema"."no.such.domain" +- List of domains +- Schema | Name | Type | Collation | Nullable | Default | Check +---------+------+------+-----------+----------+---------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \di regression."no.such.schema"."no.such.index.relation" +- List of relations +- Schema | Name | Type | Owner | Table +---------+------+------+-------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dm regression."no.such.schema"."no.such.materialized.view" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \ds regression."no.such.schema"."no.such.relation" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dt regression."no.such.schema"."no.such.relation" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dv regression."no.such.schema"."no.such.relation" +- List of relations +- Schema | Name | Type | Owner +---------+------+------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \df regression."no.such.schema"."no.such.function" +- List of functions +- Schema | Name | Result data type | Argument data types | Type +---------+------+------------------+---------------------+------ +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dF regression."no.such.schema"."no.such.text.search.configuration" +-List of text search configurations +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dFd regression."no.such.schema"."no.such.text.search.dictionary" +-List of text search dictionaries +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dFp regression."no.such.schema"."no.such.text.search.parser" +- List of text search parsers +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dFt regression."no.such.schema"."no.such.text.search.template" +-List of text search templates +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \do regression."no.such.schema"."no.such.operator" +- List of operators +- Schema | Name | Left arg type | Right arg type | Result type | Description +---------+------+---------------+----------------+-------------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dO regression."no.such.schema"."no.such.collation" +- List of collations +- Schema | Name | Collate | Ctype | ICU Locale | Provider | Deterministic? +---------+------+---------+-------+------------+----------+---------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dp regression."no.such.schema"."no.such.access.privilege" +- Access privileges +- Schema | Name | Type | Access privileges | Column privileges | Policies +---------+------+------+-------------------+-------------------+---------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dP regression."no.such.schema"."no.such.partitioned.relation" +- List of partitioned relations +- Schema | Name | Owner | Type | Parent name | Table +---------+------+-------+------+-------------+------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dT regression."no.such.schema"."no.such.data.type" +- List of data types +- Schema | Name | Description +---------+------+------------- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + \dX regression."no.such.schema"."no.such.extended.statistics" +- List of extended statistics +- Schema | Name | Definition | Ndistinct | Dependencies | MCV +---------+------+------------+-----------+--------------+----- +-(0 rows) +- ++ERROR: current transaction is aborted, commands ignored until end of transaction block + -- again, but with dotted database and dotted schema qualifications. + \dt "no.such.database"."no.such.schema"."no.such.table.relation" + cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.table.relation" 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 @@ -732,7 +1455,7 @@ diff ../../../src/test/regress/expected/publication.out ../tmp_check/regress_out SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpib_ins_trunct WITH (publish = insert); -@@ -31,18 +32,20 @@ +@@ -33,18 +34,20 @@ List of publications Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root --------------------+--------------------------+------------+---------+---------+---------+-----------+---------- @@ -772,36 +1495,54 @@ diff ../../../src/test/regress/expected/subscription.out ../tmp_check/regress_ou ERROR: invalid connection string syntax: missing "=" after "foobar" in connection info string \dRs+ -- List of subscriptions -- Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo -------------------+---------------------------+---------+-------------+--------+-----------+--------------------+----------------------------- -- regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist --(1 row) -+ List of subscriptions -+ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo -+-----------------+---------------------------+---------+---------------+--------+-----------+--------------------+----------------------------------------------- -+ regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist +- 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'; -@@ -94,11 +98,13 @@ - ALTER SUBSCRIPTION regress_testsub SET (create_slot = false); - ERROR: unrecognized subscription parameter: "create_slot" +@@ -96,11 +100,13 @@ + -- ok + ALTER SUBSCRIPTION regress_testsub SKIP (lsn = '0/12345'); \dRs+ -- List of subscriptions -- Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo -------------------+---------------------------+---------+---------------------+--------+-----------+--------------------+------------------------------ -+ List of subscriptions -+ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo -+-----------------+---------------------------+---------+---------------------+--------+-----------+--------------------+----------------------------------------------- - regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | f | off | dbname=regress_doesnotexist2 +- 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; -@@ -106,16 +112,20 @@ +@@ -120,16 +128,20 @@ List of subscriptions Name | Owner | Enabled | Publication -----------------+---------------------------+---------+--------------------- @@ -820,117 +1561,258 @@ diff ../../../src/test/regress/expected/subscription.out ../tmp_check/regress_ou COMMIT; -- fail - must be owner of subscription -@@ -129,11 +139,13 @@ +@@ -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 | Synchronous commit | Conninfo -----------------------+---------------------------+---------+---------------------+--------+-----------+--------------------+------------------------------ -+ List of subscriptions -+ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo -+---------------------+---------------------------+---------+---------------------+--------+-----------+--------------------+----------------------------------------------- - regress_testsub_foo | regress_subscription_user | f | {testpub2,testpub3} | f | f | local | dbname=regress_doesnotexist2 +- 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; -@@ -165,20 +177,24 @@ +@@ -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 | Synchronous commit | Conninfo -------------------+---------------------------+---------+-------------+--------+-----------+--------------------+----------------------------- -- regress_testsub | regress_subscription_user | f | {testpub} | t | f | off | dbname=regress_doesnotexist --(1 row) -+ List of subscriptions -+ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo -+-----------------+---------------------------+---------+---------------+--------+-----------+--------------------+----------------------------------------------- -+ regress_testsub | regress_subscription_user | f | {testpub} | t | f | off | dbname=regress_doesnotexist +- 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 | Synchronous commit | Conninfo -------------------+---------------------------+---------+-------------+--------+-----------+--------------------+----------------------------- -- regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist --(1 row) -+ List of subscriptions -+ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo -+-----------------+---------------------------+---------+---------------+--------+-----------+--------------------+----------------------------------------------- -+ regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist +- 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 -@@ -188,20 +204,24 @@ +@@ -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 | Synchronous commit | Conninfo -------------------+---------------------------+---------+-------------+--------+-----------+--------------------+----------------------------- -- regress_testsub | regress_subscription_user | f | {testpub} | f | t | off | dbname=regress_doesnotexist --(1 row) -+ List of subscriptions -+ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo -+-----------------+---------------------------+---------+---------------+--------+-----------+--------------------+----------------------------------------------- -+ regress_testsub | regress_subscription_user | f | {testpub} | f | t | off | dbname=regress_doesnotexist +- 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 | Synchronous commit | Conninfo -------------------+---------------------------+---------+-------------+--------+-----------+--------------------+----------------------------- -- regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist --(1 row) -+ List of subscriptions -+ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo -+-----------------+---------------------------+---------+---------------+--------+-----------+--------------------+----------------------------------------------- -+ regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist +- 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); -@@ -215,11 +235,13 @@ +@@ -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 | Synchronous commit | Conninfo -------------------+---------------------------+---------+-----------------------------+--------+-----------+--------------------+----------------------------- -+ List of subscriptions -+ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo -+-----------------+---------------------------+---------+-----------------------------+--------+-----------+--------------------+----------------------------------------------- - regress_testsub | regress_subscription_user | f | {testpub,testpub1,testpub2} | f | f | off | dbname=regress_doesnotexist +- 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); -@@ -233,11 +255,13 @@ +@@ -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 | Synchronous commit | Conninfo -------------------+---------------------------+---------+-------------+--------+-----------+--------------------+----------------------------- -- regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist --(1 row) -+ List of subscriptions -+ Name | Owner | Enabled | Publication | Binary | Streaming | Synchronous commit | Conninfo -+-----------------+---------------------------+---------+---------------+--------+-----------+--------------------+----------------------------------------------- -+ regress_testsub | regress_subscription_user | f | {testpub} | f | f | off | dbname=regress_doesnotexist +- 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/guc.out ../tmp_check/regress_outdir/results/guc.out +--- ../../../src/test/regress/expected/guc.out CENSORED ++++ ../tmp_check/regress_outdir/results/guc.out CENSORED +@@ -563,13 +563,14 @@ + -- Test DISCARD TEMP + -- + CREATE TEMP TABLE reset_test ( data text ) ON COMMIT DELETE ROWS; ++ERROR: unrecognized configuration parameter "plpgsql.extra_foo_warnings" + SELECT relname FROM pg_class WHERE relname = 'reset_test'; +- relname +------------- +- reset_test +-(1 row) ++ relname ++--------- ++(0 rows) + + DISCARD TEMP; ++ERROR: unrecognized configuration parameter "plpgsql.extra_foo_warnings" + SELECT relname FROM pg_class WHERE relname = 'reset_test'; + relname + --------- +@@ -584,8 +585,11 @@ + LISTEN foo_event; + SET vacuum_cost_delay = 13; + CREATE TEMP TABLE tmp_foo (data text) ON COMMIT DELETE ROWS; ++ERROR: unrecognized configuration parameter "plpgsql.extra_foo_warnings" + CREATE ROLE regress_guc_user; ++ERROR: unrecognized configuration parameter "plpgsql.extra_foo_warnings" + SET SESSION AUTHORIZATION regress_guc_user; ++ERROR: role "regress_guc_user" does not exist + -- look changes + SELECT pg_listening_channels(); + pg_listening_channels +@@ -614,13 +618,12 @@ + SELECT relname from pg_class where relname = 'tmp_foo'; + relname + --------- +- tmp_foo +-(1 row) ++(0 rows) + + SELECT current_user = 'regress_guc_user'; + ?column? + ---------- +- t ++ f + (1 row) + + -- discard everything +@@ -659,6 +662,7 @@ + (1 row) + + DROP ROLE regress_guc_user; ++ERROR: role "regress_guc_user" does not exist + -- + -- search_path should react to changes in pg_namespace + -- 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 @@ -989,7 +1871,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 @@ -998,7 +1880,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/t/001_regress.pl b/t/001_regress.pl index 85ca458e0b..e9d4541e77 100644 --- a/t/001_regress.pl +++ b/t/001_regress.pl @@ -166,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; @@ -195,9 +198,9 @@ } # 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", "/+ mtm_sub_/d", "$ENV{TESTDIR}/results/regression.diff" ]; +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", "/+ multimaster/d", "$ENV{TESTDIR}/results/regression.diff" ]; +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"); From 83c3bc125697c1fe08e6a4c1320dc6a3b0442c43 Mon Sep 17 00:00:00 2001 From: Andrei Krichinin Date: Thu, 20 Oct 2022 02:45:50 +0500 Subject: [PATCH 26/32] fix warning in the function handle_response --- src/resolver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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)); From 35f215adfd79f12737f0eae317612fa90cc11c41 Mon Sep 17 00:00:00 2001 From: Andrei Kruchinin Date: Wed, 2 Nov 2022 13:35:40 +0500 Subject: [PATCH 27/32] Clean GUC placeholders with reserved prefix. Extensions can reserve prefixes for their configuration parameters while loading. Then all parameter placeholders with reserved prefixes are removed from GUC list. Multimaster GUC list should also be cleaned. --- expected/regression_ee.diff | 58 ----------------------------- src/ddl.c | 74 +++++++++++++++++++++++++++++++++++++ src/multimaster.c | 2 + 3 files changed, 76 insertions(+), 58 deletions(-) diff --git a/expected/regression_ee.diff b/expected/regression_ee.diff index 78559855e8..290897bcbe 100644 --- a/expected/regression_ee.diff +++ b/expected/regression_ee.diff @@ -1755,64 +1755,6 @@ diff ../../../src/test/regress/expected/subscription.out ../tmp_check/regress_ou ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE); DROP SUBSCRIPTION regress_testsub; -diff ../../../src/test/regress/expected/guc.out ../tmp_check/regress_outdir/results/guc.out ---- ../../../src/test/regress/expected/guc.out CENSORED -+++ ../tmp_check/regress_outdir/results/guc.out CENSORED -@@ -563,13 +563,14 @@ - -- Test DISCARD TEMP - -- - CREATE TEMP TABLE reset_test ( data text ) ON COMMIT DELETE ROWS; -+ERROR: unrecognized configuration parameter "plpgsql.extra_foo_warnings" - SELECT relname FROM pg_class WHERE relname = 'reset_test'; -- relname -------------- -- reset_test --(1 row) -+ relname -+--------- -+(0 rows) - - DISCARD TEMP; -+ERROR: unrecognized configuration parameter "plpgsql.extra_foo_warnings" - SELECT relname FROM pg_class WHERE relname = 'reset_test'; - relname - --------- -@@ -584,8 +585,11 @@ - LISTEN foo_event; - SET vacuum_cost_delay = 13; - CREATE TEMP TABLE tmp_foo (data text) ON COMMIT DELETE ROWS; -+ERROR: unrecognized configuration parameter "plpgsql.extra_foo_warnings" - CREATE ROLE regress_guc_user; -+ERROR: unrecognized configuration parameter "plpgsql.extra_foo_warnings" - SET SESSION AUTHORIZATION regress_guc_user; -+ERROR: role "regress_guc_user" does not exist - -- look changes - SELECT pg_listening_channels(); - pg_listening_channels -@@ -614,13 +618,12 @@ - SELECT relname from pg_class where relname = 'tmp_foo'; - relname - --------- -- tmp_foo --(1 row) -+(0 rows) - - SELECT current_user = 'regress_guc_user'; - ?column? - ---------- -- t -+ f - (1 row) - - -- discard everything -@@ -659,6 +662,7 @@ - (1 row) - - DROP ROLE regress_guc_user; -+ERROR: role "regress_guc_user" does not exist - -- - -- search_path should react to changes in pg_namespace - -- 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 diff --git a/src/ddl.c b/src/ddl.c index e9e199f428..491ce57d4d 100644 --- a/src/ddl.c +++ b/src/ddl.c @@ -141,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); @@ -638,6 +639,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); + } +} /***************************************************************************** @@ -1226,6 +1292,14 @@ MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString, bool readOn } } + /* Catch GUC changes after LOAD */ + if (nodeTag(parsetree) == T_LoadStmt) + { + LoadStmt *stmt = (LoadStmt *) parsetree; + + MtmGucSync(stmt->filename); + } + if (executed) { MtmFinishDDLCommand(); diff --git a/src/multimaster.c b/src/multimaster.c index 0cd1d340b3..ff6fc73e77 100644 --- a/src/multimaster.c +++ b/src/multimaster.c @@ -717,6 +717,8 @@ 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 From 3f4dfc66b39a2042b881aaaf815d322eef4cc3ab Mon Sep 17 00:00:00 2001 From: Andrei Kruchinin Date: Thu, 3 Nov 2022 02:02:52 +0500 Subject: [PATCH 28/32] Fix for 44623f2addbd58efc27b0687b7345a06b8b71ae8 (PostgreSQL 15: all shared memory requests in shmem_request_hook()) --- src/ddl.c | 7 +++++++ src/global_tx.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/ddl.c b/src/ddl.c index 491ce57d4d..e9b1214c08 100644 --- a/src/ddl.c +++ b/src/ddl.c @@ -169,6 +169,13 @@ MtmDDLReplicationInit() 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)); + size = add_size(size, hash_estimate_size(MULTIMASTER_MAX_LOCAL_TABLES, + sizeof(Oid))); + size = MAXALIGN(size); + RequestAddinShmemSpace(size); RequestNamedLWLockTranche("mtm-ddl", 1); diff --git a/src/global_tx.c b/src/global_tx.c index 7473e1fd3c..e5cc6d197f 100644 --- a/src/global_tx.c +++ b/src/global_tx.c @@ -163,6 +163,13 @@ MtmGlobalTxInit() 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 From 459170a029ef072f1161f08ba8001487034cf647 Mon Sep 17 00:00:00 2001 From: Andrei Kruchinin Date: Tue, 15 Nov 2022 17:13:41 +0500 Subject: [PATCH 29/32] ROLLBACK TO SAVEPOINT support In transaction, faulty DDL statements ROLLBACK'ed TO SAVEPOINT reported no transaction error on current node but all following DDL statements of this transaction were silently not replicated. --- expected/regression_ee.diff | 739 ------------------------------------ src/ddl.c | 4 + 2 files changed, 4 insertions(+), 739 deletions(-) diff --git a/expected/regression_ee.diff b/expected/regression_ee.diff index 290897bcbe..4814bbea27 100644 --- a/expected/regression_ee.diff +++ b/expected/regression_ee.diff @@ -702,745 +702,6 @@ diff ../../../src/test/regress/expected/psql.out ../tmp_check/regress_outdir/res INSERT INTO oer_test VALUES (6); COMMIT; SELECT * FROM oer_test; -@@ -5472,48 +5473,47 @@ - CONTEXT: PL/pgSQL function psql_error(text) line 3 at RAISE - INSERT INTO bla VALUES ('Calvin'), ('Hobbes'); - COMMIT; -+ERROR: [MTM] failed to prepare transaction at peer node - SELECT * FROM bla ORDER BY 1; -- s ---------- -- Calvin -- Hobbes --(2 rows) -- -+ERROR: relation "bla" does not exist -+LINE 1: SELECT * FROM bla ORDER BY 1; -+ ^ - BEGIN; - INSERT INTO bla VALUES ('Susie'); -- succeeds -+ERROR: relation "bla" does not exist -+LINE 1: INSERT INTO bla VALUES ('Susie'); -+ ^ - -- now with combined queries - INSERT INTO bla VALUES ('Rosalyn') \; -- will rollback - SELECT 'before error' AS show \; -- will show nevertheless! - SELECT psql_error('boum!') \; -- failure - SELECT 'after error' AS noshow; -- hidden by preceding error -- show ---------------- -- before error --(1 row) -- --ERROR: error boum! --CONTEXT: PL/pgSQL function psql_error(text) line 3 at RAISE -+ERROR: relation "bla" does not exist -+LINE 1: INSERT INTO bla VALUES ('Rosalyn') ; -- will rollback -+ ^ - INSERT INTO bla(s) VALUES ('Moe') \; -- will rollback - SELECT psql_error('bam!'); --ERROR: error bam! --CONTEXT: PL/pgSQL function psql_error(text) line 3 at RAISE -+ERROR: relation "bla" does not exist -+LINE 1: INSERT INTO bla(s) VALUES ('Moe') ; -- will rollback -+ ^ - INSERT INTO bla VALUES ('Miss Wormwood'); -- succeeds -+ERROR: relation "bla" does not exist -+LINE 1: INSERT INTO bla VALUES ('Miss Wormwood'); -+ ^ - COMMIT; - SELECT * FROM bla ORDER BY 1; -- s ----------------- -- Calvin -- Hobbes -- Miss Wormwood -- Susie --(4 rows) -- -+ERROR: relation "bla" does not exist -+LINE 1: SELECT * FROM bla ORDER BY 1; -+ ^ - -- some with autocommit off - \set AUTOCOMMIT off - \echo '# AUTOCOMMIT:' :AUTOCOMMIT - # AUTOCOMMIT: off - -- implicit BEGIN - INSERT INTO bla VALUES ('Dad'); -- succeeds -+ERROR: relation "bla" does not exist -+LINE 1: INSERT INTO bla VALUES ('Dad'); -+ ^ - SELECT psql_error('bad!'); -- implicit partial rollback - ERROR: error bad! - CONTEXT: PL/pgSQL function psql_error(text) line 3 at RAISE -@@ -5521,38 +5521,25 @@ - SELECT COUNT(*) AS "#mum" - FROM bla WHERE s = 'Mum' \; -- but be counted here - SELECT psql_error('bad!'); -- implicit partial rollback -- #mum -------- -- 1 --(1 row) -- --ERROR: error bad! --CONTEXT: PL/pgSQL function psql_error(text) line 3 at RAISE -+ERROR: relation "bla" does not exist -+LINE 1: INSERT INTO bla VALUES ('Mum') ; -- will rollback -+ ^ - COMMIT; - SELECT COUNT(*) AS "#mum" - FROM bla WHERE s = 'Mum' \; -- no mum here - SELECT * FROM bla ORDER BY 1; -- #mum -------- -- 0 --(1 row) -- -- s ----------------- -- Calvin -- Dad -- Hobbes -- Miss Wormwood -- Susie --(5 rows) -- -+ERROR: relation "bla" does not exist -+LINE 2: FROM bla WHERE s = 'Mum' ; -- no mum here -+ ^ - -- reset all - \set AUTOCOMMIT on - \set ON_ERROR_ROLLBACK off - \echo '# final ON_ERROR_ROLLBACK:' :ON_ERROR_ROLLBACK - # final ON_ERROR_ROLLBACK: off - DROP TABLE bla; -+ERROR: table "bla" does not exist - DROP FUNCTION psql_error; -+ERROR: current transaction is aborted, commands ignored until end of transaction block - -- check describing invalid multipart names - \dA regression.heap - improper qualified name (too many dotted names): regression.heap -@@ -5776,253 +5763,90 @@ - improper qualified name (too many dotted names): nonesuch.myevt - -- check that dots within quoted name segments are not counted - \dA "no.such.access.method" --List of access methods -- Name | Type --------+------ --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dt "no.such.table.relation" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \da "no.such.aggregate.function" -- List of aggregate functions -- Schema | Name | Result data type | Argument data types | Description ----------+------+------------------+---------------------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dAc "no.such.operator.class" -- List of operator classes -- AM | Input type | Storage type | Operator class | Default? ------+------------+--------------+----------------+---------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dAf "no.such.operator.family" -- List of operator families -- AM | Operator family | Applicable types ------+-----------------+------------------ --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dAo "no.such.operator.of.operator.family" -- List of operators of operator families -- AM | Operator family | Operator | Strategy | Purpose ------+-----------------+----------+----------+--------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dAp "no.such.operator.support.function.of.operator.family" -- List of support functions of operator families -- AM | Operator family | Registered left type | Registered right type | Number | Function ------+-----------------+----------------------+-----------------------+--------+---------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \db "no.such.tablespace" -- List of tablespaces -- Name | Owner | Location --------+-------+---------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dc "no.such.conversion" -- List of conversions -- Schema | Name | Source | Destination | Default? ----------+------+--------+-------------+---------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dC "no.such.cast" -- List of casts -- Source type | Target type | Function | Implicit? ---------------+-------------+----------+----------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dd "no.such.object.description" -- Object descriptions -- Schema | Name | Object | Description ----------+------+--------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dD "no.such.domain" -- List of domains -- Schema | Name | Type | Collation | Nullable | Default | Check ----------+------+------+-----------+----------+---------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \ddp "no.such.default.access.privilege" -- Default access privileges -- Owner | Schema | Type | Access privileges ---------+--------+------+------------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \di "no.such.index.relation" -- List of relations -- Schema | Name | Type | Owner | Table ----------+------+------+-------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dm "no.such.materialized.view" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \ds "no.such.relation" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dt "no.such.relation" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dv "no.such.relation" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \des "no.such.foreign.server" -- List of foreign servers -- Name | Owner | Foreign-data wrapper --------+-------+---------------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dew "no.such.foreign.data.wrapper" -- List of foreign-data wrappers -- Name | Owner | Handler | Validator --------+-------+---------+----------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \df "no.such.function" -- List of functions -- Schema | Name | Result data type | Argument data types | Type ----------+------+------------------+---------------------+------ --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dF "no.such.text.search.configuration" --List of text search configurations -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dFd "no.such.text.search.dictionary" --List of text search dictionaries -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dFp "no.such.text.search.parser" -- List of text search parsers -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dFt "no.such.text.search.template" --List of text search templates -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dg "no.such.role" -- List of roles -- Role name | Attributes | Member of -------------+------------+----------- -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dL "no.such.language" -- List of languages -- Name | Owner | Trusted | Description --------+-------+---------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dn "no.such.schema" --List of schemas -- Name | Owner --------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \do "no.such.operator" -- List of operators -- Schema | Name | Left arg type | Right arg type | Result type | Description ----------+------+---------------+----------------+-------------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dO "no.such.collation" -- List of collations -- Schema | Name | Collate | Ctype | ICU Locale | Provider | Deterministic? ----------+------+---------+-------+------------+----------+---------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dp "no.such.access.privilege" -- Access privileges -- Schema | Name | Type | Access privileges | Column privileges | Policies ----------+------+------+-------------------+-------------------+---------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dP "no.such.partitioned.relation" -- List of partitioned relations -- Schema | Name | Owner | Type | Parent name | Table ----------+------+-------+------+-------------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \drds "no.such.setting" -- List of settings -- Role | Database | Settings --------+----------+---------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dRp "no.such.publication" -- List of publications -- Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root --------+-------+------------+---------+---------+---------+-----------+---------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dRs "no.such.subscription" -- List of subscriptions -- Name | Owner | Enabled | Publication --------+-------+---------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dT "no.such.data.type" -- List of data types -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dx "no.such.installed.extension" -- List of installed extensions -- Name | Version | Schema | Description --------+---------+--------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dX "no.such.extended.statistics" -- List of extended statistics -- Schema | Name | Definition | Ndistinct | Dependencies | MCV ----------+------+------------+-----------+--------------+----- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dy "no.such.event.trigger" -- List of event triggers -- Name | Event | Owner | Enabled | Function | Tags --------+-------+-------+---------+----------+------ --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - -- again, but with dotted schema qualifications. - \dA "no.such.schema"."no.such.access.method" - improper qualified name (too many dotted names): "no.such.schema"."no.such.access.method" - \dt "no.such.schema"."no.such.table.relation" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \da "no.such.schema"."no.such.aggregate.function" -- List of aggregate functions -- Schema | Name | Result data type | Argument data types | Description ----------+------+------------------+---------------------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dAc "no.such.schema"."no.such.operator.class" - improper qualified name (too many dotted names): "no.such.schema"."no.such.operator.class" - \dAf "no.such.schema"."no.such.operator.family" -@@ -6034,127 +5858,51 @@ - \db "no.such.schema"."no.such.tablespace" - improper qualified name (too many dotted names): "no.such.schema"."no.such.tablespace" - \dc "no.such.schema"."no.such.conversion" -- List of conversions -- Schema | Name | Source | Destination | Default? ----------+------+--------+-------------+---------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dC "no.such.schema"."no.such.cast" -- List of casts -- Source type | Target type | Function | Implicit? ---------------+-------------+----------+----------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dd "no.such.schema"."no.such.object.description" -- Object descriptions -- Schema | Name | Object | Description ----------+------+--------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dD "no.such.schema"."no.such.domain" -- List of domains -- Schema | Name | Type | Collation | Nullable | Default | Check ----------+------+------+-----------+----------+---------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \ddp "no.such.schema"."no.such.default.access.privilege" -- Default access privileges -- Owner | Schema | Type | Access privileges ---------+--------+------+------------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \di "no.such.schema"."no.such.index.relation" -- List of relations -- Schema | Name | Type | Owner | Table ----------+------+------+-------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dm "no.such.schema"."no.such.materialized.view" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \ds "no.such.schema"."no.such.relation" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dt "no.such.schema"."no.such.relation" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dv "no.such.schema"."no.such.relation" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \des "no.such.schema"."no.such.foreign.server" - improper qualified name (too many dotted names): "no.such.schema"."no.such.foreign.server" - \dew "no.such.schema"."no.such.foreign.data.wrapper" - improper qualified name (too many dotted names): "no.such.schema"."no.such.foreign.data.wrapper" - \df "no.such.schema"."no.such.function" -- List of functions -- Schema | Name | Result data type | Argument data types | Type ----------+------+------------------+---------------------+------ --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dF "no.such.schema"."no.such.text.search.configuration" --List of text search configurations -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dFd "no.such.schema"."no.such.text.search.dictionary" --List of text search dictionaries -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dFp "no.such.schema"."no.such.text.search.parser" -- List of text search parsers -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dFt "no.such.schema"."no.such.text.search.template" --List of text search templates -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dg "no.such.schema"."no.such.role" - improper qualified name (too many dotted names): "no.such.schema"."no.such.role" - \dL "no.such.schema"."no.such.language" - cross-database references are not implemented: "no.such.schema"."no.such.language" - \do "no.such.schema"."no.such.operator" -- List of operators -- Schema | Name | Left arg type | Right arg type | Result type | Description ----------+------+---------------+----------------+-------------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dO "no.such.schema"."no.such.collation" -- List of collations -- Schema | Name | Collate | Ctype | ICU Locale | Provider | Deterministic? ----------+------+---------+-------+------------+----------+---------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dp "no.such.schema"."no.such.access.privilege" -- Access privileges -- Schema | Name | Type | Access privileges | Column privileges | Policies ----------+------+------+-------------------+-------------------+---------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dP "no.such.schema"."no.such.partitioned.relation" -- List of partitioned relations -- Schema | Name | Owner | Type | Parent name | Table ----------+------+-------+------+-------------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \drds "no.such.schema"."no.such.setting" - improper qualified name (too many dotted names): "no.such.schema"."no.such.setting" - \dRp "no.such.schema"."no.such.publication" -@@ -6162,154 +5910,58 @@ - \dRs "no.such.schema"."no.such.subscription" - improper qualified name (too many dotted names): "no.such.schema"."no.such.subscription" - \dT "no.such.schema"."no.such.data.type" -- List of data types -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dx "no.such.schema"."no.such.installed.extension" - improper qualified name (too many dotted names): "no.such.schema"."no.such.installed.extension" - \dX "no.such.schema"."no.such.extended.statistics" -- List of extended statistics -- Schema | Name | Definition | Ndistinct | Dependencies | MCV ----------+------+------------+-----------+--------------+----- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dy "no.such.schema"."no.such.event.trigger" - improper qualified name (too many dotted names): "no.such.schema"."no.such.event.trigger" - -- again, but with current database and dotted schema qualifications. - \dt regression."no.such.schema"."no.such.table.relation" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \da regression."no.such.schema"."no.such.aggregate.function" -- List of aggregate functions -- Schema | Name | Result data type | Argument data types | Description ----------+------+------------------+---------------------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dc regression."no.such.schema"."no.such.conversion" -- List of conversions -- Schema | Name | Source | Destination | Default? ----------+------+--------+-------------+---------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dC regression."no.such.schema"."no.such.cast" -- List of casts -- Source type | Target type | Function | Implicit? ---------------+-------------+----------+----------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dd regression."no.such.schema"."no.such.object.description" -- Object descriptions -- Schema | Name | Object | Description ----------+------+--------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dD regression."no.such.schema"."no.such.domain" -- List of domains -- Schema | Name | Type | Collation | Nullable | Default | Check ----------+------+------+-----------+----------+---------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \di regression."no.such.schema"."no.such.index.relation" -- List of relations -- Schema | Name | Type | Owner | Table ----------+------+------+-------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dm regression."no.such.schema"."no.such.materialized.view" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \ds regression."no.such.schema"."no.such.relation" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dt regression."no.such.schema"."no.such.relation" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dv regression."no.such.schema"."no.such.relation" -- List of relations -- Schema | Name | Type | Owner ----------+------+------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \df regression."no.such.schema"."no.such.function" -- List of functions -- Schema | Name | Result data type | Argument data types | Type ----------+------+------------------+---------------------+------ --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dF regression."no.such.schema"."no.such.text.search.configuration" --List of text search configurations -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dFd regression."no.such.schema"."no.such.text.search.dictionary" --List of text search dictionaries -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dFp regression."no.such.schema"."no.such.text.search.parser" -- List of text search parsers -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dFt regression."no.such.schema"."no.such.text.search.template" --List of text search templates -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \do regression."no.such.schema"."no.such.operator" -- List of operators -- Schema | Name | Left arg type | Right arg type | Result type | Description ----------+------+---------------+----------------+-------------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dO regression."no.such.schema"."no.such.collation" -- List of collations -- Schema | Name | Collate | Ctype | ICU Locale | Provider | Deterministic? ----------+------+---------+-------+------------+----------+---------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dp regression."no.such.schema"."no.such.access.privilege" -- Access privileges -- Schema | Name | Type | Access privileges | Column privileges | Policies ----------+------+------+-------------------+-------------------+---------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dP regression."no.such.schema"."no.such.partitioned.relation" -- List of partitioned relations -- Schema | Name | Owner | Type | Parent name | Table ----------+------+-------+------+-------------+------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dT regression."no.such.schema"."no.such.data.type" -- List of data types -- Schema | Name | Description ----------+------+------------- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - \dX regression."no.such.schema"."no.such.extended.statistics" -- List of extended statistics -- Schema | Name | Definition | Ndistinct | Dependencies | MCV ----------+------+------------+-----------+--------------+----- --(0 rows) -- -+ERROR: current transaction is aborted, commands ignored until end of transaction block - -- again, but with dotted database and dotted schema qualifications. - \dt "no.such.database"."no.such.schema"."no.such.table.relation" - cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.table.relation" 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 diff --git a/src/ddl.c b/src/ddl.c index e9b1214c08..256955e599 100644 --- a/src/ddl.c +++ b/src/ddl.c @@ -1032,6 +1032,10 @@ MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString, bool readOn MtmExplicitFinishPrepared(isTopLevel, stmt->gid, false); return; + case TRANS_STMT_ROLLBACK_TO: + MtmDDLResetStatement(); + break; + default: break; } From aa4c25ba18dcd6fa03c28e057707278b89e2807c Mon Sep 17 00:00:00 2001 From: Andrei Kruchinin Date: Tue, 15 Nov 2022 18:52:43 +0500 Subject: [PATCH 30/32] Multimaster log options in TAP tests. --- Cluster.pm | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Cluster.pm b/Cluster.pm index a2c09feab7..fccda7aa1b 100644 --- a/Cluster.pm +++ b/Cluster.pm @@ -274,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); From c68af329b329da83c1a2cccbdd8791362adfd5ba Mon Sep 17 00:00:00 2001 From: Andrei Kruchinin Date: Thu, 17 Nov 2022 01:47:04 +0500 Subject: [PATCH 31/32] fix deletion of replication origin --- src/state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/state.c b/src/state.c index fae1868fd8..a05eb55a74 100644 --- a/src/state.c +++ b/src/state.c @@ -3918,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_by_name(logical_slot, false); + replorigin_drop_by_name(logical_slot, false, true); /* * Delete logical slot. It is aquired by walsender, so call with nowait = From f3947bf59b6060b9f2e571586b7a9ab00ea91e19 Mon Sep 17 00:00:00 2001 From: Andrei Kruchinin Date: Fri, 25 Nov 2022 13:18:27 +0500 Subject: [PATCH 32/32] Set worker status to Idle after applying --- src/ddl.c | 2 +- src/pglogical_apply.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ddl.c b/src/ddl.c index 256955e599..39955dae6c 100644 --- a/src/ddl.c +++ b/src/ddl.c @@ -1629,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, ""); } diff --git a/src/pglogical_apply.c b/src/pglogical_apply.c index 14bcf8d8f6..3f9c27c2d9 100644 --- a/src/pglogical_apply.c +++ b/src/pglogical_apply.c @@ -385,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; } @@ -396,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':