Ledger Objects Representation in Object Explorer (#1615)

* support for ledger objects in OE

* generated sr files

* update versionKey to sql 2022 in test env config

* more 2019 to 2022 updates

* add sql2022 instead of replacing

* missed filter on table

* add logging

* more logging

* adding Script160Compat options for sql2022

Co-authored-by: Alan Ren <alanren@microsoft.com>
This commit is contained in:
Jordan Hays
2022-08-05 13:53:17 -04:00
committed by GitHub
parent 1789fd1233
commit d78ff94b31
25 changed files with 442 additions and 53 deletions

View File

@@ -17,27 +17,27 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
/// <summary>
/// Property name
/// </summary>
public string Property { get; set; }
public string Property { get; set; } = string.Empty;
/// <summary>
/// Filter values
/// </summary>
public List<object> Values { get; set; }
public List<object> Values { get; set; } = default!;
/// <summary>
/// Type of the filter values
/// </summary>
public Type Type { get; set; }
public Type Type { get; set; } = default!;
/// <summary>
/// Indicates which platforms a filter is valid for
/// </summary>
public ValidForFlag ValidFor { get; set; }
public ValidForFlag ValidFor { get; set; } = ValidForFlag.None;
/// <summary>
/// The type of the Querier the filter can be applied to
/// </summary>
public Type TypeToReverse { get; set; }
public Type TypeToReverse { get; set; } = default!;
/// <summary>
/// Returns true if the filter can be apply to the given type and Server type

View File

@@ -29,6 +29,24 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
child.IsAlwaysLeaf = true;
}
}
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
try
{
Database? db = smoObject as Database;
if (db != null && IsPropertySupported("IsLedger", smoContext, db, CachedSmoProperties) && db.IsLedger)
{
return "Ledger";
}
}
catch
{
//Ignore the exception and just not change create custom name
}
return string.Empty;
}
}
internal static class DatabasesCustomNodeHelper
@@ -38,12 +56,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
internal static bool GetDatabaseIsUnavailable(object smoObject, SmoQueryContext smoContext, IEnumerable<NodeSmoProperty> supportedProperties)
{
Database db = smoObject as Database;
Database? db = smoObject as Database;
if (db != null && SmoChildFactoryBase.IsPropertySupported("Status", smoContext, db, supportedProperties))
{
DatabaseStatus status;
try
{
{
status = db.Status;
}
catch (SqlServer.Management.Common.ConnectionFailureException)
@@ -66,12 +84,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
internal static string GetStatus(object smoObject, SmoQueryContext smoContext, IEnumerable<NodeSmoProperty> supportedProperties)
{
Database db = smoObject as Database;
Database? db = smoObject as Database;
if (db != null && SmoChildFactoryBase.IsPropertySupported("Status", smoContext, db, supportedProperties))
{
DatabaseStatus status;
try
{
{
status = db.Status;
}
catch (SqlServer.Management.Common.ConnectionFailureException)
@@ -102,7 +120,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
else if ((status & DatabaseStatus.Inaccessible) == DatabaseStatus.Inaccessible)
{
return "Inaccessible";
}
}
else if ((status & DatabaseStatus.Shutdown) == DatabaseStatus.Shutdown)
{
return "Shutdown";
@@ -118,7 +136,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
else if ((status & DatabaseStatus.AutoClosed) == DatabaseStatus.AutoClosed)
{
return "Auto Closed";
}
}
}
return string.Empty;

View File

@@ -16,7 +16,18 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
try
{
Table table = smoObject as Table;
Table? table = smoObject as Table;
if (table != null && IsPropertySupported("LedgerType", smoContext, table, CachedSmoProperties))
{
if (table.LedgerType == LedgerTableType.AppendOnlyLedgerTable)
{
return $"{table.Schema}.{table.Name} ({SR.AppendOnlyLedger_LabelPart})";
}
else if (table.LedgerType == LedgerTableType.UpdatableLedgerTable)
{
return $"{table.Schema}.{table.Name} ({SR.UpdatableLedger_LabelPart})";
}
}
if (table != null && IsPropertySupported("IsSystemVersioned", smoContext, table, CachedSmoProperties) && table.IsSystemVersioned)
{
return $"{table.Schema}.{table.Name} ({SR.SystemVersioned_LabelPart})";
@@ -42,7 +53,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
try
{
Table table = smoObject as Table;
Table? table = smoObject as Table;
if (table != null && IsPropertySupported("LedgerType", smoContext, table, CachedSmoProperties) &&
(table.LedgerType == LedgerTableType.AppendOnlyLedgerTable || table.LedgerType == LedgerTableType.UpdatableLedgerTable))
{
return "Ledger";
}
if (table != null && IsPropertySupported("TemporalType", smoContext, table, CachedSmoProperties) && table.TemporalType != TableTemporalType.None)
{
return "Temporal";
@@ -70,13 +86,13 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
}
/// <summary>
/// Custom name for history table
/// Custom name and icon for history table
/// </summary>
internal partial class TableChildFactory : SmoChildFactoryBase
{
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
Table table = smoObject as Table;
Table? table = smoObject as Table;
if (table != null)
{
return $"{table.Schema}.{table.Name} ({SR.History_LabelPart})";
@@ -85,6 +101,22 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
return string.Empty;
}
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
try
{
Table? table = smoObject as Table;
if (table != null && IsPropertySupported("LedgerType", smoContext, table, CachedSmoProperties) &&
table.LedgerType == LedgerTableType.HistoryTable)
{
return "LedgerHistory";
}
}
catch {}
return string.Empty;
}
public override string GetNodePathName(object smoObject)
{
return TableCustomNodeHelper.GetPathName(smoObject);
@@ -95,7 +127,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
internal static string GetPathName(object smoObject)
{
Table table = smoObject as Table;
Table? table = smoObject as Table;
if (table != null)
{
return $"{table.Schema}.{table.Name}";

View File

@@ -785,6 +785,18 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{ TableTemporalType.SystemVersioned }
}
});
filters.Add(new NodePropertyFilter
{
Property = "LedgerType",
Type = typeof(Enum),
ValidFor = ValidForFlag.Sql2022|ValidForFlag.AzureV12,
Values = new List<object>
{
{ LedgerTableType.None },
{ LedgerTableType.AppendOnlyLedgerTable },
{ LedgerTableType.UpdatableLedgerTable }
}
});
return filters;
}
}
@@ -810,6 +822,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
ValidFor = ValidForFlag.Sql2016|ValidForFlag.Sql2017|ValidForFlag.Sql2019|ValidForFlag.Sql2022|ValidForFlag.AzureV12
});
properties.Add(new NodeSmoProperty
{
Name = "LedgerType",
ValidFor = ValidForFlag.Sql2022|ValidForFlag.AzureV12
});
properties.Add(new NodeSmoProperty
{
Name = "IsExternal",
ValidFor = ValidForFlag.Sql2016|ValidForFlag.Sql2017|ValidForFlag.Sql2019|ValidForFlag.Sql2022|ValidForFlag.AzureV12|ValidForFlag.SqlOnDemand
@@ -1312,21 +1329,56 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
get
{
var filters = new List<INodeFilter>();
filters.Add(new NodePropertyFilter
filters.Add(new NodeOrFilter
{
Property = "TemporalType",
Type = typeof(Enum),
TypeToReverse = typeof(SqlHistoryTableQuerier),
ValidFor = ValidForFlag.Sql2016|ValidForFlag.Sql2017|ValidForFlag.Sql2019|ValidForFlag.Sql2022|ValidForFlag.AzureV12,
Values = new List<object>
{
{ TableTemporalType.HistoryTable }
FilterList = new List<NodePropertyFilter> {
new NodePropertyFilter
{
Property = "TemporalType",
Type = typeof(Enum),
TypeToReverse = typeof(SqlHistoryTableQuerier),
ValidFor = ValidForFlag.Sql2016|ValidForFlag.Sql2017|ValidForFlag.Sql2019|ValidForFlag.Sql2022|ValidForFlag.AzureV12,
Values = new List<object>
{
{ TableTemporalType.HistoryTable }
}
},
new NodePropertyFilter
{
Property = "LedgerType",
Type = typeof(Enum),
TypeToReverse = typeof(SqlHistoryTableQuerier),
ValidFor = ValidForFlag.Sql2022|ValidForFlag.AzureV12,
Values = new List<object>
{
{ LedgerTableType.HistoryTable }
}
},
}
});
return filters;
}
}
public override IEnumerable<NodeSmoProperty> SmoProperties
{
get
{
var properties = new List<NodeSmoProperty>();
properties.Add(new NodeSmoProperty
{
Name = "LedgerType",
ValidFor = ValidForFlag.Sql2022|ValidForFlag.AzureV12
});
properties.Add(new NodeSmoProperty
{
Name = "TemporalType",
ValidFor = ValidForFlag.Sql2016|ValidForFlag.Sql2017|ValidForFlag.Sql2019|ValidForFlag.Sql2022|ValidForFlag.AzureV12
});
return properties;
}
}
protected override void OnExpandPopulateFolders(IList<TreeNode> currentChildren, TreeNode parent)
{
currentChildren.Add(new FolderNode {

View File

@@ -71,17 +71,23 @@
</Node>
<Node Name="Tables" LocLabel="SR.SchemaHierarchy_Tables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableTreeNode">
<Filters >
<Filters>
<Filter Property="IsSystemObject" Value="0" Type="bool" />
<Filter Property="TemporalType" Type="Enum" ValidFor="Sql2016|Sql2017|Sql2019|Sql2022|AzureV12">
<Value>TableTemporalType.None</Value>
<Value>TableTemporalType.SystemVersioned</Value>
</Filter>
<Filter Property="LedgerType" Type="Enum" ValidFor="Sql2022|AzureV12">
<Value>LedgerTableType.None</Value>
<Value>LedgerTableType.AppendOnlyLedgerTable</Value>
<Value>LedgerTableType.UpdatableLedgerTable</Value>
</Filter>
</Filters>
<Properties>
<Property Name="IsFileTable" ValidFor="Sql2012|Sql2014|Sql2016|Sql2017|Sql2019|Sql2022"/>
<Property Name="IsSystemVersioned" ValidFor="Sql2016|Sql2017|Sql2019|Sql2022|AzureV12"/>
<Property Name="TemporalType" ValidFor="Sql2016|Sql2017|Sql2019|Sql2022|AzureV12"/>
<Property Name="TemporalType" ValidFor="Sql2016|Sql2017|Sql2019|Sql2022|AzureV12"/>
<Property Name="LedgerType" ValidFor="Sql2022|AzureV12"/>
<Property Name="IsExternal" ValidFor="Sql2016|Sql2017|Sql2019|Sql2022|AzureV12|SqlOnDemand"/>
</Properties>
<Child Name="SystemTables" IsSystemObject="1"/>
@@ -169,10 +175,19 @@
-->
<Node Name="Table" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable;SqlHistoryTable" TreeNode="HistoryTableTreeNode">
<Filters>
<Filter TypeToReverse="SqlHistoryTable" Property="TemporalType" Type="Enum" ValidFor="Sql2016|Sql2017|Sql2019|Sql2022|AzureV12">
<Value>TableTemporalType.HistoryTable</Value>
</Filter>
<Or>
<Filter TypeToReverse="SqlHistoryTable" Property="TemporalType" Type="Enum" ValidFor="Sql2016|Sql2017|Sql2019|Sql2022|AzureV12">
<Value>TableTemporalType.HistoryTable</Value>
</Filter>
<Filter TypeToReverse="SqlHistoryTable" Property="LedgerType" Type="Enum" ValidFor="Sql2022|AzureV12">
<Value>LedgerTableType.HistoryTable</Value>
</Filter>
</Or>
</Filters>
<Properties>
<Property Name="LedgerType" ValidFor="Sql2022|AzureV12"/>
<Property Name="TemporalType" ValidFor="Sql2016|Sql2017|Sql2019|Sql2022|AzureV12"/>
</Properties>
<Child Name="Columns"/>
<Child Name="Keys"/>
<Child Name="Constraints"/>

View File

@@ -0,0 +1,67 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Custom name for view
/// </summary>
internal partial class ViewsChildFactory : SmoChildFactoryBase
{
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
try
{
View? view = smoObject as View;
if (view != null &&
IsPropertySupported("LedgerViewType", smoContext, view, CachedSmoProperties) &&
view.LedgerViewType == LedgerViewType.LedgerView)
{
return $"{view.Schema}.{view.Name} ({SR.Ledger_LabelPart})";
}
}
catch {} //Ignore the exception and just not change create custom name
return string.Empty;
}
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
try
{
View? view = smoObject as View;
if (view != null && IsPropertySupported("LedgerViewType", smoContext, view, CachedSmoProperties) &&
view.LedgerViewType == LedgerViewType.LedgerView)
{
return "Ledger";
}
}
catch {} //Ignore the exception and just not change create custom name
return string.Empty;
}
public override string GetNodePathName(object smoObject)
{
return ViewCustomNodeHelper.GetPathName(smoObject);
}
}
internal static class ViewCustomNodeHelper
{
internal static string GetPathName(object smoObject)
{
View? view = smoObject as View;
if (view != null)
{
return $"{view.Schema}.{view.Name}";
}
return string.Empty;
}
}
}