From 95a094438efa945e6c41a7ec604ae3d01ca39f16 Mon Sep 17 00:00:00 2001 From: Kim Santiago <31145923+kisantia@users.noreply.github.com> Date: Mon, 26 Jun 2023 14:01:28 -1000 Subject: [PATCH] Fix for schema compare dropping constraints (#2120) * fix for scripts that are displayed in schema compare drop constraints bug * update DacFx version * add more comments --- Packages.props | 2 +- ...chemaCompareIncludeExcludeNodeOperation.cs | 8 ++--- .../SchemaCompare/SchemaCompareOperation.cs | 2 +- .../SchemaCompare/SchemaCompareUtils.cs | 32 ++++++++++++++----- .../SchemaCompareServiceTests.cs | 8 ++--- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/Packages.props b/Packages.props index 1788f1bb..a792e2b9 100644 --- a/Packages.props +++ b/Packages.props @@ -22,7 +22,7 @@ - + diff --git a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareIncludeExcludeNodeOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareIncludeExcludeNodeOperation.cs index 0373f384..1e2f73db 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareIncludeExcludeNodeOperation.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareIncludeExcludeNodeOperation.cs @@ -71,21 +71,21 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare if(this.Parameters.IncludeRequest) { IEnumerable affectedDependencies = this.ComparisonResult.GetIncludeDependencies(node); - this.AffectedDependencies = affectedDependencies.Select(difference => SchemaCompareUtils.CreateDiffEntry(difference: difference, parent: null)).ToList(); + this.AffectedDependencies = affectedDependencies.Select(difference => SchemaCompareUtils.CreateDiffEntry(difference: difference, parent: null, schemaComparisonResult: this.ComparisonResult)).ToList(); } else { // if exclude was successful, the possible affected dependencies are given by GetIncludedDependencies() if(this.Success) { IEnumerable affectedDependencies = this.ComparisonResult.GetIncludeDependencies(node); - this.AffectedDependencies = affectedDependencies.Select(difference => SchemaCompareUtils.CreateDiffEntry(difference: difference, parent: null)).ToList(); + this.AffectedDependencies = affectedDependencies.Select(difference => SchemaCompareUtils.CreateDiffEntry(difference: difference, parent: null, schemaComparisonResult: this.ComparisonResult)).ToList(); } // if not successful, send back the exclude dependencies that caused it to fail else { IEnumerable blockingDependencies = this.ComparisonResult.GetExcludeDependencies(node); blockingDependencies = blockingDependencies.Where(difference => difference.Included == node.Included); - this.BlockingDependencies = blockingDependencies.Select(difference => SchemaCompareUtils.CreateDiffEntry(difference: difference, parent: null)).ToList(); + this.BlockingDependencies = blockingDependencies.Select(difference => SchemaCompareUtils.CreateDiffEntry(difference: difference, parent: null, schemaComparisonResult: this.ComparisonResult)).ToList(); } } @@ -122,7 +122,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare { bool result = true; // Create a diff entry from difference and check if it matches the diff entry passed - DiffEntry entryFromDifference = SchemaCompareUtils.CreateDiffEntry(difference, null); + DiffEntry entryFromDifference = SchemaCompareUtils.CreateDiffEntry(difference, null, schemaComparisonResult: this.ComparisonResult); System.Reflection.PropertyInfo[] properties = diffEntry.GetType().GetProperties(); foreach (var prop in properties) diff --git a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareOperation.cs index 1b20bb38..e0493699 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareOperation.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareOperation.cs @@ -121,7 +121,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare foreach (SchemaDifference difference in this.ComparisonResult.Differences) { - DiffEntry diffEntry = SchemaCompareUtils.CreateDiffEntry(difference, null); + DiffEntry diffEntry = SchemaCompareUtils.CreateDiffEntry(difference, null, this.ComparisonResult); this.Differences.Add(diffEntry); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareUtils.cs b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareUtils.cs index ef8ec253..2c7f91cf 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareUtils.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareUtils.cs @@ -24,7 +24,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare /// internal static partial class SchemaCompareUtils { - internal static DiffEntry CreateDiffEntry(SchemaDifference difference, DiffEntry parent) + internal static DiffEntry CreateDiffEntry(SchemaDifference difference, DiffEntry parent, SchemaComparisonResult schemaComparisonResult) { if (difference == null) { @@ -56,15 +56,31 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare // set source and target scripts if (difference.SourceObject != null) { - string sourceScript; - difference.SourceObject.TryGetScript(out sourceScript); - diffEntry.SourceScript = FormatScript(sourceScript); + string sourceScript = schemaComparisonResult.GetDiffEntrySourceScript(difference); + + // Child scripts that do not use alter need to be added if they are being changed, ex: "EXECUTE sp_addextendedproperty...". + // Don't add scripts that start with alter because those are handled by a top level element's create + // ex: if a column changes, then the parent table's script will have the column updated, but GetDiffEntrySourceScript() on the child + // will return an alter table statement for updating that column when getting the child script. The child's alter script is unecessary + // for displaying the script in schema compare because the comparison displays the create scripts + if (!sourceScript.ToLowerInvariant().StartsWith("alter")) + { + diffEntry.SourceScript = FormatScript(sourceScript); + } } if (difference.TargetObject != null) { - string targetScript; - difference.TargetObject.TryGetScript(out targetScript); - diffEntry.TargetScript = FormatScript(targetScript); + string targetScript = schemaComparisonResult.GetDiffEntryTargetScript(difference); + + // Child scripts that do not use alter need to be added if they are being changed, ex: "EXECUTE sp_addextendedproperty...". + // Don't add scripts that start with alter because those are handled by a top level element's create + // ex: if a column changes, then the parent table's script will have the column updated, but GetDiffEntrySourceScript() on the child + // will return an alter table script for updating that column when getting the child script. The child's alter script is unecessary + // for displaying the script in schema compare because the comparison displays the create scripts + if (!targetScript.ToLowerInvariant().StartsWith("alter")) + { + diffEntry.TargetScript = FormatScript(targetScript); + } } } @@ -72,7 +88,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare foreach (SchemaDifference child in difference.Children) { - diffEntry.Children.Add(CreateDiffEntry(child, diffEntry)); + diffEntry.Children.Add(CreateDiffEntry(child, diffEntry, schemaComparisonResult)); } return diffEntry; diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/SchemaCompareServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/SchemaCompareServiceTests.cs index a803e7c5..e28967f1 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/SchemaCompareServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/SchemaCompareServiceTests.cs @@ -1568,7 +1568,7 @@ WITH VALUES Assert.IsNull(schemaCompareOperation.ErrorMessage); // try to exclude - DiffEntry t2Diff = SchemaCompareUtils.CreateDiffEntry(schemaCompareOperation.ComparisonResult.Differences.Where(x => x.SourceObject != null && x.SourceObject.Name.Parts[1] == "t2").First(), null); + DiffEntry t2Diff = SchemaCompareUtils.CreateDiffEntry(schemaCompareOperation.ComparisonResult.Differences.Where(x => x.SourceObject != null && x.SourceObject.Name.Parts[1] == "t2").First(), null, schemaCompareOperation.ComparisonResult); SchemaCompareNodeParams t2ExcludeParams = new SchemaCompareNodeParams() { OperationId = schemaCompareOperation.OperationId, @@ -1585,7 +1585,7 @@ WITH VALUES Assert.True(t2ExcludeOperation.BlockingDependencies[0].SourceValue[1] == "v1", "Dependency should be View v1"); // exclude view v1, then t2 should also get excluded by this - DiffEntry v1Diff = SchemaCompareUtils.CreateDiffEntry(schemaCompareOperation.ComparisonResult.Differences.Where(x => x.SourceObject != null && x.SourceObject.Name.Parts[1] == "v1").First(), null); + DiffEntry v1Diff = SchemaCompareUtils.CreateDiffEntry(schemaCompareOperation.ComparisonResult.Differences.Where(x => x.SourceObject != null && x.SourceObject.Name.Parts[1] == "v1").First(), null, schemaCompareOperation.ComparisonResult); SchemaCompareNodeParams v1ExcludeParams = new SchemaCompareNodeParams() { OperationId = schemaCompareOperation.OperationId, @@ -1712,7 +1712,7 @@ WITH VALUES } // create Diff Entry from Difference - DiffEntry diff = SchemaCompareUtils.CreateDiffEntry(schemaCompareOperation.ComparisonResult.Differences.First(), null); + DiffEntry diff = SchemaCompareUtils.CreateDiffEntry(schemaCompareOperation.ComparisonResult.Differences.First(), null, schemaCompareOperation.ComparisonResult); int initial = schemaCompareOperation.ComparisonResult.Differences.Count(); SchemaCompareNodeParams schemaCompareExcludeNodeParams = new SchemaCompareNodeParams() @@ -1761,7 +1761,7 @@ WITH VALUES string initialScript = generateScriptOperation.ScriptGenerationResult.Script; // create Diff Entry from on Difference - DiffEntry diff = SchemaCompareUtils.CreateDiffEntry(schemaCompareOperation.ComparisonResult.Differences.First(), null); + DiffEntry diff = SchemaCompareUtils.CreateDiffEntry(schemaCompareOperation.ComparisonResult.Differences.First(), null, schemaCompareOperation.ComparisonResult); //Validate Diff Entry creation for object type ValidateDiffEntryCreation(diff, schemaCompareOperation.ComparisonResult.Differences.First());