summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera2024-04-15 13:07:47 +0000
committerAlvaro Herrera2024-04-15 13:07:47 +0000
commitcee8db3f680b737b64d747530b48d30828cf4790 (patch)
treef45fbe7ffe98414d9e4e4b8348597f3bff73ca38
parent9dfcac8e15acc3b4d4d5bc02383a56ccb07229fe (diff)
ATTACH PARTITION: Don't match a PK with a UNIQUE constraint
When matching constraints in AttachPartitionEnsureIndexes() we weren't testing the constraint type, which could make a UNIQUE key lacking a not-null constraint incorrectly satisfy a primary key requirement. Fix this by testing that the constraint types match. (Other possible mismatches are verified by comparing index properties.) Discussion: https://postgr.es/m/[email protected]
-rw-r--r--src/backend/commands/tablecmds.c5
-rw-r--r--src/backend/utils/cache/lsyscache.c22
-rw-r--r--src/include/utils/lsyscache.h2
-rw-r--r--src/test/regress/expected/constraints.out16
-rw-r--r--src/test/regress/sql/constraints.sql7
5 files changed, 52 insertions, 0 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 78b0829ffc4..027d68e5d2a 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -19550,6 +19550,11 @@ AttachPartitionEnsureIndexes(List **wqueue, Relation rel, Relation attachrel)
/* no dice */
if (!OidIsValid(cldConstrOid))
continue;
+
+ /* Ensure they're both the same type of constraint */
+ if (get_constraint_type(constraintOid) !=
+ get_constraint_type(cldConstrOid))
+ continue;
}
/* bingo. */
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 26368ffcc97..48a280d089b 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -1133,6 +1133,28 @@ get_constraint_index(Oid conoid)
return InvalidOid;
}
+/*
+ * get_constraint_type
+ * Return the pg_constraint.contype value for the given constraint.
+ *
+ * No frills.
+ */
+char
+get_constraint_type(Oid conoid)
+{
+ HeapTuple tp;
+ char contype;
+
+ tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
+ if (!HeapTupleIsValid(tp))
+ elog(ERROR, "cache lookup failed for constraint %u", conoid);
+
+ contype = ((Form_pg_constraint) GETSTRUCT(tp))->contype;
+ ReleaseSysCache(tp);
+
+ return contype;
+}
+
/* ---------- LANGUAGE CACHE ---------- */
char *
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 35a8dec2b9f..20446f6f836 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -100,6 +100,8 @@ extern char *get_collation_name(Oid colloid);
extern bool get_collation_isdeterministic(Oid colloid);
extern char *get_constraint_name(Oid conoid);
extern Oid get_constraint_index(Oid conoid);
+extern char get_constraint_type(Oid conoid);
+
extern char *get_language_name(Oid langoid, bool missing_ok);
extern Oid get_opclass_family(Oid opclass);
extern Oid get_opclass_input_type(Oid opclass);
diff --git a/src/test/regress/expected/constraints.out b/src/test/regress/expected/constraints.out
index 483681ef2c6..51157181c64 100644
--- a/src/test/regress/expected/constraints.out
+++ b/src/test/regress/expected/constraints.out
@@ -1006,6 +1006,22 @@ Inherits: cnn_grandchild,
ALTER TABLE cnn_parent DROP CONSTRAINT cnn_parent_pkey;
ERROR: constraint "cnn_parent_pkey" of relation "cnn_parent" does not exist
-- keeps these tables around, for pg_upgrade testing
+-- A primary key shouldn't attach to a unique constraint
+create table cnn2_parted (a int primary key) partition by list (a);
+create table cnn2_part1 (a int unique);
+alter table cnn2_parted attach partition cnn2_part1 for values in (1);
+\d+ cnn2_part1
+ Table "public.cnn2_part1"
+ Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
+--------+---------+-----------+----------+---------+---------+--------------+-------------
+ a | integer | | not null | | plain | |
+Partition of: cnn2_parted FOR VALUES IN (1)
+Partition constraint: ((a IS NOT NULL) AND (a = 1))
+Indexes:
+ "cnn2_part1_pkey" PRIMARY KEY, btree (a)
+ "cnn2_part1_a_key" UNIQUE CONSTRAINT, btree (a)
+
+drop table cnn2_parted;
-- ensure columns in partitions are marked not-null
create table cnn2_parted(a int primary key) partition by list (a);
create table cnn2_part1(a int);
diff --git a/src/test/regress/sql/constraints.sql b/src/test/regress/sql/constraints.sql
index 7c95f6c2aa7..2efb63e9d8f 100644
--- a/src/test/regress/sql/constraints.sql
+++ b/src/test/regress/sql/constraints.sql
@@ -657,6 +657,13 @@ ALTER TABLE cnn_parent ADD PRIMARY KEY USING INDEX b_uq;
ALTER TABLE cnn_parent DROP CONSTRAINT cnn_parent_pkey;
-- keeps these tables around, for pg_upgrade testing
+-- A primary key shouldn't attach to a unique constraint
+create table cnn2_parted (a int primary key) partition by list (a);
+create table cnn2_part1 (a int unique);
+alter table cnn2_parted attach partition cnn2_part1 for values in (1);
+\d+ cnn2_part1
+drop table cnn2_parted;
+
-- ensure columns in partitions are marked not-null
create table cnn2_parted(a int primary key) partition by list (a);
create table cnn2_part1(a int);