From 2027d592a14fa7df40ad1eb38357d9ad94739c18 Mon Sep 17 00:00:00 2001 From: Ahmet Gedemenli Date: Fri, 6 Jan 2023 14:52:08 +0300 Subject: [PATCH] Fix crash when trying to replicate a ref table that is actually dropped (#6595) DESCRIPTION: Fix crash when trying to replicate a ref table that is actually dropped see #6592 We should have a real solution for it. (cherry picked from commit bc3383170e59e2557f711c90699b2b1f0d0090bb) (cherry picked from commit 9e32e343131301c8993d9128eb4c20b918dc424b) --- .../distributed/operations/repair_shards.c | 9 +++++ .../distributed/utils/reference_table_utils.c | 6 +++ src/test/regress/expected/issue_6592.out | 37 +++++++++++++++++++ src/test/regress/multi_mx_schedule | 2 + src/test/regress/sql/issue_6592.sql | 33 +++++++++++++++++ 5 files changed, 87 insertions(+) create mode 100644 src/test/regress/expected/issue_6592.out create mode 100644 src/test/regress/sql/issue_6592.sql diff --git a/src/backend/distributed/operations/repair_shards.c b/src/backend/distributed/operations/repair_shards.c index 26928fd3a..4076f0fb0 100644 --- a/src/backend/distributed/operations/repair_shards.c +++ b/src/backend/distributed/operations/repair_shards.c @@ -1419,6 +1419,15 @@ EnsureShardCanBeCopied(int64 shardId, const char *sourceNodeName, int32 sourceNo shardId))); } } + + /* + * Make sure the relation exists. In some cases the relation is actually dropped but + * the metadata remains, such as dropping table while citus.enable_ddl_propagation + * is set to off. + */ + ShardInterval *shardInterval = LoadShardInterval(shardId); + Oid distributedTableId = shardInterval->relationId; + EnsureRelationExists(distributedTableId); } diff --git a/src/backend/distributed/utils/reference_table_utils.c b/src/backend/distributed/utils/reference_table_utils.c index 1411915f3..fb7d70c5d 100644 --- a/src/backend/distributed/utils/reference_table_utils.c +++ b/src/backend/distributed/utils/reference_table_utils.c @@ -657,6 +657,12 @@ ReplicateAllReferenceTablesToNode(WorkerNode *workerNode) ShardInterval *shardInterval = NULL; foreach_ptr(shardInterval, referenceShardIntervalList) { + /* + * Make sure the relation exists. In some cases the relation is + * actually dropped but the metadata remains, such as dropping table + * while citus.enable_ddl_propagation is set to off. + */ + EnsureRelationExists(shardInterval->relationId); uint64 shardId = shardInterval->shardId; LockShardDistributionMetadata(shardId, ExclusiveLock); diff --git a/src/test/regress/expected/issue_6592.out b/src/test/regress/expected/issue_6592.out new file mode 100644 index 000000000..b80870b41 --- /dev/null +++ b/src/test/regress/expected/issue_6592.out @@ -0,0 +1,37 @@ +-- https://github.com/citusdata/citus/issues/6592 +SET citus.next_shard_id TO 180000; +CREATE TABLE ref_table_to_be_dropped_6592 (key int); +SELECT create_reference_table('ref_table_to_be_dropped_6592'); + create_reference_table +--------------------------------------------------------------------- + +(1 row) + +CREATE TABLE ref_table_oid AS SELECT oid FROM pg_class WHERE relname = 'ref_table_to_be_dropped_6592'; +SET citus.enable_ddl_propagation TO OFF; +DROP TABLE ref_table_to_be_dropped_6592 CASCADE; -- citus_drop_all_shards doesn't drop shards and metadata +RESET citus.enable_ddl_propagation; +-- error out for the dropped reference table +SET client_min_messages to ERROR; +SELECT 1 FROM master_add_node('localhost', :master_port, groupId => 0); +ERROR: relation with OID XXXX does not exist +RESET client_min_messages; +\c - - - :worker_1_port +SET citus.enable_ddl_propagation TO OFF; +DELETE FROM pg_dist_partition WHERE logicalrelid = 'ref_table_to_be_dropped_6592'::regclass; +DELETE FROM pg_dist_placement WHERE shardid = 180000; +DELETE FROM pg_dist_shard WHERE shardid = 180000; +DROP TABLE IF EXISTS ref_table_to_be_dropped_6592; +DROP TABLE IF EXISTS ref_table_to_be_dropped_6592_180000; +\c - - - :worker_2_port +SET citus.enable_ddl_propagation TO OFF; +DELETE FROM pg_dist_partition WHERE logicalrelid = 'ref_table_to_be_dropped_6592'::regclass; +DELETE FROM pg_dist_placement WHERE shardid = 180000; +DELETE FROM pg_dist_shard WHERE shardid = 180000; +DROP TABLE IF EXISTS ref_table_to_be_dropped_6592; +DROP TABLE IF EXISTS ref_table_to_be_dropped_6592_180000; +\c - - - :master_port +DELETE FROM pg_dist_placement WHERE shardid = 180000; +DELETE FROM pg_dist_shard WHERE shardid = 180000; +DELETE FROM pg_dist_partition WHERE logicalrelid IN (SELECT oid FROM ref_table_oid); +DROP TABLE ref_table_oid; diff --git a/src/test/regress/multi_mx_schedule b/src/test/regress/multi_mx_schedule index 0bf97cc9a..fe944ad2c 100644 --- a/src/test/regress/multi_mx_schedule +++ b/src/test/regress/multi_mx_schedule @@ -67,6 +67,8 @@ test: distributed_locks test: local_shard_execution_dropped_column test: metadata_sync_helpers +test: issue_6592 + # test that no tests leaked intermediate results. This should always be last test: ensure_no_intermediate_data_leak diff --git a/src/test/regress/sql/issue_6592.sql b/src/test/regress/sql/issue_6592.sql new file mode 100644 index 000000000..47c953457 --- /dev/null +++ b/src/test/regress/sql/issue_6592.sql @@ -0,0 +1,33 @@ +-- https://github.com/citusdata/citus/issues/6592 +SET citus.next_shard_id TO 180000; +CREATE TABLE ref_table_to_be_dropped_6592 (key int); +SELECT create_reference_table('ref_table_to_be_dropped_6592'); +CREATE TABLE ref_table_oid AS SELECT oid FROM pg_class WHERE relname = 'ref_table_to_be_dropped_6592'; +SET citus.enable_ddl_propagation TO OFF; +DROP TABLE ref_table_to_be_dropped_6592 CASCADE; -- citus_drop_all_shards doesn't drop shards and metadata +RESET citus.enable_ddl_propagation; + +-- error out for the dropped reference table +SET client_min_messages to ERROR; +SELECT 1 FROM master_add_node('localhost', :master_port, groupId => 0); +RESET client_min_messages; + +\c - - - :worker_1_port +SET citus.enable_ddl_propagation TO OFF; +DELETE FROM pg_dist_partition WHERE logicalrelid = 'ref_table_to_be_dropped_6592'::regclass; +DELETE FROM pg_dist_placement WHERE shardid = 180000; +DELETE FROM pg_dist_shard WHERE shardid = 180000; +DROP TABLE IF EXISTS ref_table_to_be_dropped_6592; +DROP TABLE IF EXISTS ref_table_to_be_dropped_6592_180000; +\c - - - :worker_2_port +SET citus.enable_ddl_propagation TO OFF; +DELETE FROM pg_dist_partition WHERE logicalrelid = 'ref_table_to_be_dropped_6592'::regclass; +DELETE FROM pg_dist_placement WHERE shardid = 180000; +DELETE FROM pg_dist_shard WHERE shardid = 180000; +DROP TABLE IF EXISTS ref_table_to_be_dropped_6592; +DROP TABLE IF EXISTS ref_table_to_be_dropped_6592_180000; +\c - - - :master_port +DELETE FROM pg_dist_placement WHERE shardid = 180000; +DELETE FROM pg_dist_shard WHERE shardid = 180000; +DELETE FROM pg_dist_partition WHERE logicalrelid IN (SELECT oid FROM ref_table_oid); +DROP TABLE ref_table_oid;