add foreign keys and constraints (#1316)

* add foreign keys and constraints

* add property name
This commit is contained in:
Alan Ren
2021-11-18 15:01:10 -08:00
committed by GitHub
parent c03557aae7
commit b131d1738d
13 changed files with 353 additions and 94 deletions

View File

@@ -8509,6 +8509,78 @@ namespace Microsoft.SqlTools.ServiceLayer
}
}
public static string TableDesignerIsEnabledPropertyTitle
{
get
{
return Keys.GetString(Keys.TableDesignerIsEnabledPropertyTitle);
}
}
public static string ForeignKeyIsEnabledDescription
{
get
{
return Keys.GetString(Keys.ForeignKeyIsEnabledDescription);
}
}
public static string ForeignKeyIsNotForReplicationTitle
{
get
{
return Keys.GetString(Keys.ForeignKeyIsNotForReplicationTitle);
}
}
public static string ForeignKeyIsNotForReplicationDescription
{
get
{
return Keys.GetString(Keys.ForeignKeyIsNotForReplicationDescription);
}
}
public static string SqlForeignKeyAction_NoAction
{
get
{
return Keys.GetString(Keys.SqlForeignKeyAction_NoAction);
}
}
public static string SqlForeignKeyAction_Cascade
{
get
{
return Keys.GetString(Keys.SqlForeignKeyAction_Cascade);
}
}
public static string SqlForeignKeyAction_SetNull
{
get
{
return Keys.GetString(Keys.SqlForeignKeyAction_SetNull);
}
}
public static string SqlForeignKeyAction_SetDefault
{
get
{
return Keys.GetString(Keys.SqlForeignKeyAction_SetDefault);
}
}
public static string CheckConstraintIsEnabledDescription
{
get
{
return Keys.GetString(Keys.CheckConstraintIsEnabledDescription);
}
}
public static string ConnectionServiceListDbErrorNotConnected(string uri)
{
return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri);
@@ -8794,6 +8866,11 @@ namespace Microsoft.SqlTools.ServiceLayer
return Keys.GetString(Keys.InvalidTableEditPathException, path, editType);
}
public static string UnKnownSqlForeignKeyAction(string name)
{
return Keys.GetString(Keys.UnKnownSqlForeignKeyAction, name);
}
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Keys
{
@@ -12153,6 +12230,36 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string TableColumnIdentitySeedPropertyDescription = "TableColumnIdentitySeedPropertyDescription";
public const string TableDesignerIsEnabledPropertyTitle = "TableDesignerIsEnabledPropertyTitle";
public const string ForeignKeyIsEnabledDescription = "ForeignKeyIsEnabledDescription";
public const string ForeignKeyIsNotForReplicationTitle = "ForeignKeyIsNotForReplicationTitle";
public const string ForeignKeyIsNotForReplicationDescription = "ForeignKeyIsNotForReplicationDescription";
public const string SqlForeignKeyAction_NoAction = "SqlForeignKeyAction_NoAction";
public const string SqlForeignKeyAction_Cascade = "SqlForeignKeyAction_Cascade";
public const string SqlForeignKeyAction_SetNull = "SqlForeignKeyAction_SetNull";
public const string SqlForeignKeyAction_SetDefault = "SqlForeignKeyAction_SetDefault";
public const string UnKnownSqlForeignKeyAction = "UnKnownSqlForeignKeyAction";
public const string CheckConstraintIsEnabledDescription = "CheckConstraintIsEnabledDescription";
private Keys()
{ }

View File

@@ -4643,4 +4643,45 @@
<value>Displays the initial row value for an identity column.</value>
<comment></comment>
</data>
<data name="TableDesignerIsEnabledPropertyTitle" xml:space="preserve">
<value>Is Enabled</value>
<comment></comment>
</data>
<data name="ForeignKeyIsEnabledDescription" xml:space="preserve">
<value>Specifies whether the foreign key is Enabled</value>
<comment></comment>
</data>
<data name="ForeignKeyIsNotForReplicationTitle" xml:space="preserve">
<value>Not For Replication</value>
<comment></comment>
</data>
<data name="ForeignKeyIsNotForReplicationDescription" xml:space="preserve">
<value>Enables or disables an IDENTITY constraint for data inserted by a replication process.</value>
<comment></comment>
</data>
<data name="SqlForeignKeyAction_NoAction" xml:space="preserve">
<value>No Action</value>
<comment></comment>
</data>
<data name="SqlForeignKeyAction_Cascade" xml:space="preserve">
<value>Cascade</value>
<comment></comment>
</data>
<data name="SqlForeignKeyAction_SetNull" xml:space="preserve">
<value>Set Null</value>
<comment></comment>
</data>
<data name="SqlForeignKeyAction_SetDefault" xml:space="preserve">
<value>Set Default</value>
<comment></comment>
</data>
<data name="UnKnownSqlForeignKeyAction" xml:space="preserve">
<value>&apos;{0}&apos; is not a supported SqlForeignKeyAction.</value>
<comment>.
Parameters: 0 - name (string) </comment>
</data>
<data name="CheckConstraintIsEnabledDescription" xml:space="preserve">
<value>Specifies whether the check constraint is Enabled</value>
<comment></comment>
</data>
</root>

View File

@@ -2231,3 +2231,13 @@ TableColumnIdentityIncrementPropertyTitle = Identity Increment
TableColumnIdentityIncrementPropertyDescription = Displays the value added to the maximum existing row identity value when generating the next identity value.
TableColumnIdentitySeedPropertyTitle = Identity Seed
TableColumnIdentitySeedPropertyDescription = Displays the initial row value for an identity column.
TableDesignerIsEnabledPropertyTitle = Is Enabled
ForeignKeyIsEnabledDescription = Specifies whether the foreign key is Enabled
ForeignKeyIsNotForReplicationTitle = Not For Replication
ForeignKeyIsNotForReplicationDescription = Enables or disables an IDENTITY constraint for data inserted by a replication process.
SqlForeignKeyAction_NoAction = No Action
SqlForeignKeyAction_Cascade = Cascade
SqlForeignKeyAction_SetNull = Set Null
SqlForeignKeyAction_SetDefault = Set Default
UnKnownSqlForeignKeyAction(string name) = '{0}' is not a supported SqlForeignKeyAction.
CheckConstraintIsEnabledDescription = Specifies whether the check constraint is Enabled

View File

@@ -5645,6 +5645,57 @@
<note>.
Parameters: 0 - actual (string), 1 - estimated (string), 2 - percent (decimal) </note>
</trans-unit>
<trans-unit id="TableDesignerIsEnabledPropertyTitle">
<source>Is Enabled</source>
<target state="new">Is Enabled</target>
<note></note>
</trans-unit>
<trans-unit id="ForeignKeyIsEnabledDescription">
<source>Specifies whether the foreign key is Enabled</source>
<target state="new">Specifies whether the foreign key is Enabled</target>
<note></note>
</trans-unit>
<trans-unit id="ForeignKeyIsNotForReplicationTitle">
<source>Not For Replication</source>
<target state="new">Not For Replication</target>
<note></note>
</trans-unit>
<trans-unit id="ForeignKeyIsNotForReplicationDescription">
<source>Enables or disables an IDENTITY constraint for data inserted by a replication process.</source>
<target state="new">Enables or disables an IDENTITY constraint for data inserted by a replication process.</target>
<note></note>
</trans-unit>
<trans-unit id="SqlForeignKeyAction_NoAction">
<source>No Action</source>
<target state="new">No Action</target>
<note></note>
</trans-unit>
<trans-unit id="SqlForeignKeyAction_Cascade">
<source>Cascade</source>
<target state="new">Cascade</target>
<note></note>
</trans-unit>
<trans-unit id="SqlForeignKeyAction_SetNull">
<source>Set Null</source>
<target state="new">Set Null</target>
<note></note>
</trans-unit>
<trans-unit id="SqlForeignKeyAction_SetDefault">
<source>Set Default</source>
<target state="new">Set Default</target>
<note></note>
</trans-unit>
<trans-unit id="UnKnownSqlForeignKeyAction">
<source>'{0}' is not a supported SqlForeignKeyAction.</source>
<target state="new">'{0}' is not a supported SqlForeignKeyAction.</target>
<note>.
Parameters: 0 - name (string) </note>
</trans-unit>
<trans-unit id="CheckConstraintIsEnabledDescription">
<source>Specifies whether the check constraint is Enabled</source>
<target state="new">Specifies whether the check constraint is Enabled</target>
<note></note>
</trans-unit>
</body>
</file>
</xliff>

View File

@@ -11,6 +11,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
public const string Schema = "schema";
public const string Description = "description";
public const string Columns = "columns";
public const string ForeignKeys = "foreignKeys";
}
public static class TableColumnPropertyNames
@@ -27,4 +28,28 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
public const string IdentityIncrement = "identityIncrement";
public const string IdentitySeed = "identitySeed";
}
public static class ForeignKeyPropertyNames
{
public const string Name = "name";
public const string Enabled = "enabled";
public const string OnDeleteAction = "onDeleteAction";
public const string OnUpdateAction = "onUpdateAction";
public const string ColumnMapping = "columnMapping";
public const string PrimaryKeyTable = "primaryKeyTable";
public const string IsNotForReplication = "isNotForReplication";
}
public static class CheckConstraintPropertyNames
{
public const string Name = "name";
public const string Enabled = "enabled";
public const string Expression = "expression";
}
public static class ForeignKeyColumnMappingPropertyNames
{
public const string PrimaryKeyColumn = "primaryKeyColumn";
public const string ForeignKeyColumn = "foreignKeyColumn";
}
}

View File

@@ -12,7 +12,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
/// <summary>
/// Table component properties
/// </summary>
public abstract class TableComponentProperties<T> : ComponentPropertiesBase where T : ObjectViewModelBase
public class TableComponentProperties<T> : ComponentPropertiesBase
{
/// <summary>
/// The column names to be displayed
@@ -33,32 +33,5 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
/// The object list.
/// </summary>
public List<T> Data { get; set; } = new List<T>();
/// <summary>
/// Add a new object into the Data property
/// </summary>
public void AddNew()
{
this.Data.Add(this.CreateNew(this.GetDefaultNewObjectName()));
}
protected abstract string NewObjectNamePrefix { get; }
protected abstract T CreateNew(string name);
/// <summary>
/// Get the next available name for a new item
/// </summary>
protected string GetDefaultNewObjectName()
{
int i = 1;
string newName;
do
{
newName = string.Format("{0}{1}", this.NewObjectNamePrefix, i);
i++;
} while (this.Data?.AsEnumerable().FirstOrDefault(obj => string.Equals(obj.Name?.Value, newName, StringComparison.InvariantCultureIgnoreCase)) != null);
return newName;
}
}
}

View File

@@ -37,7 +37,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
/// <summary>
/// The name of the group the property will be placed in whe displayed in
/// </summary>
public bool ShowInPropertiesView { get; set; }
public bool ShowInPropertiesView { get; set; } = true;
/// <summary>

View File

@@ -14,13 +14,17 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
public class TableDesignerView
{
public List<DesignerDataPropertyInfo> AdditionalTableProperties { get; set; } = new List<DesignerDataPropertyInfo>();
public BuiltinTableOptions ColumnTableOptions { get; set; } = new BuiltinTableOptions();
public BuiltinTableOptions ForeignKeyTableOptions { get; set; } = new BuiltinTableOptions();
public BuiltinTableOptions CheckConstraintTableOptions { get; set; } = new BuiltinTableOptions();
}
public List<DesignerDataPropertyInfo> AdditionalTableColumnProperties { get; set; } = new List<DesignerDataPropertyInfo>();
public List<string> ColumnsTableProperties { get; set; } = new List<string>();
public bool CanAddColumns { get; set; }
public bool CanRemoveColumns { get; set; }
public class BuiltinTableOptions
{
public bool ShowTable { get; set; } = true;
public List<string> PropertiesToDisplay { get; set; } = new List<string>();
public bool canAddRows { get; set; } = true;
public bool canRemoveRows { get; set; } = true;
public List<DesignerDataPropertyInfo> AdditionalProperties { get; set; } = new List<DesignerDataPropertyInfo>();
}
}

View File

@@ -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.
//
using Newtonsoft.Json;
namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
{
/// <summary>
/// The view model of check constraint
/// </summary>
public class CheckConstraintViewModel : ObjectViewModelBase
{
public InputBoxProperties Expression { get; set; } = new InputBoxProperties();
public CheckBoxProperties Enabled { get; set; } = new CheckBoxProperties();
}
}

View File

@@ -0,0 +1,34 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Newtonsoft.Json;
namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
{
/// <summary>
/// The view model of foreign key.
/// </summary>
public class ForeignKeyViewModel : ObjectViewModelBase
{
public CheckBoxProperties Enabled { get; set; } = new CheckBoxProperties();
public DropdownProperties OnDeleteAction { get; set; } = new DropdownProperties();
public DropdownProperties OnUpdateAction { get; set; } = new DropdownProperties();
public DropdownProperties PrimaryKeyTable { get; set; } = new DropdownProperties();
public CheckBoxProperties IsNotForReplication { get; set; } = new CheckBoxProperties();
public TableComponentProperties<ForeignKeyColumnMapping> Columns { get; set; } = new TableComponentProperties<ForeignKeyColumnMapping>();
}
public class ForeignKeyColumnMapping
{
public DropdownProperties PrimaryKeyColumn { get; set; } = new DropdownProperties();
public DropdownProperties ForeignKeyColumn { get; set; } = new DropdownProperties();
}
}

View File

@@ -16,22 +16,12 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts
public InputBoxProperties Description { get; set; } = new InputBoxProperties();
public TableColumnCollection Columns { get; set; } = new TableColumnCollection();
public TableComponentProperties<TableColumnViewModel> Columns { get; set; } = new TableComponentProperties<TableColumnViewModel>();
public TableComponentProperties<ForeignKeyViewModel> ForeignKeys { get; set; } = new TableComponentProperties<ForeignKeyViewModel>();
public TableComponentProperties<CheckConstraintViewModel> CheckConstraints { get; set; } = new TableComponentProperties<CheckConstraintViewModel>();
public InputBoxProperties Script { get; set; } = new InputBoxProperties();
}
public class TableColumnCollection : TableComponentProperties<TableColumnViewModel>
{
[JsonIgnore]
protected override string NewObjectNamePrefix { get { return "column"; } }
protected override TableColumnViewModel CreateNew(string name)
{
//TODO: Add the default values
var column = new TableColumnViewModel();
column.Name.Value = this.GetDefaultNewObjectName();
return column;
}
}
}

View File

@@ -11,7 +11,7 @@ using Microsoft.Data.SqlClient;
using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts;
using Table = Microsoft.Data.Tools.Sql.DesignServices.TableDesigner.TableDesignerViewModel;
using Dac = Microsoft.Data.Tools.Sql.DesignServices.TableDesigner;
namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
{
@@ -20,7 +20,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
/// </summary>
public sealed class TableDesignerService : IDisposable
{
private Dictionary<string, Table> idTableMap = new Dictionary<string, Table>();
private Dictionary<string, Dac.TableDesignerViewModel> idTableMap = new Dictionary<string, Dac.TableDesignerViewModel>();
private bool disposed = false;
private static readonly Lazy<TableDesignerService> instance = new Lazy<TableDesignerService>(() => new TableDesignerService());
@@ -81,7 +81,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
var connectinStringbuilder = new SqlConnectionStringBuilder(tableInfo.ConnectionString);
connectinStringbuilder.InitialCatalog = tableInfo.Database;
var connectionString = connectinStringbuilder.ToString();
var table = new Table(connectionString, tableInfo.Schema, tableInfo.Name, tableInfo.IsNewTable);
var table = new Dac.TableDesignerViewModel(connectionString, tableInfo.Schema, tableInfo.Name, tableInfo.IsNewTable);
this.idTableMap.Add(tableInfo.Id, table);
var viewModel = this.GetTableViewModel(tableInfo);
var view = this.GetDesignerViewInfo(tableInfo);
@@ -230,7 +230,8 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
private TableDesignerView GetDesignerViewInfo(TableInfo tableInfo)
{
var view = new TableDesignerView();
view.AdditionalTableColumnProperties.Add(new DesignerDataPropertyInfo()
view.ColumnTableOptions.AdditionalProperties.AddRange(new DesignerDataPropertyInfo[] {
new DesignerDataPropertyInfo()
{
PropertyName = TableColumnPropertyNames.IsIdentity,
Description = SR.TableColumnIsIdentityPropertyDescription,
@@ -240,8 +241,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
{
Title = SR.TableColumnIsIdentityPropertyTitle
}
});
view.AdditionalTableColumnProperties.Add(new DesignerDataPropertyInfo()
}, new DesignerDataPropertyInfo()
{
PropertyName = TableColumnPropertyNames.IdentitySeed,
Description = SR.TableColumnIdentitySeedPropertyDescription,
@@ -251,8 +251,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
{
Title = SR.TableColumnIdentitySeedPropertyTitle
}
});
view.AdditionalTableColumnProperties.Add(new DesignerDataPropertyInfo()
},new DesignerDataPropertyInfo()
{
PropertyName = TableColumnPropertyNames.IdentityIncrement,
Description = SR.TableColumnIdentityIncrementPropertyDescription,
@@ -262,15 +261,52 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
{
Title = SR.TableColumnIdentityIncrementPropertyTitle
}
});
view.CanAddColumns = true;
view.CanRemoveColumns = true;
}});
view.ColumnTableOptions.canAddRows = true;
view.ColumnTableOptions.canRemoveRows = true;
view.ForeignKeyTableOptions.AdditionalProperties.AddRange(new DesignerDataPropertyInfo[] {
new DesignerDataPropertyInfo()
{
PropertyName = ForeignKeyPropertyNames.Enabled,
Description = SR.ForeignKeyIsEnabledDescription,
ComponentType = DesignerComponentType.Checkbox,
ComponentProperties = new CheckBoxProperties()
{
Title = SR.TableDesignerIsEnabledPropertyTitle
}
},
new DesignerDataPropertyInfo()
{
PropertyName = ForeignKeyPropertyNames.IsNotForReplication,
Description = SR.ForeignKeyIsNotForReplicationDescription,
ComponentType = DesignerComponentType.Checkbox,
ComponentProperties = new CheckBoxProperties()
{
Title = SR.ForeignKeyIsNotForReplicationTitle
}
}});
view.ForeignKeyTableOptions.canAddRows = true;
view.ForeignKeyTableOptions.canRemoveRows = true;
view.CheckConstraintTableOptions.AdditionalProperties.Add(
new DesignerDataPropertyInfo()
{
PropertyName = CheckConstraintPropertyNames.Enabled,
Description = SR.CheckConstraintIsEnabledDescription,
ComponentType = DesignerComponentType.Checkbox,
ComponentProperties = new CheckBoxProperties()
{
Title = SR.TableDesignerIsEnabledPropertyTitle
}
});
view.CheckConstraintTableOptions.canAddRows = true;
view.CheckConstraintTableOptions.canRemoveRows = true;
return view;
}
private Table GetTable(TableInfo tableInfo)
private Dac.TableDesignerViewModel GetTable(TableInfo tableInfo)
{
Table table;
Dac.TableDesignerViewModel table;
if (this.idTableMap.TryGetValue(tableInfo.Id, out table))
{
return table;

View File

@@ -1,30 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using Microsoft.SqlTools.ServiceLayer.TableDesigner.Contracts;
using NUnit.Framework;
using Newtonsoft.Json;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.TableDesigner
{
public class TableColumnCollectionTest
{
[Test]
public void AutoNameForNewItemTest()
{
var collection = new TableColumnCollection();
collection.AddNew();
Assert.AreEqual(1, collection.Data.Count, "The item count should be 1");
Assert.AreEqual("column1", collection.Data[0].Name.Value);
collection.Data.Add(new TableColumnViewModel() { Name = new InputBoxProperties() { Value = "column3" } });
Assert.AreEqual(2, collection.Data.Count, "The item count should be 2");
collection.AddNew();
Assert.AreEqual(3, collection.Data.Count, "The item count should be 3");
// the name that is not yet used should be picked
Assert.AreEqual("column2", collection.Data[2].Name.Value);
}
}
}