Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vvc5n-00AHB2-1r for pgsql-bugs@arkaria.postgresql.org; Thu, 26 Feb 2026 14:11:51 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vvc5j-00CzLW-2n for pgsql-bugs@arkaria.postgresql.org; Thu, 26 Feb 2026 14:11:47 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vvYSR-00BjkK-0n for pgsql-bugs@lists.postgresql.org; Thu, 26 Feb 2026 10:18:59 +0000 Received: from mail-lf1-f45.google.com ([209.85.167.45]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vvYSO-00000001HEs-1D4O for pgsql-bugs@lists.postgresql.org; Thu, 26 Feb 2026 10:18:58 +0000 Received: by mail-lf1-f45.google.com with SMTP id 2adb3069b0e04-59e5ea93a1aso643883e87.1 for ; Thu, 26 Feb 2026 02:18:57 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772101136; x=1772705936; h=to:subject:message-id:date:from:mime-version:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=o/XaSzSLitNufy36NkS3n1guC0lclOMloUEVoxTfIW0=; b=EJIw3eyyRODucJ9ZbrrgAaN5WOxqYeYR6zgWsZAL6JXZrkwWA1d9uQgJcK+tP99Wq8 vRewuwOKbuYQGLTFklB2MczwRQBsfpFZRRj4B5MJCOVk8O0baW0JSfgIS0wEtniZYx4i C1IDuIR+7nUnOAIQ3P4vVMhXAQ1nmDv6GKign90e8gY9EP7MYX3x7j4UC86v3YXV4Wjv sn1gPMstUUMf7a15vTQRXpqhp+xfl5CX9siwzNW6hPoykCTe6ECjmYULKW7EPVUWuupW H8yfn5S6s2wdH9b2d9JbUlM/K8dZehGV/SZBg8yn102BTq2HgDh3+NNn5g8gmYUMJShH Vd0Q== X-Gm-Message-State: AOJu0Yy/5eby0lCVBld/z5pEkuWHssoHwavSVX3mYu9ShAagcg/pJ7Qu tQ0GTyBuV7A66Mv0LidM6E6k5N+jns2e28JpSZ7QfxwRQsWsaU6JgnlKst+ZP9ljLEI= X-Gm-Gg: ATEYQzyDZLSThOIyHeKXk0WwTE05BmOqiwNh/R5glbXj1zm8nqFsDKcExuxh7Vj+63u ccID12i5wvcxGMj5z+4TSrqKw6CE35Axbons6wzyGbe70Dbbr6ZPedTIdWxJKEUOJzJYkb6lTqR xS1qgpWFVUkhBScrSsgW1AMFMpkO9a2nRibYy6iOBZf2UeIcD58yQ5PLc1FctLy/pFY2r5c0uje JlDuB42nUgwqrz6xIxmkJ7v1TAorB4l1NlkIhwX2dnOk/FF2oXsr7yO2GpxhXJD6MHBtSitjzmV lYkg0T8YQwOjymoe7ywOUV/frx+/MDw/aZ84ynqEtFp9ihPi4SBdkNUNJ4gQI8vwqM/JKXPc2cl gaRi0WIG7GlaJUH5Xl4HzBHwIU7ovgYVtQLlQFhs9MAiexFY6wB4zGQ3qqBnl1NZrBxoG2x8oUk ct4kgT75klK6KAiqfkDsa6O9dvwY06BARGOTApzgrTZ+PYK7zmIjoGJsn/zdvXobMI3Czv91EnB b2Is0+q3vYS0nshkj32yEbbOwm3HMzMBdT4hu1FYYQnEqkKn8xiNOws X-Received: by 2002:a05:6512:2c90:b0:59f:6e82:dcfc with SMTP id 2adb3069b0e04-5a1061995a2mr1071379e87.39.1772101135284; Thu, 26 Feb 2026 02:18:55 -0800 (PST) Received: from mail-lf1-f50.google.com (mail-lf1-f50.google.com. [209.85.167.50]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-389f2ffe0d2sm4625531fa.24.2026.02.26.02.18.55 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 26 Feb 2026 02:18:55 -0800 (PST) Received: by mail-lf1-f50.google.com with SMTP id 2adb3069b0e04-59dea72099eso736594e87.0 for ; Thu, 26 Feb 2026 02:18:55 -0800 (PST) X-Received: by 2002:a05:651c:31cd:b0:386:1ce2:1194 with SMTP id 38308e7fff4ca-389ee2c43dfmr12874001fa.31.1772101134929; Thu, 26 Feb 2026 02:18:54 -0800 (PST) MIME-Version: 1.0 From: Swirl Smog Dowry Date: Thu, 26 Feb 2026 11:18:43 +0100 X-Gmail-Original-Message-ID: X-Gm-Features: AaiRm52WtkB3Ybu7GTC4XfMQqfXnhOT_rmXedDA2IU_3Af7CvNxGVhkhxDWsorA Message-ID: Subject: pg_get_viewdef() produces non-round-trippable SQL for views with USING join on mismatched integer types To: pgsql-bugs@lists.postgresql.org Content-Type: multipart/alternative; boundary="000000000000a754fe064bb7723b" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000a754fe064bb7723b Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable PostgreSQL version: 18.1 (also verified on 18.2) OS: Linux Description: =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D When a view uses a USING join on columns with different integer types (integer vs bigint) and the SELECT clause contains an explicit narrowing cast, pg_get_viewdef() produces SQL that PostgreSQL itself rejects. This makes pg_dump produce dumps that fail on restore for any such view. The SELECT clause gets col::integer, while the GROUP BY gets (col::bigint) =E2=80=94 they refer to the same underlying column but with different casts, so the GROUP BY check fails to recognise the SELECT expression as covered. Minimal reproducer: =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D CREATE TABLE t1 (year integer, val numeric); CREATE TABLE t2 (year bigint, label text); INSERT INTO t1 VALUES (2025, 100), (2025, 200), (2026, 300); INSERT INTO t2 VALUES (2025, 'A'), (2026, 'B'); -- View creation succeeds and queries work fine: CREATE VIEW v AS SELECT year::integer AS year, t2.label, sum(val) AS total FROM t1 LEFT JOIN t2 USING (year) GROUP BY year, t2.label; SELECT * FROM v; -- returns correct results -- pg_get_viewdef output: SELECT pg_get_viewdef('v'::regclass, true); Output of pg_get_viewdef: =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D SELECT t1.year::integer AS year, t2.label, sum(t1.val) AS total FROM t1 LEFT JOIN t2 USING (year) GROUP BY (t1.year::bigint), t2.label; Note: SELECT has t1.year::integer, GROUP BY has (t1.year::bigint). Attempting to re-execute the pg_get_viewdef output fails: =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D CREATE VIEW v2 AS SELECT t1.year::integer AS year, t2.label, sum(t1.val) AS total FROM t1 LEFT JOIN t2 USING (year) GROUP BY (t1.year::bigint), t2.label; ERROR: column "t1.year" must appear in the GROUP BY clause or be used in an aggregate function LINE 2: SELECT t1.year::integer AS year, ^ Impact: =3D=3D=3D=3D=3D=3D=3D pg_dump uses pg_get_viewdef() to serialise view definitions. Any database containing such a view (USING join between integer and bigint columns, with an explicit cast in SELECT) will produce a dump that fails during restore with the above error. Without the explicit cast in SELECT (i.e. just SELECT year, ...) pg_get_viewdef emits t1.year::bigint in both SELECT and GROUP BY, and the round-trip works= . The bug is triggered specifically by the narrowing cast (bigint -> integer) in the SELECT list combined with a USING join. Kind regards, Swirl --000000000000a754fe064bb7723b Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
PostgreSQL version: 18.1 (also verified on 18.2)
OS: Li= nux

Description:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
When a v= iew uses a USING join on columns with different integer types (integer vsbigint) and the SELECT clause contains an explicit narrowing cast, pg_get= _viewdef()
produces SQL that PostgreSQL itself rejects. This makes pg_du= mp produce dumps that
fail on restore for any such view.

The SELE= CT clause gets col::integer, while the GROUP BY gets (col::bigint) =E2=80= =94 they
refer to the same underlying column but with different casts, s= o the GROUP BY check
fails to recognise the SELECT expression as covered= .

Minimal reproducer:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D

=C2=A0 CREATE TABLE t1 (year integer, val numeric);<= br>=C2=A0 CREATE TABLE t2 (year bigint, label text);
=C2=A0 INSERT INTO = t1 VALUES (2025, 100), (2025, 200), (2026, 300);
=C2=A0 INSERT INTO t2 V= ALUES (2025, 'A'), (2026, 'B');

=C2=A0 -- View creat= ion succeeds and queries work fine:
=C2=A0 CREATE VIEW v AS
=C2=A0 = =C2=A0 SELECT year::integer AS year, t2.label, sum(val) AS total
=C2=A0 = =C2=A0 FROM t1
=C2=A0 =C2=A0 LEFT JOIN t2 USING (year)
=C2=A0 =C2=A0 = GROUP BY year, t2.label;

=C2=A0 SELECT * FROM v; =C2=A0-- returns co= rrect results

=C2=A0 -- pg_get_viewdef output:
=C2=A0 SELECT pg_g= et_viewdef('v'::regclass, true);

Output of pg_get_viewdef:=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D

=C2=A0 =C2=A0SELECT t1.year::integer AS year,
=C2=A0 =C2=A0 = =C2=A0 t2.label,
=C2=A0 =C2=A0 =C2=A0 sum(t1.val) AS total
=C2=A0 =C2= =A0 =C2=A0FROM t1
=C2=A0 =C2=A0 =C2=A0 =C2=A0LEFT JOIN t2 USING (year)=C2=A0 =C2=A0 GROUP BY (t1.year::bigint), t2.label;

Note: SELECT h= as t1.year::integer, GROUP BY has (t1.year::bigint).

Attempting to r= e-execute the pg_get_viewdef output fails:
=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=C2=A0 CREATE VIEW v2 AS
=C2=A0 =C2=A0SELECT t1.year::integer AS year,=
=C2=A0 =C2=A0 =C2=A0 t2.label,
=C2=A0 =C2=A0 =C2=A0 sum(t1.val) AS t= otal
=C2=A0 =C2=A0 =C2=A0FROM t1
=C2=A0 =C2=A0 =C2=A0 =C2=A0LEFT JOIN= t2 USING (year)
=C2=A0 =C2=A0 GROUP BY (t1.year::bigint), t2.label;
=
=C2=A0 ERROR: =C2=A0column "t1.year" must appear in the GROUP= BY clause or be used
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 in an aggregate= function
=C2=A0 LINE 2: =C2=A0SELECT t1.year::integer AS year,
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ^

Impact= :
=3D=3D=3D=3D=3D=3D=3D
pg_dump uses pg_get_viewdef() to serialise vi= ew definitions. Any database
containing such a view (USING join between = integer and bigint columns, with
an explicit cast in SELECT) will produc= e a dump that fails during restore with
the above error.

Without = the explicit cast in SELECT (i.e. just SELECT year, ...) pg_get_viewdef
= emits t1.year::bigint in both SELECT and GROUP BY, and the round-trip works= .
The bug is triggered specifically by the narrowing cast (bigint -> = integer) in
the SELECT list combined with a USING join.
<= br>

Kind regards,

Swirl

--000000000000a754fe064bb7723b--