hi.
attached patch refactor AlterDomainAddConstraint

* change the error message:
alter domain d_int add constraint nn not null no inherit;
from
ERROR:  NOT NULL constraints cannot be marked NO INHERIT
to
ERROR:  DOMAIN with NOT NULL constraints cannot be marked NO INHERIT

basically processCASbits
from
processCASbits($3, @3, "NOT NULL")
processCASbits($5, @5, "CHECK")
to
processCASbits($3, @3, "DOMAIN with NOT NULL")
processCASbits($5, @5, "DOMAIN with CHECK")


* error out check constraint no inherit with domain. so the following
should fail.
alter domain d_int add constraint cc check(value > 1) no inherit; --should fail

* delete code in AlterDomainAddConstraint, since it will be unreachable.

* alter domain d_int add constraint cc2 check(value > 11) not
deferrable initially immediate not valid;
"not deferrable", "initially immediate" cannot error out at the moment.
maybe we can just document it in create_domain.sgml?

* some failed regress test, similar to thread (Pass ParseState as down
to utility functions)

you may also see the patch draft commit message.
From 23186a7ee0b7ebc10ecdab87558d1158676c35d9 Mon Sep 17 00:00:00 2001
From: jian he <jian.universal...@gmail.com>
Date: Fri, 6 Dec 2024 16:13:51 +0800
Subject: [PATCH v1 1/1] refactor AlterDomainAddConstraint

In gram.y only CHECK and NOT-NULL constraint are allowed for the ALTER DOMAIN ...
ADD CONSTRAINT statement.  so we can safely remove the code handles errors for
other constraint type.

as of constraint other property ([ DEFERRABLE | NOT DEFERRABLE ] [
INITIALLY DEFERRED | INITIALLY IMMEDIATE ]) we alerady handled in processCASbits
(gram.y).

however AlterDomainAddConstraint only pass single (Node *newConstraint).  that
means we cannot trigger an error for constraints specified as "NOT DEFERRABLE"
or "INITIALLY IMMEDIATE" because "NOT DEFERRABLE" or "INITIALLY IMMEDIATE" is
actualy a seperated Constraint node.

To error out case like:
alter domain d_int add constraint cc1 check(value > 1) not deferrable initially immediate;
we need to make DomainConstraint in gram.y more like TableConstraint.
that means this patch, "not deferrable" and "initially immediate" words is accepted,
maybe i should change create_domain.sgml Accordingly.

i also made "alter domain d_int add constraint cc check(value > 1) no inherit;"
fail.

the error message is not so good, for example in master, for
`alter domain d_int add constraint nn not null no inherit;`
you get:
ERROR:  NOT NULL constraints cannot be marked NO INHERIT

but NOT NULL constraints can be marked NO INHERIT.
for domain constraint part, i slightly changed the third parameter of
processCASbits while calling.  so now the error message becomes:

ERROR:  DOAMIN with NOT NULL constraints cannot be marked NO INHERIT
---
 src/backend/commands/typecmds.c      | 33 ----------------
 src/backend/parser/gram.y            |  6 +--
 src/test/regress/expected/domain.out | 58 ++++++++++++++++++++++++++++
 src/test/regress/sql/domain.sql      | 22 +++++++++++
 4 files changed, 83 insertions(+), 36 deletions(-)

diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index da591c0922..aa715402e1 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -2942,39 +2942,6 @@ AlterDomainAddConstraint(List *names, Node *newConstraint,
 			/* processed below */
 			break;
 
-		case CONSTR_UNIQUE:
-			ereport(ERROR,
-					(errcode(ERRCODE_SYNTAX_ERROR),
-					 errmsg("unique constraints not possible for domains")));
-			break;
-
-		case CONSTR_PRIMARY:
-			ereport(ERROR,
-					(errcode(ERRCODE_SYNTAX_ERROR),
-					 errmsg("primary key constraints not possible for domains")));
-			break;
-
-		case CONSTR_EXCLUSION:
-			ereport(ERROR,
-					(errcode(ERRCODE_SYNTAX_ERROR),
-					 errmsg("exclusion constraints not possible for domains")));
-			break;
-
-		case CONSTR_FOREIGN:
-			ereport(ERROR,
-					(errcode(ERRCODE_SYNTAX_ERROR),
-					 errmsg("foreign key constraints not possible for domains")));
-			break;
-
-		case CONSTR_ATTR_DEFERRABLE:
-		case CONSTR_ATTR_NOT_DEFERRABLE:
-		case CONSTR_ATTR_DEFERRED:
-		case CONSTR_ATTR_IMMEDIATE:
-			ereport(ERROR,
-					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("specifying constraint deferrability not supported for domains")));
-			break;
-
 		default:
 			elog(ERROR, "unrecognized constraint subtype: %d",
 				 (int) constr->contype);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 67eb96396a..ccab075bea 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -4321,9 +4321,9 @@ DomainConstraintElem:
 					n->location = @1;
 					n->raw_expr = $3;
 					n->cooked_expr = NULL;
-					processCASbits($5, @5, "CHECK",
+					processCASbits($5, @5, "DOMAIN with CHECK",
 								   NULL, NULL, &n->skip_validation,
-								   &n->is_no_inherit, yyscanner);
+								   NULL, yyscanner);
 					n->initially_valid = !n->skip_validation;
 					$$ = (Node *) n;
 				}
@@ -4335,7 +4335,7 @@ DomainConstraintElem:
 					n->location = @1;
 					n->keys = list_make1(makeString("value"));
 					/* no NOT VALID, NO INHERIT support */
-					processCASbits($3, @3, "NOT NULL",
+					processCASbits($3, @3, "DOMAIN with NOT NULL",
 								   NULL, NULL, NULL,
 								   NULL, yyscanner);
 					n->initially_valid = true;
diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out
index 42b6559f9c..d6ef6ba098 100644
--- a/src/test/regress/expected/domain.out
+++ b/src/test/regress/expected/domain.out
@@ -15,6 +15,64 @@ NOTICE:  drop cascades to type dependenttypetest
 -- this should fail because already gone
 drop domain domaindroptest cascade;
 ERROR:  type "domaindroptest" does not exist
+--alter domain error case.
+create domain d_int as int4;
+alter domain d_int add constraint nn not null no inherit;
+ERROR:  DOMAIN with NOT NULL constraints 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 valid;
+ERROR:  DOMAIN with NOT NULL constraints 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 deferrable;
+ERROR:  DOMAIN with NOT NULL constraints cannot be marked DEFERRABLE
+LINE 1: alter domain d_int add constraint nn not null deferrable;
+                                                      ^
+alter domain d_int add constraint nn not null initially deferred;
+ERROR:  DOMAIN with NOT NULL constraints cannot be marked DEFERRABLE
+LINE 1: alter domain d_int add constraint nn not null initially defe...
+                                                      ^
+alter domain d_int add constraint nn not null deferrable initially deferred;
+ERROR:  DOMAIN with NOT NULL constraints cannot be marked DEFERRABLE
+LINE 1: alter domain d_int add constraint nn not null deferrable ini...
+                                                      ^
+alter domain d_int add constraint nn not null deferrable not deferrable;
+ERROR:  conflicting constraint properties
+LINE 1: ...omain d_int add constraint nn not null deferrable not deferr...
+                                                             ^
+alter domain d_int add constraint cc check(value > 1) no inherit;
+ERROR:  DOMAIN with CHECK constraints 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) deferrable;
+ERROR:  DOMAIN with CHECK constraints cannot be marked DEFERRABLE
+LINE 1: ...r domain d_int add constraint cc check(value > 1) deferrable...
+                                                             ^
+alter domain d_int add constraint cc check(value > 1) initially deferred;
+ERROR:  DOMAIN with CHECK constraints cannot be marked DEFERRABLE
+LINE 1: ...r domain d_int add constraint cc check(value > 1) initially ...
+                                                             ^
+alter domain d_int add constraint cc check(value > 1) deferrable initially deferred not valid;
+ERROR:  DOMAIN with CHECK constraints cannot be marked DEFERRABLE
+LINE 1: ...r domain d_int add constraint cc check(value > 1) deferrable...
+                                                             ^
+alter domain d_int add constraint cc check(value > 1) deferrable NOT deferrable not valid;
+ERROR:  conflicting constraint properties
+LINE 1: ...int add constraint cc check(value > 1) deferrable NOT deferr...
+                                                             ^
+--alter domain valid case.
+alter domain d_int add constraint cc not null not deferrable initially IMMEDIATE; --ok
+alter domain d_int add constraint cc1 check(value > 1) not deferrable initially immediate; --ok
+alter domain d_int add constraint cc2 check(value > 11) not deferrable initially immediate not valid; --ok
+\dD d_int
+                                              List of domains
+ Schema | Name  |  Type   | Collation | Nullable | Default |                     Check                      
+--------+-------+---------+-----------+----------+---------+------------------------------------------------
+ public | d_int | integer |           | not null |         | CHECK (VALUE > 1) CHECK (VALUE > 11) NOT VALID
+(1 row)
+
+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.
diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql
index ee07b03174..ae33abea38 100644
--- a/src/test/regress/sql/domain.sql
+++ b/src/test/regress/sql/domain.sql
@@ -17,6 +17,28 @@ drop domain domaindroptest cascade;
 drop domain domaindroptest cascade;
 
 
+--alter domain error case.
+create domain d_int as int4;
+alter domain d_int add constraint nn not null no inherit;
+alter domain d_int add constraint nn not null not valid;
+alter domain d_int add constraint nn not null deferrable;
+alter domain d_int add constraint nn not null initially deferred;
+alter domain d_int add constraint nn not null deferrable initially deferred;
+alter domain d_int add constraint nn not null deferrable not deferrable;
+
+alter domain d_int add constraint cc check(value > 1) no inherit;
+alter domain d_int add constraint cc check(value > 1) deferrable;
+alter domain d_int add constraint cc check(value > 1) initially deferred;
+alter domain d_int add constraint cc check(value > 1) deferrable initially deferred not valid;
+alter domain d_int add constraint cc check(value > 1) deferrable NOT deferrable not valid;
+
+--alter domain valid case.
+alter domain d_int add constraint cc not null not deferrable initially IMMEDIATE; --ok
+alter domain d_int add constraint cc1 check(value > 1) not deferrable initially immediate; --ok
+alter domain d_int add constraint cc2 check(value > 11) not deferrable initially immediate not valid; --ok
+\dD d_int
+DROP DOMAIN d_int;
+
 -- Test domain input.
 
 -- Note: the point of checking both INSERT and COPY FROM is that INSERT
-- 
2.34.1

Reply via email to