| From: | Zsolt Parragi <zsolt(dot)parragi(at)percona(dot)com> |
|---|---|
| To: | jian he <jian(dot)universality(at)gmail(dot)com> |
| Cc: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Subject: | Re: MERGE/SPLIT PARTITIONS issues/questions |
| Date: | 2026-08-02 06:56:05 |
| Message-ID: | CAN4CZFOGAQqgYc0q+co7sDU3LXPwdVanz2cDf-9FHA5D6EkX3w@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs pgsql-hackers |
> For ALTER TABLE pp MERGE PARTITIONS (pp1, pp2) INTO pp12, a CHECK constraint
> that exists only on pp2 surely should not apply to the new pp12. Otherwise, that
> constraint would also end up being enforced against pp1's data, regardless of
> whether pp1 actually satisfies its definition, that would seem weird, IMHO.
I agree, that's why I proposed failing the MERGE in this situation,
and to only allow it to proceed if pp1 and pp2 have he same
definition.
> For this case, ALTER TABLE MERGE PARTITIONS should let the new
> partition use the partitioned table's generation expression, i think.
My issue is that no other ALTER TABLE statement does that.
Consider this scenario:
CREATE FUNCTION f(i int) RETURNS int IMMUTABLE LANGUAGE sql AS 'SELECT i * 2';
CREATE TABLE t (i int, j int, k int, g int GENERATED ALWAYS AS (f(j*k)) STORED);
INSERT INTO t VALUES (1,1,1), (2,2,2), (3,3,3);
SELECT * FROM t;
i | j | k | g
---+---+---+----
1 | 1 | 1 | 2
2 | 2 | 2 | 8
3 | 3 | 3 | 18
CREATE OR REPLACE FUNCTION f(i int) RETURNS int IMMUTABLE LANGUAGE sql
AS 'SELECT i * 3'; -- change unrelated column that completely rewrites
the table
SELECT * FROM t;
i | j | k | g
---+---+---+----
1 | 1 | 1 | 2
2 | 2 | 2 | 8
3 | 3 | 3 | 18
So we get the same results: it kept the old values. Any unrelated
ALTER that doesn't change the generator expression or its dependents
will do this: keep the generated values as is, even if it rewrites the
relation file.
And what about ALTERs that try to change one of its dependent, and
would result in an unintuitive/hidden regeneration of the generated
column?
ALTER TABLE t ALTER COLUMN j TYPE smallint;
2026-08-02 07:38:13.368 WEST [1110699] ERROR: cannot alter type of a
column used by a generated column
2026-08-02 07:38:13.368 WEST [1110699] DETAIL: Column "j" is used by
generated column "g".
2026-08-02 07:38:13.368 WEST [1110699] STATEMENT: ALTER TABLE t
ALTER COLUMN j TYPE smallint;
ERROR: cannot alter type of a column used by a generated column
DETAIL: Column "j" is used by generated column "g"
It fails. And even if I alter the type of g directly:
ALTER TABLE t ALTER COLUMN g TYPE text;
ALTER TABLE
postgres=# SELECT * FROM t;
i | j | k | g
---+---+---+----
1 | 1 | 1 | 2
2 | 2 | 2 | 8
3 | 3 | 3 | 18
(3 rows)
It doesn't change. The only ALTER that causes it to change is ALTER
TABLE t COLUMN g SET EXPRESSION, which explicitly changes the
expression.
This would be the only ALTER TABLE command that behaves differently,
every other operation that would possibly change the generated
expression in a hidden way either reuses the old values (if it safely
can), or errors out (if it can't). It would be fine if this would be
called CREATE TABLE AS MERGE PARTITIONS and CREATE TABLE AS SPLIT
PARTITIONS, but it's called an ALTER TABLE, not a CREATE TABLE.
And also, think about SPLIT PARTITION: in the split scenario, what
reasoning do we have to "reuse the partitioned table's generation
expression"? We could very easily reuse the partition's definition,
and copy the current values, there's no complex logic to follow there.
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Andrey Rachitskiy | 2026-08-02 07:29:48 | Re: BUG #19595: Three memory-safety defects in src/backend/tsearch/spell.c (dictionary loader), PG 18.3 |
| Previous Message | jian he | 2026-08-02 04:27:04 | Re: MERGE/SPLIT PARTITIONS issues/questions |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Peter Geoghegan | 2026-08-02 07:03:01 | Re: GiST multirange index scans can fail to return rows |
| Previous Message | Andrey Borodin | 2026-08-02 06:12:34 | Re: GiST multirange index scans can fail to return rows |