diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
index 70450df7..b5873445 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
@@ -8861,6 +8861,46 @@ namespace Microsoft.SqlTools.ServiceLayer
}
}
+ public static string IndexIsHashPropertyDescription
+ {
+ get
+ {
+ return Keys.GetString(Keys.IndexIsHashPropertyDescription);
+ }
+ }
+
+ public static string IndexIsHashPropertyTitle
+ {
+ get
+ {
+ return Keys.GetString(Keys.IndexIsHashPropertyTitle);
+ }
+ }
+
+ public static string IndexBucketCountPropertyDescription
+ {
+ get
+ {
+ return Keys.GetString(Keys.IndexBucketCountPropertyDescription);
+ }
+ }
+
+ public static string IndexBucketCountPropertyTitle
+ {
+ get
+ {
+ return Keys.GetString(Keys.IndexBucketCountPropertyTitle);
+ }
+ }
+
+ public static string HashIndexGroupTitle
+ {
+ get
+ {
+ return Keys.GetString(Keys.HashIndexGroupTitle);
+ }
+ }
+
public static string TableDesignerColumnsDisplayValueTitle
{
get
@@ -8869,6 +8909,102 @@ namespace Microsoft.SqlTools.ServiceLayer
}
}
+ public static string ColumnStoreIndexNamePropertyTitle
+ {
+ get
+ {
+ return Keys.GetString(Keys.ColumnStoreIndexNamePropertyTitle);
+ }
+ }
+
+ public static string ColumnStoreIndexNamePropertyDescription
+ {
+ get
+ {
+ return Keys.GetString(Keys.ColumnStoreIndexNamePropertyDescription);
+ }
+ }
+
+ public static string ColumnStoreIndexDescriptionPropertyTitle
+ {
+ get
+ {
+ return Keys.GetString(Keys.ColumnStoreIndexDescriptionPropertyTitle);
+ }
+ }
+
+ public static string ColumnStoreIndexDescriptionPropertyDescription
+ {
+ get
+ {
+ return Keys.GetString(Keys.ColumnStoreIndexDescriptionPropertyDescription);
+ }
+ }
+
+ public static string ColumnStoreIndexIsClusteredPropertyDescription
+ {
+ get
+ {
+ return Keys.GetString(Keys.ColumnStoreIndexIsClusteredPropertyDescription);
+ }
+ }
+
+ public static string ColumnStoreIndexIsClusteredPropertyTitle
+ {
+ get
+ {
+ return Keys.GetString(Keys.ColumnStoreIndexIsClusteredPropertyTitle);
+ }
+ }
+
+ public static string ColumnStoreIndexFilterPredicatePropertyDescription
+ {
+ get
+ {
+ return Keys.GetString(Keys.ColumnStoreIndexFilterPredicatePropertyDescription);
+ }
+ }
+
+ public static string ColumnStoreIndexFilterPredicatePropertyTitle
+ {
+ get
+ {
+ return Keys.GetString(Keys.ColumnStoreIndexFilterPredicatePropertyTitle);
+ }
+ }
+
+ public static string ColumnStoreIndexColumnsPropertyDescription
+ {
+ get
+ {
+ return Keys.GetString(Keys.ColumnStoreIndexColumnsPropertyDescription);
+ }
+ }
+
+ public static string ColumnStoreIndexColumnsGroupTitle
+ {
+ get
+ {
+ return Keys.GetString(Keys.ColumnStoreIndexColumnsGroupTitle);
+ }
+ }
+
+ public static string ColumnStoreIndexAddColumn
+ {
+ get
+ {
+ return Keys.GetString(Keys.ColumnStoreIndexAddColumn);
+ }
+ }
+
+ public static string ColumnStoreIndexColumnPropertyName
+ {
+ get
+ {
+ return Keys.GetString(Keys.ColumnStoreIndexColumnPropertyName);
+ }
+ }
+
public static string TableDesignerDeleteColumnConfirmationMessage
{
get
@@ -8925,6 +9061,30 @@ namespace Microsoft.SqlTools.ServiceLayer
}
}
+ public static string TableDesignerColumnStoreIndexesTableTitle
+ {
+ get
+ {
+ return Keys.GetString(Keys.TableDesignerColumnStoreIndexesTableTitle);
+ }
+ }
+
+ public static string TableDesignerColumnStoreIndexObjectType
+ {
+ get
+ {
+ return Keys.GetString(Keys.TableDesignerColumnStoreIndexObjectType);
+ }
+ }
+
+ public static string AddNewColumnStoreIndexLabel
+ {
+ get
+ {
+ return Keys.GetString(Keys.AddNewColumnStoreIndexLabel);
+ }
+ }
+
public static string TableDesignerEdgeConstraintsTabTitle
{
get
@@ -9830,6 +9990,26 @@ namespace Microsoft.SqlTools.ServiceLayer
return Keys.GetString(Keys.ComputedColumnNeedToBePersistedInForeignKeyRuleDescription, columnName, foreignKeyName);
}
+ public static string HashIndexNotSupportedInNonMemoryOptimizedTableRuleDescription(string indexName)
+ {
+ return Keys.GetString(Keys.HashIndexNotSupportedInNonMemoryOptimizedTableRuleDescription, indexName);
+ }
+
+ public static string HashIndexMustHaveBucketCountRuleDescription(string indexName)
+ {
+ return Keys.GetString(Keys.HashIndexMustHaveBucketCountRuleDescription, indexName);
+ }
+
+ public static string ColumnCanOnlyAppearOnceInNonClusteredColumnStoreIndexRuleDescription(string columnName, string indexName, int rowNumber)
+ {
+ return Keys.GetString(Keys.ColumnCanOnlyAppearOnceInNonClusteredColumnStoreIndexRuleDescription, columnName, indexName, rowNumber);
+ }
+
+ public static string NonClusteredColumnStoreIndexMustHaveColumnsRuleDescription(string indexName)
+ {
+ return Keys.GetString(Keys.NonClusteredColumnStoreIndexMustHaveColumnsRuleDescription, indexName);
+ }
+
public static string SqlProjectModelNotFound(string projectUri)
{
return Keys.GetString(Keys.SqlProjectModelNotFound, projectUri);
@@ -13346,9 +13526,60 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string IndexFilterPredicatePropertyTitle = "IndexFilterPredicatePropertyTitle";
+ public const string IndexIsHashPropertyDescription = "IndexIsHashPropertyDescription";
+
+
+ public const string IndexIsHashPropertyTitle = "IndexIsHashPropertyTitle";
+
+
+ public const string IndexBucketCountPropertyDescription = "IndexBucketCountPropertyDescription";
+
+
+ public const string IndexBucketCountPropertyTitle = "IndexBucketCountPropertyTitle";
+
+
+ public const string HashIndexGroupTitle = "HashIndexGroupTitle";
+
+
public const string TableDesignerColumnsDisplayValueTitle = "TableDesignerColumnsDisplayValueTitle";
+ public const string ColumnStoreIndexNamePropertyTitle = "ColumnStoreIndexNamePropertyTitle";
+
+
+ public const string ColumnStoreIndexNamePropertyDescription = "ColumnStoreIndexNamePropertyDescription";
+
+
+ public const string ColumnStoreIndexDescriptionPropertyTitle = "ColumnStoreIndexDescriptionPropertyTitle";
+
+
+ public const string ColumnStoreIndexDescriptionPropertyDescription = "ColumnStoreIndexDescriptionPropertyDescription";
+
+
+ public const string ColumnStoreIndexIsClusteredPropertyDescription = "ColumnStoreIndexIsClusteredPropertyDescription";
+
+
+ public const string ColumnStoreIndexIsClusteredPropertyTitle = "ColumnStoreIndexIsClusteredPropertyTitle";
+
+
+ public const string ColumnStoreIndexFilterPredicatePropertyDescription = "ColumnStoreIndexFilterPredicatePropertyDescription";
+
+
+ public const string ColumnStoreIndexFilterPredicatePropertyTitle = "ColumnStoreIndexFilterPredicatePropertyTitle";
+
+
+ public const string ColumnStoreIndexColumnsPropertyDescription = "ColumnStoreIndexColumnsPropertyDescription";
+
+
+ public const string ColumnStoreIndexColumnsGroupTitle = "ColumnStoreIndexColumnsGroupTitle";
+
+
+ public const string ColumnStoreIndexAddColumn = "ColumnStoreIndexAddColumn";
+
+
+ public const string ColumnStoreIndexColumnPropertyName = "ColumnStoreIndexColumnPropertyName";
+
+
public const string TableDesignerDeleteColumnConfirmationMessage = "TableDesignerDeleteColumnConfirmationMessage";
@@ -13370,6 +13601,15 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string TableDesignerGraphTableTypeNone = "TableDesignerGraphTableTypeNone";
+ public const string TableDesignerColumnStoreIndexesTableTitle = "TableDesignerColumnStoreIndexesTableTitle";
+
+
+ public const string TableDesignerColumnStoreIndexObjectType = "TableDesignerColumnStoreIndexObjectType";
+
+
+ public const string AddNewColumnStoreIndexLabel = "AddNewColumnStoreIndexLabel";
+
+
public const string TableDesignerEdgeConstraintsTabTitle = "TableDesignerEdgeConstraintsTabTitle";
@@ -13604,6 +13844,18 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string ComputedColumnNeedToBePersistedInForeignKeyRuleDescription = "ComputedColumnNeedToBePersistedInForeignKeyRuleDescription";
+ public const string HashIndexNotSupportedInNonMemoryOptimizedTableRuleDescription = "HashIndexNotSupportedInNonMemoryOptimizedTableRuleDescription";
+
+
+ public const string HashIndexMustHaveBucketCountRuleDescription = "HashIndexMustHaveBucketCountRuleDescription";
+
+
+ public const string ColumnCanOnlyAppearOnceInNonClusteredColumnStoreIndexRuleDescription = "ColumnCanOnlyAppearOnceInNonClusteredColumnStoreIndexRuleDescription";
+
+
+ public const string NonClusteredColumnStoreIndexMustHaveColumnsRuleDescription = "NonClusteredColumnStoreIndexMustHaveColumnsRuleDescription";
+
+
public const string TableDesignerConfirmationText = "TableDesignerConfirmationText";
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
index dbf6716d..3787f1f8 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
@@ -4847,10 +4847,78 @@ The Query Processor estimates that implementing the following index could improv
Filter Predicate
+
+ Whether the index is a hash index
+
+
+
+ Is Hash
+
+
+
+ Bucket count of the hash index, note the value will always automatically round up to the next power of 2.
+
+
+
+ Bucket Count
+
+
+
+ Hash Index
+
+
Columns
+
+ Name
+
+
+
+ Name of the column store index
+
+
+
+ Description
+
+
+
+ Description of the column store index
+
+
+
+ Whether the column store index is clustered.
+
+
+
+ Is Clustered
+
+
+
+ Filter predicate of the column store index
+
+
+
+ Filter Predicate
+
+
+
+ Columns in this column store index
+
+
+
+ Columns
+
+
+
+ Add Column
+
+
+
+ Column
+
+
Removing a column will also remove it from the indexes and foreign keys. Are you sure you want to continue?
@@ -4879,6 +4947,18 @@ The Query Processor estimates that implementing the following index could improv
None
+
+ Column Store Indexes
+
+
+
+ Column Store Index
+
+
+
+ New Column Store Index
+
+
Edge Constraints
@@ -5205,6 +5285,26 @@ The Query Processor estimates that implementing the following index could improv
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)
+
+
+ Hash index with name '{0}' is not supported on a non memory-optimized table.
+ .
+ Parameters: 0 - indexName (string)
+
+
+ Hash index '{0}' does not have a bucket count.
+ .
+ Parameters: 0 - indexName (string)
+
+
+ Column with name '{0}' has already been added to the non-clustered column store index '{1}'. Row number: {2}.
+ .
+ Parameters: 0 - columnName (string), 1 - indexName (string), 2 - rowNumber (int)
+
+
+ Non-clustered column store index '{0}' does not have any columns associated with it.
+ .
+ Parameters: 0 - indexName (string)
I have read the summary and understand the potential risks.
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
index a2932e61..f0663eb9 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
@@ -2296,7 +2296,24 @@ IndexIncludedColumnsAddColumn = Add Column
IndexIncludedColumnsColumnPropertyName = Column
IndexFilterPredicatePropertyDescription = Filter predicate of the index
IndexFilterPredicatePropertyTitle = Filter Predicate
+IndexIsHashPropertyDescription = Whether the index is a hash index
+IndexIsHashPropertyTitle = Is Hash
+IndexBucketCountPropertyDescription = Bucket count of the hash index, note the value will always automatically round up to the next power of 2.
+IndexBucketCountPropertyTitle = Bucket Count
+HashIndexGroupTitle = Hash Index
TableDesignerColumnsDisplayValueTitle = Columns
+ColumnStoreIndexNamePropertyTitle = Name
+ColumnStoreIndexNamePropertyDescription = Name of the column store index
+ColumnStoreIndexDescriptionPropertyTitle = Description
+ColumnStoreIndexDescriptionPropertyDescription = Description of the column store index
+ColumnStoreIndexIsClusteredPropertyDescription = Whether the column store index is clustered.
+ColumnStoreIndexIsClusteredPropertyTitle = Is Clustered
+ColumnStoreIndexFilterPredicatePropertyDescription = Filter predicate of the column store index
+ColumnStoreIndexFilterPredicatePropertyTitle = Filter Predicate
+ColumnStoreIndexColumnsPropertyDescription = Columns in this column store index
+ColumnStoreIndexColumnsGroupTitle = Columns
+ColumnStoreIndexAddColumn = Add Column
+ColumnStoreIndexColumnPropertyName = Column
TableDesignerDeleteColumnConfirmationMessage = Removing a column will also remove it from the indexes and foreign keys. Are you sure you want to continue?
TableDesignerGraphTableGroupTitle = Graph Table
TableDesignerGraphTableTypeTitle = Type
@@ -2304,6 +2321,9 @@ TableDesignerGraphTableTypeDescription = Specifies the table type.
TableDesignerGraphTableTypeEdge = Edge
TableDesignerGraphTableTypeNode = Node
TableDesignerGraphTableTypeNone = None
+TableDesignerColumnStoreIndexesTableTitle = Column Store Indexes
+TableDesignerColumnStoreIndexObjectType = Column Store Index
+AddNewColumnStoreIndexLabel = New Column Store Index
TableDesignerEdgeConstraintsTabTitle = Edge Constraints
TableDesignerEdgeConstraintObjectType = Edge Constraint
TableDesignerEdgeConstraintNamePropertyDescription = Name of the constraint.
@@ -2382,6 +2402,10 @@ ColumnCanOnlyAppearOnceInIndexIncludedColumnsRuleDescription(string columnName,
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}'.
+HashIndexNotSupportedInNonMemoryOptimizedTableRuleDescription(string indexName) = Hash index with name '{0}' is not supported on a non memory-optimized table.
+HashIndexMustHaveBucketCountRuleDescription(string indexName) = Hash index '{0}' does not have a bucket count.
+ColumnCanOnlyAppearOnceInNonClusteredColumnStoreIndexRuleDescription(string columnName, string indexName, int rowNumber) = Column with name '{0}' has already been added to the non-clustered column store index '{1}'. Row number: {2}.
+NonClusteredColumnStoreIndexMustHaveColumnsRuleDescription(string indexName) = Non-clustered column store index '{0}' does not have any columns associated with it.
TableDesignerConfirmationText = I have read the summary and understand the potential risks.
############################################################################
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
index 89dee44f..90d71ea0 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
@@ -6359,6 +6359,130 @@ The Query Processor estimates that implementing the following index could improv
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)
+
+
+ Hash index with name '{0}' is not supported on a non memory-optimized table.
+ Hash index with name '{0}' is not supported on a non memory-optimized table.
+ .
+ Parameters: 0 - indexName (string)
+
+
+ Hash index '{0}' does not have a bucket count.
+ Hash index '{0}' does not have a bucket count.
+ .
+ Parameters: 0 - indexName (string)
+
+
+ Whether the index is a hash index
+ Whether the index is a hash index
+
+
+
+ Is Hash
+ Is Hash
+
+
+
+ Bucket count of the hash index, note the value will always automatically round up to the next power of 2.
+ Bucket count of the hash index, note the value will always automatically round up to the next power of 2.
+
+
+
+ Bucket Count
+ Bucket Count
+
+
+
+ Hash Index
+ Hash Index
+
+
+
+ Name
+ Name
+
+
+
+ Name of the column store index
+ Name of the column store index
+
+
+
+ Description
+ Description
+
+
+
+ Description of the column store index
+ Description of the column store index
+
+
+
+ Whether the column store index is clustered.
+ Whether the column store index is clustered.
+
+
+
+ Is Clustered
+ Is Clustered
+
+
+
+ Filter predicate of the column store index
+ Filter predicate of the column store index
+
+
+
+ Filter Predicate
+ Filter Predicate
+
+
+
+ Columns in this column store index
+ Columns in this column store index
+
+
+
+ Columns
+ Columns
+
+
+
+ Add Column
+ Add Column
+
+
+
+ Column
+ Column
+
+
+
+ Column with name '{0}' has already been added to the non-clustered column store index '{1}'. Row number: {2}.
+ Column with name '{0}' has already been added to the non-clustered column store index '{1}'. Row number: {2}.
+ .
+ Parameters: 0 - columnName (string), 1 - indexName (string), 2 - rowNumber (int)
+
+
+ Column Store Indexes
+ Column Store Indexes
+
+
+
+ Column Store Index
+ Column Store Index
+
+
+
+ New Column Store Index
+ New Column Store Index
+
+
+
+ Non-clustered column store index '{0}' does not have any columns associated with it.
+ Non-clustered column store index '{0}' does not have any columns associated with it.
+ .
+ Parameters: 0 - indexName (string)
I have read the summary and understand the potential risks.
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Constants.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Constants.cs
index 310991c4..62096cf7 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Constants.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Constants.cs
@@ -14,6 +14,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
public const string ForeignKeys = "foreignKeys";
public const string CheckConstraints = "checkConstraints";
public const string Indexes = "indexes";
+ public const string ColumnStoreIndexes = "columnStoreIndexes";
public const string EdgeConstraints = "edgeConstraints";
public const string GraphTableType = "graphTableType";
public const string IsSystemVersioningEnabled = "isSystemVersioningEnabled";
@@ -86,6 +87,8 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
public const string Enabled = "enabled";
public const string IsUnique = "isUnique";
public const string IsClustered = "isClustered";
+ public const string IsHash = "isHash";
+ public const string BucketCount = "bucketCount";
public const string Columns = "columns";
public const string IncludedColumns = "includedColumns";
public const string FilterPredicate = "filterPredicate";
@@ -103,6 +106,21 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
public const string Column = "column";
}
+ public static class ColumnStoreIndexPropertyNames
+ {
+ public const string Name = "name";
+ public const string Description = "description";
+ public const string IsClustered = "isClustered";
+ public const string Columns = "columns";
+ public const string FilterPredicate = "filterPredicate";
+ public const string ColumnsDisplayValue = "columnsDisplayValue";
+ }
+
+ public static class ColumnStoreIndexColumnSpecificationPropertyNames
+ {
+ public const string Column = "column";
+ }
+
public static class EdgeConstraintPropertyNames
{
public const string Name = "name";
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/DesignerDataPropertyWithTabInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/DesignerDataPropertyWithTabInfo.cs
new file mode 100644
index 00000000..2c01d490
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/DesignerDataPropertyWithTabInfo.cs
@@ -0,0 +1,18 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
+{
+ ///
+ /// Represents a component/property with tab info in the table designer
+ ///
+ public class DesignerDataPropertyWithTabInfo : DesignerDataPropertyInfo
+ {
+ ///
+ /// The tab of the property
+ ///
+ public string Tab { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/TableDesignerView.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/TableDesignerView.cs
index bb6b8eba..67246591 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/TableDesignerView.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/TableDesignerView.cs
@@ -21,6 +21,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
public BuiltinTableOptions IndexTableOptions { get; set; } = new BuiltinTableOptions();
public BuiltinTableOptions IndexColumnSpecificationTableOptions { get; set; } = new BuiltinTableOptions();
public List AdditionalPrimaryKeyProperties { get; set; } = new List();
+ public List AdditionalComponents { get; set; } = new List();
public BuiltinTableOptions PrimaryKeyColumnSpecificationTableOptions = new BuiltinTableOptions();
public List AdditionalTabs { get; } = new List();
public bool UseAdvancedSaveMode { get; set; }
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/ColumnStoreIndexViewModel.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/ColumnStoreIndexViewModel.cs
new file mode 100644
index 00000000..b5aff70a
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/ColumnStoreIndexViewModel.cs
@@ -0,0 +1,28 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
+{
+ ///
+ /// The view model of column store index.
+ ///
+ public class ColumnStoreIndexViewModel : ObjectViewModelBase
+ {
+
+ public CheckBoxProperties IsClustered { 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 class ColumnStoreIndexedColumnSpecification
+ {
+ public DropdownProperties Column { get; set; } = new DropdownProperties();
+
+ public CheckBoxProperties Ascending { get; set; } = new CheckBoxProperties();
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/IndexViewModel.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/IndexViewModel.cs
index 394d1271..61da7717 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/IndexViewModel.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/IndexViewModel.cs
@@ -15,7 +15,9 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
public CheckBoxProperties IsClustered { get; set; } = new CheckBoxProperties();
public CheckBoxProperties IsUnique { get; set; } = new CheckBoxProperties();
+ public CheckBoxProperties IsHash { get; set; } = new CheckBoxProperties();
+ public InputBoxProperties BucketCount { get; set; } = new InputBoxProperties();
public InputBoxProperties ColumnsDisplayValue { get; set; } = new InputBoxProperties();
public InputBoxProperties FilterPredicate { get; set; } = new InputBoxProperties();
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/TableViewModel.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/TableViewModel.cs
index 8bfc6558..279ef7a1 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/TableViewModel.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/Contracts/ViewModel/TableViewModel.cs
@@ -42,6 +42,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
public TableComponentProperties EdgeConstraints { get; set; } = new TableComponentProperties();
public TableComponentProperties Indexes { get; set; } = new TableComponentProperties();
+ public TableComponentProperties ColumnStoreIndexes { get; set; } = new TableComponentProperties();
public InputBoxProperties Script { get; set; } = new InputBoxProperties();
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs
index 9a641e76..8ee9b1ef 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs
@@ -245,6 +245,9 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
case TablePropertyNames.Indexes:
table.Indexes.AddNew();
break;
+ case TablePropertyNames.ColumnStoreIndexes:
+ table.ColumnStoreIndexes.AddNew();
+ break;
case TablePropertyNames.EdgeConstraints:
table.EdgeConstraints.AddNew();
break;
@@ -290,6 +293,16 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
break;
}
break;
+ case TablePropertyNames.ColumnStoreIndexes:
+ switch (propertyNameL2)
+ {
+ case ColumnStoreIndexPropertyNames.Columns:
+ table.ColumnStoreIndexes.Items[indexL1].AddNewColumnSpecification();
+ break;
+ default:
+ break;
+ }
+ break;
case TablePropertyNames.EdgeConstraints:
switch (propertyNameL2)
{
@@ -329,6 +342,9 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
case TablePropertyNames.Indexes:
table.Indexes.RemoveAt(objIndex);
break;
+ case TablePropertyNames.ColumnStoreIndexes:
+ table.ColumnStoreIndexes.RemoveAt(objIndex);
+ break;
case TablePropertyNames.EdgeConstraints:
table.EdgeConstraints.RemoveAt(objIndex);
break;
@@ -370,6 +386,16 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
break;
}
break;
+ case TablePropertyNames.ColumnStoreIndexes:
+ switch (propertyNameL2)
+ {
+ case ColumnStoreIndexPropertyNames.Columns:
+ table.ColumnStoreIndexes.Items[indexL1].RemoveColumnSpecification(indexL2);
+ break;
+ default:
+ break;
+ }
+ break;
case TablePropertyNames.EdgeConstraints:
switch (propertyNameL2)
{
@@ -612,6 +638,32 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
case IndexPropertyNames.FilterPredicate:
sqlIndex.FilterPredicate = GetStringValue(newValue);
break;
+ case IndexPropertyNames.IsHash:
+ sqlIndex.IsHash = GetBooleanValue(newValue);
+ break;
+ case IndexPropertyNames.BucketCount:
+ sqlIndex.BucketCount = GetInt32Value(newValue);
+ break;
+ default:
+ break;
+ }
+ break;
+ case TablePropertyNames.ColumnStoreIndexes:
+ var csIndex = table.ColumnStoreIndexes.Items[indexL1];
+ switch (propertyNameL2)
+ {
+ case ColumnStoreIndexPropertyNames.IsClustered:
+ csIndex.IsClustered = GetBooleanValue(newValue);
+ break;
+ case ColumnStoreIndexPropertyNames.Name:
+ csIndex.Name = GetStringValue(newValue);
+ break;
+ case ColumnStoreIndexPropertyNames.Description:
+ csIndex.Description = GetStringValue(newValue);
+ break;
+ case ColumnStoreIndexPropertyNames.FilterPredicate:
+ csIndex.FilterPredicate = GetStringValue(newValue);
+ break;
default:
break;
}
@@ -711,6 +763,24 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
break;
}
break;
+ case TablePropertyNames.ColumnStoreIndexes:
+ var csIndex = table.ColumnStoreIndexes.Items[indexL1];
+ switch (propertyNameL2)
+ {
+ case ColumnStoreIndexPropertyNames.Columns:
+ switch (propertyNameL3)
+ {
+ case ColumnStoreIndexColumnSpecificationPropertyNames.Column:
+ csIndex.UpdateColumnName(indexL2, GetStringValue(newValue));
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
case TablePropertyNames.EdgeConstraints:
var constraint = table.EdgeConstraints.Items[indexL1];
switch (propertyNameL2)
@@ -930,10 +1000,15 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
indexVM.IsClustered.Checked = index.IsClustered;
indexVM.Enabled.Checked = index.Enabled;
indexVM.IsUnique.Checked = index.IsUnique;
+ indexVM.IsHash.Checked = index.IsHash;
+ indexVM.IsHash.Enabled = table.IsMemoryOptimized || index.IsHash;
+ indexVM.BucketCount.Value = index.BucketCount?.ToString();
+ indexVM.BucketCount.Enabled = table.IsMemoryOptimized || index.IsHash;
foreach (var columnSpec in index.Columns)
{
var columnSpecVM = new IndexedColumnSpecification();
columnSpecVM.Ascending.Checked = columnSpec.IsAscending;
+ columnSpecVM.Ascending.Enabled = index.CanEditIsAscending;
columnSpecVM.Column.Value = columnSpec.Column;
columnSpecVM.Column.Values = tableDesigner.GetColumnsForTable(table.FullName).ToList();
indexVM.Columns.Data.Add(columnSpecVM);
@@ -957,6 +1032,35 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
tableViewModel.Indexes.Data.Add(indexVM);
}
+ foreach (var index in table.ColumnStoreIndexes.Items)
+ {
+ var indexVM = new ColumnStoreIndexViewModel();
+ indexVM.Name.Value = index.Name;
+ indexVM.Description.Value = index.Description;
+ indexVM.Description.Enabled = index.CanEditDescription;
+ indexVM.IsClustered.Checked = index.IsClustered;
+ indexVM.FilterPredicate.Value = index.FilterPredicate;
+ indexVM.FilterPredicate.Enabled = !index.IsClustered || index.FilterPredicate != null;
+ indexVM.Columns.Enabled = !index.IsClustered || index.Columns.Count() > 0;
+ indexVM.Columns.CanAddRows = !index.IsClustered;
+ indexVM.ColumnsDisplayValue.Enabled = false;
+
+ // avoid populating columns for CLUSTERED column store index
+ if (!index.IsClustered)
+ {
+ indexVM.ColumnsDisplayValue.Value = index.ColumnsDisplayValue;
+
+ foreach (var columnSpec in index.Columns)
+ {
+ var columnSpecVM = new ColumnStoreIndexedColumnSpecification();
+ columnSpecVM.Column.Value = columnSpec.Column;
+ columnSpecVM.Column.Values = tableDesigner.GetColumnsForTable(table.FullName).ToList();
+ indexVM.Columns.Data.Add(columnSpecVM);
+ }
+ }
+ tableViewModel.ColumnStoreIndexes.Data.Add(indexVM);
+ }
+
foreach (var constraint in table.EdgeConstraints.Items)
{
var constraintVM = new EdgeConstraintViewModel();
@@ -993,6 +1097,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
this.SetForeignKeysViewInfo(view);
this.SetCheckConstraintsViewInfo(view);
this.SetIndexesViewInfo(view);
+ this.SetColumnStoreIndexesViewInfo(view);
this.SetGraphTableViewInfo(view, tableDesigner);
this.SetEdgeConstraintsViewInfo(view, tableDesigner);
this.SetTemporalTableViewInfo(view, tableDesigner);
@@ -1233,6 +1338,29 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
}
},
new DesignerDataPropertyInfo()
+ {
+ PropertyName = IndexPropertyNames.IsHash,
+ Description = SR.IndexIsHashPropertyDescription,
+ ComponentType = DesignerComponentType.Checkbox,
+ Group = SR.HashIndexGroupTitle,
+ ComponentProperties = new CheckBoxProperties()
+ {
+ Title = SR.IndexIsHashPropertyTitle
+ }
+ },
+ new DesignerDataPropertyInfo()
+ {
+ PropertyName = IndexPropertyNames.BucketCount,
+ Description = SR.IndexBucketCountPropertyDescription,
+ ComponentType = DesignerComponentType.Input,
+ Group = SR.HashIndexGroupTitle,
+ ComponentProperties = new InputBoxProperties()
+ {
+ Title = SR.IndexBucketCountPropertyTitle,
+ Width = 200
+ }
+ },
+ new DesignerDataPropertyInfo()
{
PropertyName = IndexPropertyNames.IncludedColumns,
Description = SR.IndexIncludedColumnsPropertyDescription,
@@ -1283,6 +1411,109 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
view.IndexColumnSpecificationTableOptions.CanInsertRows = false;
}
+ private void SetColumnStoreIndexesViewInfo(TableDesignerView view)
+ {
+ var columnStoreIndexesTableProperties = new TableComponentProperties()
+ {
+ Title = SR.TableDesignerColumnStoreIndexesTableTitle,
+ ObjectTypeDisplayName = SR.TableDesignerColumnStoreIndexObjectType,
+ LabelForAddNewButton = SR.AddNewColumnStoreIndexLabel
+ };
+ columnStoreIndexesTableProperties.Columns.AddRange(new string[] { ColumnStoreIndexPropertyNames.Name, ColumnStoreIndexPropertyNames.ColumnsDisplayValue, ColumnStoreIndexPropertyNames.IsClustered });
+ columnStoreIndexesTableProperties.ItemProperties.AddRange(new DesignerDataPropertyInfo[] {
+ new DesignerDataPropertyInfo()
+ {
+ PropertyName = ColumnStoreIndexPropertyNames.Name,
+ Description = SR.ColumnStoreIndexNamePropertyDescription,
+ ComponentType = DesignerComponentType.Input,
+ ComponentProperties = new InputBoxProperties()
+ {
+ Title = SR.ColumnStoreIndexNamePropertyTitle,
+ Width = 200
+ }
+ },
+ new DesignerDataPropertyInfo()
+ {
+ PropertyName = ColumnStoreIndexPropertyNames.Description,
+ Description = SR.ColumnStoreIndexDescriptionPropertyDescription,
+ ComponentType = DesignerComponentType.Input,
+ ComponentProperties = new InputBoxProperties()
+ {
+ Title = SR.ColumnStoreIndexDescriptionPropertyTitle,
+ Width = 200
+ }
+ },
+ new DesignerDataPropertyInfo()
+ {
+ PropertyName = ColumnStoreIndexPropertyNames.IsClustered,
+ Description = SR.ColumnStoreIndexIsClusteredPropertyDescription,
+ ComponentType = DesignerComponentType.Checkbox,
+ ComponentProperties = new CheckBoxProperties()
+ {
+ Title = SR.ColumnStoreIndexIsClusteredPropertyTitle
+ }
+ },
+ new DesignerDataPropertyInfo()
+ {
+ PropertyName = ColumnStoreIndexPropertyNames.FilterPredicate,
+ Description = SR.ColumnStoreIndexFilterPredicatePropertyDescription,
+ ComponentType = DesignerComponentType.Input,
+ ComponentProperties = new InputBoxProperties()
+ {
+ Title = SR.ColumnStoreIndexFilterPredicatePropertyTitle,
+ Width = 200
+ }
+ },
+ new DesignerDataPropertyInfo()
+ {
+ PropertyName = ColumnStoreIndexPropertyNames.ColumnsDisplayValue,
+ ShowInPropertiesView = false,
+ ComponentType = DesignerComponentType.Input,
+ ComponentProperties = new InputBoxProperties()
+ {
+ Title = SR.TableDesignerColumnsDisplayValueTitle,
+ Width = 200
+ }
+ },
+ new DesignerDataPropertyInfo()
+ {
+ PropertyName = ColumnStoreIndexPropertyNames.Columns,
+ Description = SR.ColumnStoreIndexColumnsPropertyDescription,
+ ComponentType = DesignerComponentType.Table,
+ Group = SR.ColumnStoreIndexColumnsGroupTitle,
+ ComponentProperties = new TableComponentProperties()
+ {
+ AriaLabel = SR.ColumnStoreIndexColumnsGroupTitle,
+ Columns = new List () { ColumnStoreIndexColumnSpecificationPropertyNames.Column},
+ LabelForAddNewButton = SR.ColumnStoreIndexAddColumn,
+ ItemProperties = new List()
+ {
+ new DesignerDataPropertyInfo()
+ {
+ PropertyName = ColumnStoreIndexColumnSpecificationPropertyNames.Column,
+ ComponentType = DesignerComponentType.Dropdown,
+ ComponentProperties = new DropdownProperties()
+ {
+ Title = SR.ColumnStoreIndexColumnPropertyName,
+ Width = 150
+ }
+ },
+ }
+ }
+ }
+ });
+
+ var columnStoreIndexesComponent = new DesignerDataPropertyWithTabInfo()
+ {
+ PropertyName = TablePropertyNames.ColumnStoreIndexes,
+ Tab = TablePropertyNames.Indexes,
+ ComponentType = DesignerComponentType.Table,
+ ComponentProperties = columnStoreIndexesTableProperties,
+ ShowInPropertiesView = false
+ };
+ view.AdditionalComponents.Add(columnStoreIndexesComponent);
+ }
+
private void SetGraphTableViewInfo(TableDesignerView view, Dac.TableDesigner tableDesigner)
{
if (tableDesigner.IsGraphTableSupported && (tableDesigner.IsNewTable || tableDesigner.TableViewModel.IsEdge || tableDesigner.TableViewModel.IsNode))
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerValidator.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerValidator.cs
index 7facb18e..5e986a0d 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerValidator.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerValidator.cs
@@ -39,7 +39,11 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
new ColumnCanOnlyAppearOnceInIndexIncludedColumnsRule(),
new ColumnCannotDuplicateWitIndexKeyColumnsRule(),
new ComputedColumnNeedToBePersistedAndNotNullInPrimaryKeyRule(),
- new ComputedColumnNeedToBePersistedInForeignKeyRule()
+ new ComputedColumnNeedToBePersistedInForeignKeyRule(),
+ new HashIndexNotSupportedInNonMemoryOptimizedTableRule(),
+ new HashIndexMustHaveBucketCountRule(),
+ new ColumnCanOnlyAppearOnceInNonClusteredColumnStoreIndexRule(),
+ new NonClusteredColumnStoreIndexMustHaveColumnsRule()
};
///
@@ -754,4 +758,107 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
return errors;
}
}
+
+ public class HashIndexNotSupportedInNonMemoryOptimizedTableRule : ITableDesignerValidationRule
+ {
+ public List Run(Dac.TableDesigner designer)
+ {
+ var table = designer.TableViewModel;
+ var errors = new List();
+ if (!table.IsMemoryOptimized)
+ {
+ for (int i = 0; i < table.Indexes.Items.Count; i++)
+ {
+ var index = table.Indexes.Items[i];
+ if (index.IsHash)
+ {
+ errors.Add(new TableDesignerIssue()
+ {
+ Description = SR.HashIndexNotSupportedInNonMemoryOptimizedTableRuleDescription(index.Name),
+ PropertyPath = new object[] { TablePropertyNames.Indexes, i, IndexPropertyNames.IsHash }
+ });
+ }
+ }
+ }
+ return errors;
+ }
+ }
+
+ public class HashIndexMustHaveBucketCountRule : 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.IsHash && !index.BucketCount.HasValue)
+ {
+ errors.Add(new TableDesignerIssue()
+ {
+ Description = SR.HashIndexMustHaveBucketCountRuleDescription(index.Name),
+ PropertyPath = new object[] { TablePropertyNames.Indexes, i, IndexPropertyNames.BucketCount }
+ });
+ }
+ }
+ return errors;
+ }
+ }
+
+ public class ColumnCanOnlyAppearOnceInNonClusteredColumnStoreIndexRule : ITableDesignerValidationRule
+ {
+ public List Run(Dac.TableDesigner designer)
+ {
+ var table = designer.TableViewModel;
+ var errors = new List();
+ for (int i = 0; i < table.ColumnStoreIndexes.Items.Count; i++)
+ {
+ var index = table.ColumnStoreIndexes.Items[i];
+ if (!index.IsClustered)
+ {
+ var existingColumns = new HashSet();
+ for (int j = 0; j < index.Columns.Count; j++)
+ {
+ var columnSpec = index.Columns[j];
+ if (existingColumns.Contains(columnSpec.Column))
+ {
+ errors.Add(new TableDesignerIssue()
+ {
+ Description = SR.ColumnCanOnlyAppearOnceInNonClusteredColumnStoreIndexRuleDescription(columnSpec.Column, index.Name, j + 1),
+ PropertyPath = new object[] { TablePropertyNames.ColumnStoreIndexes, i, ColumnStoreIndexPropertyNames.Columns, j }
+ });
+ }
+ else
+ {
+ existingColumns.Add(columnSpec.Column);
+ }
+ }
+ }
+ }
+ return errors;
+ }
+ }
+
+ public class NonClusteredColumnStoreIndexMustHaveColumnsRule : ITableDesignerValidationRule
+ {
+ public List Run(Dac.TableDesigner designer)
+ {
+ var table = designer.TableViewModel;
+ var errors = new List();
+ for (int i = 0; i < table.ColumnStoreIndexes.Items.Count; i++)
+ {
+ var index = table.ColumnStoreIndexes.Items[i];
+ if (!index.IsClustered && index.Columns.Count == 0)
+ {
+ errors.Add(new TableDesignerIssue()
+ {
+ Description = SR.NonClusteredColumnStoreIndexMustHaveColumnsRuleDescription(index.Name),
+ PropertyPath = new object[] { TablePropertyNames.ColumnStoreIndexes, i }
+ });
+ }
+ }
+ return errors;
+ }
+ }
}
\ No newline at end of file