Repository: ariga/atlas
Pull request #2674 (2024-04-12 05:34:09)

sql/postgres: add not-valid clause to checks/fks


Patch:
diff --git a/sql/postgres/inspect.go b/sql/postgres/inspect.go
index cb094763..1df32566 100644
--- a/sql/postgres/inspect.go
+++ b/sql/postgres/inspect.go
@@ -1066,6 +1066,12 @@ type (
 		schema.Clause
 	}
 
+	// NotValid describes the NOT VALID clause for the creation
+	// of check and foreign-key constraints.
+	NotValid struct {
+		schema.Clause
+	}
+
 	// NoInherit attribute defines the NO INHERIT flag for CHECK constraint.
 	// https://postgresql.org/docs/current/catalog-pg-constraint.html
 	NoInherit struct {
diff --git a/sql/postgres/migrate.go b/sql/postgres/migrate.go
index 0250632c..f72ce261 100644
--- a/sql/postgres/migrate.go
+++ b/sql/postgres/migrate.go
@@ -551,14 +551,19 @@ func (s *state) alterTable(t *schema.Table, changes []schema.Change) error {
 				b.P("DROP CONSTRAINT").Ident(pkName(t, change.P))
 				reverse = append(reverse, &schema.AddPrimaryKey{P: change.P})
 			case *schema.AddForeignKey:
-				b.P("ADD")
-				s.fks(b, change.F)
+				s.fks(b.P("ADD"), change.F)
+				if sqlx.Has(change.Extra, &NotValid{}) {
+					b.P("NOT VALID")
+				}
 				reverse = append(reverse, &schema.DropForeignKey{F: change.F})
 			case *schema.DropForeignKey:
 				b.P("DROP CONSTRAINT").Ident(change.F.Symbol)
 				reverse = append(reverse, &schema.AddForeignKey{F: change.F})
 			case *schema.AddCheck:
 				check(b.P("ADD"), change.C)
+				if sqlx.Has(change.Extra, &NotValid{}) {
+					b.P("NOT VALID")
+				}
 				// Reverse operation is supported if
 				// the constraint name is not generated.
 				if reversible = reversible && change.C.Name != ""; reversible {
diff --git a/sql/schema/migrate.go b/sql/schema/migrate.go
index 2d37c887..f91eafbf 100644
--- a/sql/schema/migrate.go
+++ b/sql/schema/migrate.go
@@ -273,7 +273,8 @@ type (
 
 	// AddForeignKey describes a foreign-key creation change.
 	AddForeignKey struct {
-		F *ForeignKey
+		F     *ForeignKey
+		Extra []Clause // Extra clauses and options.
 	}
 
 	// DropForeignKey describes a foreign-key removal change.
@@ -289,7 +290,8 @@ type (
 
 	// AddCheck describes a CHECK constraint creation change.
 	AddCheck struct {
-		C *Check
+		C     *Check
+		Extra []Clause // Extra clauses and options.
 	}
 
 	// DropCheck describes a CHECK constraint removal change.


Test patch:
diff --git a/sql/postgres/migrate_test.go b/sql/postgres/migrate_test.go
index 0b0f81f0..38ede5fd 100644
--- a/sql/postgres/migrate_test.go
+++ b/sql/postgres/migrate_test.go
@@ -596,6 +596,10 @@ func TestPlanChanges(t *testing.T) {
 							&schema.AddCheck{
 								C: &schema.Check{Name: "name_not_empty", Expr: `("name" <> '')`},
 							},
+							&schema.AddCheck{
+								C:     &schema.Check{Name: "positive_id", Expr: `("id" > 0)`},
+								Extra: []schema.Clause{&NotValid{}},
+							},
 							&schema.DropCheck{
 								C: &schema.Check{Name: "id_nonzero", Expr: `("id" <> 0)`},
 							},
@@ -686,8 +690,8 @@ func TestPlanChanges(t *testing.T) {
 						Reverse: `CREATE INDEX CONCURRENTLY "drop_con" ON "users" ("id")`,
 					},
 					{
-						Cmd:     `ALTER TABLE "users" DROP CONSTRAINT "id_nonzero", ADD COLUMN "name" character varying(255) NOT NULL DEFAULT 'logged_in', ADD COLUMN "last" character varying(255) NOT NULL DEFAULT 'logged_in', ADD CONSTRAINT "name_not_empty" CHECK ("name" <> ''), DROP CONSTRAINT "id_iseven", ADD CONSTRAINT "id_iseven" CHECK (("id") % 2 = 0)`,
-						Reverse: `ALTER TABLE "users" DROP CONSTRAINT "id_iseven", ADD CONSTRAINT "id_iseven" CHECK ("id" % 2 = 0), DROP CONSTRAINT "name_not_empty", DROP COLUMN "last", DROP COLUMN "name", ADD CONSTRAINT "id_nonzero" CHECK ("id" <> 0)`,
+						Cmd:     `ALTER TABLE "users" DROP CONSTRAINT "id_nonzero", ADD COLUMN "name" character varying(255) NOT NULL DEFAULT 'logged_in', ADD COLUMN "last" character varying(255) NOT NULL DEFAULT 'logged_in', ADD CONSTRAINT "name_not_empty" CHECK ("name" <> ''), ADD CONSTRAINT "positive_id" CHECK ("id" > 0) NOT VALID, DROP CONSTRAINT "id_iseven", ADD CONSTRAINT "id_iseven" CHECK (("id") % 2 = 0)`,
+						Reverse: `ALTER TABLE "users" DROP CONSTRAINT "id_iseven", ADD CONSTRAINT "id_iseven" CHECK ("id" % 2 = 0), DROP CONSTRAINT "positive_id", DROP CONSTRAINT "name_not_empty", DROP COLUMN "last", DROP COLUMN "name", ADD CONSTRAINT "id_nonzero" CHECK ("id" <> 0)`,
 					},
 					{
 						Cmd:     `CREATE INDEX "id_key" ON "users" ("id" DESC) WHERE success`,