blob: d9270f20e302c6a43fce2efcf39dd0072ec4d299 [file] [log] [blame]
-- Export distributed snapshot tests
-- start_matchsubs
-- m/[0-9a-fA-F]+-[0-9a-fA-F]+-\d/
-- s/[0-9a-fA-F]+-[0-9a-fA-F]+-\d/#######-########-#/
-- m/^DETAIL: The source process with PID \d+ is not running anymore./
-- s/^DETAIL: The source process with PID \d+ is not running anymore./DETAIL: The source process with PID is not running anymore./
-- end_matchsubs
-- start_ignore
DROP FUNCTION IF EXISTS corrupt_snapshot_file(text, text);
DROP
DROP FUNCTION IF EXISTS snapshot_file_ds_fields_exist(text);
DROP
DROP LANGUAGE IF EXISTS plpython3u;
DROP
DROP TABLE IF EXISTS export_distributed_snapshot_test1;
DROP
CREATE LANGUAGE plpython3u;
CREATE
-- end_ignore
-- Corrupt field entry for given snapshot file
CREATE OR REPLACE FUNCTION corrupt_snapshot_file(token text, field text) RETURNS integer as $$ import os content = bytearray() query = "select (select datadir from gp_segment_configuration where role='p' and content=-1) || '/pg_snapshots/' as path" rv = plpy.execute(query) abs_path = rv[0]['path'] snapshot_file = abs_path + token if not os.path.isfile(snapshot_file): plpy.info('skipping non-existent file %s' % (snapshot_file)) else: plpy.info('corrupting file %s for field %s' % (snapshot_file, field)) with open(snapshot_file , "rb+") as f: for line in f: l = line.decode() id = l.split(":")[0] if field == id: corrupt = l[:-2] + '*' + l[len(l)-1:] content.extend(corrupt.encode()) else: content.extend(line) f.seek(0) f.truncate f.write(content) f.close() return 0 $$ LANGUAGE plpython3u;
CREATE
-- Determine if field exists for given snapshot file
CREATE OR REPLACE FUNCTION snapshot_file_ds_fields_exist(token text) RETURNS boolean as $$ import os content = bytearray() query = "select (select datadir from gp_segment_configuration where role='p' and content=-1) || '/pg_snapshots/' as path" rv = plpy.execute(query) abs_path = rv[0]['path'] snapshot_file = abs_path + token if not os.path.isfile(snapshot_file): plpy.info('snapshot file %s does not exist' % (snapshot_file)) return -1 else: plpy.info('checking file %s for ds fields' % (snapshot_file)) with open(snapshot_file , "rb+") as f: for line in f: l = line.decode() if "ds" in l: return True return False $$ LANGUAGE plpython3u;
CREATE
-- INSERT test
CREATE TABLE export_distributed_snapshot_test1 (a int);
CREATE
INSERT INTO export_distributed_snapshot_test1 values(1);
INSERT 1
1: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
1: @post_run ' TOKEN=`echo "${RAW_STR}" | awk \'NR==3\' | awk \'{print $1}\'` && echo "${RAW_STR}"': SELECT pg_export_snapshot();
pg_export_snapshot
---------------------
00000007-00000011-1
(1 row)
INSERT INTO export_distributed_snapshot_test1 values(2);
INSERT 1
SELECT * FROM export_distributed_snapshot_test1;
a
---
2
1
(2 rows)
-- Transaction 2 should return 2 rows
2: SELECT * FROM export_distributed_snapshot_test1;
a
---
2
1
(2 rows)
2: COMMIT;
COMMIT
2: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
2: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': SET TRANSACTION SNAPSHOT '@TOKEN';
SET
-- Transaction 2 should now return 1 row
2: SELECT * FROM export_distributed_snapshot_test1;
a
---
1
(1 row)
2: COMMIT;
COMMIT
1: COMMIT;
COMMIT
-- DELETE test
CREATE TABLE export_distributed_snapshot_test2 (a int);
CREATE
INSERT INTO export_distributed_snapshot_test2 SELECT a FROM generate_series(1,3) a;
INSERT 3
1: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
1: @post_run ' TOKEN=`echo "${RAW_STR}" | awk \'NR==3\' | awk \'{print $1}\'` && echo "${RAW_STR}"': SELECT pg_export_snapshot();
pg_export_snapshot
---------------------
00000007-0000007C-1
(1 row)
DELETE FROM export_distributed_snapshot_test2 WHERE a=1;
DELETE 1
-- Should return 3 rows
1: SELECT * FROM export_distributed_snapshot_test2 ;
a
---
1
2
3
(3 rows)
-- Should return 2 rows
2: SELECT * FROM export_distributed_snapshot_test2;
a
---
2
3
(2 rows)
2: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
2: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': SET TRANSACTION SNAPSHOT '@TOKEN';
SET
-- Should return 3 rows
2: SELECT * FROM export_distributed_snapshot_test2;
a
---
2
3
1
(3 rows)
2: COMMIT;
COMMIT
1: COMMIT;
COMMIT
-- UPDATE test
CREATE TABLE export_distributed_snapshot_test3 (a int);
CREATE
INSERT INTO export_distributed_snapshot_test3 SELECT a FROM generate_series(1,5) a;
INSERT 5
1: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
1: @post_run ' TOKEN=`echo "${RAW_STR}" | awk \'NR==3\' | awk \'{print $1}\'` && echo "${RAW_STR}"': SELECT pg_export_snapshot();
pg_export_snapshot
---------------------
00000007-0000007D-1
(1 row)
UPDATE export_distributed_snapshot_test3 SET a=99 WHERE a=1;
UPDATE 1
-- Should return 0 rows
1: SELECT * FROM export_distributed_snapshot_test3 WHERE a=99;
a
---
(0 rows)
-- Should return 1 row
2: SELECT * FROM export_distributed_snapshot_test3 WHERE a=99;
a
----
99
(1 row)
2: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
2: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': SET TRANSACTION SNAPSHOT '@TOKEN';
SET
-- Should return 0 rows
2: SELECT * FROM export_distributed_snapshot_test3 WHERE a=99;
a
---
(0 rows)
2: COMMIT;
COMMIT
-- Should return 1 row
2: SELECT * FROM export_distributed_snapshot_test3 WHERE a=99;
a
----
99
(1 row)
1: COMMIT;
COMMIT
-- DROP test
CREATE TABLE export_distributed_snapshot_test4 (a int);
CREATE
1: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
2: BEGIN;
BEGIN
1: @post_run ' TOKEN=`echo "${RAW_STR}" | awk \'NR==3\' | awk \'{print $1}\'` && echo "${RAW_STR}"': SELECT pg_export_snapshot();
pg_export_snapshot
---------------------
00000007-00000012-1
(1 row)
1: SELECT gp_segment_id, relname from gp_dist_random('pg_class') where relname = 'export_distributed_snapshot_test4';
gp_segment_id | relname
---------------+-----------------------------------
1 | export_distributed_snapshot_test4
2 | export_distributed_snapshot_test4
0 | export_distributed_snapshot_test4
(3 rows)
-- Drop table in transaction
2: DROP TABLE export_distributed_snapshot_test4;
DROP
2: COMMIT;
COMMIT
3: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
3: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': SET TRANSACTION SNAPSHOT '@TOKEN';
SET
-- The table should still be visible to transaction 3 using transaction 1's snapshot.
3: SELECT gp_segment_id, relname from gp_dist_random('pg_class') where relname = 'export_distributed_snapshot_test4';
gp_segment_id | relname
---------------+-----------------------------------
1 | export_distributed_snapshot_test4
2 | export_distributed_snapshot_test4
0 | export_distributed_snapshot_test4
(3 rows)
3: COMMIT;
COMMIT
-- The table should no longer be visible to transaction 3.
3: SELECT gp_segment_id, relname from gp_dist_random('pg_class') where relname = 'export_distributed_snapshot_test4';
gp_segment_id | relname
---------------+---------
(0 rows)
1: COMMIT;
COMMIT
-- Test corrupt fields in snapshot file
-- xmin
1: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
1: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
1: @post_run ' TOKEN=`echo "${RAW_STR}" | awk \'NR==3\' | awk \'{print $1}\'` && echo "${RAW_STR}"': SELECT pg_export_snapshot();
pg_export_snapshot
---------------------
00000007-00000013-1
(1 row)
2: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': select corrupt_snapshot_file('@TOKEN', 'xmin');
corrupt_snapshot_file
-----------------------
0
(1 row)
2: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
2: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': SET TRANSACTION SNAPSHOT '@TOKEN';
ERROR: could not import the requested snapshot
DETAIL: The source process with PID 651456 is not running anymore.
1: END;
END
2: END;
END
-- dsxminall
1: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
1: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
1: @post_run ' TOKEN=`echo "${RAW_STR}" | awk \'NR==3\' | awk \'{print $1}\'` && echo "${RAW_STR}"': SELECT pg_export_snapshot();
pg_export_snapshot
---------------------
00000007-00000014-1
(1 row)
2: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': select corrupt_snapshot_file('@TOKEN', 'dsxminall');
corrupt_snapshot_file
-----------------------
0
(1 row)
2: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
2: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': SET TRANSACTION SNAPSHOT '@TOKEN';
SET
1: END;
END
2: END;
END
-- dsxmin
1: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
1: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
1: @post_run ' TOKEN=`echo "${RAW_STR}" | awk \'NR==3\' | awk \'{print $1}\'` && echo "${RAW_STR}"': SELECT pg_export_snapshot();
pg_export_snapshot
---------------------
00000007-00000006-1
(1 row)
2: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': select corrupt_snapshot_file('@TOKEN', 'dsxmin');
corrupt_snapshot_file
-----------------------
0
(1 row)
2: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
2: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': SET TRANSACTION SNAPSHOT '@TOKEN';
ERROR: invalid snapshot data in file "pg_snapshots/00000007-00000006-1"
1: END;
END
2: END;
END
-- Test export snapshot in utility mode does not export distributed snapshot fields
-1U: BEGIN;
BEGIN
-1U: BEGIN;
BEGIN
-1U: @post_run ' TOKEN=`echo "${RAW_STR}" | awk \'NR==3\' | awk \'{print $1}\'` && echo "${RAW_STR}"': SELECT pg_export_snapshot();
pg_export_snapshot
---------------------
00000009-00000302-1
(1 row)
-- Should return false
1: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': select snapshot_file_ds_fields_exist('@TOKEN');
snapshot_file_ds_fields_exist
-------------------------------
f
(1 row)
-1Uq: ... <quitting>
1: END;
END
-- Test import snapshot in utility mode fails if distributed snapshot fields exist
1: BEGIN;
BEGIN
1: BEGIN;
BEGIN
1: @post_run ' TOKEN=`echo "${RAW_STR}" | awk \'NR==3\' | awk \'{print $1}\'` && echo "${RAW_STR}"': SELECT pg_export_snapshot();
pg_export_snapshot
---------------------
00000006-00000008-1
(1 row)
-- Open utility mode connection on coordinator and set snapshot
-1U: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
-1U: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': SET TRANSACTION SNAPSHOT '@TOKEN';
ERROR: cannot import distributed snapshot in utility mode
HINT: export the snapshot in utility mode
-1Uq: ... <quitting>
1: END;
END
-- Test export snapshot in utility mode and import snapshot in utility mode succeeds
-1U: @db_name postgres: BEGIN;
BEGIN
-1U: BEGIN;
BEGIN
-1U: @post_run ' TOKEN=`echo "${RAW_STR}" | awk \'NR==3\' | awk \'{print $1}\'` && echo "${RAW_STR}"': SELECT pg_export_snapshot();
pg_export_snapshot
---------------------
00000009-0000030A-1
(1 row)
-- Should return false
1: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': select snapshot_file_ds_fields_exist('@TOKEN');
snapshot_file_ds_fields_exist
-------------------------------
f
(1 row)
-- Open another utility mode connection and set the snapshot
! TOKEN=$(find ${COORDINATOR_DATA_DIRECTORY}/pg_snapshots/ -name "0*" -exec basename {} \;) \ && echo ${TOKEN} \ && PGOPTIONS='-c gp_role=utility' psql postgres -Atc "BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION SNAPSHOT '${TOKEN}';";
0000000A-0000000E-1
SET
-1Uq: ... <quitting>