From 064d0422c7d918ce2c6201bdfa2fbf9c62f9ec53 Mon Sep 17 00:00:00 2001 From: Alessandro Magistroni <65421435+AMagistroni@users.noreply.github.com> Date: Mon, 13 Sep 2021 16:23:51 +0200 Subject: [PATCH] drop constraint --- SqlSchemaCompare.Core/DbStructures/Table.cs | 1 + .../TSql/Factory/TSqlTableFactory.cs | 11 ++--- .../TSql/TSqlSchemaBuilder.cs | 33 ++++++++++++--- SqlSchemaCompare.Test/TSql/TSqlTableTest.cs | 40 ++++++++++++++++++- 4 files changed, 73 insertions(+), 12 deletions(-) diff --git a/SqlSchemaCompare.Core/DbStructures/Table.cs b/SqlSchemaCompare.Core/DbStructures/Table.cs index d76b499..eb7809a 100644 --- a/SqlSchemaCompare.Core/DbStructures/Table.cs +++ b/SqlSchemaCompare.Core/DbStructures/Table.cs @@ -22,6 +22,7 @@ public enum ConstraintTypes public IEnumerable ColumnName { get; init; } public ConstraintTypes ConstraintType { get; init; } public string Value { get; init; } + public Table Table { get; init; } } public IList Columns { get; } = new List(); public IList Constraints { get; } = new List(); diff --git a/SqlSchemaCompare.Core/TSql/Factory/TSqlTableFactory.cs b/SqlSchemaCompare.Core/TSql/Factory/TSqlTableFactory.cs index 2c90600..8fd4e97 100644 --- a/SqlSchemaCompare.Core/TSql/Factory/TSqlTableFactory.cs +++ b/SqlSchemaCompare.Core/TSql/Factory/TSqlTableFactory.cs @@ -30,7 +30,7 @@ public DbObject Create(ParserRuleContext context, ICharStream stream) } else if (columnTree.table_constraint() != null) { - table.AddConstraint(CreatePrimaryKeyConstraint(columnTree.table_constraint(), stream, table.Identifier)); + table.AddConstraint(CreatePrimaryKeyConstraint(columnTree.table_constraint(), stream, table)); } } return table; @@ -49,15 +49,16 @@ private Table.Column CreateColumn(TSqlParser.Column_def_table_constraintContext }; } - public Table.TableConstraint CreatePrimaryKeyConstraint(TSqlParser.Table_constraintContext constraintContext, ICharStream stream, string tableName) + public Table.TableConstraint CreatePrimaryKeyConstraint(TSqlParser.Table_constraintContext constraintContext, ICharStream stream, Table table) { return new Table.TableConstraint { Sql = stream.GetText(new Interval(constraintContext.start.StartIndex, constraintContext.stop.StopIndex)), - Name = constraintContext.id_()[0].GetText(), - ParentName = tableName, + Name = constraintContext.constraint?.GetText(), + ParentName = table.Identifier, ColumnName = constraintContext.column_name_list_with_order().id_().Select(x => x.GetText()), - ConstraintType = Table.TableConstraint.ConstraintTypes.PrimaryKey + ConstraintType = Table.TableConstraint.ConstraintTypes.PrimaryKey, + Table = table }; } diff --git a/SqlSchemaCompare.Core/TSql/TSqlSchemaBuilder.cs b/SqlSchemaCompare.Core/TSql/TSqlSchemaBuilder.cs index 37b78f3..6916f0e 100644 --- a/SqlSchemaCompare.Core/TSql/TSqlSchemaBuilder.cs +++ b/SqlSchemaCompare.Core/TSql/TSqlSchemaBuilder.cs @@ -48,22 +48,43 @@ public string BuildSeparator() { return "GO\r\n"; } - private string BuildTableConstraint(Table.TableConstraint alterTable, Operation operation, ResultProcessDbObject resultProcessDbObject) + private string BuildTableConstraint(Table.TableConstraint constraint, Operation operation, ResultProcessDbObject resultProcessDbObject) { switch (operation) { case Operation.Create: - if (!resultProcessDbObject.GetDbObject(DbObjectType.Column, Operation.Create).Any(x => alterTable.ColumnName.Contains(x.Name))) + if (!resultProcessDbObject.GetDbObject(DbObjectType.Column, Operation.Create).Any(x => constraint.ColumnName.Contains(x.Name))) { - if (alterTable.ConstraintType == Table.TableConstraint.ConstraintTypes.PrimaryKey) + if (constraint.ConstraintType == Table.TableConstraint.ConstraintTypes.PrimaryKey) { - return $"ALTER TABLE ADD {alterTable.Sql}"; + return $"ALTER TABLE {constraint.ParentName} ADD {constraint.Sql}"; } - return alterTable.Sql; + return constraint.Sql; } return string.Empty; case Operation.Drop: - return $"ALTER TABLE {alterTable.ParentName} DROP CONSTRAINT {alterTable.Name}"; + if (String.IsNullOrEmpty(constraint.Name)) + { + var tableSchema = constraint.Table.Schema.Replace("[", "").Replace("]", ""); + var tableName = constraint.Table.Name.Replace("[", "").Replace("]", ""); + return +@$"DECLARE @PrimaryKeyName_{tableSchema}_{tableName} sysname = +( + SELECT CONSTRAINT_NAME + FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS + WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_SCHEMA='{tableSchema}' AND TABLE_NAME = '{tableName}' +) + +IF @PrimaryKeyName_{tableSchema}_{tableName} IS NOT NULL +BEGIN + DECLARE @SQL_PK_{tableSchema}_{tableName} NVARCHAR(MAX) = 'ALTER TABLE {constraint.ParentName} DROP CONSTRAINT ' + @PrimaryKeyName_{tableSchema}_{tableName} + EXEC sp_executesql @SQL_PK_{tableSchema}_{tableName}; +END"; + } + else + { + return $"ALTER TABLE {constraint.ParentName} DROP CONSTRAINT {constraint.Name}"; + } default: throw new NotSupportedException("Alter not supported on schema"); }; diff --git a/SqlSchemaCompare.Test/TSql/TSqlTableTest.cs b/SqlSchemaCompare.Test/TSql/TSqlTableTest.cs index 522ac04..69f59c8 100644 --- a/SqlSchemaCompare.Test/TSql/TSqlTableTest.cs +++ b/SqlSchemaCompare.Test/TSql/TSqlTableTest.cs @@ -470,7 +470,7 @@ ALTER TABLE [dbo].[tbl] WITH CHECK ADD CONSTRAINT [FK_constraint] FOREIGN KEY([c REFERENCES [dbo].[tblLookup] ([ID]) GO -ALTER TABLE ADD CONSTRAINT [PK] PRIMARY KEY CLUSTERED +ALTER TABLE [dbo].[tblLookup] ADD CONSTRAINT [PK] PRIMARY KEY CLUSTERED ( [ID] ASC, [description] DESC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [db] @@ -480,6 +480,44 @@ ALTER TABLE ADD CONSTRAINT [PK] PRIMARY KEY CLUSTERED errors.ShouldBeEmpty(); } + [Fact] + public void DropConstraintWithoutName() + { + const string origin = +@"CREATE TABLE [schema].[tbl]( + [ID] [int] IDENTITY(0,1) NOT NULL) +GO"; + + const string destination = +@"CREATE TABLE [schema].[tbl]( + [ID] [int] IDENTITY(0,1) NOT NULL, +PRIMARY KEY CLUSTERED +( + [ID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [db] +) ON [db] TEXTIMAGE_ON [db] +GO"; + + (string updateSchema, string errors) = UtilityTest.UpdateSchema(origin, destination, SelectedObjects); + + updateSchema.ShouldBe( +@"DECLARE @PrimaryKeyName_schema_tbl sysname = +( + SELECT CONSTRAINT_NAME + FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS + WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_SCHEMA='schema' AND TABLE_NAME = 'tbl' +) + +IF @PrimaryKeyName_schema_tbl IS NOT NULL +BEGIN + DECLARE @SQL_PK_schema_tbl NVARCHAR(MAX) = 'ALTER TABLE [schema].[tbl] DROP CONSTRAINT ' + @PrimaryKeyName_schema_tbl + EXEC sp_executesql @SQL_PK_schema_tbl; +END +GO + +"); + errors.ShouldBeEmpty(); + } [Fact] public void AddColumnAndAddDefaultConstraintOnSameStatement()