From 32fb19911c8be3f811b2fcc8985b5fae59eaad6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mehmet=20furkan=20=C5=9Fahin?= Date: Fri, 27 Oct 2017 16:11:10 +0300 Subject: [PATCH] Add Constraint %s Add Primary Key Using index %s support This commit makes a change in relay_event_utility.c to check if the Alter Table command adds a constraint using index. If this is the case, it appends the shard id to the index name. --- .../distributed/relay/relay_event_utility.c | 15 +- .../multi_alter_table_add_constraints.out | 128 ++++++++++++++++++ .../sql/multi_alter_table_add_constraints.sql | 87 ++++++++++++ 3 files changed, 228 insertions(+), 2 deletions(-) diff --git a/src/backend/distributed/relay/relay_event_utility.c b/src/backend/distributed/relay/relay_event_utility.c index 3ea3ff800..827e737af 100644 --- a/src/backend/distributed/relay/relay_event_utility.c +++ b/src/backend/distributed/relay/relay_event_utility.c @@ -100,8 +100,19 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId) { AlterTableCmd *command = (AlterTableCmd *) lfirst(commandCell); - if (command->subtype == AT_AddConstraint || - command->subtype == AT_DropConstraint) + if (command->subtype == AT_AddConstraint) + { + Constraint *constraint = (Constraint *) command->def; + + if (constraint->contype == CONSTR_PRIMARY && constraint->indexname) + { + char **indexName = &(constraint->indexname); + AppendShardIdToName(indexName, shardId); + } + + AppendShardIdToConstraintName(command, shardId); + } + if (command->subtype == AT_DropConstraint) { AppendShardIdToConstraintName(command, shardId); } diff --git a/src/test/regress/expected/multi_alter_table_add_constraints.out b/src/test/regress/expected/multi_alter_table_add_constraints.out index 7ae817e8a..67c832d5e 100644 --- a/src/test/regress/expected/multi_alter_table_add_constraints.out +++ b/src/test/regress/expected/multi_alter_table_add_constraints.out @@ -488,3 +488,131 @@ SELECT "Constraint", "Definition" FROM table_checks WHERE relid='public.products \c - - - :master_port DROP TABLE products; +SET citus.shard_count to 2; +-- Test if the ALTER TABLE %s ADD %s PRIMARY KEY %s works +CREATE SCHEMA sc1; +CREATE TABLE sc1.alter_add_prim_key(x int, y int); +CREATE UNIQUE INDEX CONCURRENTLY alter_pk_idx ON sc1.alter_add_prim_key(x); +ALTER TABLE sc1.alter_add_prim_key ADD CONSTRAINT alter_pk_idx PRIMARY KEY USING INDEX alter_pk_idx; +SELECT create_distributed_table('sc1.alter_add_prim_key', 'x'); + create_distributed_table +-------------------------- + +(1 row) + +SELECT (run_command_on_workers($$ + SELECT + kc.constraint_name + FROM + information_schema.table_constraints tc join information_schema.key_column_usage kc on (kc.table_name = tc.table_name and kc.table_schema = tc.table_schema and kc.constraint_name = tc.constraint_name) + WHERE + kc.table_schema = 'sc1' and tc.constraint_type = 'PRIMARY KEY' and kc.table_name LIKE 'alter_add_prim_key_%' + ORDER BY + 1 + LIMIT + 1; + $$)).* +ORDER BY + 1,2,3,4; + nodename | nodeport | success | result +-----------+----------+---------+---------------------- + localhost | 57637 | t | alter_pk_idx_1450234 + localhost | 57638 | t | alter_pk_idx_1450234 +(2 rows) + +CREATE SCHEMA sc2; +CREATE TABLE sc2.alter_add_prim_key(x int, y int); +SET search_path TO 'sc2'; +SELECT create_distributed_table('alter_add_prim_key', 'x'); + create_distributed_table +-------------------------- + +(1 row) + +CREATE UNIQUE INDEX CONCURRENTLY alter_pk_idx ON alter_add_prim_key(x); +ALTER TABLE alter_add_prim_key ADD CONSTRAINT alter_pk_idx PRIMARY KEY USING INDEX alter_pk_idx; +NOTICE: using one-phase commit for distributed DDL commands +HINT: You can enable two-phase commit for extra safety with: SET citus.multi_shard_commit_protocol TO '2pc' +SELECT (run_command_on_workers($$ + SELECT + kc.constraint_name + FROM + information_schema.table_constraints tc join information_schema.key_column_usage kc on (kc.table_name = tc.table_name and kc.table_schema = tc.table_schema and kc.constraint_name = tc.constraint_name) + WHERE + kc.table_schema = 'sc2' and tc.constraint_type = 'PRIMARY KEY' and kc.table_name LIKE 'alter_add_prim_key_%' + ORDER BY + 1 + LIMIT + 1; + $$)).* +ORDER BY + 1,2,3,4; + nodename | nodeport | success | result +-----------+----------+---------+---------------------- + localhost | 57637 | t | alter_pk_idx_1450236 + localhost | 57638 | t | alter_pk_idx_1450236 +(2 rows) + +-- We are running almost the same test with a slight change on the constraint name because if the constraint has a different name than the index, Postgres renames the index. +CREATE SCHEMA sc3; +CREATE TABLE sc3.alter_add_prim_key(x int); +INSERT INTO sc3.alter_add_prim_key(x) SELECT generate_series(1,100); +SET search_path TO 'sc3'; +SELECT create_distributed_table('alter_add_prim_key', 'x'); +NOTICE: Copying data from local table... + create_distributed_table +-------------------------- + +(1 row) + +CREATE UNIQUE INDEX CONCURRENTLY alter_pk_idx ON alter_add_prim_key(x); +ALTER TABLE alter_add_prim_key ADD CONSTRAINT a_constraint PRIMARY KEY USING INDEX alter_pk_idx; +NOTICE: ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index "alter_pk_idx" to "a_constraint" +SELECT (run_command_on_workers($$ + SELECT + kc.constraint_name + FROM + information_schema.table_constraints tc join information_schema.key_column_usage kc on (kc.table_name = tc.table_name and kc.table_schema = tc.table_schema and kc.constraint_name = tc.constraint_name) + WHERE + kc.table_schema = 'sc3' and tc.constraint_type = 'PRIMARY KEY' and kc.table_name LIKE 'alter_add_prim_key_%' + ORDER BY + 1 + LIMIT + 1; + $$)).* +ORDER BY + 1,2,3,4; + nodename | nodeport | success | result +-----------+----------+---------+---------------------- + localhost | 57637 | t | a_constraint_1450238 + localhost | 57638 | t | a_constraint_1450238 +(2 rows) + +ALTER TABLE alter_add_prim_key DROP CONSTRAINT a_constraint; +SELECT (run_command_on_workers($$ + SELECT + kc.constraint_name + FROM + information_schema.table_constraints tc join information_schema.key_column_usage kc on (kc.table_name = tc.table_name and kc.table_schema = tc.table_schema and kc.constraint_name = tc.constraint_name) + WHERE + kc.table_schema = 'sc3' and tc.constraint_type = 'PRIMARY KEY' and kc.table_name LIKE 'alter_add_prim_key_%' + ORDER BY + 1 + LIMIT + 1; + $$)).* +ORDER BY + 1,2,3,4; + nodename | nodeport | success | result +-----------+----------+---------+-------- + localhost | 57637 | t | + localhost | 57638 | t | +(2 rows) + +SET search_path TO 'public'; +DROP SCHEMA sc1 CASCADE; +NOTICE: drop cascades to table sc1.alter_add_prim_key +DROP SCHEMA sc2 CASCADE; +NOTICE: drop cascades to table sc2.alter_add_prim_key +DROP SCHEMA sc3 CASCADE; +NOTICE: drop cascades to table sc3.alter_add_prim_key diff --git a/src/test/regress/sql/multi_alter_table_add_constraints.sql b/src/test/regress/sql/multi_alter_table_add_constraints.sql index 51ce02a1a..1b1f9a47b 100644 --- a/src/test/regress/sql/multi_alter_table_add_constraints.sql +++ b/src/test/regress/sql/multi_alter_table_add_constraints.sql @@ -422,3 +422,90 @@ SELECT "Constraint", "Definition" FROM table_checks WHERE relid='public.products \c - - - :master_port DROP TABLE products; + +SET citus.shard_count to 2; +-- Test if the ALTER TABLE %s ADD %s PRIMARY KEY %s works +CREATE SCHEMA sc1; +CREATE TABLE sc1.alter_add_prim_key(x int, y int); +CREATE UNIQUE INDEX CONCURRENTLY alter_pk_idx ON sc1.alter_add_prim_key(x); +ALTER TABLE sc1.alter_add_prim_key ADD CONSTRAINT alter_pk_idx PRIMARY KEY USING INDEX alter_pk_idx; +SELECT create_distributed_table('sc1.alter_add_prim_key', 'x'); +SELECT (run_command_on_workers($$ + SELECT + kc.constraint_name + FROM + information_schema.table_constraints tc join information_schema.key_column_usage kc on (kc.table_name = tc.table_name and kc.table_schema = tc.table_schema and kc.constraint_name = tc.constraint_name) + WHERE + kc.table_schema = 'sc1' and tc.constraint_type = 'PRIMARY KEY' and kc.table_name LIKE 'alter_add_prim_key_%' + ORDER BY + 1 + LIMIT + 1; + $$)).* +ORDER BY + 1,2,3,4; + +CREATE SCHEMA sc2; +CREATE TABLE sc2.alter_add_prim_key(x int, y int); +SET search_path TO 'sc2'; +SELECT create_distributed_table('alter_add_prim_key', 'x'); +CREATE UNIQUE INDEX CONCURRENTLY alter_pk_idx ON alter_add_prim_key(x); +ALTER TABLE alter_add_prim_key ADD CONSTRAINT alter_pk_idx PRIMARY KEY USING INDEX alter_pk_idx; +SELECT (run_command_on_workers($$ + SELECT + kc.constraint_name + FROM + information_schema.table_constraints tc join information_schema.key_column_usage kc on (kc.table_name = tc.table_name and kc.table_schema = tc.table_schema and kc.constraint_name = tc.constraint_name) + WHERE + kc.table_schema = 'sc2' and tc.constraint_type = 'PRIMARY KEY' and kc.table_name LIKE 'alter_add_prim_key_%' + ORDER BY + 1 + LIMIT + 1; + $$)).* +ORDER BY + 1,2,3,4; + +-- We are running almost the same test with a slight change on the constraint name because if the constraint has a different name than the index, Postgres renames the index. +CREATE SCHEMA sc3; +CREATE TABLE sc3.alter_add_prim_key(x int); +INSERT INTO sc3.alter_add_prim_key(x) SELECT generate_series(1,100); +SET search_path TO 'sc3'; +SELECT create_distributed_table('alter_add_prim_key', 'x'); +CREATE UNIQUE INDEX CONCURRENTLY alter_pk_idx ON alter_add_prim_key(x); +ALTER TABLE alter_add_prim_key ADD CONSTRAINT a_constraint PRIMARY KEY USING INDEX alter_pk_idx; +SELECT (run_command_on_workers($$ + SELECT + kc.constraint_name + FROM + information_schema.table_constraints tc join information_schema.key_column_usage kc on (kc.table_name = tc.table_name and kc.table_schema = tc.table_schema and kc.constraint_name = tc.constraint_name) + WHERE + kc.table_schema = 'sc3' and tc.constraint_type = 'PRIMARY KEY' and kc.table_name LIKE 'alter_add_prim_key_%' + ORDER BY + 1 + LIMIT + 1; + $$)).* +ORDER BY + 1,2,3,4; + +ALTER TABLE alter_add_prim_key DROP CONSTRAINT a_constraint; +SELECT (run_command_on_workers($$ + SELECT + kc.constraint_name + FROM + information_schema.table_constraints tc join information_schema.key_column_usage kc on (kc.table_name = tc.table_name and kc.table_schema = tc.table_schema and kc.constraint_name = tc.constraint_name) + WHERE + kc.table_schema = 'sc3' and tc.constraint_type = 'PRIMARY KEY' and kc.table_name LIKE 'alter_add_prim_key_%' + ORDER BY + 1 + LIMIT + 1; + $$)).* +ORDER BY + 1,2,3,4; +SET search_path TO 'public'; + +DROP SCHEMA sc1 CASCADE; +DROP SCHEMA sc2 CASCADE; +DROP SCHEMA sc3 CASCADE;