| From: | Álvaro Herrera <alvherre(at)kurilemu(dot)de> |
|---|---|
| To: | Richard Guo <rguo(at)postgresql(dot)org> |
| Cc: | pgsql-hackers(at)lists(dot)postgresql(dot)org |
| Subject: | Re: pgsql: Don't trust NOT NULL on virtual generated columns of partitioned |
| Date: | 2026-10-13 12:42:51 |
| Message-ID: | as4kni55JMYBpXnq@alvherre.pgsql |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-committers pgsql-hackers |
On 2026-Oct-10, Richard Guo wrote:
> Don't trust NOT NULL on virtual generated columns of partitioned tables
[...]
> That is not safe for a partitioned table. A partition can have a
> generation expression different from its parent's, and it enforces the
> NOT NULL constraint against its own expression, whereas a query on the
> parent computes the column using the parent's expression. So the
> column can be NULL when read through the parent despite the
> constraint, and the anti-join would then produce wrong results, as it
> returns rows that NOT IN should have rejected.
I find this very surprising. Are we sure that it makes sense for a
partition to have a generating expression that differs from the one in
the parent table?
Copying from the test case you added,
CREATE TABLE gtestnn_parent2 (a int NOT NULL, b int GENERATED ALWAYS AS (nullif(a, 0)) VIRTUAL NOT NULL) PARTITION BY LIST (a);
CREATE TABLE gtestnn_child2 PARTITION OF gtestnn_parent2 (b GENERATED ALWAYS AS (a + 1) VIRTUAL) FOR VALUES IN (0);
INSERT INTO gtestnn_parent2 VALUES (0);
we read a NULL value from a column that's marked as not-null, which
shouldn't happen.
alvherre=# select * from gtestnn_parent2 ;
a | b
---+--------
0 | (null)
(1 row)
alvherre=# \d gtestnn_parent2
Partitioned table "public.gtestnn_parent2"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+------------------------------------
a | integer | | not null |
b | integer | | not null | generated always as (NULLIF(a, 0))
Partition key: LIST (a)
Number of partitions: 1 (Use \d+ to list them.)
The row is of course different if I read it directly from the partition.
alvherre=# select * from gtestnn_child2 ;
a | b
---+---
0 | 1
(1 row)
I didn't try but I imagine that allowing partitions to have a different
generating expression than the parent can break all kinds of constraint,
not just not-null ones, if generating expressions are "broken" enough.
Maybe we should disallow expressions to be different, and force users to
use STORED virtual columns if they want to do that. This seems
dangerous.
Alternatively, you could argue that at read time the row should get its
virtual column values using the expressions from the children rather
than for the parent.
--
Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/
"Las navajas y los monos deben estar siempre distantes" (Germán Poo)
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Richard Guo | 2026-10-13 14:34:50 | Re: pgsql: Don't trust NOT NULL on virtual generated columns of partitioned |
| Previous Message | Heikki Linnakangas | 2026-10-13 11:34:40 | pgsql: Apply auto-vectorization to the loop in accum_sum_add() |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Jim Jones | 2026-10-13 12:56:11 | Re: Unlogged materialized views |
| Previous Message | Boris Mironov | 2026-10-13 12:17:36 | Re: Idea to enhance pgbench by more modes to generate data (multi-TXNs, UNNEST, COPY BINARY) |