Re: Commit 4dba331cb3 broke ATTACH PARTITION behaviour. - Mailing list pgsql-hackers
From | Alvaro Herrera |
---|---|
Subject | Re: Commit 4dba331cb3 broke ATTACH PARTITION behaviour. |
Date | |
Msg-id | 20180402191112.wneiyj4v5upnfjst@alvherre.pgsql Whole thread Raw |
In response to | Re: Commit 4dba331cb3 broke ATTACH PARTITION behaviour. (Alvaro Herrera <alvherre@alvh.no-ip.org>) |
Responses |
Re: Commit 4dba331cb3 broke ATTACH PARTITION behaviour.
Re: Commit 4dba331cb3 broke ATTACH PARTITION behaviour. |
List | pgsql-hackers |
Why do we need AccessExclusiveLock on all children of a relation that we want to scan to search for rows not satisfying the constraint? I think it should be enough to get ShareLock, which prevents INSERT, no? I have a feeling I'm missing something here, but I don't know what, and all tests pass with that change. Also: the change proposed to remove the get_default_oid_from_partdesc() call actually fixes the bug, but to me it was not at all obvious why. To figure out why, I first had to realize that ValidatePartitionConstraints was lying to me, both in name and in comments: it doesn't actually validate anything, it merely queues entries so that alter table's phase 3 would do the validation. I found this extremely confusing, so I fixed the comments to match reality, and later decided to rename the function also. At that point I was able to understand what the problem was: when attaching the default partition, we were setting the constraint to be validated for that partition to the correctly computed partition constraint; and later in the same function we would set the constraint to "the immature constraint" because we were now seeing that the default partition OID was not invalid. So it was rather a bug in ValidatePartitionConstraints, in that it was accepting to set the expression to validate when another expression had already been set! I added an assert to protect against this. And then changed the decision of whether or not to run this block based on the attached partition being the default one or not; because as the "if" test was, it was just a recipe for confusion. (Now, if you look carefully you realize that the new test for bound->is_default I added is kinda redundant: it can only be set if there was a default partition OID at start of the function, and therefore we know we're not adding a default partition. And for the case where we *are* adding the default partition, it is still Invalid because we don't re-read its own OID. But relying on that seems brittle because it breaks if we happen to update the default partition OID in the middle of that function, which is what we were doing. Hence the new is_default test.) I looked at the implementation of ValidatePartitionConstraints and didn't like it, so I rewrote it also. This comment is mistaken, too: - /* - * Skip if the partition is itself a partitioned table. We can only - * ever scan RELKIND_RELATION relations. - */ ... because it ignores the possibility of a partition being a foreign table. The code seems to work, but I think there is no test to cover the case that a foreign table containing data that doesn't satisfy the constraint is attached, because when I set that case to return doing nothing (ie. ATGetQueueEntry is not called for a foreign partition), no test failed. Generally speaking, I didn't like ATExecAttachPartition; it's doing too much that should have been done in ATPrepAttachPartition. The only reason that's not broken is because we don't allow ATTACH PARTITION to appear together with other commands in alter table, which seems disappointing ... for example, when attaching multiple tables and a default partition exist, you have to scan the default one multiple times, which is lame. (Speaking of lame: I noticed that RelationGetPartitionQual obtains lock on the parent relation ... I wonder if this can be used to cause a deadlock during InitResultRelationInfo.) BTW, I think this is already broken for the case where the default partition is partitioned and you attach a partition colliding with a row that's being concurrently inserted in a partition of the default partition, though I didn't bother to write a test for that. Anyway, I'm just an onlooker fixing a CommandCounterIncrement change. -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
Attachment
pgsql-hackers by date: