From 23072250b7aeb867ccfc3f128d7073e4c06bab46 Mon Sep 17 00:00:00 2001 From: Hai Cao Date: Thu, 25 Aug 2022 16:30:47 -0700 Subject: [PATCH] [Table Designer] Add validators for computed col in PK and FK (#1653) --- .../Localization/sr.cs | 16 ++++++ .../Localization/sr.resx | 10 ++++ .../Localization/sr.strings | 4 +- .../Localization/sr.xlf | 12 ++++ .../TableDesigner/TableDesignerValidator.cs | 55 ++++++++++++++++++- 5 files changed, 95 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs index 57f8a752..f1753057 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs @@ -9804,6 +9804,16 @@ namespace Microsoft.SqlTools.ServiceLayer return Keys.GetString(Keys.ColumnCannotDuplicateWitIndexKeyColumnsRuleDescription, columnName, indexName, rowNumber); } + public static string ComputedColumnNeedToBePersistedAndNotNullInPrimaryKeyRuleDescription(string columnName) + { + return Keys.GetString(Keys.ComputedColumnNeedToBePersistedAndNotNullInPrimaryKeyRuleDescription, columnName); + } + + public static string ComputedColumnNeedToBePersistedInForeignKeyRuleDescription(string columnName, string foreignKeyName) + { + return Keys.GetString(Keys.ComputedColumnNeedToBePersistedInForeignKeyRuleDescription, columnName, foreignKeyName); + } + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Keys { @@ -13562,6 +13572,12 @@ namespace Microsoft.SqlTools.ServiceLayer public const string ColumnCannotDuplicateWitIndexKeyColumnsRuleDescription = "ColumnCannotDuplicateWitIndexKeyColumnsRuleDescription"; + public const string ComputedColumnNeedToBePersistedAndNotNullInPrimaryKeyRuleDescription = "ComputedColumnNeedToBePersistedAndNotNullInPrimaryKeyRuleDescription"; + + + public const string ComputedColumnNeedToBePersistedInForeignKeyRuleDescription = "ComputedColumnNeedToBePersistedInForeignKeyRuleDescription"; + + private Keys() { } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx index 21fd7ee7..21d4d2b4 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx @@ -5196,4 +5196,14 @@ The Query Processor estimates that implementing the following index could improv . Parameters: 0 - columnName (string), 1 - indexName (string), 2 - rowNumber (int) + + The computed column with name '{0}' has to be persisted and not nullable to be part of a primary key. + . + Parameters: 0 - columnName (string) + + + The computed column with name '{0}' has to be persisted to be part of the foreign key '{1}'. + . + Parameters: 0 - columnName (string), 1 - foreignKeyName (string) + diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings index cc825486..466e7ad8 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings @@ -2379,4 +2379,6 @@ MutipleCreateTableStatementsInScriptRuleDescription = There are multiple table d ClusteredIndexCannotHaveIncludedColumnsRuleDescription = Included columns are not supported for a clustered index. ClusteredIndexCannotHaveFilterPredicateRuleDescription = Filter predicate is not supported for a clustered index. ColumnCanOnlyAppearOnceInIndexIncludedColumnsRuleDescription(string columnName, string indexName, int rowNumber) = Column with name '{0}' has already been included to the index '{1}'. Row number: {2}. -ColumnCannotDuplicateWitIndexKeyColumnsRuleDescription(string columnName, string indexName, int rowNumber) = Included column with name '{0}' has already been part of the index '{1}' and it cannot be included. Row number: {2}. \ No newline at end of file +ColumnCannotDuplicateWitIndexKeyColumnsRuleDescription(string columnName, string indexName, int rowNumber) = Included column with name '{0}' has already been part of the index '{1}' and it cannot be included. Row number: {2}. +ComputedColumnNeedToBePersistedAndNotNullInPrimaryKeyRuleDescription(string columnName) = The computed column with name '{0}' has to be persisted and not nullable to be part of a primary key. +ComputedColumnNeedToBePersistedInForeignKeyRuleDescription(string columnName, string foreignKeyName) = The computed column with name '{0}' has to be persisted to be part of the foreign key '{1}'. \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf index c51e3949..2611c891 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf @@ -6331,6 +6331,18 @@ The Query Processor estimates that implementing the following index could improv Dropped Ledger Views + + The computed column with name '{0}' has to be persisted and not nullable to be part of a primary key. + The computed column with name '{0}' has to be persisted and not nullable to be part of a primary key. + . + Parameters: 0 - columnName (string) + + + The computed column with name '{0}' has to be persisted to be part of the foreign key '{1}'. + The computed column with name '{0}' has to be persisted to be part of the foreign key '{1}'. + . + Parameters: 0 - columnName (string), 1 - foreignKeyName (string) + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerValidator.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerValidator.cs index 767538b7..7facb18e 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerValidator.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerValidator.cs @@ -37,7 +37,9 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner new ClusteredIndexCannotHaveFilterPredicate(), new ClusteredIndexCannotHaveIncludedColumnsRule(), new ColumnCanOnlyAppearOnceInIndexIncludedColumnsRule(), - new ColumnCannotDuplicateWitIndexKeyColumnsRule() + new ColumnCannotDuplicateWitIndexKeyColumnsRule(), + new ComputedColumnNeedToBePersistedAndNotNullInPrimaryKeyRule(), + new ComputedColumnNeedToBePersistedInForeignKeyRule() }; /// @@ -664,6 +666,57 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner } } + public class ComputedColumnNeedToBePersistedAndNotNullInPrimaryKeyRule : ITableDesignerValidationRule + { + public List Run(Dac.TableDesigner designer) + { + var table = designer.TableViewModel; + var errors = new List(); + if (table.PrimaryKey != null) + { + for (int i = 0; i < table.PrimaryKey.Columns.Count; i++) + { + var columnSpec = table.PrimaryKey.Columns[i]; + var col = table.Columns.Items.First(item => item.Name == columnSpec.Column); + if (col != null && col.IsComputed && !(col.IsComputedPersisted == true && col.IsComputedPersistedNullable == false)) + { + errors.Add(new TableDesignerIssue() + { + Description = SR.ComputedColumnNeedToBePersistedAndNotNullInPrimaryKeyRuleDescription(col.Name), + PropertyPath = new object[] { TablePropertyNames.PrimaryKeyColumns, i, IndexColumnSpecificationPropertyNames.Column } + }); + } + } + } + return errors; + } + } + + public class ComputedColumnNeedToBePersistedInForeignKeyRule : ITableDesignerValidationRule + { + public List Run(Dac.TableDesigner designer) + { + var table = designer.TableViewModel; + var errors = new List(); + for (int i = 0; i < table.ForeignKeys.Items.Count; i++) + { + for (int j = 0; j < table.ForeignKeys.Items[i].Columns.Count; j++) + { + var col = table.Columns.Items.First(item => item.Name == table.ForeignKeys.Items[i].Columns[j]); + if (col != null && col.IsComputed && col.IsComputedPersisted != true) + { + errors.Add(new TableDesignerIssue() + { + Description = SR.ComputedColumnNeedToBePersistedInForeignKeyRuleDescription(col.Name, table.ForeignKeys.Items[i].SystemName), + PropertyPath = new object[] { TablePropertyNames.ForeignKeys, i, ForeignKeyPropertyNames.ColumnMapping, j, ForeignKeyColumnMappingPropertyNames.Column } + }); + } + } + } + return errors; + } + } + public class MemoryOptimizedCannotBeEnabledWhenNotSupportedRule : ITableDesignerValidationRule { public List Run(Dac.TableDesigner designer)