Thread: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
Hi,
On the latest master head, I can see a $subject bug that seems to be related
commit #b0e96f311985:
Here is the table definition:
commit #b0e96f311985:
Here is the table definition:
create table foo(i int, j int, CONSTRAINT pk PRIMARY KEY(i) DEFERRABLE);
And after restore from the dump, it shows a descriptor where column 'i' not
marked NOT NULL:
marked NOT NULL:
=# \d foo
Table "public.foo"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
i | integer | | |
j | integer | | |
Indexes:
"pk" PRIMARY KEY, btree (i) DEFERRABLE
Table "public.foo"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
i | integer | | |
j | integer | | |
Indexes:
"pk" PRIMARY KEY, btree (i) DEFERRABLE
The pg_attribute entry:
=# select attname, attnotnull from pg_attribute
where attrelid = 'foo'::regclass and attnum > 0;
attname | attnotnull
---------+------------
i | f
j | f
(2 rows)
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Alvaro Herrera
Date:
On 2023-Sep-20, Amul Sul wrote: > On the latest master head, I can see a $subject bug that seems to be related > commit #b0e96f311985: > > Here is the table definition: > create table foo(i int, j int, CONSTRAINT pk PRIMARY KEY(i) DEFERRABLE); Interesting, thanks for the report. Your attribution to that commit is correct. The table is dumped like this: CREATE TABLE public.foo ( i integer CONSTRAINT pgdump_throwaway_notnull_0 NOT NULL NO INHERIT, j integer ); ALTER TABLE ONLY public.foo ADD CONSTRAINT pk PRIMARY KEY (i) DEFERRABLE; ALTER TABLE ONLY public.foo DROP CONSTRAINT pgdump_throwaway_notnull_0; so the problem here is that the deferrable PK is not considered a reason to keep attnotnull set, so we produce a throwaway constraint that we then drop. This is already bogus, but what is more bogus is the fact that the backend accepts the DROP CONSTRAINT at all. The pg_dump failing should be easy to fix, but fixing the backend to error out sounds more critical. So, the reason for this behavior is that RelationGetIndexList doesn't want to list an index that isn't marked indimmediate as a primary key. I can easily hack around that by doing diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 7234cb3da6..971d9c8738 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4794,7 +4794,6 @@ RelationGetIndexList(Relation relation) * check them. */ if (!index->indisunique || - !index->indimmediate || !heap_attisnull(htup, Anum_pg_index_indpred, NULL)) continue; @@ -4821,6 +4820,9 @@ RelationGetIndexList(Relation relation) relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)) pkeyIndex = index->indexrelid; + if (!index->indimmediate) + continue; + if (!index->indisvalid) continue; But of course this is not great, since it impacts unrelated bits of code that are relying on relation->pkindex or RelationGetIndexAttrBitmap having their current behavior with non-immediate index. I think a real solution is to stop relying on RelationGetIndexAttrBitmap in ATExecDropNotNull(). (And, again, pg_dump needs some patch as well to avoid printing a throwaway NOT NULL constraint at this point.) -- Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/
On Wed, Sep 20, 2023 at 8:29 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2023-Sep-20, Amul Sul wrote:
> On the latest master head, I can see a $subject bug that seems to be related
> commit #b0e96f311985:
>
> Here is the table definition:
> create table foo(i int, j int, CONSTRAINT pk PRIMARY KEY(i) DEFERRABLE);
Interesting, thanks for the report. Your attribution to that commit is
correct. The table is dumped like this:
CREATE TABLE public.foo (
i integer CONSTRAINT pgdump_throwaway_notnull_0 NOT NULL NO INHERIT,
j integer
);
ALTER TABLE ONLY public.foo
ADD CONSTRAINT pk PRIMARY KEY (i) DEFERRABLE;
ALTER TABLE ONLY public.foo DROP CONSTRAINT pgdump_throwaway_notnull_0;
so the problem here is that the deferrable PK is not considered a reason
to keep attnotnull set, so we produce a throwaway constraint that we
then drop. This is already bogus, but what is more bogus is the fact
that the backend accepts the DROP CONSTRAINT at all.
The pg_dump failing should be easy to fix, but fixing the backend to
error out sounds more critical. So, the reason for this behavior is
that RelationGetIndexList doesn't want to list an index that isn't
marked indimmediate as a primary key. I can easily hack around that by
doing
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 7234cb3da6..971d9c8738 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -4794,7 +4794,6 @@ RelationGetIndexList(Relation relation)
* check them.
*/
if (!index->indisunique ||
- !index->indimmediate ||
!heap_attisnull(htup, Anum_pg_index_indpred, NULL))
continue;
@@ -4821,6 +4820,9 @@ RelationGetIndexList(Relation relation)
relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
pkeyIndex = index->indexrelid;
+ if (!index->indimmediate)
+ continue;
+
if (!index->indisvalid)
continue;
But of course this is not great, since it impacts unrelated bits of code
that are relying on relation->pkindex or RelationGetIndexAttrBitmap
having their current behavior with non-immediate index.
True, but still wondering why would relation->rd_pkattr skipped for a
deferrable primary key, which seems to be a bit incorrect to me since it
sensing that relation doesn't have PK at all. Anyway, that is unrelated.
deferrable primary key, which seems to be a bit incorrect to me since it
sensing that relation doesn't have PK at all. Anyway, that is unrelated.
I think a real solution is to stop relying on RelationGetIndexAttrBitmap
in ATExecDropNotNull(). (And, again, pg_dump needs some patch as well
to avoid printing a throwaway NOT NULL constraint at this point.)
I might not have understood this, but I think, if it is ok to skip throwaway NOT
NULL for deferrable PK then that would be enough for the reported issue
to be fixed. I quickly tried with the attached patch which looks sufficient
to skip that, but, TBH, I haven't thought carefully about this change.
NULL for deferrable PK then that would be enough for the reported issue
to be fixed. I quickly tried with the attached patch which looks sufficient
to skip that, but, TBH, I haven't thought carefully about this change.
Regards,
Amul
Attachment
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
vignesh C
Date:
On Fri, 22 Sept 2023 at 18:45, Amul Sul <sulamul@gmail.com> wrote: > > > > On Wed, Sep 20, 2023 at 8:29 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote: >> >> On 2023-Sep-20, Amul Sul wrote: >> >> > On the latest master head, I can see a $subject bug that seems to be related >> > commit #b0e96f311985: >> > >> > Here is the table definition: >> > create table foo(i int, j int, CONSTRAINT pk PRIMARY KEY(i) DEFERRABLE); >> >> Interesting, thanks for the report. Your attribution to that commit is >> correct. The table is dumped like this: >> >> CREATE TABLE public.foo ( >> i integer CONSTRAINT pgdump_throwaway_notnull_0 NOT NULL NO INHERIT, >> j integer >> ); >> ALTER TABLE ONLY public.foo >> ADD CONSTRAINT pk PRIMARY KEY (i) DEFERRABLE; >> ALTER TABLE ONLY public.foo DROP CONSTRAINT pgdump_throwaway_notnull_0; >> >> so the problem here is that the deferrable PK is not considered a reason >> to keep attnotnull set, so we produce a throwaway constraint that we >> then drop. This is already bogus, but what is more bogus is the fact >> that the backend accepts the DROP CONSTRAINT at all. >> >> The pg_dump failing should be easy to fix, but fixing the backend to >> error out sounds more critical. So, the reason for this behavior is >> that RelationGetIndexList doesn't want to list an index that isn't >> marked indimmediate as a primary key. I can easily hack around that by >> doing >> >> diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c >> index 7234cb3da6..971d9c8738 100644 >> --- a/src/backend/utils/cache/relcache.c >> +++ b/src/backend/utils/cache/relcache.c >> @@ -4794,7 +4794,6 @@ RelationGetIndexList(Relation relation) >> * check them. >> */ >> if (!index->indisunique || >> - !index->indimmediate || >> !heap_attisnull(htup, Anum_pg_index_indpred, NULL)) >> continue; >> >> @@ -4821,6 +4820,9 @@ RelationGetIndexList(Relation relation) >> relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)) >> pkeyIndex = index->indexrelid; >> >> + if (!index->indimmediate) >> + continue; >> + >> if (!index->indisvalid) >> continue; >> >> >> But of course this is not great, since it impacts unrelated bits of code >> that are relying on relation->pkindex or RelationGetIndexAttrBitmap >> having their current behavior with non-immediate index. > > > True, but still wondering why would relation->rd_pkattr skipped for a > deferrable primary key, which seems to be a bit incorrect to me since it > sensing that relation doesn't have PK at all. Anyway, that is unrelated. > >> >> I think a real solution is to stop relying on RelationGetIndexAttrBitmap >> in ATExecDropNotNull(). (And, again, pg_dump needs some patch as well >> to avoid printing a throwaway NOT NULL constraint at this point.) > > > I might not have understood this, but I think, if it is ok to skip throwaway NOT > NULL for deferrable PK then that would be enough for the reported issue > to be fixed. I quickly tried with the attached patch which looks sufficient > to skip that, but, TBH, I haven't thought carefully about this change. I did not see any test addition for this, can we add it? Regards, Vignesh
On Sat, Jan 20, 2024 at 7:55 AM vignesh C <vignesh21@gmail.com> wrote:
On Fri, 22 Sept 2023 at 18:45, Amul Sul <sulamul@gmail.com> wrote:
>
>
>
> On Wed, Sep 20, 2023 at 8:29 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
>>
>> On 2023-Sep-20, Amul Sul wrote:
>>
>> > On the latest master head, I can see a $subject bug that seems to be related
>> > commit #b0e96f311985:
>> >
>> > Here is the table definition:
>> > create table foo(i int, j int, CONSTRAINT pk PRIMARY KEY(i) DEFERRABLE);
>>
>> Interesting, thanks for the report. Your attribution to that commit is
>> correct. The table is dumped like this:
>>
>> CREATE TABLE public.foo (
>> i integer CONSTRAINT pgdump_throwaway_notnull_0 NOT NULL NO INHERIT,
>> j integer
>> );
>> ALTER TABLE ONLY public.foo
>> ADD CONSTRAINT pk PRIMARY KEY (i) DEFERRABLE;
>> ALTER TABLE ONLY public.foo DROP CONSTRAINT pgdump_throwaway_notnull_0;
>>
>> so the problem here is that the deferrable PK is not considered a reason
>> to keep attnotnull set, so we produce a throwaway constraint that we
>> then drop. This is already bogus, but what is more bogus is the fact
>> that the backend accepts the DROP CONSTRAINT at all.
>>
>> The pg_dump failing should be easy to fix, but fixing the backend to
>> error out sounds more critical. So, the reason for this behavior is
>> that RelationGetIndexList doesn't want to list an index that isn't
>> marked indimmediate as a primary key. I can easily hack around that by
>> doing
>>
>> diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
>> index 7234cb3da6..971d9c8738 100644
>> --- a/src/backend/utils/cache/relcache.c
>> +++ b/src/backend/utils/cache/relcache.c
>> @@ -4794,7 +4794,6 @@ RelationGetIndexList(Relation relation)
>> * check them.
>> */
>> if (!index->indisunique ||
>> - !index->indimmediate ||
>> !heap_attisnull(htup, Anum_pg_index_indpred, NULL))
>> continue;
>>
>> @@ -4821,6 +4820,9 @@ RelationGetIndexList(Relation relation)
>> relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
>> pkeyIndex = index->indexrelid;
>>
>> + if (!index->indimmediate)
>> + continue;
>> +
>> if (!index->indisvalid)
>> continue;
>>
>>
>> But of course this is not great, since it impacts unrelated bits of code
>> that are relying on relation->pkindex or RelationGetIndexAttrBitmap
>> having their current behavior with non-immediate index.
>
>
> True, but still wondering why would relation->rd_pkattr skipped for a
> deferrable primary key, which seems to be a bit incorrect to me since it
> sensing that relation doesn't have PK at all. Anyway, that is unrelated.
>
>>
>> I think a real solution is to stop relying on RelationGetIndexAttrBitmap
>> in ATExecDropNotNull(). (And, again, pg_dump needs some patch as well
>> to avoid printing a throwaway NOT NULL constraint at this point.)
>
>
> I might not have understood this, but I think, if it is ok to skip throwaway NOT
> NULL for deferrable PK then that would be enough for the reported issue
> to be fixed. I quickly tried with the attached patch which looks sufficient
> to skip that, but, TBH, I haven't thought carefully about this change.
I did not see any test addition for this, can we add it?
Ok, added it in the attached version.
This was an experimental patch, I was looking for the comment on the proposed
approach -- whether we could simply skip the throwaway NOT NULL constraint for
deferred PK constraint. Moreover, skip that for any PK constraint.
This was an experimental patch, I was looking for the comment on the proposed
approach -- whether we could simply skip the throwaway NOT NULL constraint for
deferred PK constraint. Moreover, skip that for any PK constraint.
Regards,
Amul
Attachment
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Aleksander Alekseev
Date:
Hi hackers, >> I did not see any test addition for this, can we add it? > > > Ok, added it in the attached version. > > This was an experimental patch, I was looking for the comment on the proposed > approach -- whether we could simply skip the throwaway NOT NULL constraint for > deferred PK constraint. Moreover, skip that for any PK constraint. I confirm that the patch fixes the bug. All the tests pass. Looks like RfC to me. -- Best regards, Aleksander Alekseev
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Dean Rasheed
Date:
On Mon, 4 Mar 2024 at 12:34, Aleksander Alekseev <aleksander@timescale.com> wrote: > > > This was an experimental patch, I was looking for the comment on the proposed > > approach -- whether we could simply skip the throwaway NOT NULL constraint for > > deferred PK constraint. Moreover, skip that for any PK constraint. > > I confirm that the patch fixes the bug. All the tests pass. Looks like > RfC to me. > I don't think that this is the right fix. ISTM that the real issue is that dropping a NOT NULL constraint should not mark the column as nullable if it is part of a PK, whether or not that PK is deferrable -- a deferrable PK still marks a column as not nullable. The reason pg_dump creates these throwaway NOT NULL constraints is to avoid a table scan to check for NULLs when the PK is later created. That rationale still applies to deferrable PKs, so we still want the throwaway NOT NULL constraints in that case, otherwise we'd be hurting performance of restore. Regards, Dean
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Alvaro Herrera
Date:
On 2024-Mar-04, Dean Rasheed wrote: > I don't think that this is the right fix. ISTM that the real issue is > that dropping a NOT NULL constraint should not mark the column as > nullable if it is part of a PK, whether or not that PK is deferrable > -- a deferrable PK still marks a column as not nullable. Yeah. As I said upthread, a good fix seems to require no longer relying on RelationGetIndexAttrBitmap to obtain the columns in the primary key, because that function does not include deferred primary keys. I came up with the attached POC, which seems to fix the reported problem, but of course it needs more polish, a working test case, and verifying whether the new function should be used in more places -- in particular, whether it can be used to revert the changes to RelationGetIndexList that b0e96f311985 did. -- Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/ "La persona que no quería pecar / estaba obligada a sentarse en duras y empinadas sillas / desprovistas, por cierto de blandos atenuantes" (Patricio Vogel)
Attachment
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Dean Rasheed
Date:
On Tue, 5 Mar 2024 at 12:36, Alvaro Herrera <alvherre@alvh.no-ip.org> wrote: > > Yeah. As I said upthread, a good fix seems to require no longer relying > on RelationGetIndexAttrBitmap to obtain the columns in the primary key, > because that function does not include deferred primary keys. I came up > with the attached POC, which seems to fix the reported problem, but of > course it needs more polish, a working test case, and verifying whether > the new function should be used in more places -- in particular, whether > it can be used to revert the changes to RelationGetIndexList that > b0e96f311985 did. > Looking at the other places that call RelationGetIndexAttrBitmap() with INDEX_ATTR_BITMAP_PRIMARY_KEY, they all appear to want to include deferrable PKs, since they are relying on the result to see which columns are not nullable. So there are other bugs here. For example: CREATE TABLE foo (id int PRIMARY KEY DEFERRABLE, val text); CREATE TABLE bar (LIKE foo); now fails to mark bar.id as not nullable, whereas prior to b0e96f311985 it would have been. So I think RelationGetIndexAttrBitmap() should include deferrable PKs, but not all the changes made to RelationGetIndexList() by b0e96f311985 need reverting. Regards, Dean
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Alvaro Herrera
Date:
On 2024-Mar-05, Dean Rasheed wrote: > Looking at the other places that call RelationGetIndexAttrBitmap() > with INDEX_ATTR_BITMAP_PRIMARY_KEY, they all appear to want to include > deferrable PKs, since they are relying on the result to see which > columns are not nullable. Hmm, I find this pretty surprising, but you are right. Somehow I had the idea that INDEX_ATTR_BITMAP_PRIMARY_KEY was used for planning activities so I didn't want to modify its behavior ... but clearly that's not at all the case. It's only used for DDL, and one check in logical replication. > So there are other bugs here. For example: > > CREATE TABLE foo (id int PRIMARY KEY DEFERRABLE, val text); > CREATE TABLE bar (LIKE foo); > > now fails to mark bar.id as not nullable, whereas prior to > b0e96f311985 it would have been. Fun. (Thankfully, easy to fix. But I'll add this as a test too.) > So I think RelationGetIndexAttrBitmap() should include deferrable PKs, Yeah, I'll go make it so. I think I'll add a test for the case that changes behavior in logical replication first (which is that the target relation of logical replication is currently not marked as updatable, when its PK is deferrable). > but not all the changes made to RelationGetIndexList() by b0e96f311985 > need reverting. I'll give this a look too. -- Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/ "Once again, thank you and all of the developers for your hard work on PostgreSQL. This is by far the most pleasant management experience of any database I've worked on." (Dan Harris) http://archives.postgresql.org/pgsql-performance/2006-04/msg00247.php
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Alvaro Herrera
Date:
On 2024-Mar-05, Dean Rasheed wrote: > So I think RelationGetIndexAttrBitmap() should include deferrable PKs, I tried this, but it doesn't actually lead to a good place, because if we allow deferrable PKs to identify rows, then they are not useful to find the tuple to update when replicating. Consider the following case: $node_publisher->safe_psql('postgres', 'create table deferred_pk (id int primary key initially deferred, hidden int, value text)'); $node_subscriber->safe_psql('postgres', 'create table deferred_pk (id int primary key initially deferred, hidden int, value text)'); $node_subscriber->safe_psql('postgres', 'alter subscription tap_sub refresh publication'); $node_publisher->safe_psql('postgres', "insert into deferred_pk (id, hidden, value) values (1, 1, 'first')"); $node_publisher->wait_for_catchup('tap_sub'); $node_publisher->safe_psql('postgres', qq{ begin; insert into deferred_pk values (1, 2, 'conflicting'); update deferred_pk set value = value || ', updated' where id = 1 and hidden = 2; update deferred_pk set id = 3, value = value || ', updated' where hidden = 2; commit}); $node_publisher->wait_for_catchup('tap_sub'); my $pubdata = $node_publisher->safe_psql('postgres', 'select * from deferred_pk order by id'); my $subsdata = $node_subscriber->safe_psql('postgres', 'select * from deferred_pk order by id'); is($subsdata, $pubdata, "data is equal"); Here, the publisher's transaction first creates a new record with the same PK, which only works because the PK is deferred; then we update its payload column. When this is replicated, the row is identified by the PK ... but replication actually updates the other row, because it's found first: # Failed test 'data is equal' # at t/003_constraints.pl line 163. # got: '1|2|conflicting # 3|2|conflicting, updated, updated' # expected: '1|1|first # 3|2|conflicting, updated, updated' Actually, is that what happened here? I'm not sure, but clearly this is bogus. So I think the original developers of REPLICA IDENTITY had the right idea here (commit 07cacba983ef), and we mustn't change this aspect, because it'll lead to data corruption in replication. Using a deferred PK for DDL considerations seems OK, but it seems certain that for actual data replication it's going to be a disaster. -- Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Dean Rasheed
Date:
On Thu, 7 Mar 2024 at 13:00, Alvaro Herrera <alvherre@alvh.no-ip.org> wrote: > > So I think the original developers of REPLICA IDENTITY had the right > idea here (commit 07cacba983ef), and we mustn't change this aspect, > because it'll lead to data corruption in replication. Using a deferred > PK for DDL considerations seems OK, but it seems certain that for actual > data replication it's going to be a disaster. > Yes, that makes sense. If I understand correctly though, the replication code uses relation->rd_replidindex (not relation->rd_pkindex), although sometimes it's the same thing. So can we get away with making sure that RelationGetIndexList() doesn't set relation->rd_replidindex to a deferrable PK, while still allowing relation->rd_pkindex to be one? Regards, Dean
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Alvaro Herrera
Date:
On 2024-Mar-07, Dean Rasheed wrote: > On Thu, 7 Mar 2024 at 13:00, Alvaro Herrera <alvherre@alvh.no-ip.org> wrote: > > > > So I think the original developers of REPLICA IDENTITY had the right > > idea here (commit 07cacba983ef), and we mustn't change this aspect, > > because it'll lead to data corruption in replication. Using a deferred > > PK for DDL considerations seems OK, but it seems certain that for actual > > data replication it's going to be a disaster. > > Yes, that makes sense. If I understand correctly though, the > replication code uses relation->rd_replidindex (not > relation->rd_pkindex), although sometimes it's the same thing. So can > we get away with making sure that RelationGetIndexList() doesn't set > relation->rd_replidindex to a deferrable PK, while still allowing > relation->rd_pkindex to be one? Well, not really, because the logical replication code for some reason uses GetRelationIdentityOrPK(), which falls back to rd->pk_index (via RelationGetPrimaryKeyIndex) if rd_replindex is not set. Maybe we can add a flag RelationData->rd_ispkdeferred, so that RelationGetPrimaryKeyIndex returned InvalidOid for deferrable PKs; then logical replication would continue to not know about this PK, which perhaps is what we want. I'll do some testing with this. -- Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Alvaro Herrera
Date:
On 2024-Mar-07, Alvaro Herrera wrote: > Maybe we can add a flag RelationData->rd_ispkdeferred, so that > RelationGetPrimaryKeyIndex returned InvalidOid for deferrable PKs; then > logical replication would continue to not know about this PK, which > perhaps is what we want. I'll do some testing with this. This seems to work okay. -- Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/ “Cuando no hay humildad las personas se degradan” (A. Christie)
Attachment
On Thu, Mar 7, 2024 at 11:02 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote:
On 2024-Mar-07, Alvaro Herrera wrote:
> Maybe we can add a flag RelationData->rd_ispkdeferred, so that
> RelationGetPrimaryKeyIndex returned InvalidOid for deferrable PKs; then
> logical replication would continue to not know about this PK, which
> perhaps is what we want. I'll do some testing with this.
This seems to work okay.
Thank you for working on this, the patch works nicely.
Regards,
Amul
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Dean Rasheed
Date:
On Thu, 7 Mar 2024 at 17:32, Alvaro Herrera <alvherre@alvh.no-ip.org> wrote: > > This seems to work okay. > Yes, this looks good. I tested it against CREATE TABLE ... LIKE, and it worked as expected. It might be worth adding a test case for that, to ensure that it doesn't get broken in the future. Do we also want a test case that does what pg_dump would do: - Add a NOT NULL constraint - Add a deferrable PK constraint - Drop the NOT NULL constraint - Check the column is still not nullable Looking at rel.h, I think that the new field should probably come after rd_pkindex, under the comment "data managed by RelationGetIndexList", and have its own comment. Also, if I'm nitpicking, the new field and local variables should use the term "deferrable" rather than "deferred". A DEFERRABLE constraint can be set to be either DEFERRED or IMMEDIATE within a transaction, but "deferrable" is the right term to use to describe the persistent property of an index/constraint that can be deferred. (The same objection applies to the field name "indimmediate", but it's too late to change that.) Also, for neatness/consistency, the new field should probably be reset in load_relcache_init_file(), alongside rd_pkindex, though I don't think it can matter in practice. Regards, Dean
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Robert Haas
Date:
On Thu, Mar 7, 2024 at 12:32 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote: > On 2024-Mar-07, Alvaro Herrera wrote: > > Maybe we can add a flag RelationData->rd_ispkdeferred, so that > > RelationGetPrimaryKeyIndex returned InvalidOid for deferrable PKs; then > > logical replication would continue to not know about this PK, which > > perhaps is what we want. I'll do some testing with this. > > This seems to work okay. There is a CommitFest entry for this patch. Should that entry be closed in view of the not-NULL revert (6f8bb7c1e9610dd7af20cdaf74c4ff6e6d678d44)? -- Robert Haas EDB: http://www.enterprisedb.com
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Alvaro Herrera
Date:
On 2024-May-14, Robert Haas wrote: > On Thu, Mar 7, 2024 at 12:32 PM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote: > > On 2024-Mar-07, Alvaro Herrera wrote: > > > Maybe we can add a flag RelationData->rd_ispkdeferred, so that > > > RelationGetPrimaryKeyIndex returned InvalidOid for deferrable PKs; then > > > logical replication would continue to not know about this PK, which > > > perhaps is what we want. I'll do some testing with this. > > > > This seems to work okay. > > There is a CommitFest entry for this patch. Should that entry be > closed in view of the not-NULL revert > (6f8bb7c1e9610dd7af20cdaf74c4ff6e6d678d44)? Uhmm, I didn't realize there was a CF entry. I don't know why it was there; this should have been an open item, not a bugfix CF entry. This had already been committed as 270af6f0df76 (the day before it was sent to the next commitfest). This commit wasn't included in the reverted set, though, so you still get deferrable PKs from RelationGetIndexList. I don't think this is necessarily a bad thing, though these don't have any usefulness as things stand (and if we deal with PKs by forcing not-null constraints to be underneath, then we won't need them either). -- Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/ "Postgres is bloatware by design: it was built to house PhD theses." (Joey Hellerstein, SIGMOD annual conference 2002)
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Robert Haas
Date:
On Tue, May 14, 2024 at 10:42 AM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote: > This had already been committed as 270af6f0df76 (the day before it was > sent to the next commitfest). This commit wasn't included in the > reverted set, though, so you still get deferrable PKs from > RelationGetIndexList. I don't think this is necessarily a bad thing, > though these don't have any usefulness as things stand (and if we deal > with PKs by forcing not-null constraints to be underneath, then we won't > need them either). So, are you saying this should be marked Committed in the commitfest? -- Robert Haas EDB: http://www.enterprisedb.com
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Alvaro Herrera
Date:
On 2024-May-14, Robert Haas wrote: > On Tue, May 14, 2024 at 10:42 AM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote: > > This had already been committed as 270af6f0df76 (the day before it was > > sent to the next commitfest). This commit wasn't included in the > > reverted set, though, so you still get deferrable PKs from > > RelationGetIndexList. I don't think this is necessarily a bad thing, > > though these don't have any usefulness as things stand (and if we deal > > with PKs by forcing not-null constraints to be underneath, then we won't > > need them either). > > So, are you saying this should be marked Committed in the commitfest? Yeah. I've done so. -- Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/ "Pero la cosa no es muy grave ..." (le petit Nicolas -- René Goscinny)
Re: Dump-restore loosing 'attnotnull' bit for DEFERRABLE PRIMARY KEY column(s).
From
Robert Haas
Date:
On Tue, May 14, 2024 at 11:11 AM Alvaro Herrera <alvherre@alvh.no-ip.org> wrote: > > So, are you saying this should be marked Committed in the commitfest? > > Yeah. I've done so. Great, thanks. -- Robert Haas EDB: http://www.enterprisedb.com