Обсуждение: ERROR: cache lookup failed for collation 0 on DELETE query after upgrading from 9.X to 12.3

Поиск
Список
Период
Сортировка

Hi

we are upgrading to 12.3 from 9.X and encountered an error with delete statements.


2020-07-14 15:26:20.728 CEST [67736] ERROR:  cache lookup failed for collation 0
2020-07-14 15:26:20.728 CEST [67736] STATEMENT:  delete from my-table where id='004b8d45-d205-4036-9e70-c8340a015674'

ID column is of type UUID. Additionally, we have an implicit cast function from varchar to UUID due to a JPA implementation which is having problems handling of UUID types.


CREATE FUNCTION varchar_to_uuid(VARCHAR) RETURNS uuid AS $$
SELECT uuid_in($1::cstring);
$$ LANGUAGE sql immutable;
CREATE CAST (VARCHAR AS UUID) WITH FUNCTION varchar_to_uuid(VARCHAR) AS IMPLICIT;

I suspected the problem would be connected to this cast but even after dropping the cast and the function I get the same error so it probably has nothing to do with it.
Other than that there is nothing particularly interesting with this table or the setup.
We encountered the same problem on 12.3 debian docker aswell as MacOS brew package which I use locally for development.


Best regards, cen


Additional log line with verbose error logging:


2020-07-14 15:52:46.195 CEST [69575] LOCATION:  get_collation_isdeterministic, lsyscache.c:950

On 14. 07. 20 15:41, cen wrote:

Hi

we are upgrading to 12.3 from 9.X and encountered an error with delete statements.


2020-07-14 15:26:20.728 CEST [67736] ERROR:  cache lookup failed for collation 0
2020-07-14 15:26:20.728 CEST [67736] STATEMENT:  delete from my-table where id='004b8d45-d205-4036-9e70-c8340a015674'

ID column is of type UUID. Additionally, we have an implicit cast function from varchar to UUID due to a JPA implementation which is having problems handling of UUID types.


CREATE FUNCTION varchar_to_uuid(VARCHAR) RETURNS uuid AS $$
SELECT uuid_in($1::cstring);
$$ LANGUAGE sql immutable;
CREATE CAST (VARCHAR AS UUID) WITH FUNCTION varchar_to_uuid(VARCHAR) AS IMPLICIT;

I suspected the problem would be connected to this cast but even after dropping the cast and the function I get the same error so it probably has nothing to do with it.
Other than that there is nothing particularly interesting with this table or the setup.
We encountered the same problem on 12.3 debian docker aswell as MacOS brew package which I use locally for development.


Best regards, cen


cen <cen.is.imba@gmail.com> writes:
> we are upgrading to 12.3 from 9.X and encountered an error with delete 
> statements.
> 2020-07-14 15:26:20.728 CEST [67736] ERROR:  cache lookup failed for 
> collation 0

Please supply a self-contained example.  (Mostly, I'm not interested
in trying to guess at your table schema.)

            regards, tom lane



Found a repro after some trial and error.

The bug appears when you specify a foreign key of type varchar to point 
to primary key of type uuid. This is obviously a developer error for 
specifying the wrong type

but somehow this used to work in 9.X but fails with internal error on 12.3.


CREATE TABLE public.revisions
(
     id uuid NOT NULL,
     revisions_previous_id character varying COLLATE 
pg_catalog."default", --oops, should have used uuid here
     revisions_next_id character varying COLLATE pg_catalog."default", 
--same here..
     customer_notice character varying COLLATE pg_catalog."default",
     CONSTRAINT pk_revisions PRIMARY KEY (id),
     CONSTRAINT fk_revisions_next FOREIGN KEY (revisions_next_id)
         REFERENCES public.revisions (id) MATCH SIMPLE
         ON UPDATE CASCADE
         ON DELETE CASCADE,
     CONSTRAINT fk_revisions_previous FOREIGN KEY (revisions_previous_id)
         REFERENCES public.revisions (id) MATCH SIMPLE
         ON UPDATE CASCADE
         ON DELETE CASCADE
)

TABLESPACE pg_default;

CREATE INDEX idx_fk_revisions_cart_revisions_next_id
     ON public.revisions USING btree
     (revisions_next_id COLLATE pg_catalog."default" ASC NULLS LAST)  
--no collate needed here..
     TABLESPACE pg_default;

CREATE INDEX idx_fk_revisions_cart_revisions_previous_id
     ON public.revisions USING btree
     (revisions_previous_id COLLATE pg_catalog."default" ASC NULLS LAST) 
--and here also..
     TABLESPACE pg_default;


INSERT INTO public.revisions(
     id, revisions_previous_id, revisions_next_id, customer_notice)
     VALUES ('5c617ce7-688d-4bea-9d66-c0f0ebc635da', null, null, 'hi');

delete from revisions where id='5c617ce7-688d-4bea-9d66-c0f0ebc635da' -- 
produces error



I will probably be able to fix our db simply by changing the fk columns 
to uuid and redefine the indexes.

I am leaving it to the postgres team to evaluate this bug further 
whether it works as expected or whether it is a regression and should be 
fixed.


Best regards, cen


On 14. 07. 20 16:11, Tom Lane wrote:
> cen <cen.is.imba@gmail.com> writes:
>> we are upgrading to 12.3 from 9.X and encountered an error with delete
>> statements.
>> 2020-07-14 15:26:20.728 CEST [67736] ERROR:  cache lookup failed for
>> collation 0
> Please supply a self-contained example.  (Mostly, I'm not interested
> in trying to guess at your table schema.)
>
>             regards, tom lane



cen <cen.is.imba@gmail.com> writes:
> The bug appears when you specify a foreign key of type varchar to point 
> to primary key of type uuid.

Ah-hah.  For the record, attached is an actually-self-contained test
case.

The problem comes from this bit in RI_FKey_cascade_del, which evidently
was added as part of the nondeterministic-collations patch (5e1963fb7):

            if (pk_coll != fk_coll && !get_collation_isdeterministic(pk_coll))
                ri_GenerateQualCollation(&querybuf, pk_coll);

which is failing to guard against the possibility that pk_coll is
InvalidOid, i.e. the referenced column is non-collatable.
ri_GenerateQualCollation would correctly do nothing in that case,
but we don't get there because get_collation_isdeterministic has
already fallen over.

While the fix seems relatively straightforward --- probably we just
need to add an OidIsValid(pk_coll) clause here and in the similar tests
elsewhere in ri_triggers.c --- I'm still going to hold Peter's feet
to the fire about this code, because I consider the state of its
documentation to be absolutely unforgivable.  There is NO comment
explaining why it'd be appropriate to do this for a nondeterministic
PK collation (and not otherwise).  Nor has anything been done to fix the
multiple ways in which this addition falsified ri_GenerateQualCollation's
header comment.

            regards, tom lane

-- Need this cast, or the FK constraint definitions will be rejected:
CREATE FUNCTION varchar_to_uuid(VARCHAR) RETURNS uuid AS $$
SELECT uuid_in($1::cstring);
$$ LANGUAGE sql immutable;

CREATE CAST (VARCHAR AS UUID) WITH FUNCTION varchar_to_uuid(VARCHAR) AS IMPLICIT;

CREATE TABLE public.revisions
(
     id uuid NOT NULL,
     revisions_previous_id character varying COLLATE
pg_catalog."default", --oops, should have used uuid here
     revisions_next_id character varying COLLATE pg_catalog."default",
--same here..
     customer_notice character varying COLLATE pg_catalog."default",
     CONSTRAINT pk_revisions PRIMARY KEY (id),
     CONSTRAINT fk_revisions_next FOREIGN KEY (revisions_next_id)
         REFERENCES public.revisions (id) MATCH SIMPLE
         ON UPDATE CASCADE
         ON DELETE CASCADE,
     CONSTRAINT fk_revisions_previous FOREIGN KEY (revisions_previous_id)
         REFERENCES public.revisions (id) MATCH SIMPLE
         ON UPDATE CASCADE
         ON DELETE CASCADE
);

CREATE INDEX idx_fk_revisions_cart_revisions_next_id
     ON public.revisions USING btree
     (revisions_next_id COLLATE pg_catalog."default" ASC NULLS LAST)
;

CREATE INDEX idx_fk_revisions_cart_revisions_previous_id
     ON public.revisions USING btree
     (revisions_previous_id COLLATE pg_catalog."default" ASC NULLS LAST)
;

INSERT INTO public.revisions(
     id, revisions_previous_id, revisions_next_id, customer_notice)
     VALUES ('5c617ce7-688d-4bea-9d66-c0f0ebc635da', null, null, 'hi');

-- fails:
delete from revisions where id='5c617ce7-688d-4bea-9d66-c0f0ebc635da';