mirror of https://github.com/citusdata/citus.git
412 lines
13 KiB
Plaintext
412 lines
13 KiB
Plaintext
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 1340000;
|
|
-- ===================================================================
|
|
-- test end-to-end modification functionality for mx tables in transactions
|
|
-- ===================================================================
|
|
-- add some data
|
|
INSERT INTO researchers_mx VALUES (1, 1, 'Donald Knuth');
|
|
INSERT INTO researchers_mx VALUES (2, 1, 'Niklaus Wirth');
|
|
INSERT INTO researchers_mx VALUES (3, 2, 'Tony Hoare');
|
|
INSERT INTO researchers_mx VALUES (4, 2, 'Kenneth Iverson');
|
|
-- replace a researcher, reusing their id on the coordinator
|
|
BEGIN;
|
|
DELETE FROM researchers_mx WHERE lab_id = 1 AND id = 2;
|
|
INSERT INTO researchers_mx VALUES (2, 1, 'John Backus');
|
|
COMMIT;
|
|
SELECT name FROM researchers_mx WHERE lab_id = 1 AND id = 2;
|
|
name
|
|
---------------------------------------------------------------------
|
|
John Backus
|
|
(1 row)
|
|
|
|
-- do it on the worker node as well
|
|
\c - - - :worker_1_port
|
|
BEGIN;
|
|
DELETE FROM researchers_mx WHERE lab_id = 1 AND id = 2;
|
|
INSERT INTO researchers_mx VALUES (2, 1, 'John Backus Worker 1');
|
|
COMMIT;
|
|
SELECT name FROM researchers_mx WHERE lab_id = 1 AND id = 2;
|
|
name
|
|
---------------------------------------------------------------------
|
|
John Backus Worker 1
|
|
(1 row)
|
|
|
|
-- do it on the worker other node as well
|
|
\c - - - :worker_2_port
|
|
BEGIN;
|
|
DELETE FROM researchers_mx WHERE lab_id = 1 AND id = 2;
|
|
INSERT INTO researchers_mx VALUES (2, 1, 'John Backus Worker 2');
|
|
COMMIT;
|
|
SELECT name FROM researchers_mx WHERE lab_id = 1 AND id = 2;
|
|
name
|
|
---------------------------------------------------------------------
|
|
John Backus Worker 2
|
|
(1 row)
|
|
|
|
\c - - - :master_port
|
|
-- abort a modification
|
|
BEGIN;
|
|
DELETE FROM researchers_mx WHERE lab_id = 1 AND id = 1;
|
|
ABORT;
|
|
SELECT name FROM researchers_mx WHERE lab_id = 1 AND id = 1;
|
|
name
|
|
---------------------------------------------------------------------
|
|
Donald Knuth
|
|
(1 row)
|
|
|
|
\c - - - :worker_1_port
|
|
-- abort a modification on the worker node
|
|
BEGIN;
|
|
DELETE FROM researchers_mx WHERE lab_id = 1 AND id = 1;
|
|
ABORT;
|
|
SELECT name FROM researchers_mx WHERE lab_id = 1 AND id = 1;
|
|
name
|
|
---------------------------------------------------------------------
|
|
Donald Knuth
|
|
(1 row)
|
|
|
|
\c - - - :worker_2_port
|
|
-- abort a modification on the other worker node
|
|
BEGIN;
|
|
DELETE FROM researchers_mx WHERE lab_id = 1 AND id = 1;
|
|
ABORT;
|
|
SELECT name FROM researchers_mx WHERE lab_id = 1 AND id = 1;
|
|
name
|
|
---------------------------------------------------------------------
|
|
Donald Knuth
|
|
(1 row)
|
|
|
|
-- switch back to the first worker node
|
|
\c - - - :worker_1_port
|
|
-- creating savepoints should work...
|
|
BEGIN;
|
|
INSERT INTO researchers_mx VALUES (5, 3, 'Dennis Ritchie');
|
|
SAVEPOINT hire_thompson;
|
|
INSERT INTO researchers_mx VALUES (6, 3, 'Ken Thompson');
|
|
COMMIT;
|
|
SELECT name FROM researchers_mx WHERE lab_id = 3 AND id = 6;
|
|
name
|
|
---------------------------------------------------------------------
|
|
Ken Thompson
|
|
(1 row)
|
|
|
|
-- even if created by PL/pgSQL...
|
|
\set VERBOSITY terse
|
|
BEGIN;
|
|
DO $$
|
|
BEGIN
|
|
INSERT INTO researchers_mx VALUES (10, 10, 'Edsger Dijkstra');
|
|
EXCEPTION
|
|
WHEN not_null_violation THEN
|
|
RAISE NOTICE 'caught not_null_violation';
|
|
END $$;
|
|
COMMIT;
|
|
-- rollback should also work
|
|
BEGIN;
|
|
INSERT INTO researchers_mx VALUES (7, 4, 'Jim Gray');
|
|
SAVEPOINT hire_engelbart;
|
|
INSERT INTO researchers_mx VALUES (8, 4, 'Douglas Engelbart');
|
|
ROLLBACK TO hire_engelbart;
|
|
COMMIT;
|
|
SELECT name FROM researchers_mx WHERE lab_id = 4;
|
|
name
|
|
---------------------------------------------------------------------
|
|
Jim Gray
|
|
(1 row)
|
|
|
|
BEGIN;
|
|
DO $$
|
|
BEGIN
|
|
INSERT INTO researchers_mx VALUES (NULL, 10, 'Edsger Dijkstra');
|
|
EXCEPTION
|
|
WHEN not_null_violation THEN
|
|
RAISE NOTICE 'caught not_null_violation';
|
|
END $$;
|
|
NOTICE: caught not_null_violation
|
|
COMMIT;
|
|
\set VERBOSITY default
|
|
-- should be valid to edit labs_mx after researchers_mx...
|
|
BEGIN;
|
|
INSERT INTO researchers_mx VALUES (8, 5, 'Douglas Engelbart');
|
|
INSERT INTO labs_mx VALUES (5, 'Los Alamos');
|
|
COMMIT;
|
|
SELECT * FROM researchers_mx, labs_mx WHERE labs_mx.id = researchers_mx.lab_id and researchers_mx.lab_id = 5;;
|
|
id | lab_id | name | id | name
|
|
---------------------------------------------------------------------
|
|
8 | 5 | Douglas Engelbart | 5 | Los Alamos
|
|
(1 row)
|
|
|
|
-- and the other way around is also allowed
|
|
BEGIN;
|
|
SET LOCAL citus.enable_local_execution TO off;
|
|
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
|
INSERT INTO researchers_mx VALUES (9, 6, 'Leslie Lamport');
|
|
COMMIT;
|
|
-- have the same test on the other worker node
|
|
\c - - - :worker_2_port
|
|
-- should be valid to edit labs_mx after researchers_mx...
|
|
BEGIN;
|
|
INSERT INTO researchers_mx VALUES (8, 5, 'Douglas Engelbart');
|
|
INSERT INTO labs_mx VALUES (5, 'Los Alamos');
|
|
COMMIT;
|
|
SELECT * FROM researchers_mx, labs_mx WHERE labs_mx.id = researchers_mx.lab_id and researchers_mx.lab_id = 5;
|
|
id | lab_id | name | id | name
|
|
---------------------------------------------------------------------
|
|
8 | 5 | Douglas Engelbart | 5 | Los Alamos
|
|
8 | 5 | Douglas Engelbart | 5 | Los Alamos
|
|
8 | 5 | Douglas Engelbart | 5 | Los Alamos
|
|
8 | 5 | Douglas Engelbart | 5 | Los Alamos
|
|
(4 rows)
|
|
|
|
-- and the other way around is also allowed
|
|
BEGIN;
|
|
SET LOCAL citus.enable_local_execution TO off;
|
|
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
|
INSERT INTO researchers_mx VALUES (9, 6, 'Leslie Lamport');
|
|
COMMIT;
|
|
-- switch back to the worker node
|
|
\c - - - :worker_1_port
|
|
-- this logic doesn't apply to router SELECTs occurring after a modification:
|
|
-- selecting from the modified node is fine...
|
|
BEGIN;
|
|
SET LOCAL citus.enable_local_execution TO off;
|
|
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
|
SELECT count(*) FROM researchers_mx WHERE lab_id = 6;
|
|
count
|
|
---------------------------------------------------------------------
|
|
2
|
|
(1 row)
|
|
|
|
ABORT;
|
|
-- doesn't apply to COPY after modifications
|
|
BEGIN;
|
|
SET LOCAL citus.enable_local_execution TO off;
|
|
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
|
\copy labs_mx from stdin delimiter ','
|
|
COMMIT;
|
|
-- copy will also work if before any modifications
|
|
BEGIN;
|
|
\copy labs_mx from stdin delimiter ','
|
|
SELECT name FROM labs_mx WHERE id = 10;
|
|
name
|
|
---------------------------------------------------------------------
|
|
Weyland-Yutani-1
|
|
Weyland-Yutani-2
|
|
(2 rows)
|
|
|
|
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
|
COMMIT;
|
|
\c - - - :worker_1_port
|
|
-- test primary key violations
|
|
BEGIN;
|
|
INSERT INTO objects_mx VALUES (1, 'apple');
|
|
INSERT INTO objects_mx VALUES (1, 'orange');
|
|
ERROR: duplicate key value violates unique constraint "objects_mx_pkey_1220103"
|
|
DETAIL: Key (id)=(X) already exists.
|
|
COMMIT;
|
|
-- data shouldn't have persisted...
|
|
SELECT * FROM objects_mx WHERE id = 1;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- same test on the second worker node
|
|
\c - - - :worker_2_port
|
|
-- test primary key violations
|
|
BEGIN;
|
|
INSERT INTO objects_mx VALUES (1, 'apple');
|
|
INSERT INTO objects_mx VALUES (1, 'orange');
|
|
ERROR: duplicate key value violates unique constraint "objects_mx_pkey_1220103"
|
|
DETAIL: Key (id)=(X) already exists.
|
|
CONTEXT: while executing command on localhost:xxxxx
|
|
COMMIT;
|
|
-- data shouldn't have persisted...
|
|
SELECT * FROM objects_mx WHERE id = 1;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- create trigger on one worker to reject certain values
|
|
\c - - - :worker_1_port
|
|
SET citus.enable_metadata_sync TO OFF;
|
|
CREATE FUNCTION reject_bad_mx() RETURNS trigger AS $rb$
|
|
BEGIN
|
|
IF (NEW.name = 'BAD') THEN
|
|
RAISE 'illegal value';
|
|
END IF;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$rb$ LANGUAGE plpgsql;
|
|
RESET citus.enable_metadata_sync;
|
|
CREATE CONSTRAINT TRIGGER reject_bad_mx
|
|
AFTER INSERT ON objects_mx_1220103
|
|
DEFERRABLE INITIALLY IMMEDIATE
|
|
FOR EACH ROW EXECUTE PROCEDURE reject_bad_mx();
|
|
-- test partial failure; statement 1 successed, statement 2 fails
|
|
\set VERBOSITY terse
|
|
BEGIN;
|
|
INSERT INTO labs_mx VALUES (7, 'E Corp');
|
|
INSERT INTO objects_mx VALUES (2, 'BAD');
|
|
ERROR: illegal value
|
|
COMMIT;
|
|
-- data should NOT be persisted
|
|
SELECT * FROM objects_mx WHERE id = 2;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
SELECT * FROM labs_mx WHERE id = 7;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- same failure test from worker 2
|
|
\c - - - :worker_2_port
|
|
-- test partial failure; statement 1 successed, statement 2 fails
|
|
BEGIN;
|
|
INSERT INTO labs_mx VALUES (7, 'E Corp');
|
|
INSERT INTO objects_mx VALUES (2, 'BAD');
|
|
ERROR: illegal value
|
|
COMMIT;
|
|
-- data should NOT be persisted
|
|
SELECT * FROM objects_mx WHERE id = 2;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
SELECT * FROM labs_mx WHERE id = 7;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
\c - - - :worker_1_port
|
|
-- what if there are errors on different shards at different times?
|
|
\c - - - :worker_1_port
|
|
CREATE CONSTRAINT TRIGGER reject_bad_mx
|
|
AFTER INSERT ON labs_mx_1220102
|
|
DEFERRABLE INITIALLY IMMEDIATE
|
|
FOR EACH ROW EXECUTE PROCEDURE reject_bad_mx();
|
|
BEGIN;
|
|
SET LOCAL citus.enable_local_execution TO off;
|
|
INSERT INTO objects_mx VALUES (1, 'apple');
|
|
INSERT INTO objects_mx VALUES (2, 'BAD');
|
|
ERROR: illegal value
|
|
INSERT INTO labs_mx VALUES (8, 'Aperture Science');
|
|
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
INSERT INTO labs_mx VALUES (9, 'BAD');
|
|
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
COMMIT;
|
|
-- data should NOT be persisted
|
|
SELECT * FROM objects_mx WHERE id = 1;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
SELECT * FROM labs_mx WHERE id = 8;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- same test from the other worker
|
|
\c - - - :worker_2_port
|
|
BEGIN;
|
|
INSERT INTO objects_mx VALUES (1, 'apple');
|
|
INSERT INTO objects_mx VALUES (2, 'BAD');
|
|
ERROR: illegal value
|
|
INSERT INTO labs_mx VALUES (8, 'Aperture Science');
|
|
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
INSERT INTO labs_mx VALUES (9, 'BAD');
|
|
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
COMMIT;
|
|
-- data should NOT be persisted
|
|
SELECT * FROM objects_mx WHERE id = 1;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
SELECT * FROM labs_mx WHERE id = 8;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- what if the failures happen at COMMIT time?
|
|
\c - - - :worker_1_port
|
|
DROP TRIGGER reject_bad_mx ON objects_mx_1220103;
|
|
CREATE CONSTRAINT TRIGGER reject_bad_mx
|
|
AFTER INSERT ON objects_mx_1220103
|
|
DEFERRABLE INITIALLY DEFERRED
|
|
FOR EACH ROW EXECUTE PROCEDURE reject_bad_mx();
|
|
-- should be the same story as before, just at COMMIT time
|
|
BEGIN;
|
|
SET LOCAL citus.enable_local_execution TO off;
|
|
INSERT INTO objects_mx VALUES (1, 'apple');
|
|
INSERT INTO objects_mx VALUES (2, 'BAD');
|
|
INSERT INTO labs_mx VALUES (9, 'Umbrella Corporation');
|
|
COMMIT;
|
|
WARNING: illegal value
|
|
WARNING: failed to commit transaction on localhost:xxxxx
|
|
ERROR: could not commit transaction for shard xxxxx on at least one active node
|
|
-- data should NOT be persisted
|
|
SELECT * FROM objects_mx WHERE id = 2;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
SELECT * FROM labs_mx WHERE id = 7;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
DROP TRIGGER reject_bad_mx ON labs_mx_1220102;
|
|
CREATE CONSTRAINT TRIGGER reject_bad_mx
|
|
AFTER INSERT ON labs_mx_1220102
|
|
DEFERRABLE INITIALLY DEFERRED
|
|
FOR EACH ROW EXECUTE PROCEDURE reject_bad_mx();
|
|
BEGIN;
|
|
SET LOCAL citus.enable_local_execution TO off;
|
|
INSERT INTO objects_mx VALUES (1, 'apple');
|
|
INSERT INTO objects_mx VALUES (2, 'BAD');
|
|
INSERT INTO labs_mx VALUES (8, 'Aperture Science');
|
|
INSERT INTO labs_mx VALUES (9, 'BAD');
|
|
COMMIT;
|
|
WARNING: illegal value
|
|
WARNING: failed to commit transaction on localhost:xxxxx
|
|
ERROR: could not commit transaction for shard xxxxx on at least one active node
|
|
-- data should NOT be persisted
|
|
SELECT * FROM objects_mx WHERE id = 1;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
SELECT * FROM labs_mx WHERE id = 8;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- what if one shard (objects_mx) succeeds but another (labs_mx) completely fails?
|
|
\c - - - :worker_1_port
|
|
DROP TRIGGER reject_bad_mx ON objects_mx_1220103;
|
|
BEGIN;
|
|
SET LOCAL citus.enable_local_execution TO off;
|
|
INSERT INTO objects_mx VALUES (1, 'apple');
|
|
INSERT INTO labs_mx VALUES (8, 'Aperture Science');
|
|
INSERT INTO labs_mx VALUES (9, 'BAD');
|
|
COMMIT;
|
|
WARNING: illegal value
|
|
WARNING: failed to commit transaction on localhost:xxxxx
|
|
ERROR: could not commit transaction for shard xxxxx on at least one active node
|
|
-- no data should persists
|
|
SELECT * FROM objects_mx WHERE id = 1;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
SELECT * FROM labs_mx WHERE id = 8;
|
|
id | name
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
TRUNCATE objects_mx, labs_mx, researchers_mx;
|
|
DROP TRIGGER reject_bad_mx ON labs_mx_1220102;
|
|
DROP FUNCTION reject_bad_mx;
|