diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
index 31c6f8b2..9adff211 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
@@ -8797,6 +8797,54 @@ namespace Microsoft.SqlTools.ServiceLayer
}
}
+ public static string IndexIncludedColumnsGroupTitle
+ {
+ get
+ {
+ return Keys.GetString(Keys.IndexIncludedColumnsGroupTitle);
+ }
+ }
+
+ public static string IndexIncludedColumnsPropertyDescription
+ {
+ get
+ {
+ return Keys.GetString(Keys.IndexIncludedColumnsPropertyDescription);
+ }
+ }
+
+ public static string IndexIncludedColumnsAddColumn
+ {
+ get
+ {
+ return Keys.GetString(Keys.IndexIncludedColumnsAddColumn);
+ }
+ }
+
+ public static string IndexIncludedColumnsColumnPropertyName
+ {
+ get
+ {
+ return Keys.GetString(Keys.IndexIncludedColumnsColumnPropertyName);
+ }
+ }
+
+ public static string IndexFilterPredicatePropertyDescription
+ {
+ get
+ {
+ return Keys.GetString(Keys.IndexFilterPredicatePropertyDescription);
+ }
+ }
+
+ public static string IndexFilterPredicatePropertyTitle
+ {
+ get
+ {
+ return Keys.GetString(Keys.IndexFilterPredicatePropertyTitle);
+ }
+ }
+
public static string TableDesignerColumnsDisplayValueTitle
{
get
@@ -9349,6 +9397,22 @@ namespace Microsoft.SqlTools.ServiceLayer
}
}
+ public static string ClusteredIndexCannotHaveIncludedColumnsRuleDescription
+ {
+ get
+ {
+ return Keys.GetString(Keys.ClusteredIndexCannotHaveIncludedColumnsRuleDescription);
+ }
+ }
+
+ public static string ClusteredIndexCannotHaveFilterPredicateRuleDescription
+ {
+ get
+ {
+ return Keys.GetString(Keys.ClusteredIndexCannotHaveFilterPredicateRuleDescription);
+ }
+ }
+
public static string ConnectionServiceListDbErrorNotConnected(string uri)
{
return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri);
@@ -9714,6 +9778,16 @@ namespace Microsoft.SqlTools.ServiceLayer
return Keys.GetString(Keys.ColumnCannotBeListedMoreThanOnceInPrimaryKeyRuleDescription, columnName);
}
+ public static string ColumnCanOnlyAppearOnceInIndexIncludedColumnsRuleDescription(string columnName, string indexName, int rowNumber)
+ {
+ return Keys.GetString(Keys.ColumnCanOnlyAppearOnceInIndexIncludedColumnsRuleDescription, columnName, indexName, rowNumber);
+ }
+
+ public static string ColumnCannotDuplicateWitIndexKeyColumnsRuleDescription(string columnName, string indexName, int rowNumber)
+ {
+ return Keys.GetString(Keys.ColumnCannotDuplicateWitIndexKeyColumnsRuleDescription, columnName, indexName, rowNumber);
+ }
+
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Keys
{
@@ -13196,6 +13270,24 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string IndexColumnIsAscendingPropertyTitle = "IndexColumnIsAscendingPropertyTitle";
+ public const string IndexIncludedColumnsGroupTitle = "IndexIncludedColumnsGroupTitle";
+
+
+ public const string IndexIncludedColumnsPropertyDescription = "IndexIncludedColumnsPropertyDescription";
+
+
+ public const string IndexIncludedColumnsAddColumn = "IndexIncludedColumnsAddColumn";
+
+
+ public const string IndexIncludedColumnsColumnPropertyName = "IndexIncludedColumnsColumnPropertyName";
+
+
+ public const string IndexFilterPredicatePropertyDescription = "IndexFilterPredicatePropertyDescription";
+
+
+ public const string IndexFilterPredicatePropertyTitle = "IndexFilterPredicatePropertyTitle";
+
+
public const string TableDesignerColumnsDisplayValueTitle = "TableDesignerColumnsDisplayValueTitle";
@@ -13436,6 +13528,18 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string MutipleCreateTableStatementsInScriptRuleDescription = "MutipleCreateTableStatementsInScriptRuleDescription";
+ public const string ClusteredIndexCannotHaveIncludedColumnsRuleDescription = "ClusteredIndexCannotHaveIncludedColumnsRuleDescription";
+
+
+ public const string ClusteredIndexCannotHaveFilterPredicateRuleDescription = "ClusteredIndexCannotHaveFilterPredicateRuleDescription";
+
+
+ public const string ColumnCanOnlyAppearOnceInIndexIncludedColumnsRuleDescription = "ColumnCanOnlyAppearOnceInIndexIncludedColumnsRuleDescription";
+
+
+ public const string ColumnCannotDuplicateWitIndexKeyColumnsRuleDescription = "ColumnCannotDuplicateWitIndexKeyColumnsRuleDescription";
+
+
private Keys()
{ }
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
index 118bcc61..30a0d870 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
@@ -4815,6 +4815,30 @@ The Query Processor estimates that implementing the following index could improv
Is Ascending
+
+ Included Columns
+
+
+
+ The included columns of the index
+
+
+
+ Add Column
+
+
+
+ Column
+
+
+
+ Filter predicate of the index
+
+
+
+ Filter Predicate
+
+
Columns
@@ -5146,4 +5170,22 @@ The Query Processor estimates that implementing the following index could improv
There are multiple table definitions in the script, only the first table can be edited in the designer.
+
+ Included columns are not supported for a clustered index.
+
+
+
+ Filter predicate is not supported for a clustered index.
+
+
+
+ Column with name '{0}' has already been included to the index '{1}'. Row number: {2}.
+ .
+ Parameters: 0 - columnName (string), 1 - indexName (string), 2 - rowNumber (int)
+
+
+ Included column with name '{0}' has already been part of the index '{1}' and it cannot be included. Row number: {2}.
+ .
+ Parameters: 0 - columnName (string), 1 - indexName (string), 2 - rowNumber (int)
+
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
index 1ac60e70..6ce2b1d0 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
@@ -2286,6 +2286,12 @@ IndexIsUniquePropertyDescription = Whether the data entered into this index must
TableDesignerIsUniquePropertyTitle = Is Unique
IndexColumnIsAscendingPropertyDescription = Specifies the sort order of the column.
IndexColumnIsAscendingPropertyTitle = Is Ascending
+IndexIncludedColumnsGroupTitle = Included Columns
+IndexIncludedColumnsPropertyDescription = The included columns of the index
+IndexIncludedColumnsAddColumn = Add Column
+IndexIncludedColumnsColumnPropertyName = Column
+IndexFilterPredicatePropertyDescription = Filter predicate of the index
+IndexFilterPredicatePropertyTitle = Filter Predicate
TableDesignerColumnsDisplayValueTitle = Columns
TableDesignerDeleteColumnConfirmationMessage = Removing a column will also remove it from the indexes and foreign keys. Are you sure you want to continue?
TableDesignerGraphTableGroupTitle = Graph Table
@@ -2365,4 +2371,8 @@ MemoryOptimizedTableIdentityColumnRuleDescription = The use of seed and incremen
TableShouldAvoidHavingMultipleEdgeConstraintsRuleDescription = The table has more than one edge constraint on it. This is only useful as a temporary state when modifying existing edge constraints, and should not be used in other cases.
ColumnCannotBeListedMoreThanOnceInPrimaryKeyRuleDescription(string columnName) = Cannot use duplicate column names in primary key, column name: {0}
MemoryOptimizedCannotBeEnabledWhenNotSupportedRuleDescription = Memory-optimized table is not supported for this database.
-MutipleCreateTableStatementsInScriptRuleDescription = There are multiple table definitions in the script, only the first table can be edited in the designer.
\ No newline at end of file
+MutipleCreateTableStatementsInScriptRuleDescription = There are multiple table definitions in the script, only the first table can be edited in the designer.
+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
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
index 48338fe5..7e0720a3 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
@@ -6254,6 +6254,58 @@ The Query Processor estimates that implementing the following index could improv
Average Row Size
+
+ Included Columns
+ Included Columns
+
+
+
+ The included columns of the index
+ The included columns of the index
+
+
+
+ Add Column
+ Add Column
+
+
+
+ Column
+ Column
+
+
+
+ Filter predicate of the index
+ Filter predicate of the index
+
+
+
+ Filter Predicate
+ Filter Predicate
+
+
+
+ Included columns are not supported for a clustered index.
+ Included columns are not supported for a clustered index.
+
+
+
+ Filter predicate is not supported for a clustered index.
+ Filter predicate is not supported for a clustered index.
+
+
+
+ Column with name '{0}' has already been included to the index '{1}'. Row number: {2}.
+ Column with name '{0}' has already been included to the index '{1}'. Row number: {2}.
+ .
+ Parameters: 0 - columnName (string), 1 - indexName (string), 2 - rowNumber (int)
+
+
+ Included column with name '{0}' has already been part of the index '{1}' and it cannot be included. Row number: {2}.
+ Included column with name '{0}' has already been part of the index '{1}' and it cannot be included. Row number: {2}.
+ .
+ Parameters: 0 - columnName (string), 1 - indexName (string), 2 - rowNumber (int)
+ Updatable LedgerUpdatable Ledger
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Constants.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Constants.cs
index b20d8276..310991c4 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Constants.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Constants.cs
@@ -87,6 +87,8 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
public const string IsUnique = "isUnique";
public const string IsClustered = "isClustered";
public const string Columns = "columns";
+ public const string IncludedColumns = "includedColumns";
+ public const string FilterPredicate = "filterPredicate";
public const string ColumnsDisplayValue = "columnsDisplayValue";
}
@@ -96,6 +98,11 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
public const string Ascending = "ascending";
}
+ public static class IndexIncludedColumnSpecificationPropertyNames
+ {
+ public const string Column = "column";
+ }
+
public static class EdgeConstraintPropertyNames
{
public const string Name = "name";
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/IndexViewModel.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/IndexViewModel.cs
index 8b9a5844..394d1271 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/IndexViewModel.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/IndexViewModel.cs
@@ -17,8 +17,10 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
public CheckBoxProperties IsUnique { get; set; } = new CheckBoxProperties();
public InputBoxProperties ColumnsDisplayValue { get; set; } = new InputBoxProperties();
+ public InputBoxProperties FilterPredicate { get; set; } = new InputBoxProperties();
public TableComponentProperties Columns { get; set; } = new TableComponentProperties();
+ public TableComponentProperties IncludedColumns { get; set; } = new TableComponentProperties();
}
public class IndexedColumnSpecification
@@ -27,4 +29,9 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
public CheckBoxProperties Ascending { get; set; } = new CheckBoxProperties();
}
+
+ public class IndexIncludedColumnSpecification
+ {
+ public DropdownProperties Column { get; set; } = new DropdownProperties();
+ }
}
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs
index aaab396c..f1925714 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs
@@ -281,6 +281,9 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
case IndexPropertyNames.Columns:
table.Indexes.Items[indexL1].AddNewColumnSpecification();
break;
+ case IndexPropertyNames.IncludedColumns:
+ table.Indexes.Items[indexL1].AddNewIncludedColumn();
+ break;
default:
break;
}
@@ -358,6 +361,9 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
case IndexPropertyNames.Columns:
table.Indexes.Items[indexL1].RemoveColumnSpecification(indexL2);
break;
+ case IndexPropertyNames.IncludedColumns:
+ table.Indexes.Items[indexL1].RemoveIncludedColumn(indexL2);
+ break;
default:
break;
}
@@ -601,6 +607,9 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
case IndexPropertyNames.Description:
sqlIndex.Description = GetStringValue(newValue);
break;
+ case IndexPropertyNames.FilterPredicate:
+ sqlIndex.FilterPredicate = GetStringValue(newValue);
+ break;
default:
break;
}
@@ -686,6 +695,16 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
break;
}
break;
+ case IndexPropertyNames.IncludedColumns:
+ switch (propertyNameL3)
+ {
+ case IndexIncludedColumnSpecificationPropertyNames.Column:
+ sqlIndex.UpdateIncludedColumn(indexL2, GetStringValue(newValue));
+ break;
+ default:
+ break;
+ }
+ break;
default:
break;
}
@@ -917,6 +936,20 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
columnSpecVM.Column.Values = tableDesigner.GetColumnsForTable(table.FullName).ToList();
indexVM.Columns.Data.Add(columnSpecVM);
}
+
+ indexVM.FilterPredicate.Value = index.FilterPredicate;
+ indexVM.FilterPredicate.Enabled = !index.IsClustered || index.FilterPredicate != null;
+ indexVM.IncludedColumns.Enabled = !index.IsClustered || index.IncludedColumns.Count() > 0;
+ indexVM.IncludedColumns.CanAddRows = !index.IsClustered;
+
+ foreach (var column in index.IncludedColumns)
+ {
+ var includedColumnsVM = new IndexIncludedColumnSpecification();
+ includedColumnsVM.Column.Value = column;
+ includedColumnsVM.Column.Values = tableDesigner.GetColumnsForTable(table.FullName).ToList();
+ indexVM.IncludedColumns.Data.Add(includedColumnsVM);
+ }
+
indexVM.ColumnsDisplayValue.Value = index.ColumnsDisplayValue;
indexVM.ColumnsDisplayValue.Enabled = false;
tableViewModel.Indexes.Data.Add(indexVM);
@@ -1185,6 +1218,43 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
{
Title = SR.TableDesignerIsUniquePropertyTitle
}
+ },
+ new DesignerDataPropertyInfo()
+ {
+ PropertyName = IndexPropertyNames.FilterPredicate,
+ Description = SR.IndexFilterPredicatePropertyDescription,
+ ComponentType = DesignerComponentType.Input,
+ ComponentProperties = new InputBoxProperties()
+ {
+ Title = SR.IndexFilterPredicatePropertyTitle,
+ Width = 200
+ }
+ },
+ new DesignerDataPropertyInfo()
+ {
+ PropertyName = IndexPropertyNames.IncludedColumns,
+ Description = SR.IndexIncludedColumnsPropertyDescription,
+ ComponentType = DesignerComponentType.Table,
+ Group = SR.IndexIncludedColumnsGroupTitle,
+ ComponentProperties = new TableComponentProperties()
+ {
+ AriaLabel = SR.IndexIncludedColumnsGroupTitle,
+ Columns = new List () { IndexIncludedColumnSpecificationPropertyNames.Column},
+ LabelForAddNewButton = SR.IndexIncludedColumnsAddColumn,
+ ItemProperties = new List()
+ {
+ new DesignerDataPropertyInfo()
+ {
+ PropertyName = IndexIncludedColumnSpecificationPropertyNames.Column,
+ ComponentType = DesignerComponentType.Dropdown,
+ ComponentProperties = new DropdownProperties()
+ {
+ Title = SR.IndexIncludedColumnsColumnPropertyName,
+ Width = 150
+ }
+ },
+ }
+ }
}
});
view.IndexTableOptions.PropertiesToDisplay = new List() { IndexPropertyNames.Name, IndexPropertyNames.ColumnsDisplayValue, IndexPropertyNames.IsClustered, IndexPropertyNames.IsUnique };
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerValidator.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerValidator.cs
index 65f5bef0..767538b7 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerValidator.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerValidator.cs
@@ -33,7 +33,11 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
new MemoryOptimizedTableIdentityColumnRule(),
new TableShouldAvoidHavingMultipleEdgeConstraintsRule(),
new ColumnCannotBeListedMoreThanOnceInPrimaryKeyRule(),
- new MutipleCreateTableStatementsInScriptRule()
+ new MutipleCreateTableStatementsInScriptRule(),
+ new ClusteredIndexCannotHaveFilterPredicate(),
+ new ClusteredIndexCannotHaveIncludedColumnsRule(),
+ new ColumnCanOnlyAppearOnceInIndexIncludedColumnsRule(),
+ new ColumnCannotDuplicateWitIndexKeyColumnsRule()
};
///
@@ -77,6 +81,50 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
}
}
+ public class ClusteredIndexCannotHaveIncludedColumnsRule : ITableDesignerValidationRule
+ {
+ public List Run(Dac.TableDesigner designer)
+ {
+ var table = designer.TableViewModel;
+ var errors = new List();
+ for (int i = 0; i < table.Indexes.Items.Count; i++)
+ {
+ var index = table.Indexes.Items[i];
+ if (index.IsClustered && index.IncludedColumns.Count != 0)
+ {
+ errors.Add(new TableDesignerIssue()
+ {
+ Description = SR.ClusteredIndexCannotHaveIncludedColumnsRuleDescription,
+ PropertyPath = new object[] { TablePropertyNames.Indexes, i, IndexPropertyNames.IncludedColumns, 0 }
+ });
+ }
+ }
+ return errors;
+ }
+ }
+
+ public class ClusteredIndexCannotHaveFilterPredicate : ITableDesignerValidationRule
+ {
+ public List Run(Dac.TableDesigner designer)
+ {
+ var table = designer.TableViewModel;
+ var errors = new List();
+ for (int i = 0; i < table.Indexes.Items.Count; i++)
+ {
+ var index = table.Indexes.Items[i];
+ if (index.IsClustered && index.FilterPredicate != null)
+ {
+ errors.Add(new TableDesignerIssue()
+ {
+ Description = SR.ClusteredIndexCannotHaveFilterPredicateRuleDescription,
+ PropertyPath = new object[] { TablePropertyNames.Indexes, i, IndexPropertyNames.FilterPredicate }
+ });
+ }
+ }
+ return errors;
+ }
+ }
+
public class ForeignKeyMustHaveColumnsRule : ITableDesignerValidationRule
{
public List Run(Dac.TableDesigner designer)
@@ -130,6 +178,64 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
}
}
+ public class ColumnCanOnlyAppearOnceInIndexIncludedColumnsRule : ITableDesignerValidationRule
+ {
+ public List Run(Dac.TableDesigner designer)
+ {
+ var table = designer.TableViewModel;
+ var errors = new List();
+ for (int i = 0; i < table.Indexes.Items.Count; i++)
+ {
+ var index = table.Indexes.Items[i];
+ var existingColumns = new HashSet();
+ for (int j = 0; j < index.IncludedColumns.Count; j++)
+ {
+ var col = index.IncludedColumns[j];
+ if (existingColumns.Contains(col))
+ {
+ errors.Add(new TableDesignerIssue()
+ {
+ Description = SR.ColumnCanOnlyAppearOnceInIndexIncludedColumnsRuleDescription(col, index.Name, j + 1),
+ PropertyPath = new object[] { TablePropertyNames.Indexes, i, IndexPropertyNames.IncludedColumns, j }
+ });
+ }
+ else
+ {
+ existingColumns.Add(col);
+ }
+ }
+ }
+ return errors;
+ }
+ }
+
+ public class ColumnCannotDuplicateWitIndexKeyColumnsRule : ITableDesignerValidationRule
+ {
+ public List Run(Dac.TableDesigner designer)
+ {
+ var table = designer.TableViewModel;
+ var errors = new List();
+ for (int i = 0; i < table.Indexes.Items.Count; i++)
+ {
+ var index = table.Indexes.Items[i];
+ var keyCols = new HashSet(index.Columns.Select(s => s.Column));
+ for (int j = 0; j < index.IncludedColumns.Count; j++)
+ {
+ var col = index.IncludedColumns[j];
+ if (keyCols.Contains(col))
+ {
+ errors.Add(new TableDesignerIssue()
+ {
+ Description = SR.ColumnCannotDuplicateWitIndexKeyColumnsRuleDescription(col, index.Name, j + 1),
+ PropertyPath = new object[] { TablePropertyNames.Indexes, i, IndexPropertyNames.IncludedColumns, j }
+ });
+ }
+ }
+ }
+ return errors;
+ }
+ }
+
public class ColumnCanOnlyAppearOnceInForeignKeyRule : ITableDesignerValidationRule
{
public List Run(Dac.TableDesigner designer)