On Mon, Nov 24, 2025 at 10:45 PM Peter Eisentraut <[email protected]> wrote: > > On 10.03.25 19:37, Alvaro Herrera wrote: > > > > I had forgotten this thread, and I ended up implementing a different > > solution for this issue, which I just posted at > > https://postgr.es/m/[email protected] > > > > I like my patch better than this approach because it allows us to solve > > the same problem as it appears in other parts of the grammar, and also > > because it avoids the bit fiddling which is harder to maintain later on. > > If you'd care to have a look at it, I'd appreciate it. > > Where are we on this? Which of the two patches should we pursue? >
hi. if you go to this link https://postgr.es/m/[email protected] check v2-0001-Improve-processCASbits-API-with-a-seen-struct.patch you will find that it added a struct CAS_flags to processCASbits. +typedef struct CAS_flags +{ + bool seen_deferrability; + bool seen_enforced; + bool seen_valid; + bool seen_inherit; +} CAS_flags; In v2-0001, most of the case processCASbits just pass a NULL CAS_flags(seen). CAS_flags are not used in table constraints at all. but CAS_flags indeed used for error message handling in ALTER DOMAIN ADD CONSTRAINT. (IMHO, it looks like big efforts to solve the same problem, also these bit fiddling for domain constraint unlikely to change in the future, e.g. we are unlike to add DEFERRABLE, INITIALLY DEFERRED, NO INHERIT constraints to domain.) anyway, both patches are attached. this thread: v5-0001-ALTER-DOMAIN-ADD-CONSTRAINT-error-message-enhance.patch thread: https://postgr.es/m/[email protected] v5-0001-Improve-processCASbits-API-with-a-seen-struct.no-cfbot v5-0002-handle-constraints-on-domains-too.no-cfbot -- jian https://www.enterprisedb.com
From 6e9815976016c3aea10f929f7a66251e1d0a57fd Mon Sep 17 00:00:00 2001 From: jian he <[email protected]> Date: Wed, 26 Nov 2025 12:26:49 +0800 Subject: [PATCH v5 1/1] ALTER DOMAIN ADD CONSTRAINT error message enhance DomainConstraintElem syntax in gram.y can specify constraint properties such as ([ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE | NO INHERIT ] [ENFORCED | NOT ENFORCED]) ALTER DOMAIN synopsis section indicate none of these properties are allowed. These properties (DomainConstraintElem) are wrapped up as a separate individual Constraints node (see DefineDomain). However, AlterDomainAddConstraint can only cope with a single Constraints node. therefore, error out at AlterDomainAddConstraint is not possible, so error message handling stay at gram.y. discussion: https://postgr.es/m/cacjufxhitd5lglbssapshhtdwxt0vivkthinkyw-skbx93t...@mail.gmail.com --- src/backend/parser/gram.y | 53 +++++++++++++++++++++++++--- src/test/regress/expected/domain.out | 42 ++++++++++++++++++++-- src/test/regress/sql/domain.sql | 12 +++++++ 3 files changed, 101 insertions(+), 6 deletions(-) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index c3a0a354a9c..920e611cfb9 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -4447,8 +4447,28 @@ DomainConstraintElem: n->raw_expr = $3; n->cooked_expr = NULL; processCASbits($5, @5, "CHECK", - NULL, NULL, NULL, &n->skip_validation, - &n->is_no_inherit, yyscanner); + &n->deferrable, &n->initdeferred, &n->is_enforced, + &n->skip_validation, &n->is_no_inherit, yyscanner); + + if ($5 & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE | CAS_INITIALLY_IMMEDIATE | + CAS_INITIALLY_DEFERRED)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("specifying constraint deferrability not supported for domains"), + parser_errposition(@5)); + + if ($5 & (CAS_NOT_ENFORCED | CAS_ENFORCED)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("specifying constraint enforceability not supported for domains"), + parser_errposition(@5)); + + if (n->is_no_inherit) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("check constraints for domains cannot be marked %s", "NO INHERIT"), + parser_errposition(@5)); + n->is_enforced = true; n->initially_valid = !n->skip_validation; $$ = (Node *) n; @@ -4462,8 +4482,33 @@ DomainConstraintElem: n->keys = list_make1(makeString("value")); /* no NOT VALID, NO INHERIT support */ processCASbits($3, @3, "NOT NULL", - NULL, NULL, NULL, - NULL, NULL, yyscanner); + &n->deferrable, &n->initdeferred, &n->is_enforced, + &n->skip_validation, &n->is_no_inherit, yyscanner); + if (($3 & CAS_NOT_VALID) != 0) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("not-null constraints on domains cannot be marked %s", "NOT VALID"), + parser_errposition(@3)); + + if ($3 & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE | CAS_INITIALLY_IMMEDIATE | + CAS_INITIALLY_DEFERRED)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("specifying constraint deferrability not supported for domains"), + parser_errposition(@3)); + + if ($3 & (CAS_NOT_ENFORCED | CAS_ENFORCED)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("specifying constraint enforceability not supported for domains"), + parser_errposition(@3)); + + if (n->is_no_inherit) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("not-null constraints on domains cannot be marked %s", "NO INHERIT"), + parser_errposition(@3)); + n->initially_valid = true; $$ = (Node *) n; } diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out index 62a48a523a2..357dac1f555 100644 --- a/src/test/regress/expected/domain.out +++ b/src/test/regress/expected/domain.out @@ -68,6 +68,44 @@ create domain d_fail as int4 constraint cc check (values > 1) deferrable; ERROR: specifying constraint deferrability not supported for domains LINE 1: ...n d_fail as int4 constraint cc check (values > 1) deferrable... ^ +create domain d_int as int4; +alter domain d_int add constraint nn not null not valid; +ERROR: not-null constraints on domains cannot be marked NOT VALID +LINE 1: alter domain d_int add constraint nn not null not valid; + ^ +alter domain d_int add constraint nn not null no inherit; +ERROR: not-null constraints on domains cannot be marked NO INHERIT +LINE 1: alter domain d_int add constraint nn not null no inherit; + ^ +alter domain d_int add constraint nn not null not enforced; +ERROR: specifying constraint enforceability not supported for domains +LINE 1: alter domain d_int add constraint nn not null not enforced; + ^ +alter domain d_int add constraint nn not null not deferrable initially immediate; +ERROR: specifying constraint deferrability not supported for domains +LINE 1: alter domain d_int add constraint nn not null not deferrable... + ^ +alter domain d_int add constraint cc check(value > 1) no inherit; +ERROR: check constraints for domains cannot be marked NO INHERIT +LINE 1: ...r domain d_int add constraint cc check(value > 1) no inherit... + ^ +alter domain d_int add constraint cc check(value > 1) not enforced; +ERROR: specifying constraint enforceability not supported for domains +LINE 1: ...r domain d_int add constraint cc check(value > 1) not enforc... + ^ +alter domain d_int add constraint cc check(value > 1) enforced; +ERROR: specifying constraint enforceability not supported for domains +LINE 1: ...er domain d_int add constraint cc check(value > 1) enforced; + ^ +alter domain d_int add constraint cc check(value > 1) not deferrable initially immediate; +ERROR: specifying constraint deferrability not supported for domains +LINE 1: ...r domain d_int add constraint cc check(value > 1) not deferr... + ^ +alter domain d_int add constraint cc check(value > 1) deferrable initially deferred; +ERROR: specifying constraint deferrability not supported for domains +LINE 1: ...r domain d_int add constraint cc check(value > 1) deferrable... + ^ +drop domain d_int; -- Test domain input. -- Note: the point of checking both INSERT and COPY FROM is that INSERT -- exercises CoerceToDomain while COPY exercises domain_in. @@ -1369,11 +1407,11 @@ LINE 1: ...S int CONSTRAINT the_constraint CHECK (value > 0) NOT ENFORC... CREATE DOMAIN constraint_enforced_dom AS int; -- XXX misleading error messages ALTER DOMAIN constraint_enforced_dom ADD CONSTRAINT the_constraint CHECK (value > 0) ENFORCED; -ERROR: CHECK constraints cannot be marked ENFORCED +ERROR: specifying constraint enforceability not supported for domains LINE 1: ...om ADD CONSTRAINT the_constraint CHECK (value > 0) ENFORCED; ^ ALTER DOMAIN constraint_enforced_dom ADD CONSTRAINT the_constraint CHECK (value > 0) NOT ENFORCED; -ERROR: CHECK constraints cannot be marked NOT ENFORCED +ERROR: specifying constraint enforceability not supported for domains LINE 1: ...m ADD CONSTRAINT the_constraint CHECK (value > 0) NOT ENFORC... ^ DROP DOMAIN constraint_enforced_dom; diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql index b8f5a639712..b0c13a75e3a 100644 --- a/src/test/regress/sql/domain.sql +++ b/src/test/regress/sql/domain.sql @@ -31,6 +31,18 @@ create domain d_fail as int4 constraint cc generated by default as identity; create domain d_fail as int4 constraint cc check (values > 1) no inherit; create domain d_fail as int4 constraint cc check (values > 1) deferrable; +create domain d_int as int4; +alter domain d_int add constraint nn not null not valid; +alter domain d_int add constraint nn not null no inherit; +alter domain d_int add constraint nn not null not enforced; +alter domain d_int add constraint nn not null not deferrable initially immediate; +alter domain d_int add constraint cc check(value > 1) no inherit; +alter domain d_int add constraint cc check(value > 1) not enforced; +alter domain d_int add constraint cc check(value > 1) enforced; +alter domain d_int add constraint cc check(value > 1) not deferrable initially immediate; +alter domain d_int add constraint cc check(value > 1) deferrable initially deferred; +drop domain d_int; + -- Test domain input. -- Note: the point of checking both INSERT and COPY FROM is that INSERT -- 2.34.1
v5-0001-Improve-processCASbits-API-with-a-seen-struct.no-cfbot
Description: Binary data
v5-0002-handle-constraints-on-domains-too.no-cfbot
Description: Binary data
