Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
395 changes: 395 additions & 0 deletions src/test/regress/expected/failure_copy_on_hash_0.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,395 @@
--
-- Failure tests for COPY to hash distributed tables
--
CREATE SCHEMA copy_distributed_table;
SET search_path TO 'copy_distributed_table';
SET citus.next_shard_id TO 1710000;
SELECT citus.mitmproxy('conn.allow()');
mitmproxy
---------------------------------------------------------------------

(1 row)

-- With one placement COPY should error out and placement should stay healthy.
SET citus.shard_replication_factor TO 1;
SET citus.shard_count to 4;
SET citus.max_cached_conns_per_worker to 0;
CREATE TABLE test_table(id int, value_1 int);
SELECT create_distributed_table('test_table','id');
create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE VIEW unhealthy_shard_count AS
SELECT count(*)
FROM pg_dist_shard_placement pdsp
JOIN
pg_dist_shard pds
ON pdsp.shardid=pds.shardid
WHERE logicalrelid='copy_distributed_table.test_table'::regclass AND shardstate != 1;
-- Just kill the connection after sending the first query to the worker.
SELECT citus.mitmproxy('conn.kill()');
mitmproxy
---------------------------------------------------------------------

(1 row)

\COPY test_table FROM stdin delimiter ',';
ERROR: connection to the remote node postgres@localhost:xxxxx failed with the following error: connection not open
CONTEXT: COPY test_table, line 1: "1,2"
SELECT citus.mitmproxy('conn.allow()');
mitmproxy
---------------------------------------------------------------------

(1 row)

SELECT * FROM unhealthy_shard_count;
count
---------------------------------------------------------------------
0
(1 row)

SELECT count(*) FROM test_table;
count
---------------------------------------------------------------------
0
(1 row)

-- Now, kill the connection while copying the data
SELECT citus.mitmproxy('conn.onCopyData().kill()');
mitmproxy
---------------------------------------------------------------------

(1 row)

\COPY test_table FROM stdin delimiter ',';
ERROR: failed to COPY to shard xxxxx on localhost:xxxxx
SELECT citus.mitmproxy('conn.allow()');
mitmproxy
---------------------------------------------------------------------

(1 row)

SELECT * FROM unhealthy_shard_count;
count
---------------------------------------------------------------------
0
(1 row)

SELECT count(*) FROM test_table;
count
---------------------------------------------------------------------
0
(1 row)

-- Similar to the above one, but now cancel the connection
-- instead of killing it.
SELECT citus.mitmproxy('conn.onCopyData().cancel(' || pg_backend_pid() || ')');
mitmproxy
---------------------------------------------------------------------

(1 row)

\COPY test_table FROM stdin delimiter ',';
ERROR: canceling statement due to user request
SELECT citus.mitmproxy('conn.allow()');
mitmproxy
---------------------------------------------------------------------

(1 row)

SELECT * FROM unhealthy_shard_count;
count
---------------------------------------------------------------------
0
(1 row)

SELECT count(*) FROM test_table;
count
---------------------------------------------------------------------
0
(1 row)

-- kill the connection after worker sends command complete message
SELECT citus.mitmproxy('conn.onCommandComplete(command="COPY 1").kill()');
mitmproxy
---------------------------------------------------------------------

(1 row)

\COPY test_table FROM stdin delimiter ',';
ERROR: failed to COPY to shard xxxxx on localhost:xxxxx
SELECT citus.mitmproxy('conn.allow()');
mitmproxy
---------------------------------------------------------------------

(1 row)

SELECT * FROM unhealthy_shard_count;
count
---------------------------------------------------------------------
0
(1 row)

SELECT count(*) FROM test_table;
count
---------------------------------------------------------------------
0
(1 row)

-- similar to above one, but cancel the connection on command complete
SELECT citus.mitmproxy('conn.onCommandComplete(command="COPY 1").cancel(' || pg_backend_pid() || ')');
mitmproxy
---------------------------------------------------------------------

(1 row)

\COPY test_table FROM stdin delimiter ',';
ERROR: canceling statement due to user request
SELECT citus.mitmproxy('conn.allow()');
mitmproxy
---------------------------------------------------------------------

(1 row)

SELECT * FROM unhealthy_shard_count;
count
---------------------------------------------------------------------
0
(1 row)

SELECT count(*) FROM test_table;
count
---------------------------------------------------------------------
0
(1 row)

-- kill the connection on PREPARE TRANSACTION
SELECT citus.mitmproxy('conn.onQuery(query="PREPARE TRANSACTION").kill()');
mitmproxy
---------------------------------------------------------------------

(1 row)

\COPY test_table FROM stdin delimiter ',';
ERROR: connection not open
CONTEXT: while executing command on localhost:xxxxx
SELECT citus.mitmproxy('conn.allow()');
mitmproxy
---------------------------------------------------------------------

(1 row)

SELECT * FROM unhealthy_shard_count;
count
---------------------------------------------------------------------
0
(1 row)

SELECT count(*) FROM test_table;
count
---------------------------------------------------------------------
0
(1 row)

-- we don't want to see the prepared transaction numbers in the warnings
SET client_min_messages TO ERROR;
-- kill on command complete on COMMIT PREPARE, command should succeed
SELECT citus.mitmproxy('conn.onCommandComplete(command="COMMIT PREPARED").kill()');
mitmproxy
---------------------------------------------------------------------

(1 row)

\COPY test_table FROM stdin delimiter ',';
SET client_min_messages TO NOTICE;
SELECT citus.mitmproxy('conn.allow()');
mitmproxy
---------------------------------------------------------------------

(1 row)

SELECT * FROM unhealthy_shard_count;
count
---------------------------------------------------------------------
0
(1 row)

SELECT count(*) FROM test_table;
count
---------------------------------------------------------------------
4
(1 row)

TRUNCATE TABLE test_table;
-- kill on ROLLBACK, command could be rollbacked
SELECT citus.mitmproxy('conn.onQuery(query="ROLLBACK").kill()');
mitmproxy
---------------------------------------------------------------------

(1 row)

BEGIN;
\COPY test_table FROM stdin delimiter ',';
ROLLBACK;
WARNING: connection not open
CONTEXT: while executing command on localhost:xxxxx
SELECT citus.mitmproxy('conn.allow()');
mitmproxy
---------------------------------------------------------------------

(1 row)

SELECT * FROM unhealthy_shard_count;
count
---------------------------------------------------------------------
0
(1 row)

SELECT count(*) FROM test_table;
count
---------------------------------------------------------------------
0
(1 row)

DROP TABLE test_table CASCADE;
NOTICE: drop cascades to view unhealthy_shard_count
-- With two placement, should we error out or mark untouched shard placements as inactive?
SET citus.shard_replication_factor TO 2;
CREATE TABLE test_table_2(id int, value_1 int);
SELECT create_distributed_table('test_table_2','id');
create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT citus.mitmproxy('conn.kill()');
mitmproxy
---------------------------------------------------------------------

(1 row)

SELECT :VERSION_NUM / 10000 = 19 AND :'VERSION_NAME' ~ '^19(beta([3-9]|[1-9][0-9]+)|rc[1-9][0-9]*|[.][0-9]+)?([[:space:]].*)?$' AS psql_version_ge_19beta3 \gset
\if :psql_version_ge_19beta3
\COPY test_table_2 FROM PROGRAM 'true' delimiter ',';
ERROR: connection to the remote node postgres@localhost:xxxxx failed with the following error: connection not open
\else
\COPY test_table_2 FROM stdin delimiter ',';
\endif
SELECT citus.mitmproxy('conn.allow()');
mitmproxy
---------------------------------------------------------------------

(1 row)

SELECT pds.logicalrelid, pdsd.shardid, pdsd.shardstate
FROM pg_dist_shard_placement as pdsd
INNER JOIN pg_dist_shard as pds
ON pdsd.shardid = pds.shardid
WHERE pds.logicalrelid = 'test_table_2'::regclass
ORDER BY shardid, nodeport;
logicalrelid | shardid | shardstate
---------------------------------------------------------------------
test_table_2 | 1710004 | 1
test_table_2 | 1710004 | 1
test_table_2 | 1710005 | 1
test_table_2 | 1710005 | 1
test_table_2 | 1710006 | 1
test_table_2 | 1710006 | 1
test_table_2 | 1710007 | 1
test_table_2 | 1710007 | 1
(8 rows)

-- Create test_table_2 again to have healthy one
DROP TABLE test_table_2;
CREATE TABLE test_table_2(id int, value_1 int);
SELECT create_distributed_table('test_table_2','id');
create_distributed_table
---------------------------------------------------------------------

(1 row)

-- Kill the connection when we try to start the COPY
-- The query should abort
SELECT citus.mitmproxy('conn.onQuery(query="FROM STDIN WITH").killall()');
mitmproxy
---------------------------------------------------------------------

(1 row)

\COPY test_table_2 FROM stdin delimiter ',';
ERROR: connection not open
CONTEXT: while executing command on localhost:xxxxx
COPY test_table_2, line 1: "1,2"
SELECT citus.mitmproxy('conn.allow()');
mitmproxy
---------------------------------------------------------------------

(1 row)

SELECT pds.logicalrelid, pdsd.shardid, pdsd.shardstate
FROM pg_dist_shard_placement as pdsd
INNER JOIN pg_dist_shard as pds
ON pdsd.shardid = pds.shardid
WHERE pds.logicalrelid = 'test_table_2'::regclass
ORDER BY shardid, nodeport;
logicalrelid | shardid | shardstate
---------------------------------------------------------------------
test_table_2 | 1710008 | 1
test_table_2 | 1710008 | 1
test_table_2 | 1710009 | 1
test_table_2 | 1710009 | 1
test_table_2 | 1710010 | 1
test_table_2 | 1710010 | 1
test_table_2 | 1710011 | 1
test_table_2 | 1710011 | 1
(8 rows)

-- Create test_table_2 again to have healthy one
DROP TABLE test_table_2;
CREATE TABLE test_table_2(id int, value_1 int);
SELECT create_distributed_table('test_table_2','id');
create_distributed_table
---------------------------------------------------------------------

(1 row)

-- When kill on copying data, it will be rollbacked and placements won't be labaled as invalid.
-- Note that now we sent data to shard xxxxx, yet it is not marked as invalid.
-- You can check the issue about this behaviour: https://github.com/citusdata/citus/issues/1933
SELECT citus.mitmproxy('conn.onCopyData().kill()');
mitmproxy
---------------------------------------------------------------------

(1 row)

\COPY test_table_2 FROM stdin delimiter ',';
ERROR: failed to COPY to shard xxxxx on localhost:xxxxx
SELECT citus.mitmproxy('conn.allow()');
mitmproxy
---------------------------------------------------------------------

(1 row)

SELECT pds.logicalrelid, pdsd.shardid, pdsd.shardstate
FROM pg_dist_shard_placement as pdsd
INNER JOIN pg_dist_shard as pds
ON pdsd.shardid = pds.shardid
WHERE pds.logicalrelid = 'test_table_2'::regclass
ORDER BY shardid, nodeport;
logicalrelid | shardid | shardstate
---------------------------------------------------------------------
test_table_2 | 1710012 | 1
test_table_2 | 1710012 | 1
test_table_2 | 1710013 | 1
test_table_2 | 1710013 | 1
test_table_2 | 1710014 | 1
test_table_2 | 1710014 | 1
test_table_2 | 1710015 | 1
test_table_2 | 1710015 | 1
(8 rows)

DROP SCHEMA copy_distributed_table CASCADE;
NOTICE: drop cascades to table test_table_2
SET search_path TO default;
Loading
Loading