aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/commands/tablecmds.c39
-rw-r--r--src/test/regress/expected/foreign_key.out9
-rw-r--r--src/test/regress/sql/foreign_key.sql10
3 files changed, 28 insertions, 30 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index b6968d23ed5..1402755c36c 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -9844,6 +9844,9 @@ addFkRecurseReferenced(Constraint *fkconstraint, Relation rel,
Oid deleteTriggerOid,
updateTriggerOid;
+ Assert(CheckRelationLockedByMe(pkrel, ShareRowExclusiveLock, true));
+ Assert(CheckRelationLockedByMe(rel, ShareRowExclusiveLock, true));
+
/*
* Create the action triggers that enforce the constraint.
*/
@@ -9870,6 +9873,7 @@ addFkRecurseReferenced(Constraint *fkconstraint, Relation rel,
Oid partIndexId;
ObjectAddress address;
+ /* XXX would it be better to acquire these locks beforehand? */
partRel = table_open(pd->oids[i], ShareRowExclusiveLock);
/*
@@ -9970,7 +9974,9 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
Oid insertTriggerOid,
updateTriggerOid;
- AssertArg(OidIsValid(parentConstr));
+ Assert(OidIsValid(parentConstr));
+ Assert(CheckRelationLockedByMe(rel, ShareRowExclusiveLock, true));
+ Assert(CheckRelationLockedByMe(pkrel, ShareRowExclusiveLock, true));
if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
ereport(ERROR,
@@ -10259,13 +10265,8 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel)
continue;
}
- /*
- * Because we're only expanding the key space at the referenced side,
- * we don't need to prevent any operation in the referencing table, so
- * AccessShareLock suffices (assumes that dropping the constraint
- * acquires AccessExclusiveLock).
- */
- fkRel = table_open(constrForm->conrelid, AccessShareLock);
+ /* We need the same lock level that CreateTrigger will acquire */
+ fkRel = table_open(constrForm->conrelid, ShareRowExclusiveLock);
indexOid = constrForm->conindid;
DeconstructFkConstraintRow(tuple,
@@ -18822,8 +18823,7 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent,
foreach(cell, fks)
{
ForeignKeyCacheInfo *fk = lfirst(cell);
- HeapTuple contup,
- parentConTup;
+ HeapTuple contup;
Form_pg_constraint conform;
Oid insertTriggerOid,
updateTriggerOid;
@@ -18841,13 +18841,6 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent,
continue;
}
- Assert(OidIsValid(conform->conparentid));
- parentConTup = SearchSysCache1(CONSTROID,
- ObjectIdGetDatum(conform->conparentid));
- if (!HeapTupleIsValid(parentConTup))
- elog(ERROR, "cache lookup failed for constraint %u",
- conform->conparentid);
-
/*
* The constraint on this table must be marked no longer a child of
* the parent's constraint, as do its check triggers.
@@ -18888,7 +18881,6 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent,
Oid conffeqop[INDEX_MAX_KEYS];
int numfkdelsetcols;
AttrNumber confdelsetcols[INDEX_MAX_KEYS];
- AttrMap *attmap;
Relation refdRel;
DeconstructFkConstraintRow(contup,
@@ -18921,19 +18913,19 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent,
fkconstraint->old_pktable_oid = InvalidOid;
fkconstraint->location = -1;
- attmap = build_attrmap_by_name(RelationGetDescr(partRel),
- RelationGetDescr(rel));
+ /* set up colnames, used to generate the constraint name */
for (int i = 0; i < numfks; i++)
{
Form_pg_attribute att;
att = TupleDescAttr(RelationGetDescr(partRel),
- attmap->attnums[conkey[i] - 1] - 1);
+ conkey[i] - 1);
+
fkconstraint->fk_attrs = lappend(fkconstraint->fk_attrs,
makeString(NameStr(att->attname)));
}
- refdRel = table_open(fk->confrelid, AccessShareLock);
+ refdRel = table_open(fk->confrelid, ShareRowExclusiveLock);
addFkRecurseReferenced(fkconstraint, partRel,
refdRel,
@@ -18949,11 +18941,10 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent,
confdelsetcols,
true,
InvalidOid, InvalidOid);
- table_close(refdRel, AccessShareLock);
+ table_close(refdRel, NoLock); /* keep lock till end of xact */
}
ReleaseSysCache(contup);
- ReleaseSysCache(parentConTup);
}
list_free_deep(fks);
if (trigrel)
diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out
index 02cf78ee26a..fb9e7603eff 100644
--- a/src/test/regress/expected/foreign_key.out
+++ b/src/test/regress/expected/foreign_key.out
@@ -2944,17 +2944,20 @@ CREATE SCHEMA fkpart12
CREATE TABLE fk_p ( id int, jd int, PRIMARY KEY(id, jd)) PARTITION BY list (id)
CREATE TABLE fk_p_1 PARTITION OF fk_p FOR VALUES IN (1) PARTITION BY list (jd)
CREATE TABLE fk_p_1_1 PARTITION OF fk_p_1 FOR VALUES IN (1)
- CREATE TABLE fk_p_1_2 PARTITION OF fk_p_1 FOR VALUES IN (2)
+ CREATE TABLE fk_p_1_2 (x int, y int, jd int NOT NULL, id int NOT NULL)
CREATE TABLE fk_p_2 PARTITION OF fk_p FOR VALUES IN (2) PARTITION BY list (jd)
CREATE TABLE fk_p_2_1 PARTITION OF fk_p_2 FOR VALUES IN (1)
CREATE TABLE fk_p_2_2 PARTITION OF fk_p_2 FOR VALUES IN (2)
- CREATE TABLE fk_r_1 ( id int PRIMARY KEY, p_id int NOT NULL, p_jd int NOT NULL)
+ CREATE TABLE fk_r_1 ( p_jd int NOT NULL, x int, id int PRIMARY KEY, p_id int NOT NULL)
CREATE TABLE fk_r_2 ( id int PRIMARY KEY, p_id int NOT NULL, p_jd int NOT NULL) PARTITION BY list (id)
CREATE TABLE fk_r_2_1 PARTITION OF fk_r_2 FOR VALUES IN (2, 1)
CREATE TABLE fk_r ( id int PRIMARY KEY, p_id int NOT NULL, p_jd int NOT NULL,
FOREIGN KEY (p_id, p_jd) REFERENCES fk_p (id, jd)
) PARTITION BY list (id);
SET search_path TO fkpart12;
+ALTER TABLE fk_p_1_2 DROP COLUMN x, DROP COLUMN y;
+ALTER TABLE fk_p_1 ATTACH PARTITION fk_p_1_2 FOR VALUES IN (2);
+ALTER TABLE fk_r_1 DROP COLUMN x;
INSERT INTO fk_p VALUES (1, 1);
ALTER TABLE fk_r ATTACH PARTITION fk_r_1 FOR VALUES IN (1);
ALTER TABLE fk_r ATTACH PARTITION fk_r_2 FOR VALUES IN (2);
@@ -2993,7 +2996,7 @@ Foreign-key constraints:
"fk_r_p_id_p_jd_fkey" FOREIGN KEY (p_id, p_jd) REFERENCES fk_p(id, jd)
Number of partitions: 1 (Use \d+ to list them.)
-INSERT INTO fk_r_1 VALUES (2, 1, 2); -- should fail
+INSERT INTO fk_r_1 (id, p_id, p_jd) VALUES (2, 1, 2); -- should fail
ERROR: insert or update on table "fk_r_1" violates foreign key constraint "fk_r_p_id_p_jd_fkey"
DETAIL: Key (p_id, p_jd)=(1, 2) is not present in table "fk_p".
DELETE FROM fk_p; -- should fail
diff --git a/src/test/regress/sql/foreign_key.sql b/src/test/regress/sql/foreign_key.sql
index 9f424f2e143..4128e4e4049 100644
--- a/src/test/regress/sql/foreign_key.sql
+++ b/src/test/regress/sql/foreign_key.sql
@@ -2097,11 +2097,11 @@ CREATE SCHEMA fkpart12
CREATE TABLE fk_p ( id int, jd int, PRIMARY KEY(id, jd)) PARTITION BY list (id)
CREATE TABLE fk_p_1 PARTITION OF fk_p FOR VALUES IN (1) PARTITION BY list (jd)
CREATE TABLE fk_p_1_1 PARTITION OF fk_p_1 FOR VALUES IN (1)
- CREATE TABLE fk_p_1_2 PARTITION OF fk_p_1 FOR VALUES IN (2)
+ CREATE TABLE fk_p_1_2 (x int, y int, jd int NOT NULL, id int NOT NULL)
CREATE TABLE fk_p_2 PARTITION OF fk_p FOR VALUES IN (2) PARTITION BY list (jd)
CREATE TABLE fk_p_2_1 PARTITION OF fk_p_2 FOR VALUES IN (1)
CREATE TABLE fk_p_2_2 PARTITION OF fk_p_2 FOR VALUES IN (2)
- CREATE TABLE fk_r_1 ( id int PRIMARY KEY, p_id int NOT NULL, p_jd int NOT NULL)
+ CREATE TABLE fk_r_1 ( p_jd int NOT NULL, x int, id int PRIMARY KEY, p_id int NOT NULL)
CREATE TABLE fk_r_2 ( id int PRIMARY KEY, p_id int NOT NULL, p_jd int NOT NULL) PARTITION BY list (id)
CREATE TABLE fk_r_2_1 PARTITION OF fk_r_2 FOR VALUES IN (2, 1)
CREATE TABLE fk_r ( id int PRIMARY KEY, p_id int NOT NULL, p_jd int NOT NULL,
@@ -2109,6 +2109,10 @@ CREATE SCHEMA fkpart12
) PARTITION BY list (id);
SET search_path TO fkpart12;
+ALTER TABLE fk_p_1_2 DROP COLUMN x, DROP COLUMN y;
+ALTER TABLE fk_p_1 ATTACH PARTITION fk_p_1_2 FOR VALUES IN (2);
+ALTER TABLE fk_r_1 DROP COLUMN x;
+
INSERT INTO fk_p VALUES (1, 1);
ALTER TABLE fk_r ATTACH PARTITION fk_r_1 FOR VALUES IN (1);
@@ -2124,7 +2128,7 @@ ALTER TABLE fk_r DETACH PARTITION fk_r_2;
\d fk_r_2
-INSERT INTO fk_r_1 VALUES (2, 1, 2); -- should fail
+INSERT INTO fk_r_1 (id, p_id, p_jd) VALUES (2, 1, 2); -- should fail
DELETE FROM fk_p; -- should fail
ALTER TABLE fk_r ATTACH PARTITION fk_r_1 FOR VALUES IN (1);