Re: BUG #18970: Atempt to alter type of table column used in row type with check leads to assertion failure
jian he <jian.universality@gmail.com>
From: jian he <jian.universality@gmail.com>
To: Tom Lane <tgl@sss.pgh.pa.us>
Cc: exclusion@gmail.com, pgsql-bugs@lists.postgresql.org
Date: 2025-07-01T03:25:20Z
Lists: pgsql-bugs
Attachments
- v3-0001-fix-bug-18970.patch (text/x-patch) patch v3-0001
On Mon, Jun 30, 2025 at 11:14 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
> jian he <jian.universality@gmail.com> writes:
> > SET EXPRESSION both can have this issue.
> > so i also add more test cases for stored/virtual generated columns.
>
> This patch is a lot larger than I was expecting, and I think it's
> misguided. You argue that
>
> + * Changing a virtual generated column's expression is akin to altering its
> + * type, requiring a call to find_composite_type_dependencies to check if
> + * the virtual generated column is used in any table.
> + * Therefore we need add this defval to tab->newvals for virtual generated
> + * column too, so Phase3 will call find_composite_type_dependencies.
>
> but I think that is in fact wrong. The implementation restriction
> we have is that we lack code to run around and physically change
> the stored values of columns that are not top-level table columns.
> However, in the case of a virtual column we don't need to change
> anything about the storage: once we've fixed the catalog metadata,
> we're done. So I'm not seeing the need to add all this stuff
> other than the additional locking calls.
>
CREATE TABLE t1(a int generated always as ('1') stored);
CREATE TABLE t2(b t1 CHECK ((b).a IS NOT NULL));
INSERT INTO t2 default values returning *;
ERROR: new row for relation "t2" violates check constraint "t2_b_check"
DETAIL: Failing row contains (null).
INSERT INTO t2 values '(1)' returning *;
ALTER TABLE t1 ALTER COLUMN a SET EXPRESSION AS (NULL);
Currently we disallow this "SET EXPRESSION AS".
I am wondering why we disallow it?
at that time, I was mainly initrucugged by this comment about
composite type default
in ATRewriteTables:
* If we change column data types, the operation has to be propagated
* to tables that use this table's rowtype as a column type.
* tab->newvals will also be non-NULL in the case where we're adding a
* column with a default. We choose to forbid that case as well,
* since composite types might eventually support defaults.
I’ve added some tests to generated_stored.sql, but not to generated_virtual.sql.
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Obtain required table lock during cross-table constraint updates.
- c15798cf94c4 16.10 landed
- bbfcbc4cde4a 17.6 landed
- 8319e5cb5493 18.0 landed
- 614ffb26d1cd 15.14 landed
- 25cab4473525 14.19 landed
- 13f1e9f26a11 13.22 landed
-
Add assertions that we hold some relevant lock during relation open.
- b04aeb0a053e 12.0 cited