From: | Álvaro Herrera <alvherre(at)kurilemu(dot)de> |
---|---|
To: | Ranier Vilela <ranier(dot)vf(at)gmail(dot)com> |
Cc: | Pg Hackers <pgsql-hackers(at)postgresql(dot)org> |
Subject: | Re: Avoid overwiriting cache entry (src/backend/utils/cache/relcache.c) |
Date: | 2025-08-29 10:58:52 |
Message-ID: | 202508291058.q2zscdcs64fj@alvherre.pgsql |
Views: | Whole Thread | Raw Message | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
On 2025-Aug-26, Ranier Vilela wrote:
> In function *CheckNNConstraintFetch* the array index is
> incremented only when "null combin" is not found.
>
> IMO the last cache entry can be overwriting if the next tuple is null,
> because, the fill array fields is not syncronized with array index
> increment.
Hmm, yeah this is wrong. However, If you do hit the case where conbin
is null the behavior is unpleasant but I don't see any crashers, and the
case would amount to catalog corruption. Overall I agree that it seems
better to not modify the entry at all unless we increment the counter,
which your patch achieves.
Not very excited about this though. For instance, I don't think we
reach the point of _using_ the corrupted entry:
=# create table bar (a int check (a > 0), b int constraint tssk check (null));
CREATE TABLE
=# update pg_constraint set conbin = null where conname = 'tssk';
UPDATE 1
=# insert into bar values (-1);
WARNING: null conbin for relation "bar"
LÍNEA 1: insert into bar values (-1);
^
WARNING: 1 pg_constraint record(s) missing for relation "bar"
LÍNEA 1: insert into bar values (-1);
^
ERROR: 1 pg_constraint record(s) missing for relation "bar"
The WARNINGs come from CheckNNConstraintFetch itself, but the error
comes from ExecRelCheck. Did you find a way to make the code behave
worse than this? Can you find any crashers?
Now consider this:
=# alter table bar add check (b > 0);
WARNING: unexpected pg_constraint record found for relation "bar"
ALTER TABLE
For some reason, here we set relchecks to 0, which makes no sense.
Which leads to
=# drop table bar;
WARNING: unexpected pg_constraint record found for relation "bar"
WARNING: unexpected pg_constraint record found for relation "bar"
ERROR: relation "bar" has relchecks = 0
This suggests that we should relax that error and make it a warning,
perhaps like
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 6002fd0002f..9944e4bd2d1 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -937,10 +937,12 @@ RemoveConstraintById(Oid conId)
con->conrelid);
classForm = (Form_pg_class) GETSTRUCT(relTup);
- if (classForm->relchecks == 0) /* should not happen */
- elog(ERROR, "relation \"%s\" has relchecks = 0",
- RelationGetRelationName(rel));
- classForm->relchecks--;
+ if (classForm->relchecks > 0)
+ classForm->relchecks--;
+ else
+ /* should not happen */
+ elog(WARNING, "relation \"%s\" has relchecks = %d",
+ RelationGetRelationName(rel), classForm->relchecks);
CatalogTupleUpdate(pgrel, &relTup->t_self, relTup);
(There's another decrement for coninhcount in line 1155 of the same
file. Maybe that deserves the same treatment, not sure.)
--
Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/
From | Date | Subject | |
---|---|---|---|
Next Message | Ashutosh Bapat | 2025-08-29 11:01:21 | Re: Trivial fix of code comment |
Previous Message | Ashutosh Bapat | 2025-08-29 10:44:14 | Re: Improve pg_sync_replication_slots() to wait for primary to advance |