Thread
-
[PATCH] no table rewrite when set column type to constrained domain
jian he <jian.universality@gmail.com> — 2025-07-09T18:00:15Z
hi. the attached patch is to implement the $subject feature. i was mainly intrigued by the discussion in https://www.postgresql.org/message-id/20190226061450.GA1665944@rfd.leadboat.com the main gotcha is struct NewColumnValue. we do ``palloc0(sizeof(NewColumnValue));`` in ATExecAddColumn, ATExecSetExpression, ATPrepAlterColumnType. ATExecAddColumn: Adding a new column with domain with constraints will cause table rewrite. ATExecSetExpression: for stored generated column will cause table rewrite, we do not support domain over virtual generated columns now. ATPrepAlterColumnType: we only do table rewriting occasionally. see ATColumnChangeRequiresRewrite. If table rewrite is required, then there is nothing we can do. so we only need to focus on ATPrepAlterColumnType. we can add a new boolean field, coerce_to_domain, to NewColumnValue. this field is set to true only when changing an existing column's type to a constrained domain. In such cases, a table scan is enough—no table rewrite is needed. coerce_to_domain will set to false, if table rewrite is required. -
Re: [PATCH] no table rewrite when set column type to constrained domain
jian he <jian.universality@gmail.com> — 2025-08-26T03:26:16Z
On Thu, Jul 10, 2025 at 2:00 AM jian he <jian.universality@gmail.com> wrote: > > we can add a new boolean field, coerce_to_domain, to NewColumnValue. this field > is set to true only when changing an existing column's type to a constrained > domain. In such cases, a table scan is enough—no table rewrite is needed. > coerce_to_domain will set to false, if table rewrite is required. I realized that "coerce_to_domain" is not so good in this context. maybe there are other scenarios, we added a NewColumnValue and we also only need table scan. so I changed it to scan_only. /* * .... * If scan_only is true, it means only a table scan is required. * Currently, this is supported only by the ALTER COLUMN SET DATA TYPE command, * where the column's data type is being changed to a constrained domain. */ typedef struct NewColumnValue { AttrNumber attnum; /* which column */ Expr *expr; /* expression to compute */ ExprState *exprstate; /* execution state */ bool is_generated; /* is it a GENERATED expression? */ bool scan_only; /* table scan only */ } NewColumnValue; -
Re: [PATCH] no table rewrite when set column type to constrained domain
jian he <jian.universality@gmail.com> — 2025-12-15T07:06:40Z
On Tue, Aug 26, 2025 at 11:26 AM jian he <jian.universality@gmail.com> wrote: > > typedef struct NewColumnValue > { > AttrNumber attnum; /* which column */ > Expr *expr; /* expression to compute */ > ExprState *exprstate; /* execution state */ > bool is_generated; /* is it a GENERATED expression? */ > bool scan_only; /* table scan only */ > } NewColumnValue; I changed scan_only to need_compute. + * + * If need_compute is true, we will evaluate the new column value in Phase 3. + * Currently, this is only used in ALTER COLUMN SET DATA TYPE command, where the + * column’s data type is being changed to a constrained domain, and all the + * domain's constraints are non-volatile. In case table rewrite, we also set it + * to true. */ typedef struct NewColumnValue { @@ -238,6 +244,7 @@ typedef struct NewColumnValue Expr *expr; /* expression to compute */ ExprState *exprstate; /* execution state */ bool is_generated; /* is it a GENERATED expression? */ + bool need_compute; /* compute this new expression in Phase 3 */ } NewColumnValue; I use domain over domain for regress tests. I also constrained the no–table-rewrite behavior to cases where the coercion is to a domain type and all constraints of the new domain are non-volatile. Demo: CREATE DOMAIN domain1 AS INT CHECK(VALUE > 1) NOT NULL; CREATE DOMAIN domain11 AS domain1 CHECK(VALUE > 1) NOT NULL; CREATE DOMAIN domain21 AS domain1 CHECK(VALUE > random(min=>10, max=>10)) NOT NULL; CREATE DOMAIN domain3 AS INT8; CREATE TABLE t22(a INT, b INT); INSERT INTO t22 VALUES(-2, -1); -- no table rewrite, but fail at domain constraint check ALTER TABLE t22 ALTER COLUMN a SET DATA TYPE domain11 USING a::domain11; -- no table rewrite, but fail at domain constraint check ALTER TABLE t22 ALTER COLUMN b SET DATA TYPE domain11 USING b::domain11; -- table rewrite ALTER TABLE t22 ALTER COLUMN a SET DATA TYPE domain21; ALTER TABLE t22 ALTER COLUMN b SET DATA TYPE domain3; ALTER TABLE t22 ALTER COLUMN a SET DATA TYPE domain1 USING (a+0)::domain1; -- jian https://www.enterprisedb.com -
Re: [PATCH] no table rewrite when set column type to constrained domain
solai v <solai.cdac@gmail.com> — 2026-05-14T09:18:12Z
Hi, I tested the latest v6 patch on current master with a few different scenarios.For the simple int to constrained-domain type change case,the scan-only patch was used and the relfilenode stayed unchanged before and after ALTER TABLE ,so the rewrite was avoided as expected. I also tried USING expression cases,invalid domain values,and NULL values.The behavior looked correct in those cases as well. I tested with both small tables and a 1M row table. Regards, Solai