From: | Alvaro Herrera <alvherre(at)2ndquadrant(dot)com> |
---|---|
To: | Jehan-Guillaume de Rorthais <jgdr(at)dalibo(dot)com> |
Cc: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
Subject: | Re: FK violation in partitioned table after truncating a referenced partition |
Date: | 2020-02-06 23:01:29 |
Message-ID: | 20200206230129.GA9760@alvherre.pgsql |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-bugs |
On 2020-Feb-06, Alvaro Herrera wrote:
> On 2020-Feb-06, Alvaro Herrera wrote:
>
> > I agree that patching heap_truncate_find_FKs is a reasonable way to fix.
> > I propose a slightly different formulation: instead of the loop that you
> > have, we can just use the second loop, and add more parent constraints
> > to the list if any constraint we scan in turn has a parent constraint.
> > So we don't repeat the whole thing, but only that second loop.
>
> Hmm, this doesn't actually work; I modified your test case and I see
> that my code fails to do the right thing.
Yeah, AFAICS both algorithms posted so far (yours and mine) are wrong.
Maybe there's another way to fix it, but I think we're going to need the
find_all_inheritors call you didn't want; here's a rough sketch of what
I'm thinking:
while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
{
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
/* Not referencing one of our list of tables */
if (!list_member_oid(oids, con->confrelid))
continue;
/*
* If the constraint has a parent, climb up the partition hierarchy
* all the way to the top. We need to process all the partitions
* covered by the topmost constraint.
*/
while (OidIsValid(con->conparentid))
{
scan2 = systable_beginscan(fkeyRel, ConstraintParentIndexId,
true, NULL, 1, &key);
tup2 = heap_copytuple(systable_getnext(scan2)); /* XXX leaks memory */
con = (Form_pg_constraint) GETSTRUCT(tup2);
systable_endscan(scan2);
}
/* Add referencer to result, unless present in input list */
if (!list_member_oid(relationIds, con->conrelid))
result = lappend_oid(result, con->conrelid);
if (conrelid is partitioned)
{
add each partition to result list;
}
}
ENOTIME to complete it now, though ... also: I'm not sure about having
heap_truncate_find_FKs() acquire the locks on partitions; but what
happens if there's a concurrent detach?
This is a larger can of worms than I imagined. Maybe a simpler solution
is to say that you cannot truncate a partition; if you want that,
truncate the topmost relation. No functionality seems lost with that
restriction, or is it? And the semantics seem better defined anyway.
(AFAICS this is implemented easily: if we see a non-invalid conparentid,
raise an error).
--
Álvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From | Date | Subject | |
---|---|---|---|
Next Message | Pavel Stehule | 2020-02-07 06:40:06 | Re: BUG #16246: Need compatible odbc driver to establish connectivity with SAP BOBJ 4.2 |
Previous Message | Alvaro Herrera | 2020-02-06 22:30:15 | Re: FK violation in partitioned table after truncating a referenced partition |