From e3aa00904edb8481585f7d27b18213f30423696e Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Mon, 9 Dec 2024 16:39:59 +0800
Subject: [PATCH v3 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.

further simplify DomainConstraintElem syntax in gram.y. Specifying constraint properties
([ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE | NO INHERIT ])
will be syntax error at parse stage.

in gram.y DomainConstraintElem will be:

  CHECK '(' a_expr ')'
| CHECK '(' a_expr ')' NOT VALID
| NOT NULL_P

discussion: https://postgr.es/m/CACJufxHitd5LGLBSSAPShhtDWxT0ViVKTHinkYW-skBX93TcpA@mail.gmail.com
---
 src/backend/commands/tablecmds.c |  2 +-
 src/backend/commands/typecmds.c  | 56 +++++---------------------------
 src/backend/parser/gram.y        | 25 ++++++++------
 src/backend/tcop/utility.c       |  3 +-
 src/include/commands/typecmds.h  |  2 +-
 5 files changed, 28 insertions(+), 60 deletions(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 6ccae4cb4a..2dd33c0435 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5390,7 +5390,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
 			address =
 				AlterDomainAddConstraint(((AlterDomainStmt *) cmd->def)->typeName,
 										 ((AlterDomainStmt *) cmd->def)->def,
-										 NULL);
+										 NULL, context->queryString);
 			break;
 		case AT_ReAddComment:	/* Re-add existing comment */
 			address = CommentObject((CommentStmt *) cmd->def);
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index da591c0922..71080f1598 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -2903,7 +2903,7 @@ AlterDomainDropConstraint(List *names, const char *constrName,
  */
 ObjectAddress
 AlterDomainAddConstraint(List *names, Node *newConstraint,
-						 ObjectAddress *constrAddr)
+						 ObjectAddress *constrAddr, const char *querystring)
 {
 	TypeName   *typename;
 	Oid			domainoid;
@@ -2913,10 +2913,13 @@ AlterDomainAddConstraint(List *names, Node *newConstraint,
 	Constraint *constr;
 	char	   *ccbin;
 	ObjectAddress address = InvalidObjectAddress;
+	ParseState 	*pstate;
+	pstate = make_parsestate(NULL);
+	pstate->p_sourcetext = querystring;
 
 	/* Make a TypeName so we can use standard type lookup machinery */
 	typename = makeTypeNameFromNameList(names);
-	domainoid = typenameTypeId(NULL, typename);
+	domainoid = typenameTypeId(pstate, typename);
 
 	/* Look up the domain in the type table */
 	typrel = table_open(TypeRelationId, RowExclusiveLock);
@@ -2935,51 +2938,10 @@ AlterDomainAddConstraint(List *names, Node *newConstraint,
 
 	constr = (Constraint *) newConstraint;
 
-	switch (constr->contype)
-	{
-		case CONSTR_CHECK:
-		case CONSTR_NOTNULL:
-			/* 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);
-			break;
-	}
+	if (constr->contype != CONSTR_CHECK && constr->contype !=  CONSTR_NOTNULL)
+		ereport(ERROR,
+				errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				errmsg("domain only support CHECK and NOT-NULL constraints"));
 
 	if (constr->contype == CONSTR_CHECK)
 	{
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 67eb96396a..573f2e8643 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -4313,7 +4313,7 @@ DomainConstraint:
 		;
 
 DomainConstraintElem:
-			CHECK '(' a_expr ')' ConstraintAttributeSpec
+			CHECK '(' a_expr ')'
 				{
 					Constraint *n = makeNode(Constraint);
 
@@ -4321,23 +4321,28 @@ DomainConstraintElem:
 					n->location = @1;
 					n->raw_expr = $3;
 					n->cooked_expr = NULL;
-					processCASbits($5, @5, "CHECK",
-								   NULL, NULL, &n->skip_validation,
-								   &n->is_no_inherit, yyscanner);
-					n->initially_valid = !n->skip_validation;
+					n->initially_valid = true;
 					$$ = (Node *) n;
 				}
-			| NOT NULL_P ConstraintAttributeSpec
+			| CHECK '(' a_expr ')' NOT VALID
+				{
+					Constraint *n = makeNode(Constraint);
+
+					n->contype = CONSTR_CHECK;
+					n->location = @1;
+					n->raw_expr = $3;
+					n->cooked_expr = NULL;
+					n->initially_valid = false;
+					n->skip_validation = true;
+					$$ = (Node *) n;
+				}
+			| NOT NULL_P
 				{
 					Constraint *n = makeNode(Constraint);
 
 					n->contype = CONSTR_NOTNULL;
 					n->location = @1;
 					n->keys = list_make1(makeString("value"));
-					/* no NOT VALID, NO INHERIT support */
-					processCASbits($3, @3, "NOT NULL",
-								   NULL, NULL, NULL,
-								   NULL, yyscanner);
 					n->initially_valid = true;
 					$$ = (Node *) n;
 				}
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index f28bf37105..38bb99a750 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1367,7 +1367,8 @@ ProcessUtilitySlow(ParseState *pstate,
 							address =
 								AlterDomainAddConstraint(stmt->typeName,
 														 stmt->def,
-														 &secondaryObject);
+														 &secondaryObject,
+														 queryString);
 							break;
 						case 'X':	/* DROP CONSTRAINT */
 							address =
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index e1b02927c4..76b2528b36 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -35,7 +35,7 @@ extern Oid	AssignTypeMultirangeArrayOid(void);
 extern ObjectAddress AlterDomainDefault(List *names, Node *defaultRaw);
 extern ObjectAddress AlterDomainNotNull(List *names, bool notNull);
 extern ObjectAddress AlterDomainAddConstraint(List *names, Node *newConstraint,
-											  ObjectAddress *constrAddr);
+											  ObjectAddress *constrAddr, const char* querstring);
 extern ObjectAddress AlterDomainValidateConstraint(List *names, const char *constrName);
 extern ObjectAddress AlterDomainDropConstraint(List *names, const char *constrName,
 											   DropBehavior behavior, bool missing_ok);
-- 
2.34.1

