From 655649886da1f9877ec44b058f4689bbe2b5b2d2 Mon Sep 17 00:00:00 2001 From: jhe Date: Fri, 13 Sep 2024 01:44:32 -0700 Subject: [PATCH] [#23897] xClusterDDLRepl: Support create table with partition by primary key Summary: When creating a table with a partition by the primary key, the primary index created is classified as RELKIND_PARTITIONED_INDEX instead of RELKIND_INDEX. Adding support in the ddlrepl extension to handle this type of index as well - since this index is the same table as the parent table, we don't need to search for / replicate this index. Fixes #23897. Jira: DB-12801 Test Plan: ``` ybd --java-test "org.yb.pgsql.TestPgRegressYbExtensionsYbXclusterDdlReplication" ``` Reviewers: xCluster, yyan Reviewed By: yyan Subscribers: ybase, yql Differential Revision: https://phorge.dev.yugabyte.com/D38033 --- .../expected/create_drop_index.out | 20 ++++++++-------- .../expected/create_drop_table.out | 23 +++++++++++++++---- .../source_ddl_end_handler.c | 4 +++- .../sql/create_drop_table.sql | 6 +++++ 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/postgres/yb-extensions/yb_xcluster_ddl_replication/expected/create_drop_index.out b/src/postgres/yb-extensions/yb_xcluster_ddl_replication/expected/create_drop_index.out index 63311ae83163..937a0b818a5d 100644 --- a/src/postgres/yb-extensions/yb_xcluster_ddl_replication/expected/create_drop_index.out +++ b/src/postgres/yb-extensions/yb_xcluster_ddl_replication/expected/create_drop_index.out @@ -28,11 +28,11 @@ SET ROLE NONE; SELECT yb_data FROM yb_xcluster_ddl_replication.ddl_queue ORDER BY start_time; yb_data ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - {"user": "yugabyte", "query": "CREATE TABLE foo(i int PRIMARY KEY, a int, b text, c int);", "schema": "create_index", "version": 1, "command_tag": "CREATE TABLE", "new_rel_map": [{"rel_name": "foo", "relfile_oid": 16451}]} - {"user": "yugabyte", "query": "CREATE INDEX foo_idx_simple ON foo(a);", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_simple", "relfile_oid": 16456}]} - {"user": "yugabyte", "query": "CREATE UNIQUE INDEX foo_idx_unique ON foo(b);", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_unique", "relfile_oid": 16457}]} - {"user": "yugabyte", "query": "CREATE INDEX foo_idx_filtered ON foo(c ASC, a) WHERE a > c;", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_filtered", "relfile_oid": 16458}]} - {"user": "new_role", "query": "CREATE INDEX foo_idx_include ON foo(lower(b)) INCLUDE (a) SPLIT INTO 2 TABLETS;", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_include", "relfile_oid": 16459}]} + {"user": "yugabyte", "query": "CREATE TABLE foo(i int PRIMARY KEY, a int, b text, c int);", "schema": "create_index", "version": 1, "command_tag": "CREATE TABLE", "new_rel_map": [{"rel_name": "foo", "relfile_oid": 16459}]} + {"user": "yugabyte", "query": "CREATE INDEX foo_idx_simple ON foo(a);", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_simple", "relfile_oid": 16464}]} + {"user": "yugabyte", "query": "CREATE UNIQUE INDEX foo_idx_unique ON foo(b);", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_unique", "relfile_oid": 16465}]} + {"user": "yugabyte", "query": "CREATE INDEX foo_idx_filtered ON foo(c ASC, a) WHERE a > c;", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_filtered", "relfile_oid": 16466}]} + {"user": "new_role", "query": "CREATE INDEX foo_idx_include ON foo(lower(b)) INCLUDE (a) SPLIT INTO 2 TABLETS;", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_include", "relfile_oid": 16467}]} (5 rows) SELECT * FROM yb_xcluster_ddl_replication.replicated_ddls ORDER BY start_time; @@ -54,11 +54,11 @@ DROP TABLE foo; SELECT yb_data FROM yb_xcluster_ddl_replication.ddl_queue ORDER BY start_time; yb_data ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - {"user": "yugabyte", "query": "CREATE TABLE foo(i int PRIMARY KEY, a int, b text, c int);", "schema": "create_index", "version": 1, "command_tag": "CREATE TABLE", "new_rel_map": [{"rel_name": "foo", "relfile_oid": 16451}]} - {"user": "yugabyte", "query": "CREATE INDEX foo_idx_simple ON foo(a);", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_simple", "relfile_oid": 16456}]} - {"user": "yugabyte", "query": "CREATE UNIQUE INDEX foo_idx_unique ON foo(b);", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_unique", "relfile_oid": 16457}]} - {"user": "yugabyte", "query": "CREATE INDEX foo_idx_filtered ON foo(c ASC, a) WHERE a > c;", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_filtered", "relfile_oid": 16458}]} - {"user": "new_role", "query": "CREATE INDEX foo_idx_include ON foo(lower(b)) INCLUDE (a) SPLIT INTO 2 TABLETS;", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_include", "relfile_oid": 16459}]} + {"user": "yugabyte", "query": "CREATE TABLE foo(i int PRIMARY KEY, a int, b text, c int);", "schema": "create_index", "version": 1, "command_tag": "CREATE TABLE", "new_rel_map": [{"rel_name": "foo", "relfile_oid": 16459}]} + {"user": "yugabyte", "query": "CREATE INDEX foo_idx_simple ON foo(a);", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_simple", "relfile_oid": 16464}]} + {"user": "yugabyte", "query": "CREATE UNIQUE INDEX foo_idx_unique ON foo(b);", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_unique", "relfile_oid": 16465}]} + {"user": "yugabyte", "query": "CREATE INDEX foo_idx_filtered ON foo(c ASC, a) WHERE a > c;", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_filtered", "relfile_oid": 16466}]} + {"user": "new_role", "query": "CREATE INDEX foo_idx_include ON foo(lower(b)) INCLUDE (a) SPLIT INTO 2 TABLETS;", "schema": "create_index", "version": 1, "command_tag": "CREATE INDEX", "new_rel_map": [{"rel_name": "foo_idx_include", "relfile_oid": 16467}]} {"user": "yugabyte", "query": "DROP INDEX foo_idx_unique;", "schema": "create_index", "version": 1, "command_tag": "DROP INDEX"} {"user": "yugabyte", "query": "DROP INDEX foo_idx_filtered;", "schema": "create_index", "version": 1, "command_tag": "DROP INDEX"} {"user": "yugabyte", "query": "DROP TABLE foo;", "schema": "create_index", "version": 1, "command_tag": "DROP TABLE"} diff --git a/src/postgres/yb-extensions/yb_xcluster_ddl_replication/expected/create_drop_table.out b/src/postgres/yb-extensions/yb_xcluster_ddl_replication/expected/create_drop_table.out index a918473fd897..33a29b58ca20 100644 --- a/src/postgres/yb-extensions/yb_xcluster_ddl_replication/expected/create_drop_table.out +++ b/src/postgres/yb-extensions/yb_xcluster_ddl_replication/expected/create_drop_table.out @@ -36,6 +36,9 @@ SELECT * FROM yb_xcluster_ddl_replication.replicated_ddls ORDER BY start_time; 3 | 1 | {"query": "CREATE TABLE unique_foo(i int PRIMARY KEY, u text UNIQUE);"} (3 rows) +-- Test tables partitioned by their primary key or a column. +CREATE TABLE foo_partitioned_by_pkey(id int, PRIMARY KEY (id)) PARTITION BY RANGE (id); +CREATE TABLE foo_partitioned_by_col(id int) PARTITION BY RANGE (id); -- Now test dropping these tables. DROP TABLE foo; -- Check with manual replication flags enabled, ddl string is captured with flag. @@ -44,6 +47,8 @@ DROP TABLE manual_foo; SET yb_xcluster_ddl_replication.enable_manual_ddl_replication = 0; DROP TABLE extra_foo; DROP TABLE unique_foo; +DROP TABLE foo_partitioned_by_pkey; +DROP TABLE foo_partitioned_by_col; SELECT yb_data FROM yb_xcluster_ddl_replication.ddl_queue ORDER BY start_time; yb_data ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -51,11 +56,15 @@ SELECT yb_data FROM yb_xcluster_ddl_replication.ddl_queue ORDER BY start_time; {"user": "yugabyte", "query": "CREATE TABLE manual_foo(i int PRIMARY KEY);", "schema": "public", "version": 1, "command_tag": "CREATE TABLE", "manual_replication": true} {"user": "yugabyte", "query": "CREATE TABLE extra_foo(i int PRIMARY KEY) WITH (COLOCATION = false) SPLIT INTO 1 TABLETS;", "schema": "public", "version": 1, "command_tag": "CREATE TABLE", "new_rel_map": [{"rel_name": "extra_foo", "relfile_oid": 16422}]} {"user": "yugabyte", "query": "CREATE TABLE unique_foo(i int PRIMARY KEY, u text UNIQUE);", "schema": "public", "version": 1, "command_tag": "CREATE TABLE", "new_rel_map": [{"rel_name": "unique_foo", "relfile_oid": 16427}, {"rel_name": "unique_foo_u_key", "relfile_oid": 16432}]} + {"user": "yugabyte", "query": "CREATE TABLE foo_partitioned_by_pkey(id int, PRIMARY KEY (id)) PARTITION BY RANGE (id);", "schema": "public", "version": 1, "command_tag": "CREATE TABLE", "new_rel_map": [{"rel_name": "foo_partitioned_by_pkey", "relfile_oid": 16434}]} + {"user": "yugabyte", "query": "CREATE TABLE foo_partitioned_by_col(id int) PARTITION BY RANGE (id);", "schema": "public", "version": 1, "command_tag": "CREATE TABLE", "new_rel_map": [{"rel_name": "foo_partitioned_by_col", "relfile_oid": 16439}]} {"user": "yugabyte", "query": "DROP TABLE foo;", "schema": "public", "version": 1, "command_tag": "DROP TABLE"} {"user": "yugabyte", "query": "DROP TABLE manual_foo;", "schema": "public", "version": 1, "command_tag": "DROP TABLE", "manual_replication": true} {"user": "yugabyte", "query": "DROP TABLE extra_foo;", "schema": "public", "version": 1, "command_tag": "DROP TABLE"} {"user": "yugabyte", "query": "DROP TABLE unique_foo;", "schema": "public", "version": 1, "command_tag": "DROP TABLE"} -(8 rows) + {"user": "yugabyte", "query": "DROP TABLE foo_partitioned_by_pkey;", "schema": "public", "version": 1, "command_tag": "DROP TABLE"} + {"user": "yugabyte", "query": "DROP TABLE foo_partitioned_by_col;", "schema": "public", "version": 1, "command_tag": "DROP TABLE"} +(12 rows) SELECT * FROM yb_xcluster_ddl_replication.replicated_ddls ORDER BY start_time; start_time | query_id | yb_data @@ -63,10 +72,14 @@ SELECT * FROM yb_xcluster_ddl_replication.replicated_ddls ORDER BY start_time; 1 | 1 | {"query": "CREATE TABLE foo(i int PRIMARY KEY);"} 2 | 1 | {"query": "CREATE TABLE extra_foo(i int PRIMARY KEY) WITH (COLOCATION = false) SPLIT INTO 1 TABLETS;"} 3 | 1 | {"query": "CREATE TABLE unique_foo(i int PRIMARY KEY, u text UNIQUE);"} - 4 | 1 | {"query": "DROP TABLE foo;"} - 5 | 1 | {"query": "DROP TABLE extra_foo;"} - 6 | 1 | {"query": "DROP TABLE unique_foo;"} -(6 rows) + 4 | 1 | {"query": "CREATE TABLE foo_partitioned_by_pkey(id int, PRIMARY KEY (id)) PARTITION BY RANGE (id);"} + 5 | 1 | {"query": "CREATE TABLE foo_partitioned_by_col(id int) PARTITION BY RANGE (id);"} + 6 | 1 | {"query": "DROP TABLE foo;"} + 7 | 1 | {"query": "DROP TABLE extra_foo;"} + 8 | 1 | {"query": "DROP TABLE unique_foo;"} + 9 | 1 | {"query": "DROP TABLE foo_partitioned_by_pkey;"} + 10 | 1 | {"query": "DROP TABLE foo_partitioned_by_col;"} +(10 rows) -- Test mix of temp and regular tables. SET yb_xcluster_ddl_replication.replication_role = SOURCE; diff --git a/src/postgres/yb-extensions/yb_xcluster_ddl_replication/source_ddl_end_handler.c b/src/postgres/yb-extensions/yb_xcluster_ddl_replication/source_ddl_end_handler.c index 49a876d25787..02993dded2ca 100644 --- a/src/postgres/yb-extensions/yb_xcluster_ddl_replication/source_ddl_end_handler.c +++ b/src/postgres/yb-extensions/yb_xcluster_ddl_replication/source_ddl_end_handler.c @@ -88,7 +88,9 @@ ShouldReplicateCreateRelation(Oid rel_oid, List **new_rel_list) // Ignore temporary tables and primary indexes (same as main table). if (!IsYBBackedRelation(rel) || - (rel->rd_rel->relkind == RELKIND_INDEX && rel->rd_index->indisprimary)) + ((rel->rd_rel->relkind == RELKIND_INDEX || + rel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) && + rel->rd_index->indisprimary)) { RelationClose(rel); return false; diff --git a/src/postgres/yb-extensions/yb_xcluster_ddl_replication/sql/create_drop_table.sql b/src/postgres/yb-extensions/yb_xcluster_ddl_replication/sql/create_drop_table.sql index 6bd5f55bf7c8..66d53b232cf2 100644 --- a/src/postgres/yb-extensions/yb_xcluster_ddl_replication/sql/create_drop_table.sql +++ b/src/postgres/yb-extensions/yb_xcluster_ddl_replication/sql/create_drop_table.sql @@ -25,6 +25,10 @@ CREATE TABLE unique_foo(i int PRIMARY KEY, u text UNIQUE); SELECT yb_data FROM yb_xcluster_ddl_replication.ddl_queue ORDER BY start_time; SELECT * FROM yb_xcluster_ddl_replication.replicated_ddls ORDER BY start_time; +-- Test tables partitioned by their primary key or a column. +CREATE TABLE foo_partitioned_by_pkey(id int, PRIMARY KEY (id)) PARTITION BY RANGE (id); +CREATE TABLE foo_partitioned_by_col(id int) PARTITION BY RANGE (id); + -- Now test dropping these tables. DROP TABLE foo; @@ -35,6 +39,8 @@ SET yb_xcluster_ddl_replication.enable_manual_ddl_replication = 0; DROP TABLE extra_foo; DROP TABLE unique_foo; +DROP TABLE foo_partitioned_by_pkey; +DROP TABLE foo_partitioned_by_col; SELECT yb_data FROM yb_xcluster_ddl_replication.ddl_queue ORDER BY start_time; SELECT * FROM yb_xcluster_ddl_replication.replicated_ddls ORDER BY start_time;