-- Every DDL path that can give a partition a VIRTUAL generation expression -- different from its parent's, each with a control that uses the parent's -- expression and must keep working. Run with ON_ERROR_STOP off; the -- expected outcome is in the comment of each statement: -- [div] divergent: accepted on unpatched builds, should fail with the patch -- [same] same expression: should succeed on every build -- [keep] outside the patch's scope: should behave as before -- At the end, the find-mismatches query lists what got through. \pset null '(null)' select current_setting('server_version') as server_version; -- P1. CREATE TABLE ... PARTITION OF, LIST create table l (a int, v int generated always as (a * 2) virtual) partition by list (a); create table l1 partition of l (v generated always as (a * 3) virtual) for values in (1); -- [div] create table l2 partition of l (v generated always as (a * 2) virtual) for values in (2); -- [same] create table l3 partition of l for values in (3); -- [same] -- P2. RANGE and HASH create table r (a int, v int generated always as (a * 2) virtual) partition by range (a); create table r1 partition of r (v generated always as (a * 3) virtual) for values from (0) to (10); -- [div] create table h (a int, v int generated always as (a * 2) virtual) partition by hash (a); create table h1 partition of h (v generated always as (a * 3) virtual) for values with (modulus 2, remainder 0); -- [div] -- P3. ATTACH PARTITION, also with a different column order create table l4 (a int, v int generated always as (a * 3) virtual); alter table l attach partition l4 for values in (4); -- [div] create table l5 (v int generated always as (a * 2) virtual, a int); alter table l attach partition l5 for values in (5); -- [same] -- P4. DEFAULT partition create table l6 partition of l (v generated always as (a * 3) virtual) default; -- [div] -- P5. SET EXPRESSION alter table l2 alter column v set expression as (a * 5); -- [div] alter table only l alter column v set expression as (a * 5); -- [div] alter table l alter column v set expression as (a * 7); -- [same] select c.relname, pg_get_expr(d.adbin, d.adrelid) as expr from pg_class c join pg_attrdef d on d.adrelid = c.oid where c.oid = 'l'::regclass or c.oid in (select inhrelid from pg_inherits where inhparent = 'l'::regclass) order by 1; -- P6. Multi-level: a partitioned partition create table m (a int, b int, v int generated always as (a * 2) virtual) partition by list (a); create table m1 partition of m (v generated always as (a * 3) virtual) for values in (1) partition by list (b); -- [div] create table m2 partition of m for values in (2) partition by list (b); -- [same] create table m2a partition of m2 (v generated always as (a * 3) virtual) for values in (1); -- [div] create table m2b partition of m2 for values in (2); -- [same] alter table m2 alter column v set expression as (a * 9); -- [div] -- a standalone partitioned table whose own leaf matches it, attached -- to a parent with a different expression create table m3 (a int, b int, v int generated always as (a * 3) virtual) partition by list (b); create table m3a partition of m3 for values in (1); -- [same] alter table m attach partition m3 for values in (3); -- [div] -- P7. Foreign table as a partition (no handler needed for DDL) create foreign data wrapper vgd_fdw; create server vgd_srv foreign data wrapper vgd_fdw; create foreign table f1 partition of l (v generated always as (a * 3) virtual) for values in (7) server vgd_srv; -- [div] create foreign table f2 (a int, v int generated always as (a * 3) virtual) server vgd_srv; alter table l attach partition f2 for values in (8); -- [div] -- P8. Unchanged by design: STORED and plain inheritance create table s (a int, v int generated always as (a * 2) stored) partition by list (a); create table s1 partition of s (v generated always as (a * 3) stored) for values in (1); -- [keep] create table i (a int, v int generated always as (a * 2) virtual); create table i1 (a int, v int generated always as (a * 3) virtual) inherits (i); -- [keep] alter table i1 alter column v set expression as (a * 4); -- [keep] -- What got through: the patch's own find-mismatches query select c.oid::pg_catalog.regclass as partition, i.inhparent::pg_catalog.regclass as parent, a.attname as column, pg_catalog.pg_get_expr(dc.adbin, dc.adrelid) as partition_expr, pg_catalog.pg_get_expr(dp.adbin, dp.adrelid) as parent_expr from pg_catalog.pg_class c join pg_catalog.pg_inherits i on i.inhrelid = c.oid join pg_catalog.pg_attribute a on a.attrelid = c.oid join pg_catalog.pg_attribute pa on pa.attrelid = i.inhparent and pa.attname = a.attname join pg_catalog.pg_attrdef dc on dc.adrelid = a.attrelid and dc.adnum = a.attnum join pg_catalog.pg_attrdef dp on dp.adrelid = pa.attrelid and dp.adnum = pa.attnum where c.relispartition and a.attgenerated = 'v' and pg_catalog.pg_get_expr(dc.adbin, dc.adrelid) <> pg_catalog.pg_get_expr(dp.adbin, dp.adrelid) order by 1, 3;