From: Peter Eisentraut Date: Thu, 5 Jan 2012 17:48:55 +0000 (+0200) Subject: Improve ALTER DOMAIN / DROP CONSTRAINT with nonexistent constraint X-Git-Tag: REL9_2_BETA1~618 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=104e7dac28c56dcaf9b778dff60a5daefc3a0661;p=postgresql Improve ALTER DOMAIN / DROP CONSTRAINT with nonexistent constraint ALTER DOMAIN / DROP CONSTRAINT on a nonexistent constraint name did not report any error. Now it reports an error. The IF EXISTS option was added to get the usual behavior of ignoring nonexistent objects to drop. --- diff --git a/doc/src/sgml/ref/alter_domain.sgml b/doc/src/sgml/ref/alter_domain.sgml index 29504ccd7c..2511a125d3 100644 --- a/doc/src/sgml/ref/alter_domain.sgml +++ b/doc/src/sgml/ref/alter_domain.sgml @@ -30,7 +30,7 @@ ALTER DOMAIN name ALTER DOMAIN name ADD domain_constraint [ NOT VALID ] ALTER DOMAIN name - DROP CONSTRAINT constraint_name [ RESTRICT | CASCADE ] + DROP CONSTRAINT [ IF EXISTS ] constraint_name [ RESTRICT | CASCADE ] ALTER DOMAIN name VALIDATE CONSTRAINT constraint_name ALTER DOMAIN name @@ -92,10 +92,12 @@ ALTER DOMAIN name - DROP CONSTRAINT + DROP CONSTRAINT [ IF EXISTS ] This form drops constraints on a domain. + If IF EXISTS is specified and the constraint + does not exist, no error is thrown. In this case a notice is issued instead. diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 4bbbaf36c9..0f8af31fee 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -2264,7 +2264,7 @@ AlterDomainNotNull(List *names, bool notNull) */ void AlterDomainDropConstraint(List *names, const char *constrName, - DropBehavior behavior) + DropBehavior behavior, bool missing_ok) { TypeName *typename; Oid domainoid; @@ -2274,6 +2274,7 @@ AlterDomainDropConstraint(List *names, const char *constrName, SysScanDesc conscan; ScanKeyData key[1]; HeapTuple contup; + bool found = false; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); @@ -2317,6 +2318,7 @@ AlterDomainDropConstraint(List *names, const char *constrName, conobj.objectSubId = 0; performDeletion(&conobj, behavior); + found = true; } } /* Clean up after the scan */ @@ -2324,6 +2326,19 @@ AlterDomainDropConstraint(List *names, const char *constrName, heap_close(conrel, RowExclusiveLock); heap_close(rel, NoLock); + + if (!found) + { + if (!missing_ok) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("constraint \"%s\" of domain \"%s\" does not exist", + constrName, TypeNameToString(typename)))); + else + ereport(NOTICE, + (errmsg("constraint \"%s\" of domain \"%s\" does not exist, skipping", + constrName, TypeNameToString(typename)))); + } } /* diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index c9d3e2ee51..756e3a689b 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -2568,6 +2568,7 @@ _copyAlterDomainStmt(const AlterDomainStmt *from) COPY_STRING_FIELD(name); COPY_NODE_FIELD(def); COPY_SCALAR_FIELD(behavior); + COPY_SCALAR_FIELD(missing_ok); return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index efe2c96fea..9eff42f707 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1034,6 +1034,7 @@ _equalAlterDomainStmt(const AlterDomainStmt *a, const AlterDomainStmt *b) COMPARE_STRING_FIELD(name); COMPARE_NODE_FIELD(def); COMPARE_SCALAR_FIELD(behavior); + COMPARE_SCALAR_FIELD(missing_ok); return true; } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 29df0c16b3..87d7305c76 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -7616,6 +7616,18 @@ AlterDomainStmt: n->typeName = $3; n->name = $6; n->behavior = $7; + n->missing_ok = false; + $$ = (Node *)n; + } + /* ALTER DOMAIN DROP CONSTRAINT IF EXISTS [RESTRICT|CASCADE] */ + | ALTER DOMAIN_P any_name DROP CONSTRAINT IF_P EXISTS name opt_drop_behavior + { + AlterDomainStmt *n = makeNode(AlterDomainStmt); + n->subtype = 'X'; + n->typeName = $3; + n->name = $8; + n->behavior = $9; + n->missing_ok = true; $$ = (Node *)n; } /* ALTER DOMAIN VALIDATE CONSTRAINT */ diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 923da6a3f3..704bbe9ced 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -768,7 +768,8 @@ standard_ProcessUtility(Node *parsetree, case 'X': /* DROP CONSTRAINT */ AlterDomainDropConstraint(stmt->typeName, stmt->name, - stmt->behavior); + stmt->behavior, + stmt->missing_ok); break; case 'V': /* VALIDATE CONSTRAINT */ AlterDomainValidateConstraint(stmt->typeName, diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h index 11d05b894f..3748bd56af 100644 --- a/src/include/commands/typecmds.h +++ b/src/include/commands/typecmds.h @@ -33,7 +33,7 @@ extern void AlterDomainNotNull(List *names, bool notNull); extern void AlterDomainAddConstraint(List *names, Node *constr); extern void AlterDomainValidateConstraint(List *names, char *constrName); extern void AlterDomainDropConstraint(List *names, const char *constrName, - DropBehavior behavior); + DropBehavior behavior, bool missing_ok); extern List *GetDomainConstraints(Oid typeOid); diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index bee0e1883f..0be3fb1174 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1264,6 +1264,7 @@ typedef struct AlterDomainStmt char *name; /* column or constraint name to act on */ Node *def; /* definition of default or constraint */ DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */ + bool missing_ok; /* skip error if missing? */ } AlterDomainStmt; diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out index 3e44e3b533..4f47374b5d 100644 --- a/src/test/regress/expected/domain.out +++ b/src/test/regress/expected/domain.out @@ -358,6 +358,10 @@ alter domain con drop constraint t; insert into domcontest values (-5); --fails ERROR: value for domain con violates check constraint "con_check" insert into domcontest values (42); +alter domain con drop constraint nonexistent; +ERROR: constraint "nonexistent" of domain "con" does not exist +alter domain con drop constraint if exists nonexistent; +NOTICE: constraint "nonexistent" of domain "con" does not exist, skipping -- Test ALTER DOMAIN .. CONSTRAINT .. NOT VALID create domain things AS INT; CREATE TABLE thethings (stuff things); diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql index 1fd39008e6..ad049b7ba5 100644 --- a/src/test/regress/sql/domain.sql +++ b/src/test/regress/sql/domain.sql @@ -259,6 +259,9 @@ alter domain con drop constraint t; insert into domcontest values (-5); --fails insert into domcontest values (42); +alter domain con drop constraint nonexistent; +alter domain con drop constraint if exists nonexistent; + -- Test ALTER DOMAIN .. CONSTRAINT .. NOT VALID create domain things AS INT; CREATE TABLE thethings (stuff things);