Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 05b38c7

Browse files
committed
Fix partitioned index attachment
When an existing index in a partition is attached to a new index on its parent, we forgot to set the "relispartition" flag correctly, which meant that it was not possible to find the index in various operations, such as adding a foreign key constraint that references that partitioned table. One of four places that was assigning the parent index was forgetting to do that, so fix by shifting responsibility of updating the flag to the routine that changes the parent. Author: Amit Langote, Álvaro Herrera Reported-by: Hubert "depesz" Lubaczewski Discussion: https://postgr.es/m/CA+HiwqHMsRtRYRWYTWavKJ8x14AFsv7bmAV46mYwnfD3vy8goQ@mail.gmail.com
1 parent c247ae0 commit 05b38c7

File tree

4 files changed

+46
-37
lines changed

4 files changed

+46
-37
lines changed

src/backend/commands/indexcmds.c

+24
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ static void RangeVarCallbackForReindexIndex(const RangeVar *relation,
8989
Oid relId, Oid oldRelId, void *arg);
9090
static bool ReindexRelationConcurrently(Oid relationOid, int options);
9191
static void ReindexPartitionedIndex(Relation parentIdx);
92+
static void update_relispartition(Oid relationId, bool newval);
9293

9394
/*
9495
* CheckIndexCompatible
@@ -3388,6 +3389,9 @@ IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
33883389
if (OidIsValid(parentOid))
33893390
SetRelationHasSubclass(parentOid, true);
33903391

3392+
/* set relispartition correctly on the partition */
3393+
update_relispartition(partRelid, OidIsValid(parentOid));
3394+
33913395
if (fix_dependencies)
33923396
{
33933397
/*
@@ -3424,3 +3428,23 @@ IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
34243428
CommandCounterIncrement();
34253429
}
34263430
}
3431+
3432+
/*
3433+
* Subroutine of IndexSetParentIndex to update the relispartition flag of the
3434+
* given index to the given value.
3435+
*/
3436+
static void
3437+
update_relispartition(Oid relationId, bool newval)
3438+
{
3439+
HeapTuple tup;
3440+
Relation classRel;
3441+
3442+
classRel = table_open(RelationRelationId, RowExclusiveLock);
3443+
tup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
3444+
Assert(((Form_pg_class) GETSTRUCT(tup))->relispartition != newval);
3445+
((Form_pg_class) GETSTRUCT(tup))->relispartition = newval;
3446+
CatalogTupleUpdate(classRel, &tup->t_self, tup);
3447+
heap_freetuple(tup);
3448+
3449+
table_close(classRel, RowExclusiveLock);
3450+
}

src/backend/commands/tablecmds.c

-37
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,6 @@ static ObjectAddress ATExecAttachPartitionIdx(List **wqueue, Relation rel,
525525
static void validatePartitionedIndex(Relation partedIdx, Relation partedTbl);
526526
static void refuseDupeIndexAttach(Relation parentIdx, Relation partIdx,
527527
Relation partitionTbl);
528-
static void update_relispartition(Relation classRel, Oid relationId,
529-
bool newval);
530528
static List *GetParentedForeignKeyRefs(Relation partition);
531529
static void ATDetachCheckNoForeignKeyRefs(Relation partition);
532530

@@ -15714,7 +15712,6 @@ AttachPartitionEnsureIndexes(Relation rel, Relation attachrel)
1571415712
if (OidIsValid(constraintOid))
1571515713
ConstraintSetParentConstraint(cldConstrOid, constraintOid,
1571615714
RelationGetRelid(attachrel));
15717-
update_relispartition(NULL, cldIdxId, true);
1571815715
found = true;
1571915716

1572015717
CommandCounterIncrement();
@@ -15970,7 +15967,6 @@ ATExecDetachPartition(Relation rel, RangeVar *name)
1597015967

1597115968
idx = index_open(idxid, AccessExclusiveLock);
1597215969
IndexSetParentIndex(idx, InvalidOid);
15973-
update_relispartition(classRel, idxid, false);
1597415970

1597515971
/* If there's a constraint associated with the index, detach it too */
1597615972
constrOid = get_relation_idx_constraint_oid(RelationGetRelid(partRel),
@@ -16268,7 +16264,6 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name)
1626816264
if (OidIsValid(constraintOid))
1626916265
ConstraintSetParentConstraint(cldConstrId, constraintOid,
1627016266
RelationGetRelid(partTbl));
16271-
update_relispartition(NULL, partIdxId, true);
1627216267

1627316268
pfree(attmap);
1627416269

@@ -16401,38 +16396,6 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl)
1640116396
}
1640216397
}
1640316398

16404-
/*
16405-
* Update the relispartition flag of the given relation to the given value.
16406-
*
16407-
* classRel is the pg_class relation, already open and suitably locked.
16408-
* It can be passed as NULL, in which case it's opened and closed locally.
16409-
*/
16410-
static void
16411-
update_relispartition(Relation classRel, Oid relationId, bool newval)
16412-
{
16413-
HeapTuple tup;
16414-
HeapTuple newtup;
16415-
Form_pg_class classForm;
16416-
bool opened = false;
16417-
16418-
if (classRel == NULL)
16419-
{
16420-
classRel = table_open(RelationRelationId, RowExclusiveLock);
16421-
opened = true;
16422-
}
16423-
16424-
tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relationId));
16425-
newtup = heap_copytuple(tup);
16426-
classForm = (Form_pg_class) GETSTRUCT(newtup);
16427-
classForm->relispartition = newval;
16428-
CatalogTupleUpdate(classRel, &tup->t_self, newtup);
16429-
heap_freetuple(newtup);
16430-
ReleaseSysCache(tup);
16431-
16432-
if (opened)
16433-
table_close(classRel, RowExclusiveLock);
16434-
}
16435-
1643616399
/*
1643716400
* Return an OID list of constraints that reference the given relation
1643816401
* that are marked as having a parent constraints.

src/test/regress/expected/foreign_key.out

+12
Original file line numberDiff line numberDiff line change
@@ -2367,3 +2367,15 @@ SELECT tableoid::regclass, * FROM fk;
23672367
(2 rows)
23682368

23692369
DROP TABLE fk;
2370+
-- test for reported bug: relispartition not set
2371+
-- https://postgr.es/m/CA+HiwqHMsRtRYRWYTWavKJ8x14AFsv7bmAV46mYwnfD3vy8goQ@mail.gmail.com
2372+
CREATE SCHEMA fkpart7
2373+
CREATE TABLE pkpart (a int) PARTITION BY LIST (a)
2374+
CREATE TABLE pkpart1 PARTITION OF pkpart FOR VALUES IN (1);
2375+
ALTER TABLE fkpart7.pkpart1 ADD PRIMARY KEY (a);
2376+
ALTER TABLE fkpart7.pkpart ADD PRIMARY KEY (a);
2377+
CREATE TABLE fkpart7.fk (a int REFERENCES fkpart7.pkpart);
2378+
DROP SCHEMA fkpart7 CASCADE;
2379+
NOTICE: drop cascades to 2 other objects
2380+
DETAIL: drop cascades to table fkpart7.pkpart
2381+
drop cascades to table fkpart7.fk

src/test/regress/sql/foreign_key.sql

+10
Original file line numberDiff line numberDiff line change
@@ -1657,3 +1657,13 @@ DELETE FROM pk WHERE a = 20;
16571657
UPDATE pk SET a = 90 WHERE a = 30;
16581658
SELECT tableoid::regclass, * FROM fk;
16591659
DROP TABLE fk;
1660+
1661+
-- test for reported bug: relispartition not set
1662+
-- https://postgr.es/m/CA+HiwqHMsRtRYRWYTWavKJ8x14AFsv7bmAV46mYwnfD3vy8goQ@mail.gmail.com
1663+
CREATE SCHEMA fkpart7
1664+
CREATE TABLE pkpart (a int) PARTITION BY LIST (a)
1665+
CREATE TABLE pkpart1 PARTITION OF pkpart FOR VALUES IN (1);
1666+
ALTER TABLE fkpart7.pkpart1 ADD PRIMARY KEY (a);
1667+
ALTER TABLE fkpart7.pkpart ADD PRIMARY KEY (a);
1668+
CREATE TABLE fkpart7.fk (a int REFERENCES fkpart7.pkpart);
1669+
DROP SCHEMA fkpart7 CASCADE;

0 commit comments

Comments
 (0)