mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-30 09:35:38 -05:00
[Table Designer] Support filter predicate and included columns for index (#1619)
This commit is contained in:
@@ -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";
|
||||
|
||||
@@ -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<IndexedColumnSpecification> Columns { get; set; } = new TableComponentProperties<IndexedColumnSpecification>();
|
||||
public TableComponentProperties<IndexIncludedColumnSpecification> IncludedColumns { get; set; } = new TableComponentProperties<IndexIncludedColumnSpecification>();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -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<IndexIncludedColumnSpecification>()
|
||||
{
|
||||
AriaLabel = SR.IndexIncludedColumnsGroupTitle,
|
||||
Columns = new List<string> () { IndexIncludedColumnSpecificationPropertyNames.Column},
|
||||
LabelForAddNewButton = SR.IndexIncludedColumnsAddColumn,
|
||||
ItemProperties = new List<DesignerDataPropertyInfo>()
|
||||
{
|
||||
new DesignerDataPropertyInfo()
|
||||
{
|
||||
PropertyName = IndexIncludedColumnSpecificationPropertyNames.Column,
|
||||
ComponentType = DesignerComponentType.Dropdown,
|
||||
ComponentProperties = new DropdownProperties()
|
||||
{
|
||||
Title = SR.IndexIncludedColumnsColumnPropertyName,
|
||||
Width = 150
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
view.IndexTableOptions.PropertiesToDisplay = new List<string>() { IndexPropertyNames.Name, IndexPropertyNames.ColumnsDisplayValue, IndexPropertyNames.IsClustered, IndexPropertyNames.IsUnique };
|
||||
|
||||
@@ -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()
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -77,6 +81,50 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
|
||||
}
|
||||
}
|
||||
|
||||
public class ClusteredIndexCannotHaveIncludedColumnsRule : ITableDesignerValidationRule
|
||||
{
|
||||
public List<TableDesignerIssue> Run(Dac.TableDesigner designer)
|
||||
{
|
||||
var table = designer.TableViewModel;
|
||||
var errors = new List<TableDesignerIssue>();
|
||||
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<TableDesignerIssue> Run(Dac.TableDesigner designer)
|
||||
{
|
||||
var table = designer.TableViewModel;
|
||||
var errors = new List<TableDesignerIssue>();
|
||||
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<TableDesignerIssue> Run(Dac.TableDesigner designer)
|
||||
@@ -130,6 +178,64 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
|
||||
}
|
||||
}
|
||||
|
||||
public class ColumnCanOnlyAppearOnceInIndexIncludedColumnsRule : ITableDesignerValidationRule
|
||||
{
|
||||
public List<TableDesignerIssue> Run(Dac.TableDesigner designer)
|
||||
{
|
||||
var table = designer.TableViewModel;
|
||||
var errors = new List<TableDesignerIssue>();
|
||||
for (int i = 0; i < table.Indexes.Items.Count; i++)
|
||||
{
|
||||
var index = table.Indexes.Items[i];
|
||||
var existingColumns = new HashSet<string>();
|
||||
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<TableDesignerIssue> Run(Dac.TableDesigner designer)
|
||||
{
|
||||
var table = designer.TableViewModel;
|
||||
var errors = new List<TableDesignerIssue>();
|
||||
for (int i = 0; i < table.Indexes.Items.Count; i++)
|
||||
{
|
||||
var index = table.Indexes.Items[i];
|
||||
var keyCols = new HashSet<string>(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<TableDesignerIssue> Run(Dac.TableDesigner designer)
|
||||
|
||||
Reference in New Issue
Block a user