Creating a new Sql Core project that stores OE classes. (#2165)

* init

* More fixes

* moving filters from contracts to core OE classes

* Fixing some tests

* More fixes and added doc comments

* Fixing tests

* Quick refactoring

* more cleanups

* cleanup

* Adding stateless OE

* Adding null checks

* Making group by schema independent of settings

* Fixing tests

* Removing node info from core oe code

* Fixing tests and moving OE code to its own project

* moving oe to own project

* Removing changes to Kusto

* Removing azure access token from service layer

* Fixing project description and title

* Fixing file name typo

* Removing unused  strings from service layer

* Fixing localized strings in tests
Adding comments to stateless OE

* Fixing stuff

* Update src/Microsoft.SqlTools.SqlCore/Microsoft.SqlTools.SqlCore.csproj

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* Fixing project nesting

* Fixing more stuff and removing OE class

* Cleanup

* Code cleanup

* fixing oe service provider

* Fixing test name

* Remove using

* Update src/Microsoft.SqlTools.SqlCore/ObjectExplorer/SmoModel/SmoQueryContext.cs

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* Fixing syntax error

* Adding project to locproject

* Fixing stuff

* Fixing errors

* sorting usings

---------

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
This commit is contained in:
Aasim Khan
2023-08-17 05:11:35 +00:00
committed by GitHub
parent 4ae9534ac8
commit 73c2a75fba
98 changed files with 6755 additions and 6116 deletions

View File

@@ -17,6 +17,7 @@ using AzureEdition = Microsoft.SqlTools.ServiceLayer.Admin.AzureSqlDbHelper.Azur
using System;
using System.Data;
using Microsoft.SqlTools.Utility;
using Microsoft.SqlTools.SqlCore.Utility;
namespace Microsoft.SqlTools.ServiceLayer.Admin
{
@@ -377,7 +378,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
private static string CreateAzureAlterDbStatement(string dbName, string options)
{
return string.Format(CultureInfo.InvariantCulture, AlterDbStatementFormat,
CUtils.EscapeString(CUtils.EscapeString(dbName, ']'), '\''),
StringUtils.EscapeString(StringUtils.EscapeString(dbName, ']'), '\''),
options);
}
}

View File

@@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Data.Common;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.SqlCore.Connection;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.Connection

View File

@@ -29,6 +29,7 @@ using Microsoft.SqlTools.Authentication;
using System.IO;
using Microsoft.SqlTools.Hosting.Utility;
using Constants = Microsoft.SqlTools.Hosting.Protocol.Constants;
using Microsoft.SqlTools.SqlCore.Connection;
namespace Microsoft.SqlTools.ServiceLayer.Connection
{
@@ -1983,24 +1984,4 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
return databaseName != null ? databaseName.IndexOf('@') != -1 : false;
}
}
public class AzureAccessToken : IRenewableToken
{
public DateTimeOffset TokenExpiry { get; set; }
public string Resource { get; set; }
public string Tenant { get; set; }
public string UserId { get; set; }
private string accessToken;
public AzureAccessToken(string accessToken)
{
this.accessToken = accessToken;
}
public string GetAccessToken()
{
return this.accessToken;
}
}
}

View File

@@ -1,27 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
{
public class SecurityToken
{
/// <summary>
/// Gets or sets the refresh token.
/// </summary>
public string Token { get; set; }
/// <summmary>
/// Gets or sets the token expiration, a Unix epoch
/// </summary>
public int? ExpiresOn { get; set; }
/// <summmary>
/// Gets or sets the token type, e.g. 'Bearer'
/// </summary>
public string? TokenType { get; set; }
}
}

View File

@@ -11,7 +11,7 @@ using System.Data.Common;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlTools.ServiceLayer.Admin.Contracts;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.SqlCore.Utility;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.Connection

View File

@@ -11,9 +11,9 @@ using System.Data.Common;
using Microsoft.Data.SqlClient;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
using Microsoft.SqlTools.ServiceLayer.Utility.SqlScriptFormatters;
using Microsoft.SqlTools.SqlCore.Connection;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.EditData

View File

@@ -82,7 +82,8 @@ namespace Microsoft.SqlTools.ServiceLayer
ExtensionServiceProvider serviceProvider = ExtensionServiceProvider.CreateDefaultServiceProvider(new string[] {
"microsofsqltoolscredentials.dll",
"microsoft.sqltools.hosting.dll",
"microsoftsqltoolsservicelayer.dll"
"microsoftsqltoolsservicelayer.dll",
"microsoftsqltoolssqlcore.dll"
});
serviceProvider.RegisterSingleService(sqlToolsContext);
serviceProvider.RegisterSingleService(serviceHost);

View File

@@ -6,7 +6,7 @@
#nullable disable
using Microsoft.SqlTools.ServiceLayer.LanguageExtensibility.Contracts;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.SqlCore.Utility;
using Microsoft.SqlTools.Utility;
using System;
using System.Collections.Generic;
@@ -67,7 +67,7 @@ ORDER BY platform";
private string GetDropScript(string languageName)
{
return $@"{DropScript} [{CUtils.EscapeStringCBracket(languageName)}]";
return $@"{DropScript} [{StringUtils.EscapeStringCBracket(languageName)}]";
}
/// <summary>
@@ -262,7 +262,7 @@ ORDER BY platform";
contentScript = $"{contentScript}{seperator}{GetLanguageContent(content, i, parameters)}";
}
string ownerScript = string.IsNullOrWhiteSpace(language.Owner) ? "" : $"AUTHORIZATION [{CUtils.EscapeStringCBracket(language.Owner)}]";
string ownerScript = string.IsNullOrWhiteSpace(language.Owner) ? "" : $"AUTHORIZATION [{StringUtils.EscapeStringCBracket(language.Owner)}]";
string scriptAction = modifyType == ModifyType.Create ? CreateScript : AlterScript;
string contentAction = "FROM";
if (modifyType == ModifyType.Alter)
@@ -281,7 +281,7 @@ ORDER BY platform";
}
}
return $@"
{scriptAction} [{CUtils.EscapeStringCBracket(language.Name)}]
{scriptAction} [{StringUtils.EscapeStringCBracket(language.Name)}]
{ownerScript}
{contentAction} {contentScript}
";
@@ -289,7 +289,7 @@ ORDER BY platform";
private string AddStringParameter(string paramName, string prefix, string paramValue)
{
string value = string.IsNullOrWhiteSpace(paramValue) ? paramValue : CUtils.EscapeStringSQuote(paramValue);
string value = string.IsNullOrWhiteSpace(paramValue) ? paramValue : StringUtils.EscapeStringSQuote(paramValue);
return $"{prefix} {paramName} = N'{value}'";
}

File diff suppressed because it is too large Load Diff

View File

@@ -678,854 +678,6 @@
<value>Scalar column missing scale</value>
<comment></comment>
</data>
<data name="TreeNodeError" xml:space="preserve">
<value>Error expanding: {0}</value>
<comment></comment>
</data>
<data name="ServerNodeConnectionError" xml:space="preserve">
<value>Error connecting to {0}</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Aggregates" xml:space="preserve">
<value>Aggregates</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerRoles" xml:space="preserve">
<value>Server Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ApplicationRoles" xml:space="preserve">
<value>Application Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Assemblies" xml:space="preserve">
<value>Assemblies</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_AssemblyFiles" xml:space="preserve">
<value>Assembly Files</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_AsymmetricKeys" xml:space="preserve">
<value>Asymmetric Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseAsymmetricKeys" xml:space="preserve">
<value>Asymmetric Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DataCompressionOptions" xml:space="preserve">
<value>Data Compression Options</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Certificates" xml:space="preserve">
<value>Certificates</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FileTables" xml:space="preserve">
<value>FileTables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseCertificates" xml:space="preserve">
<value>Certificates</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_CheckConstraints" xml:space="preserve">
<value>Check Constraints</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Columns" xml:space="preserve">
<value>Columns</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Constraints" xml:space="preserve">
<value>Constraints</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Contracts" xml:space="preserve">
<value>Contracts</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Credentials" xml:space="preserve">
<value>Credentials</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ErrorMessages" xml:space="preserve">
<value>Error Messages</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerRoleMembership" xml:space="preserve">
<value>Server Role Membership</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseOptions" xml:space="preserve">
<value>Database Options</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseRoles" xml:space="preserve">
<value>Database Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_RoleMemberships" xml:space="preserve">
<value>Role Memberships</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseTriggers" xml:space="preserve">
<value>Database Triggers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DefaultConstraints" xml:space="preserve">
<value>Default Constraints</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Defaults" xml:space="preserve">
<value>Defaults</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Sequences" xml:space="preserve">
<value>Sequences</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Endpoints" xml:space="preserve">
<value>Endpoints</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_EventNotifications" xml:space="preserve">
<value>Event Notifications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerEventNotifications" xml:space="preserve">
<value>Server Event Notifications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExtendedProperties" xml:space="preserve">
<value>Extended Properties</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FileGroups" xml:space="preserve">
<value>Filegroups</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ForeignKeys" xml:space="preserve">
<value>Foreign Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FullTextCatalogs" xml:space="preserve">
<value>Full-Text Catalogs</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FullTextIndexes" xml:space="preserve">
<value>Full-Text Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Functions" xml:space="preserve">
<value>Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Indexes" xml:space="preserve">
<value>Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_InlineFunctions" xml:space="preserve">
<value>Inline Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Keys" xml:space="preserve">
<value>Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_LinkedServers" xml:space="preserve">
<value>Linked Servers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Logins" xml:space="preserve">
<value>Logins</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_MasterKey" xml:space="preserve">
<value>Master Key</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_MasterKeys" xml:space="preserve">
<value>Master Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_MessageTypes" xml:space="preserve">
<value>Message Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_MultiSelectFunctions" xml:space="preserve">
<value>Table-Valued Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Parameters" xml:space="preserve">
<value>Parameters</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_PartitionFunctions" xml:space="preserve">
<value>Partition Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_PartitionSchemes" xml:space="preserve">
<value>Partition Schemes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Permissions" xml:space="preserve">
<value>Permissions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_PrimaryKeys" xml:space="preserve">
<value>Primary Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Programmability" xml:space="preserve">
<value>Programmability</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Queues" xml:space="preserve">
<value>Queues</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_RemoteServiceBindings" xml:space="preserve">
<value>Remote Service Bindings</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ReturnedColumns" xml:space="preserve">
<value>Returned Columns</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Roles" xml:space="preserve">
<value>Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Routes" xml:space="preserve">
<value>Routes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Rules" xml:space="preserve">
<value>Rules</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Schemas" xml:space="preserve">
<value>Schemas</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_BuiltInSchema" xml:space="preserve">
<value>Built-in Schemas</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Security" xml:space="preserve">
<value>Security</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerObjects" xml:space="preserve">
<value>Server Objects</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Management" xml:space="preserve">
<value>Management</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerTriggers" xml:space="preserve">
<value>Triggers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServiceBroker" xml:space="preserve">
<value>Service Broker</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Services" xml:space="preserve">
<value>Services</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Signatures" xml:space="preserve">
<value>Signatures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_LogFiles" xml:space="preserve">
<value>Log Files</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Statistics" xml:space="preserve">
<value>Statistics</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Storage" xml:space="preserve">
<value>Storage</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_StoredProcedures" xml:space="preserve">
<value>Stored Procedures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SymmetricKeys" xml:space="preserve">
<value>Symmetric Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Synonyms" xml:space="preserve">
<value>Synonyms</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Tables" xml:space="preserve">
<value>Tables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Triggers" xml:space="preserve">
<value>Triggers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Types" xml:space="preserve">
<value>Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UniqueKeys" xml:space="preserve">
<value>Unique Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UserDefinedDataTypes" xml:space="preserve">
<value>User-Defined Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UserDefinedTypes" xml:space="preserve">
<value>User-Defined Types (CLR)</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Users" xml:space="preserve">
<value>Users</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Views" xml:space="preserve">
<value>Views</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_XmlIndexes" xml:space="preserve">
<value>XML Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_XMLSchemaCollections" xml:space="preserve">
<value>XML Schema Collections</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UserDefinedTableTypes" xml:space="preserve">
<value>User-Defined Table Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FilegroupFiles" xml:space="preserve">
<value>Files</value>
<comment></comment>
</data>
<data name="MissingCaption" xml:space="preserve">
<value>Missing Caption</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_BrokerPriorities" xml:space="preserve">
<value>Broker Priorities</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_CryptographicProviders" xml:space="preserve">
<value>Cryptographic Providers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseAuditSpecifications" xml:space="preserve">
<value>Database Audit Specifications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseEncryptionKeys" xml:space="preserve">
<value>Database Encryption Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_EventSessions" xml:space="preserve">
<value>Event Sessions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FullTextStopLists" xml:space="preserve">
<value>Full Text Stoplists</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ResourcePools" xml:space="preserve">
<value>Resource Pools</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerAudits" xml:space="preserve">
<value>Audits</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerAuditSpecifications" xml:space="preserve">
<value>Server Audit Specifications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SpatialIndexes" xml:space="preserve">
<value>Spatial Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_WorkloadGroups" xml:space="preserve">
<value>Workload Groups</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SqlFiles" xml:space="preserve">
<value>SQL Files</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerFunctions" xml:space="preserve">
<value>Server Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SqlType" xml:space="preserve">
<value>SQL Type</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerOptions" xml:space="preserve">
<value>Server Options</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseDiagrams" xml:space="preserve">
<value>Database Diagrams</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemTables" xml:space="preserve">
<value>System Tables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Databases" xml:space="preserve">
<value>Databases</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemContracts" xml:space="preserve">
<value>System Contracts</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemDatabases" xml:space="preserve">
<value>System Databases</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemMessageTypes" xml:space="preserve">
<value>System Message Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemQueues" xml:space="preserve">
<value>System Queues</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemServices" xml:space="preserve">
<value>System Services</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemStoredProcedures" xml:space="preserve">
<value>System Stored Procedures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemViews" xml:space="preserve">
<value>System Views</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DataTierApplications" xml:space="preserve">
<value>Data-tier Applications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExtendedStoredProcedures" xml:space="preserve">
<value>Extended Stored Procedures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemAggregateFunctions" xml:space="preserve">
<value>Aggregate Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemApproximateNumerics" xml:space="preserve">
<value>Approximate Numerics</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemBinaryStrings" xml:space="preserve">
<value>Binary Strings</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemCharacterStrings" xml:space="preserve">
<value>Character Strings</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemCLRDataTypes" xml:space="preserve">
<value>CLR Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemConfigurationFunctions" xml:space="preserve">
<value>Configuration Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemCursorFunctions" xml:space="preserve">
<value>Cursor Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemDataTypes" xml:space="preserve">
<value>System Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemDateAndTime" xml:space="preserve">
<value>Date and Time</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemDateAndTimeFunctions" xml:space="preserve">
<value>Date and Time Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemExactNumerics" xml:space="preserve">
<value>Exact Numerics</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemFunctions" xml:space="preserve">
<value>System Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemHierarchyIdFunctions" xml:space="preserve">
<value>Hierarchy Id Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemMathematicalFunctions" xml:space="preserve">
<value>Mathematical Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemMetadataFunctions" xml:space="preserve">
<value>Metadata Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemOtherDataTypes" xml:space="preserve">
<value>Other Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemOtherFunctions" xml:space="preserve">
<value>Other Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemRowsetFunctions" xml:space="preserve">
<value>Rowset Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemSecurityFunctions" xml:space="preserve">
<value>Security Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemSpatialDataTypes" xml:space="preserve">
<value>Spatial Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemStringFunctions" xml:space="preserve">
<value>String Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemSystemStatisticalFunctions" xml:space="preserve">
<value>System Statistical Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemTextAndImageFunctions" xml:space="preserve">
<value>Text and Image Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemUnicodeCharacterStrings" xml:space="preserve">
<value>Unicode Character Strings</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_AggregateFunctions" xml:space="preserve">
<value>Aggregate Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ScalarValuedFunctions" xml:space="preserve">
<value>Scalar-valued Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_TableValuedFunctions" xml:space="preserve">
<value>Table-valued Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemExtendedStoredProcedures" xml:space="preserve">
<value>System Extended Stored Procedures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_BuiltInType" xml:space="preserve">
<value>Built-in Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_BuiltInServerRole" xml:space="preserve">
<value>Built-in Server Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UserWithPassword" xml:space="preserve">
<value>User with Password</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SearchPropertyList" xml:space="preserve">
<value>Search Property List</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SecurityPolicies" xml:space="preserve">
<value>Security Policies</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SecurityPredicates" xml:space="preserve">
<value>Security Predicates</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerRole" xml:space="preserve">
<value>Server Role</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SearchPropertyLists" xml:space="preserve">
<value>Search Property Lists</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ColumnStoreIndexes" xml:space="preserve">
<value>Column Store Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_TableTypeIndexes" xml:space="preserve">
<value>Table Type Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Server" xml:space="preserve">
<value>Server</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SelectiveXmlIndexes" xml:space="preserve">
<value>Selective XML Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_XmlNamespaces" xml:space="preserve">
<value>XML Namespaces</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_XmlTypedPromotedPaths" xml:space="preserve">
<value>XML Typed Promoted Paths</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SqlTypedPromotedPaths" xml:space="preserve">
<value>T-SQL Typed Promoted Paths</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseScopedCredentials" xml:space="preserve">
<value>Database Scoped Credentials</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExternalDataSources" xml:space="preserve">
<value>External Data Sources</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExternalFileFormats" xml:space="preserve">
<value>External File Formats</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExternalResources" xml:space="preserve">
<value>External Resources</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExternalTables" xml:space="preserve">
<value>External Tables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DroppedLedgerColumns" xml:space="preserve">
<value>Dropped Ledger Columns</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DroppedLedgerTables" xml:space="preserve">
<value>Dropped Ledger Tables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DroppedLedgerViews" xml:space="preserve">
<value>Dropped Ledger Views</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_AlwaysEncryptedKeys" xml:space="preserve">
<value>Always Encrypted Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ColumnMasterKeys" xml:space="preserve">
<value>Column Master Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ColumnEncryptionKeys" xml:space="preserve">
<value>Column Encryption Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SubroutineParameterLabelFormatString" xml:space="preserve">
<value>{0} ({1}, {2}, {3})</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SubroutineParameterNoDefaultLabel" xml:space="preserve">
<value>No default</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SubroutineParameterInputLabel" xml:space="preserve">
<value>Input</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SubroutineParameterInputOutputLabel" xml:space="preserve">
<value>Input/Output</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SubroutineParameterInputReadOnlyLabel" xml:space="preserve">
<value>Input/ReadOnly</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SubroutineParameterInputOutputReadOnlyLabel" xml:space="preserve">
<value>Input/Output/ReadOnly</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SubroutineParameterDefaultLabel" xml:space="preserve">
<value>Default</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_NullColumn_Label" xml:space="preserve">
<value>null</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_NotNullColumn_Label" xml:space="preserve">
<value>not null</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UDDTLabelWithType" xml:space="preserve">
<value>{0} ({1}, {2})</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UDDTLabelWithoutType" xml:space="preserve">
<value>{0} ({1})</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ComputedColumnLabelWithType" xml:space="preserve">
<value>{0} ({1}Computed, {2}, {3})</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ComputedColumnLabelWithoutType" xml:space="preserve">
<value>{0} ({1}Computed)</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ColumnSetLabelWithoutType" xml:space="preserve">
<value>{0} (Column Set, {1})</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ColumnSetLabelWithType" xml:space="preserve">
<value>{0} (Column Set, {1}{2}, {3})</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ColumnSetLabelWithTypeAndKeyString" xml:space="preserve">
<value>{0} (Column Set, {1}, {2}, {3})</value>
<comment></comment>
</data>
<data name="UniqueIndex_LabelPart" xml:space="preserve">
<value>Unique</value>
<comment></comment>
</data>
<data name="NonUniqueIndex_LabelPart" xml:space="preserve">
<value>Non-Unique</value>
<comment></comment>
</data>
<data name="ClusteredIndex_LabelPart" xml:space="preserve">
<value>Clustered</value>
<comment></comment>
</data>
<data name="NonClusteredIndex_LabelPart" xml:space="preserve">
<value>Non-Clustered</value>
<comment></comment>
</data>
<data name="History_LabelPart" xml:space="preserve">
<value>History</value>
<comment></comment>
</data>
<data name="SystemVersioned_LabelPart" xml:space="preserve">
<value>System-Versioned</value>
<comment></comment>
</data>
<data name="UpdatableLedger_LabelPart" xml:space="preserve">
<value>Updatable Ledger</value>
<comment></comment>
</data>
<data name="AppendOnlyLedger_LabelPart" xml:space="preserve">
<value>Append-Only Ledger</value>
<comment></comment>
</data>
<data name="Ledger_LabelPart" xml:space="preserve">
<value>Ledger</value>
<comment></comment>
</data>
<data name="External_LabelPart" xml:space="preserve">
<value>External</value>
<comment></comment>
</data>
<data name="FileTable_LabelPart" xml:space="preserve">
<value>File Table</value>
<comment></comment>
</data>
<data name="DatabaseNotAccessible" xml:space="preserve">
<value>The database {0} is not accessible.</value>
<comment></comment>
</data>
<data name="FilterName" xml:space="preserve">
<value>Name</value>
<comment></comment>
</data>
<data name="FilterNameDescription" xml:space="preserve">
<value>Include or exclude objects based on the name or part of a name.</value>
<comment></comment>
</data>
<data name="FilterSchema" xml:space="preserve">
<value>Schema</value>
<comment></comment>
</data>
<data name="FilterSchemaDescription" xml:space="preserve">
<value> Include or exclude objects based on the schema or part of a schema name.</value>
<comment></comment>
</data>
<data name="FilterOwner" xml:space="preserve">
<value>Owner</value>
<comment></comment>
</data>
<data name="FilterOwnerDescription" xml:space="preserve">
<value>Include or exclude objects based on the owner or part of an owner name.</value>
<comment></comment>
</data>
<data name="FilterDurabilityType" xml:space="preserve">
<value>Durability Type</value>
<comment></comment>
</data>
<data name="FilterDurabilityTypeDescription" xml:space="preserve">
<value>Include or exclude objects based on the durability type.</value>
<comment></comment>
</data>
<data name="FilterDurabilitySchemaOnly" xml:space="preserve">
<value>Schema Only</value>
<comment></comment>
</data>
<data name="FilterDurabilitySchemaAndData" xml:space="preserve">
<value>Schema and Data</value>
<comment></comment>
</data>
<data name="FilterIsMemoryOptimized" xml:space="preserve">
<value>Is Memory Optimized</value>
<comment></comment>
</data>
<data name="FilterIsMemoryOptimizedDescription" xml:space="preserve">
<value>Include or exclude objects based on whether the object is memory optimized.</value>
<comment></comment>
</data>
<data name="FilterCreateDate" xml:space="preserve">
<value>Create Date</value>
<comment></comment>
</data>
<data name="FilterCreateDateDescription" xml:space="preserve">
<value>Include or exclude objects based on their creation date.</value>
<comment></comment>
</data>
<data name="FilterIsNativelyCompiled" xml:space="preserve">
<value>Is Natively Compiled</value>
<comment></comment>
</data>
<data name="FilterIsNativelyCompiledDescription" xml:space="preserve">
<value>Include or exclude objects based on whether the object is natively compiled.</value>
<comment></comment>
</data>
<data name="FilterInPrimaryKey" xml:space="preserve">
<value>In Primary Key</value>
<comment></comment>
</data>
<data name="FilterInPrimaryKeyDescription" xml:space="preserve">
<value>Include or exclude objects based on whether the column is in a primary key.</value>
<comment></comment>
</data>
<data name="ScriptingParams_ConnectionString_Property_Invalid" xml:space="preserve">
<value>Error parsing ScriptingParams.ConnectionString property.</value>
<comment></comment>

View File

@@ -327,416 +327,6 @@ SqlScriptFormatterLengthTypeMissingSize = Column with length is missing size
SqlScriptFormatterScalarTypeMissingScale = Scalar column missing scale
############################################################################
# Object Explorer Service
TreeNodeError = Error expanding: {0}
ServerNodeConnectionError = Error connecting to {0}
SchemaHierarchy_Aggregates = Aggregates
SchemaHierarchy_ServerRoles = Server Roles
SchemaHierarchy_ApplicationRoles = Application Roles
SchemaHierarchy_Assemblies = Assemblies
SchemaHierarchy_AssemblyFiles = Assembly Files
SchemaHierarchy_AsymmetricKeys = Asymmetric Keys
SchemaHierarchy_DatabaseAsymmetricKeys = Asymmetric Keys
SchemaHierarchy_DataCompressionOptions = Data Compression Options
SchemaHierarchy_Certificates = Certificates
SchemaHierarchy_FileTables = FileTables
SchemaHierarchy_DatabaseCertificates = Certificates
SchemaHierarchy_CheckConstraints = Check Constraints
SchemaHierarchy_Columns = Columns
SchemaHierarchy_Constraints = Constraints
SchemaHierarchy_Contracts = Contracts
SchemaHierarchy_Credentials = Credentials
SchemaHierarchy_ErrorMessages = Error Messages
SchemaHierarchy_ServerRoleMembership = Server Role Membership
SchemaHierarchy_DatabaseOptions = Database Options
SchemaHierarchy_DatabaseRoles = Database Roles
SchemaHierarchy_RoleMemberships = Role Memberships
SchemaHierarchy_DatabaseTriggers = Database Triggers
SchemaHierarchy_DefaultConstraints = Default Constraints
SchemaHierarchy_Defaults = Defaults
SchemaHierarchy_Sequences = Sequences
SchemaHierarchy_Endpoints = Endpoints
SchemaHierarchy_EventNotifications = Event Notifications
SchemaHierarchy_ServerEventNotifications = Server Event Notifications
SchemaHierarchy_ExtendedProperties = Extended Properties
SchemaHierarchy_FileGroups = Filegroups
SchemaHierarchy_ForeignKeys = Foreign Keys
SchemaHierarchy_FullTextCatalogs = Full-Text Catalogs
SchemaHierarchy_FullTextIndexes = Full-Text Indexes
SchemaHierarchy_Functions = Functions
SchemaHierarchy_Indexes = Indexes
SchemaHierarchy_InlineFunctions = Inline Functions
SchemaHierarchy_Keys = Keys
SchemaHierarchy_LinkedServers = Linked Servers
SchemaHierarchy_Logins = Logins
SchemaHierarchy_MasterKey = Master Key
SchemaHierarchy_MasterKeys = Master Keys
SchemaHierarchy_MessageTypes = Message Types
SchemaHierarchy_MultiSelectFunctions = Table-Valued Functions
SchemaHierarchy_Parameters = Parameters
SchemaHierarchy_PartitionFunctions = Partition Functions
SchemaHierarchy_PartitionSchemes = Partition Schemes
SchemaHierarchy_Permissions = Permissions
SchemaHierarchy_PrimaryKeys = Primary Keys
SchemaHierarchy_Programmability = Programmability
SchemaHierarchy_Queues = Queues
SchemaHierarchy_RemoteServiceBindings = Remote Service Bindings
SchemaHierarchy_ReturnedColumns = Returned Columns
SchemaHierarchy_Roles = Roles
SchemaHierarchy_Routes = Routes
SchemaHierarchy_Rules = Rules
SchemaHierarchy_Schemas = Schemas
SchemaHierarchy_BuiltInSchema = Built-in Schemas
SchemaHierarchy_Security = Security
SchemaHierarchy_ServerObjects = Server Objects
SchemaHierarchy_Management = Management
SchemaHierarchy_ServerTriggers = Triggers
SchemaHierarchy_ServiceBroker = Service Broker
SchemaHierarchy_Services = Services
SchemaHierarchy_Signatures = Signatures
SchemaHierarchy_LogFiles = Log Files
SchemaHierarchy_Statistics = Statistics
SchemaHierarchy_Storage = Storage
SchemaHierarchy_StoredProcedures = Stored Procedures
SchemaHierarchy_SymmetricKeys = Symmetric Keys
SchemaHierarchy_Synonyms = Synonyms
SchemaHierarchy_Tables = Tables
SchemaHierarchy_Triggers = Triggers
SchemaHierarchy_Types = Types
SchemaHierarchy_UniqueKeys = Unique Keys
SchemaHierarchy_UserDefinedDataTypes = User-Defined Data Types
SchemaHierarchy_UserDefinedTypes = User-Defined Types (CLR)
SchemaHierarchy_Users = Users
SchemaHierarchy_Views = Views
SchemaHierarchy_XmlIndexes = XML Indexes
SchemaHierarchy_XMLSchemaCollections = XML Schema Collections
SchemaHierarchy_UserDefinedTableTypes = User-Defined Table Types
SchemaHierarchy_FilegroupFiles = Files
MissingCaption = Missing Caption
SchemaHierarchy_BrokerPriorities = Broker Priorities
SchemaHierarchy_CryptographicProviders = Cryptographic Providers
SchemaHierarchy_DatabaseAuditSpecifications = Database Audit Specifications
SchemaHierarchy_DatabaseEncryptionKeys = Database Encryption Keys
SchemaHierarchy_EventSessions = Event Sessions
SchemaHierarchy_FullTextStopLists = Full Text Stoplists
SchemaHierarchy_ResourcePools = Resource Pools
SchemaHierarchy_ServerAudits = Audits
SchemaHierarchy_ServerAuditSpecifications = Server Audit Specifications
SchemaHierarchy_SpatialIndexes = Spatial Indexes
SchemaHierarchy_WorkloadGroups = Workload Groups
SchemaHierarchy_SqlFiles = SQL Files
SchemaHierarchy_ServerFunctions = Server Functions
SchemaHierarchy_SqlType = SQL Type
SchemaHierarchy_ServerOptions = Server Options
SchemaHierarchy_DatabaseDiagrams = Database Diagrams
SchemaHierarchy_SystemTables = System Tables
SchemaHierarchy_Databases = Databases
SchemaHierarchy_SystemContracts = System Contracts
SchemaHierarchy_SystemDatabases = System Databases
SchemaHierarchy_SystemMessageTypes = System Message Types
SchemaHierarchy_SystemQueues = System Queues
SchemaHierarchy_SystemServices = System Services
SchemaHierarchy_SystemStoredProcedures = System Stored Procedures
SchemaHierarchy_SystemViews = System Views
SchemaHierarchy_DataTierApplications = Data-tier Applications
SchemaHierarchy_ExtendedStoredProcedures = Extended Stored Procedures
SchemaHierarchy_SystemAggregateFunctions = Aggregate Functions
SchemaHierarchy_SystemApproximateNumerics = Approximate Numerics
SchemaHierarchy_SystemBinaryStrings = Binary Strings
SchemaHierarchy_SystemCharacterStrings = Character Strings
SchemaHierarchy_SystemCLRDataTypes = CLR Data Types
SchemaHierarchy_SystemConfigurationFunctions = Configuration Functions
SchemaHierarchy_SystemCursorFunctions = Cursor Functions
SchemaHierarchy_SystemDataTypes = System Data Types
SchemaHierarchy_SystemDateAndTime = Date and Time
SchemaHierarchy_SystemDateAndTimeFunctions = Date and Time Functions
SchemaHierarchy_SystemExactNumerics = Exact Numerics
SchemaHierarchy_SystemFunctions = System Functions
SchemaHierarchy_SystemHierarchyIdFunctions = Hierarchy Id Functions
SchemaHierarchy_SystemMathematicalFunctions = Mathematical Functions
SchemaHierarchy_SystemMetadataFunctions = Metadata Functions
SchemaHierarchy_SystemOtherDataTypes = Other Data Types
SchemaHierarchy_SystemOtherFunctions = Other Functions
SchemaHierarchy_SystemRowsetFunctions = Rowset Functions
SchemaHierarchy_SystemSecurityFunctions = Security Functions
SchemaHierarchy_SystemSpatialDataTypes = Spatial Data Types
SchemaHierarchy_SystemStringFunctions = String Functions
SchemaHierarchy_SystemSystemStatisticalFunctions = System Statistical Functions
SchemaHierarchy_SystemTextAndImageFunctions = Text and Image Functions
SchemaHierarchy_SystemUnicodeCharacterStrings = Unicode Character Strings
SchemaHierarchy_AggregateFunctions = Aggregate Functions
SchemaHierarchy_ScalarValuedFunctions = Scalar-valued Functions
SchemaHierarchy_TableValuedFunctions = Table-valued Functions
SchemaHierarchy_SystemExtendedStoredProcedures = System Extended Stored Procedures
SchemaHierarchy_BuiltInType = Built-in Types
SchemaHierarchy_BuiltInServerRole = Built-in Server Roles
SchemaHierarchy_UserWithPassword = User with Password
SchemaHierarchy_SearchPropertyList = Search Property List
SchemaHierarchy_SecurityPolicies = Security Policies
SchemaHierarchy_SecurityPredicates = Security Predicates
SchemaHierarchy_ServerRole = Server Role
SchemaHierarchy_SearchPropertyLists = Search Property Lists
SchemaHierarchy_ColumnStoreIndexes = Column Store Indexes
SchemaHierarchy_TableTypeIndexes = Table Type Indexes
SchemaHierarchy_Server = Server
SchemaHierarchy_SelectiveXmlIndexes = Selective XML Indexes
SchemaHierarchy_XmlNamespaces = XML Namespaces
SchemaHierarchy_XmlTypedPromotedPaths = XML Typed Promoted Paths
SchemaHierarchy_SqlTypedPromotedPaths = T-SQL Typed Promoted Paths
SchemaHierarchy_DatabaseScopedCredentials = Database Scoped Credentials
SchemaHierarchy_ExternalDataSources = External Data Sources
SchemaHierarchy_ExternalFileFormats = External File Formats
SchemaHierarchy_ExternalResources = External Resources
SchemaHierarchy_ExternalTables = External Tables
SchemaHierarchy_DroppedLedgerColumns = Dropped Ledger Columns
SchemaHierarchy_DroppedLedgerTables = Dropped Ledger Tables
SchemaHierarchy_DroppedLedgerViews = Dropped Ledger Views
SchemaHierarchy_AlwaysEncryptedKeys = Always Encrypted Keys
SchemaHierarchy_ColumnMasterKeys = Column Master Keys
SchemaHierarchy_ColumnEncryptionKeys = Column Encryption Keys
SchemaHierarchy_SubroutineParameterLabelFormatString = {0} ({1}, {2}, {3})
SchemaHierarchy_SubroutineParameterNoDefaultLabel = No default
SchemaHierarchy_SubroutineParameterInputLabel = Input
SchemaHierarchy_SubroutineParameterInputOutputLabel = Input/Output
SchemaHierarchy_SubroutineParameterInputReadOnlyLabel = Input/ReadOnly
SchemaHierarchy_SubroutineParameterInputOutputReadOnlyLabel = Input/Output/ReadOnly
SchemaHierarchy_SubroutineParameterDefaultLabel = Default
SchemaHierarchy_NullColumn_Label = null
SchemaHierarchy_NotNullColumn_Label = not null
SchemaHierarchy_UDDTLabelWithType = {0} ({1}, {2})
SchemaHierarchy_UDDTLabelWithoutType = {0} ({1})
SchemaHierarchy_ComputedColumnLabelWithType = {0} ({1}Computed, {2}, {3})
SchemaHierarchy_ComputedColumnLabelWithoutType = {0} ({1}Computed)
SchemaHierarchy_ColumnSetLabelWithoutType = {0} (Column Set, {1})
SchemaHierarchy_ColumnSetLabelWithType = {0} (Column Set, {1}{2}, {3})
SchemaHierarchy_ColumnSetLabelWithTypeAndKeyString = {0} (Column Set, {1}, {2}, {3})
UniqueIndex_LabelPart = Unique
NonUniqueIndex_LabelPart = Non-Unique
ClusteredIndex_LabelPart = Clustered
NonClusteredIndex_LabelPart = Non-Clustered
History_LabelPart = History
SystemVersioned_LabelPart = System-Versioned
UpdatableLedger_LabelPart = Updatable Ledger
AppendOnlyLedger_LabelPart = Append-Only Ledger
Ledger_LabelPart = Ledger
External_LabelPart = External
FileTable_LabelPart = File Table
DatabaseNotAccessible = The database {0} is not accessible.
FilterName = Name
FilterNameDescription = Include or exclude objects based on the name or part of a name.
FilterSchema = Schema
FilterSchemaDescription = Include or exclude objects based on the schema or part of a schema name.
FilterOwner = Owner
FilterOwnerDescription = Include or exclude objects based on the owner or part of an owner name.
FilterDurabilityType = Durability Type
FilterDurabilityTypeDescription = Include or exclude objects based on the durability type.
FilterDurabilitySchemaOnly = Schema Only
FilterDurabilitySchemaAndData = Schema and Data
FilterIsMemoryOptimized = Is Memory Optimized
FilterIsMemoryOptimizedDescription = Include or exclude objects based on whether the object is memory optimized.
FilterCreateDate = Create Date
FilterCreateDateDescription = Include or exclude objects based on their creation date.
FilterIsNativelyCompiled = Is Natively Compiled
FilterIsNativelyCompiledDescription = Include or exclude objects based on whether the object is natively compiled.
FilterInPrimaryKey = In Primary Key
FilterInPrimaryKeyDescription = Include or exclude objects based on whether the column is in a primary key.
############################################################################
# Scripting Service

File diff suppressed because it is too large Load Diff

View File

@@ -8,9 +8,9 @@
using System;
using Microsoft.Data.SqlClient;
using System.Globalization;
using System.Text;
using Microsoft.SqlServer.Management.Common;
using SMO = Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.SqlCore.Utility;
namespace Microsoft.SqlTools.ServiceLayer.Management
{
@@ -173,7 +173,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
{
string query = string.Format(CultureInfo.InvariantCulture,
"select top 1 1 from [{0}].sys.filegroups where type = 'FX'",
CUtils.EscapeString(dbName, ']'));
StringUtils.EscapeString(dbName, ']'));
if (server.ConnectionContext.ExecuteScalar(query) != null)
{
hasMemoryOptimizedFileGroup = true;
@@ -552,101 +552,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
return sqlerror.Number;
}
/// <summary>
/// Function doubles up specified character in a string
/// </summary>
/// <param name="s"></param>
/// <param name="cEsc"></param>
/// <returns></returns>
public static String EscapeString(string s, char cEsc)
{
if (string.IsNullOrWhiteSpace(s))
{
return s;
}
StringBuilder sb = new StringBuilder(s.Length * 2);
foreach (char c in s)
{
sb.Append(c);
if (cEsc == c)
sb.Append(c);
}
return sb.ToString();
}
/// <summary>
/// Function doubles up ']' character in a string
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static String EscapeStringCBracket(string s)
{
return CUtils.EscapeString(s, ']');
}
/// <summary>
/// Function doubles up '\'' character in a string
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static String EscapeStringSQuote(string s)
{
return CUtils.EscapeString(s, '\'');
}
/// <summary>
/// Function removes doubled up specified character from a string
/// </summary>
/// <param name="s"></param>
/// <param name="cEsc"></param>
/// <returns></returns>
public static String UnEscapeString(string s, char cEsc)
{
StringBuilder sb = new StringBuilder(s.Length);
bool foundBefore = false;
foreach (char c in s)
{
if (cEsc == c) // character to unescape
{
if (foundBefore) // skip second occurrence
{
foundBefore = false;
}
else // set the flag to skip next time around
{
sb.Append(c);
foundBefore = true;
}
}
else
{
sb.Append(c);
foundBefore = false;
}
}
return sb.ToString();
}
/// <summary>
/// Function removes doubled up ']' character from a string
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static String UnEscapeStringCBracket(string s)
{
return CUtils.UnEscapeString(s, ']');
}
/// <summary>
/// Function removes doubled up '\'' character from a string
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static String UnEscapeStringSQuote(string s)
{
return CUtils.UnEscapeString(s, '\'');
}
/// <summary>
/// Get the windows login name with the domain portion in all-caps

View File

@@ -6,6 +6,7 @@
#nullable disable
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
using Microsoft.SqlTools.SqlCore.Metadata;
namespace Microsoft.SqlTools.ServiceLayer.Metadata.Contracts
{

View File

@@ -1,42 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
namespace Microsoft.SqlTools.ServiceLayer.Metadata.Contracts
{
/// <summary>
/// Metadata type enumeration
/// </summary>
public enum MetadataType
{
Table = 0,
View = 1,
SProc = 2,
Function = 3,
Schema = 4,
Database = 5
}
/// <summary>
/// Object metadata information
/// </summary>
public class ObjectMetadata
{
public MetadataType MetadataType { get; set; }
public string MetadataTypeName { get; set; }
public string Schema { get; set; }
public string Name { get; set; }
public string ParentName { get; set; }
public string ParentTypeName { get; set; }
public string Urn { get; set; }
}
}

View File

@@ -14,6 +14,7 @@ using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.Metadata.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.SqlCore.Metadata;
namespace Microsoft.SqlTools.ServiceLayer.Metadata
{

View File

@@ -11,9 +11,9 @@ using System.Data.Common;
using Microsoft.Data.SqlClient;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
using Microsoft.SqlTools.ServiceLayer.Utility.SqlScriptFormatters;
using Microsoft.SqlTools.SqlCore.Connection;
namespace Microsoft.SqlTools.ServiceLayer.Metadata
{

View File

@@ -60,13 +60,13 @@
<ProjectReference Include="../Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj" />
<ProjectReference Include="../Microsoft.SqlTools.Credentials/Microsoft.SqlTools.Credentials.csproj" />
<ProjectReference Include="../Microsoft.SqlTools.ManagedBatchParser/Microsoft.SqlTools.ManagedBatchParser.csproj" />
<ProjectReference Include="..\Microsoft.SqlTools.Authentication\Microsoft.SqlTools.Authentication.csproj" />
<ProjectReference Include="../Microsoft.SqlTools.Authentication/Microsoft.SqlTools.Authentication.csproj" />
<ProjectReference Include="../Microsoft.SqlTools.SqlCore/Microsoft.SqlTools.SqlCore.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="..\..\Notice.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<EmbeddedResource Include="ObjectExplorer\SmoModel\SmoTreeNodesDefinition.xml" />
<EmbeddedResource Include="Localization\*.resx" />
<None Include="Localization\sr.strings" />
</ItemGroup>

View File

@@ -5,9 +5,8 @@
#nullable disable
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.ServiceLayer.ModelManagement.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.SqlCore.Utility;
using System;
using System.Collections.Generic;
using System.Data;
@@ -253,12 +252,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ModelManagement
private static string GetThreePartsTableName(string dbName, string tableName, string schemaName)
{
return $"[{CUtils.EscapeStringCBracket(dbName)}].[{CUtils.EscapeStringCBracket(schemaName)}].[{CUtils.EscapeStringCBracket(tableName)}]";
return $"[{StringUtils.EscapeStringCBracket(dbName)}].[{StringUtils.EscapeStringCBracket(schemaName)}].[{StringUtils.EscapeStringCBracket(tableName)}]";
}
private static string GetTwoPartsTableName(string tableName, string schemaName)
{
return $"[{CUtils.EscapeStringCBracket(schemaName)}].[{CUtils.EscapeStringCBracket(tableName)}]";
return $"[{StringUtils.EscapeStringCBracket(schemaName)}].[{StringUtils.EscapeStringCBracket(tableName)}]";
}
private static string GetSelectModelsQuery(string dbName, string tableName, string schemaName)
@@ -272,24 +271,24 @@ namespace Microsoft.SqlTools.ServiceLayer.ModelManagement
private static string GetConfigTableVerificationQuery(string dbName, string tableName, string schemaName)
{
string twoPartsTableName = GetTwoPartsTableName(CUtils.EscapeStringSQuote(tableName), CUtils.EscapeStringSQuote(schemaName));
string twoPartsTableName = GetTwoPartsTableName(StringUtils.EscapeStringSQuote(tableName), StringUtils.EscapeStringSQuote(schemaName));
return $@"
IF NOT EXISTS (
SELECT name
FROM sys.databases
WHERE name = N'{CUtils.EscapeStringSQuote(dbName)}'
WHERE name = N'{StringUtils.EscapeStringSQuote(dbName)}'
)
BEGIN
SELECT 0
END
ELSE
BEGIN
USE [{CUtils.EscapeStringCBracket(dbName)}]
USE [{StringUtils.EscapeStringCBracket(dbName)}]
IF EXISTS
( SELECT t.name, s.name
FROM sys.tables t join sys.schemas s on t.schema_id=t.schema_id
WHERE t.name = '{CUtils.EscapeStringSQuote(tableName)}'
AND s.name = '{CUtils.EscapeStringSQuote(schemaName)}'
WHERE t.name = '{StringUtils.EscapeStringSQuote(tableName)}'
AND s.name = '{StringUtils.EscapeStringSQuote(schemaName)}'
)
BEGIN
IF EXISTS (SELECT * FROM syscolumns WHERE ID=OBJECT_ID('{twoPartsTableName}') AND NAME='model_name')
@@ -323,8 +322,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ModelManagement
IF NOT EXISTS
( SELECT t.name, s.name
FROM sys.tables t join sys.schemas s on t.schema_id=t.schema_id
WHERE t.name = '{CUtils.EscapeStringSQuote(tableName)}'
AND s.name = '{CUtils.EscapeStringSQuote(schemaName)}'
WHERE t.name = '{StringUtils.EscapeStringSQuote(tableName)}'
AND s.name = '{StringUtils.EscapeStringSQuote(schemaName)}'
)
BEGIN
CREATE TABLE {GetTwoPartsTableName(tableName, schemaName)} (
@@ -339,12 +338,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ModelManagement
[deployed_by] [int] NULL,
[model_description] [varchar](256) NULL,
[run_id] [varchar](256) NULL,
CONSTRAINT [{CUtils.EscapeStringCBracket(tableName)}_models_pk] PRIMARY KEY CLUSTERED
CONSTRAINT [{StringUtils.EscapeStringCBracket(tableName)}_models_pk] PRIMARY KEY CLUSTERED
(
[model_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
ALTER TABLE {GetTwoPartsTableName(tableName, schemaName)} ADD CONSTRAINT [{CUtils.EscapeStringCBracket(tableName)}_deployment_time] DEFAULT (getdate()) FOR [model_deployment_time]
ALTER TABLE {GetTwoPartsTableName(tableName, schemaName)} ADD CONSTRAINT [{StringUtils.EscapeStringCBracket(tableName)}_deployment_time] DEFAULT (getdate()) FOR [model_deployment_time]
END
";
}
@@ -357,14 +356,14 @@ namespace Microsoft.SqlTools.ServiceLayer.ModelManagement
INSERT INTO {twoPartsTableName}
(model_name, model, model_version, model_description, model_creation_time, model_framework, model_framework_version, run_id, deployed_by)
VALUES (
{DatabaseUtils.AddStringParameterForInsert(model.ModelName ?? "")},
{DatabaseUtils.AddByteArrayParameterForInsert("Content", model.FilePath ?? "", parameters)},
{DatabaseUtils.AddStringParameterForInsert(model.Version ?? "")},
{DatabaseUtils.AddStringParameterForInsert(model.Description ?? "")},
{DatabaseUtils.AddStringParameterForInsert(model.Created)},
{DatabaseUtils.AddStringParameterForInsert(model.Framework ?? "")},
{DatabaseUtils.AddStringParameterForInsert(model.FrameworkVersion ?? "")},
{DatabaseUtils.AddStringParameterForInsert(model.RunId ?? "")},
{Utility.DatabaseUtils.AddStringParameterForInsert(model.ModelName ?? "")},
{Utility.DatabaseUtils.AddByteArrayParameterForInsert("Content", model.FilePath ?? "", parameters)},
{Utility.DatabaseUtils.AddStringParameterForInsert(model.Version ?? "")},
{Utility.DatabaseUtils.AddStringParameterForInsert(model.Description ?? "")},
{Utility.DatabaseUtils.AddStringParameterForInsert(model.Created)},
{Utility.DatabaseUtils.AddStringParameterForInsert(model.Framework ?? "")},
{Utility.DatabaseUtils.AddStringParameterForInsert(model.FrameworkVersion ?? "")},
{Utility.DatabaseUtils.AddStringParameterForInsert(model.RunId ?? "")},
USER_ID (Current_User)
)
";
@@ -378,13 +377,13 @@ namespace Microsoft.SqlTools.ServiceLayer.ModelManagement
return $@"
UPDATE {twoPartsTableName}
SET
{DatabaseUtils.AddStringParameterForUpdate("model_name", model.ModelName ?? "")},
{DatabaseUtils.AddStringParameterForUpdate("model_version", model.Version ?? "")},
{DatabaseUtils.AddStringParameterForUpdate("model_description", model.Description ?? "")},
{DatabaseUtils.AddStringParameterForUpdate("model_creation_time", model.Created)},
{DatabaseUtils.AddStringParameterForUpdate("model_framework", model.Framework ?? "")},
{DatabaseUtils.AddStringParameterForUpdate("model_framework_version", model.FrameworkVersion ?? "")},
{DatabaseUtils.AddStringParameterForUpdate("run_id", model.RunId ?? "")}
{Utility.DatabaseUtils.AddStringParameterForUpdate("model_name", model.ModelName ?? "")},
{Utility.DatabaseUtils.AddStringParameterForUpdate("model_version", model.Version ?? "")},
{Utility.DatabaseUtils.AddStringParameterForUpdate("model_description", model.Description ?? "")},
{Utility.DatabaseUtils.AddStringParameterForUpdate("model_creation_time", model.Created)},
{Utility.DatabaseUtils.AddStringParameterForUpdate("model_framework", model.Framework ?? "")},
{Utility.DatabaseUtils.AddStringParameterForUpdate("model_framework_version", model.FrameworkVersion ?? "")},
{Utility.DatabaseUtils.AddStringParameterForUpdate("run_id", model.RunId ?? "")}
WHERE model_id = @{ModelIdParameterName}
";

View File

@@ -6,7 +6,7 @@
#nullable disable
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.SqlCore.Connection;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts
{

View File

@@ -5,7 +5,10 @@
#nullable disable
using Microsoft.SqlTools.ServiceLayer.Metadata.Contracts;
using System;
using System.Collections.Generic;
using Microsoft.SqlTools.SqlCore.Metadata;
using Microsoft.SqlTools.SqlCore.ObjectExplorer.Nodes;
using Newtonsoft.Json.Linq;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts
@@ -76,6 +79,25 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts
/// Filterable properties that this node supports
/// </summary>
public NodeFilterProperty[] FilterableProperties { get; set; }
public NodeInfo()
{
}
public NodeInfo(TreeNode treeNode)
{
IsLeaf = treeNode.IsAlwaysLeaf;
Label = treeNode.Label;
NodePath = treeNode.GetNodePath();
ParentNodePath = treeNode.Parent?.GetNodePath() ?? string.Empty;
NodeType = treeNode.NodeType;
Metadata = treeNode.ObjectMetadata;
NodeStatus = treeNode.NodeStatus;
NodeSubType = treeNode.NodeSubType;
ErrorMessage = treeNode.ErrorMessage;
ObjectType = treeNode.NodeTypeId.ToString();
FilterableProperties = treeNode.FilterProperties;
}
}
/// <summary>
@@ -103,45 +125,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts
}
}
/// <summary>
/// The filterable properties that a node supports
/// </summary>
public class NodeFilterProperty
{
/// <summary>
/// The name of the filter property
/// </summary>
public string Name { get; set; }
/// <summary>
/// The name of the filter property displayed to the user
/// </summary>
public string DisplayName { get; set; }
/// <summary>
/// The description of the filter property
/// </summary>
public string Description { get; set; }
/// <summary>
/// The data type of the filter property
/// </summary>
public NodeFilterPropertyDataType Type { get; set; }
/// <summary>
/// The list of choices for the filter property if the type is choice
/// </summary>
public NodeFilterPropertyChoice[] Choices { get; set; }
}
/// <summary>
/// The data type of the filter property. Matches NodeFilterPropertyDataType enum in ADS : https://github.com/microsoft/azuredatastudio/blob/main/src/sql/azdata.proposed.d.ts#L1847-L1853
/// </summary>
public enum NodeFilterPropertyDataType
{
String = 0,
Number = 1,
Boolean = 2,
Date = 3,
Choice = 4
}
/// <summary>
/// The operator of the filter property. Matches NodeFilterOperator enum in ADS: https://github.com/microsoft/azuredatastudio/blob/main/src/sql/azdata.proposed.d.ts#L1855-L1868
/// </summary>
@@ -182,22 +165,109 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts
/// The applied values of the filter property
/// </summary>
public JToken Value { get; set; }
}
/// <summary>
/// The choice for the filter property if the type is choice
/// </summary>
public class NodeFilterPropertyChoice
{
/// <summary>
/// The dropdown display value for the choice
/// </summary>
/// <value></value>
public string DisplayName { get; set; }
public INodeFilter ToINodeFilter(NodeFilterProperty filterProperty)
{
Type type = typeof(string);
/// <summary>
/// The value of the choice
/// </summary>
public string Value { get; set; }
var IsDateTime = filterProperty.Type == NodeFilterPropertyDataType.Date;
FilterType filterType = FilterType.EQUALS;
bool isNotFilter = false;
object filterValue = null;
switch (filterProperty.Type)
{
case NodeFilterPropertyDataType.String:
case NodeFilterPropertyDataType.Date:
case NodeFilterPropertyDataType.Choice:
type = typeof(string);
filterValue = this.Value.ToString();
break;
case NodeFilterPropertyDataType.Number:
type = typeof(int);
filterValue = this.Value.ToObject<int>();
break;
case NodeFilterPropertyDataType.Boolean:
type = typeof(bool);
filterValue = this.Value.ToObject<bool>() ? 1 : 0;
break;
}
switch (this.Operator)
{
case NodeFilterOperator.Equals:
filterType = FilterType.EQUALS;
break;
case NodeFilterOperator.NotEquals:
filterType = FilterType.EQUALS;
isNotFilter = true;
break;
case NodeFilterOperator.LessThan:
filterType = FilterType.LESSTHAN;
break;
case NodeFilterOperator.LessThanOrEquals:
filterType = FilterType.LESSTHANOREQUAL;
break;
case NodeFilterOperator.GreaterThan:
filterType = FilterType.GREATERTHAN;
break;
case NodeFilterOperator.GreaterThanOrEquals:
filterType = FilterType.GREATERTHANOREQUAL;
break;
case NodeFilterOperator.Between:
filterType = FilterType.BETWEEN;
break;
case NodeFilterOperator.NotBetween:
filterType = FilterType.NOTBETWEEN;
isNotFilter = true;
break;
case NodeFilterOperator.Contains:
filterType = FilterType.CONTAINS;
break;
case NodeFilterOperator.NotContains:
filterType = FilterType.CONTAINS;
isNotFilter = true;
break;
case NodeFilterOperator.StartsWith:
filterType = FilterType.STARTSWITH;
break;
case NodeFilterOperator.NotStartsWith:
filterType = FilterType.STARTSWITH;
isNotFilter = true;
break;
case NodeFilterOperator.EndsWith:
filterType = FilterType.ENDSWITH;
break;
case NodeFilterOperator.NotEndsWith:
filterType = FilterType.ENDSWITH;
isNotFilter = true;
break;
}
if (this.Operator == NodeFilterOperator.Between || this.Operator == NodeFilterOperator.NotBetween)
{
if (filterProperty.Type == NodeFilterPropertyDataType.Number)
{
filterValue = this.Value.ToObject<int[]>();
}
else if (filterProperty.Type == NodeFilterPropertyDataType.Date)
{
filterValue = this.Value.ToObject<string[]>();
}
}
return new NodePropertyFilter
{
Property = filterProperty.Name,
Type = type,
Values = new List<object> { filterValue },
IsNotFilter = isNotFilter,
FilterType = filterType,
IsDateTime = IsDateTime
};
}
}
}

View File

@@ -1,84 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System.Collections.Generic;
using System.Threading;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// A <see cref="ChildFactory"/> supports creation of <see cref="TreeNode"/> children
/// for a class of objects in the tree. The
/// </summary>
public abstract class ChildFactory
{
/// <summary>
/// The set of applicable parents for which the factory can create children.
/// </summary>
/// <returns>
/// the string names for each <see cref="TreeNode.NodeType"/> that
/// this factory can create children for
/// </returns>
public abstract IEnumerable<string> ApplicableParents();
/// <summary>
/// Expands an element in the
/// </summary>
/// <param name="parent">Parent Node</param>
/// <param name="refresh">force to refresh</param>
/// <param name="name">name of the sql object to filter</param>
/// <param name="includeSystemObjects">include system objects</param>
/// <param name="cancellationToken">cancellation token</param>
/// <param name="filters">filters to apply</param>
public abstract IEnumerable<TreeNode> Expand(TreeNode parent, bool refresh, string name, bool includeSystemObjects, CancellationToken cancellationToken, IEnumerable<NodeFilter>? filters);
/// <summary>
/// The list of filters that should be applied on the smo object list
/// </summary>
public abstract IEnumerable<INodeFilter> Filters { get; }
/// <summary>
/// The list of properties to be loaded with the object
/// </summary>
public abstract IEnumerable<NodeSmoProperty> SmoProperties { get; }
/// <summary>
/// Returns the node sub type if the object can have sub types otehr wise returns empty string
/// </summary>
public abstract string GetNodeSubType(object smoObject, SmoQueryContext smoContext);
/// <summary>
/// Returns the status of the object assigned to node. If the object doesn't spport status returns empty string
/// </summary>
public abstract string GetNodeStatus(object smoObject, SmoQueryContext smoContext);
/// <summary>
/// Returns the custom name of the object assigned to the node. If the object doesn't have custom name, returns empty string
/// </summary>
public abstract string GetNodeCustomName(object smoObject, SmoQueryContext smoContext);
/// <summary>
/// Returns the name of the object as shown in its Object Explorer node path
/// </summary>
public abstract string GetNodePathName(object smoObject);
public abstract bool CanCreateChild(TreeNode parent, object context);
public abstract TreeNode CreateChild(TreeNode parent, object context);
// TODO Consider whether Remove operations need to be supported
//public abstract bool CanRemoveChild(TreeNode parent, object context);
//public abstract int GetChildIndexToRemove(TreeNode parent, object context);
/// <summary>
/// A flag that puts child folders after nodes when the node is expanded.
/// </summary>
/// <value></value>
public virtual bool PutFoldersAfterNodes => false;
}
}

View File

@@ -1,78 +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 System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// Has information for filtering a SMO object by properties
/// </summary>
public interface INodeFilter
{
/// <summary>
/// Returns true if the filter can be apply to the given type and Server type
/// </summary>
/// <param name="type">Type of the querier</param>
/// <param name="validForFlag">Server Type</param>
/// <returns></returns>
bool CanApplyFilter(Type type, ValidForFlag validForFlag);
/// <summary>
/// Creates a string from the filter property and values to be used in the Urn to query the SQL objects
/// Example of the output:[@ IsSystemObject = 0]
/// </summary>
/// <returns></returns>
string ToPropertyFilterString(Type type, ValidForFlag validForFlag);
/// <summary>
/// Creates a fully paramaterized property filter string for the URN query for SQL objects.
/// Example of the output:[@ IsSystemObject = 0]
/// </summary>
/// <returns></returns>
public static string GetPropertyFilter(IEnumerable<INodeFilter> filters, Type type, ValidForFlag validForFlag)
{
StringBuilder filter = new StringBuilder();
foreach (var value in filters)
{
string andPrefix = filter.Length == 0 ? string.Empty : " and ";
var filterString = value.ToPropertyFilterString(type, validForFlag);
if (filterString != string.Empty)
{
filter.Append($"{andPrefix}{filterString}");
}
}
if (filter.Length != 0)
{
return "[" + filter.ToString() + "]";
}
return string.Empty;
}
/// <summary>
/// Appends a list of property filters to an URN query string
/// </summary>
public static string AddPropertyFilterToFilterString(string filterString, IEnumerable<INodeFilter> filters, Type type, ValidForFlag validForFlag)
{
if (string.IsNullOrEmpty(filterString))
{
return GetPropertyFilter(filters, type, validForFlag);
}
foreach (var value in filters ?? Enumerable.Empty<INodeFilter>())
{
var filter = value.ToPropertyFilterString(type, validForFlag);
if (filter != string.Empty)
{
filterString = filterString.Remove(filterString.Length - 1, 1) + $" and {filter}" + "]";
}
}
return filterString;
}
}
}

View File

@@ -1,197 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// A collection class for <see cref="TreeNode"/>
/// </summary>
public sealed class NodeObservableCollection : ObservableCollection<TreeNode>
{
public event EventHandler Initialized;
private int? numInits;
private static int cleanupBlocker;
public bool IsInitialized
{
get { return numInits.HasValue && numInits == 0; }
}
public bool IsPopulating
{
get { return numInits.HasValue && numInits != 0; }
}
public bool IsSorted
{
get
{
// SMO objects are already sorted so no need to sort them again, unless they have dropped folders
bool anyDroppedFolders = this.Any(
node => node is FolderNode &&
(node.NodeTypeId == NodeTypes.DroppedLedgerTables ||
node.NodeTypeId == NodeTypes.DroppedLedgerViews ||
node.NodeTypeId == NodeTypes.DroppedLedgerColumns));
return this.FirstOrDefault() is SmoTreeNode && !anyDroppedFolders;
}
}
public void BeginInit()
{
if (!numInits.HasValue)
{
numInits = 1;
}
else
{
numInits = numInits + 1;
}
}
public void EndInit()
{
IList<TreeNode> empty = null;
EndInit(null, ref empty);
}
public void EndInit(TreeNode parent, ref IList<TreeNode> deferredChildren)
{
if (numInits.HasValue &&
numInits.Value == 1)
{
try
{
if (!IsSorted)
{
DoSort();
}
if (deferredChildren != null)
{
// Set the parents so the children know how to sort themselves
foreach (var item in deferredChildren)
{
item.Parent = parent;
}
deferredChildren = deferredChildren.OrderBy(x => x).ToList();
// Add the deferredChildren
foreach (var item in deferredChildren)
{
this.Add(item);
}
}
}
finally
{
if (deferredChildren != null)
{
deferredChildren.Clear();
}
numInits = numInits - 1;
}
Initialized?.Invoke(this, EventArgs.Empty);
}
else
{
numInits = numInits - 1;
}
}
/// <summary>
/// Repositions this child in the list
/// </summary>
public void ReSortChild(TreeNode child)
{
if (child == null)
return;
List<TreeNode> sorted = this.OrderBy(x => x).ToList();
// Remove without cleanup
try
{
cleanupBlocker++;
Remove(child);
}
finally
{
cleanupBlocker--;
}
// Then insert
for (int i = 0; i < sorted.Count; i++)
{
if (sorted[i] == child)
{
Insert(i, child);
return;
}
}
}
protected override void RemoveItem(int index)
{
// Cleanup all the children
Cleanup(this[index]);
base.RemoveItem(index);
}
protected override void ClearItems()
{
// Cleanup all the children
foreach (var child in this)
{
Cleanup(child);
}
base.ClearItems();
}
private static void Cleanup(TreeNode parent)
{
if (cleanupBlocker > 0 ||
parent.Parent == null)
return;
// TODO implement cleanup policy / pattern
//ICleanupPattern parentAsCleanup = parent as ICleanupPattern;
//if (parentAsCleanup != null)
// parentAsCleanup.DoCleanup();
//foreach (var child in parent.Children)
//{
// Cleanup(child);
//}
parent.Parent = null;
}
private void DoSort()
{
List<TreeNode> sorted = this.OrderBy(x => x).ToList();
for (int i = 0; i < sorted.Count; i++)
{
int index = IndexOf(sorted[i]);
if (index != i)
{
Move(IndexOf(sorted[i]), i);
}
}
}
}
}

View File

@@ -1,60 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections.Generic;
using System.Text;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// Has information for filtering a SMO object by properties
/// </summary>
public class NodeOrFilter : INodeFilter
{
/// <summary>
/// Filter values
/// </summary>
public List<NodePropertyFilter> FilterList { get; set; }
/// <summary>
/// Returns true if any of the filters within the FilterList apply to the type and server type.
/// </summary>
/// <param name="type">Type of the querier</param>
/// <param name="validForFlag">Server Type</param>
public bool CanApplyFilter(Type type, ValidForFlag validForFlag) {
return this.FilterList.Exists(f => f.CanApplyFilter(type, validForFlag));
}
/// <summary>
/// Creates a string representation of a node "or" filter, which is combined in the INodeFilter interface to construct the filter used in the URN to query the SQL objects.
/// Example of the output: ((@TableTemporalType = 1) or (@LedgerTableType = 1))
/// </summary>
/// <returns></returns>
public string ToPropertyFilterString(Type type, ValidForFlag validForFlag)
{
StringBuilder filter = new StringBuilder();
foreach (var nodeFilter in FilterList)
{
string orPrefix = filter.Length == 0 ? string.Empty : " or ";
// For "or" filter, have to check each node as it's processed for whether it's valid.
var filterString = nodeFilter.ToPropertyFilterString(type, validForFlag);
if (filterString != string.Empty)
{
filter.Append($"{orPrefix}{filterString}");
}
}
if (filter.Length != 0)
{
return "(" + filter.ToString() + ")";
}
return string.Empty;
}
}
}

View File

@@ -1,313 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// Has information for filtering a SMO object by properties
/// </summary>
public partial class NodePropertyFilter : INodeFilter
{
/// <summary>
/// Property name
/// </summary>
public string Property { get; set; } = string.Empty;
/// <summary>
/// Filter values
/// </summary>
public List<object> Values { get; set; } = default!;
/// <summary>
/// Type of the filter values
/// </summary>
public Type Type { get; set; } = default!;
/// <summary>
/// Indicates which platforms a filter is valid for
/// </summary>
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; } = default!;
/// <summary>
/// Indicates if the filter is a "not" filter. Eg (not(@IsSystemObject = 0))
/// </summary>
public bool IsNotFilter { get; set; } = false;
/// <summary>
/// Indicates if the values are for type datetime
/// </summary>
public bool IsDateTime { get; set; } = false;
/// <summary>
/// Indicates the type of the filter. It can be EQUALS, DATETIME, FALSE or CONTAINS
/// More information can be found here:
/// https://learn.microsoft.com/en-us/sql/powershell/query-expressions-and-uniform-resource-names?view=sql-server-ver16#examples
/// </summary>
public FilterType FilterType { get; set; } = FilterType.EQUALS;
/// <summary>
/// Returns true if the filter can be apply to the given type and Server type
/// </summary>
/// <param name="type">Type of the querier</param>
/// <param name="validForFlag">Server Type</param>
/// <returns></returns>
public bool CanApplyFilter(Type type, ValidForFlag validForFlag)
{
bool canApplyFilter = false;
canApplyFilter = TypeToReverse == null || TypeToReverse == type;
canApplyFilter = canApplyFilter && (ValidFor == 0 || ValidFor.HasFlag(validForFlag));
return canApplyFilter;
}
/// <summary>
/// Creates a string representation of a given node filter, which is combined in the INodeFilter interface to construct the filter used in the URN to query the SQL objects.
/// Example of the output: (@ IsSystemObject = 0)
/// </summary>
/// <returns></returns>
public string ToPropertyFilterString(Type type, ValidForFlag validForFlag)
{
// check first if the filter can be applied; if not just return empty string
if (!CanApplyFilter(type, validForFlag))
{
return string.Empty;
}
StringBuilder filter = new StringBuilder();
foreach (var value in Values)
{
string filterText = string.Empty;
if (IsDateTime)
{
string Value1;
string Value2;
switch (FilterType)
{
case FilterType.BETWEEN:
string[] betweenValues = (string[])value;
Value1 = DateTime.Parse((string)betweenValues[0]).ToString("yyyy-MM-dd 00:00:00.000");
Value2 = DateTime.Parse((string)betweenValues[1]).ToString("yyyy-MM-dd 23:59:59.999");
filterText = $"@{Property} >= datetime('{Value1}') and @{Property} <= datetime('{Value2}')";
break;
case FilterType.NOTBETWEEN:
IsNotFilter = true;
string[] notBetweenValues = (string[])value;
Value1 = DateTime.Parse((string)notBetweenValues[0]).ToString("yyyy-MM-dd 00:00:00.000");
Value2 = DateTime.Parse((string)notBetweenValues[1]).ToString("yyyy-MM-dd 23:59:59.999");
filterText = $"@{Property} >= datetime('{Value1}') and @{Property} <= datetime('{Value2}')";
break;
case FilterType.EQUALS:
Value1 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 00:00:00.000");
Value2 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 23:59:59.999");
filterText = $"@{Property} >= datetime('{Value1}') and @{Property} <= datetime('{Value2}')";
break;
case FilterType.GREATERTHAN:
Value1 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 23:59:59.999");
filterText = $"@{Property} > datetime('{Value1}')";
break;
case FilterType.LESSTHAN:
Value1 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 00:00:00.000");
filterText = $"@{Property} < datetime('{Value1}')";
break;
case FilterType.GREATERTHANOREQUAL:
Value1 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 00:00:00.000");
filterText = $"@{Property} >= datetime('{Value1}')";
break;
case FilterType.LESSTHANOREQUAL:
Value1 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 23:59:59.999");
filterText = $"@{Property} <= datetime('{Value1}')";
break;
case FilterType.NOTEQUALS:
IsNotFilter = true;
Value1 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 00:00:00.000");
Value2 = DateTime.Parse((string)value).ToString("yyyy-MM-dd 23:59:59.999");
filterText = $"@{Property} >= datetime('{Value1}') and @{Property} <= datetime('{Value2}')";
break;
default:
break;
}
}
else if (IsNumericType(Type))
{
switch (FilterType)
{
case FilterType.BETWEEN:
object[] betweenValues = (object[])value;
filterText = $"@{Property} >= {Decimal.Parse(betweenValues[0].ToString())} and @{Property} <= {Decimal.Parse(betweenValues[1].ToString())}";
break;
case FilterType.NOTBETWEEN:
IsNotFilter = true;
object[] notBetweenValues = (object[])value;
filterText = $"@{Property} >= {Decimal.Parse(notBetweenValues[0].ToString())} and @{Property} <= {Decimal.Parse(notBetweenValues[1].ToString())}";
break;
case FilterType.EQUALS:
filterText = $"@{Property} = {Decimal.Parse(value.ToString())}";
break;
case FilterType.GREATERTHAN:
filterText = $"@{Property} > {Decimal.Parse(value.ToString())}";
break;
case FilterType.LESSTHAN:
filterText = $"@{Property} < {Decimal.Parse(value.ToString())}";
break;
case FilterType.GREATERTHANOREQUAL:
filterText = $"@{Property} >= {Decimal.Parse(value.ToString())}";
break;
case FilterType.LESSTHANOREQUAL:
filterText = $"@{Property} <= {Decimal.Parse(value.ToString())}";
break;
case FilterType.NOTEQUALS:
filterText = $"@{Property} != {Decimal.Parse(value.ToString())}";
break;
default:
break;
}
}
else
{
object propertyValue = value;
if (Type == typeof(string))
{
//Replacing quotes with double quotes
var escapedString = CUtils.EscapeStringSQuote(propertyValue.ToString());
if (this.FilterType == FilterType.STARTSWITH || this.FilterType == FilterType.ENDSWITH)
{
escapedString = EscapeLikeURNRegex().Replace(escapedString, "[$0]");
if (this.FilterType == FilterType.STARTSWITH)
{
propertyValue = $"'{escapedString}%'";
}
else if (this.FilterType == FilterType.ENDSWITH)
{
propertyValue = $"'%{escapedString}'";
}
}
else
{
propertyValue = $"'{escapedString}'";
}
}
else if (Type == typeof(Enum))
{
propertyValue = (int)Convert.ChangeType(value, Type);
}
switch (FilterType)
{
case FilterType.EQUALS:
filterText = $"@{Property} = {propertyValue}";
break;
case FilterType.NOTEQUALS:
filterText = $"@{Property} != {propertyValue}";
break;
case FilterType.LESSTHAN:
filterText = $"@{Property} < {propertyValue}";
break;
case FilterType.GREATERTHAN:
filterText = $"@{Property} > {propertyValue}";
break;
case FilterType.LESSTHANOREQUAL:
filterText = $"@{Property} <= {propertyValue}";
break;
case FilterType.GREATERTHANOREQUAL:
filterText = $"@{Property} >= {propertyValue}";
break;
case FilterType.DATETIME:
filterText = $"@{Property} = datetime({propertyValue})";
break;
case FilterType.FALSE:
filterText = $"@{Property} = false()";
break;
case FilterType.ISNULL:
filterText = $"isnull(@{Property})";
break;
case FilterType.CONTAINS:
filterText = $"contains(@{Property}, {propertyValue})";
break;
case FilterType.STARTSWITH:
case FilterType.ENDSWITH:
filterText = $"like(@{Property}, {propertyValue})";
break;
}
}
string orPrefix = filter.Length == 0 ? string.Empty : " or ";
if (IsNotFilter)
{
filter.Append($"{orPrefix}not({filterText})");
}
else
{
filter.Append($"{orPrefix}{filterText}");
}
}
if (filter.Length != 0)
{
return "(" + filter.ToString() + ")";
}
return string.Empty;
}
public static bool IsNumericType(Type type)
{
switch (Type.GetTypeCode(type))
{
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single:
return true;
default:
return false;
}
}
// For filters that use the LIKE operator, we need to escape the following characters: %, _, [, ^
// we do this by wrapping them in square brackets eg: [%], [_], [[], [^]
[GeneratedRegexAttribute(@"%|_|\[|\^")]
public static partial Regex EscapeLikeURNRegex();
}
public enum FilterType
{
EQUALS,
DATETIME,
FALSE,
ISNULL,
NOTEQUALS,
LESSTHAN,
GREATERTHAN,
LESSTHANOREQUAL,
GREATERTHANOREQUAL,
BETWEEN,
NOTBETWEEN,
CONTAINS,
STARTSWITH,
ENDSWITH
}
}

View File

@@ -1,26 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// Has information for SMO object properties to be loaded with the SMO object
/// </summary>
public class NodeSmoProperty
{
/// <summary>
/// Property name
/// </summary>
public string Name { get; set; }
/// <summary>
/// Indicates which platforms a filter is valid for
/// </summary>
public ValidForFlag ValidFor { get; set; }
}
}

View File

@@ -1,142 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
// This file was generated by a T4 Template. Do not modify directly, instead update the SmoTreeNodesDefinition.xml file
// and re-run the T4 template. This can be done in Visual Studio by right-click in and choosing "Run Custom Tool",
// or from the command-line on any platform by running "build.cmd -Target=CodeGen" or "build.sh -Target=CodeGen"
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// Enum listing possible node types in the object explorer tree
/// </summary>
public enum NodeTypes
{
AggregateFunction,
AggregateFunctionParameters,
AggregateFunctions,
AlwaysEncryptedKeys,
ApplicationRoles,
Assemblies,
AsymmetricKeys,
BrokerPriorities,
BuiltInSchemas,
Certificates,
ColumnEncryptionKeys,
ColumnMasterKeys,
Columns,
Constraints,
Contracts,
Database,
DatabaseAndQueueEventNotifications,
DatabaseAuditSpecifications,
DatabaseEncryptionKeys,
DatabaseRoles,
Databases,
DatabaseScopedCredentials,
DatabaseTriggers,
DroppedLedgerColumns,
DroppedLedgerTables,
DroppedLedgerViews,
ExpandableSchema,
ExpandableSchemaProgrammability,
ExternalDataSources,
ExternalFileFormats,
ExternalResource,
ExternalResources,
ExternalTable,
ExternalTables,
FileGroup,
FileGroupFiles,
FileGroups,
Folder,
FullTextCatalogs,
FullTextStopLists,
Functions,
HistoryTable,
Indexes,
Keys,
MasterKeys,
MessageTypes,
PartitionFunctions,
PartitionSchemes,
Programmability,
Queues,
RemoteServiceBindings,
Roles,
ScalarValuedFunction,
ScalarValuedFunctionParameters,
ScalarValuedFunctions,
Schemas,
SearchPropertyLists,
Security,
SecurityPolicies,
Sequences,
Server,
ServerLevelCredentials,
ServerLevelCryptographicProviders,
ServerLevelEndpoints,
ServerLevelErrorMessages,
ServerLevelLinkedServers,
ServerLevelLogins,
ServerLevelSecurity,
ServerLevelServerAudits,
ServerLevelServerAuditSpecifications,
ServerLevelServerObjects,
ServerLevelServerRoles,
ServerLevelServerTriggers,
ServiceBroker,
Services,
Signatures,
SqlLogFiles,
Statistics,
Storage,
StoredProcedure,
StoredProcedureParameters,
StoredProcedures,
SymmetricKeys,
Synonyms,
SystemApproximateNumerics,
SystemBinaryStrings,
SystemCharacterStrings,
SystemClrDataTypes,
SystemContracts,
SystemDatabases,
SystemDataTypes,
SystemDateAndTimes,
SystemExactNumerics,
SystemFunctions,
SystemMessageTypes,
SystemOtherDataTypes,
SystemQueues,
SystemScalarValuedFunctions,
SystemServices,
SystemSpatialDataTypes,
SystemStoredProcedures,
SystemTables,
SystemTableValuedFunctions,
SystemUnicodeCharacterStrings,
SystemViews,
Table,
Tables,
TableValuedFunction,
TableValuedFunctionParameters,
TableValuedFunctions,
Triggers,
Types,
UserDefinedDataTypes,
UserDefinedTableType,
UserDefinedTableTypeColumns,
UserDefinedTableTypeConstraints,
UserDefinedTableTypeKeys,
UserDefinedTableTypes,
UserDefinedTypes,
Users,
View,
Views,
XmlSchemaCollections,
}
}

View File

@@ -1,117 +0,0 @@
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Xml.dll" #>
<#@ assembly name="System.Core.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq"#>
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
// This file was generated by a T4 Template. Do not modify directly, instead update the SmoTreeNodesDefinition.xml file
// and re-run the T4 template. This can be done in Visual Studio by right-click in and choosing "Run Custom Tool",
// or from the command-line on any platform by running "build.cmd -Target=CodeGen" or "build.sh -Target=CodeGen"
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// Enum listing possible node types in the object explorer tree
/// </summary>
public enum NodeTypes
{
<#
var directory = Path.GetDirectoryName(Host.TemplateFile);
string xmlFile = Path.Combine(directory, "..\\SmoModel\\SmoTreeNodesDefinition.xml");
var allTreeNodes = GetUniqueNodeTypes(xmlFile);
foreach (var name in allTreeNodes)
{
WriteLine(" {0},", name);
}
#>
}
}
<#+
public static List<string> GetUniqueNodeTypes(string xmlFile)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
// Adding all node types
HashSet<string> retElements = new HashSet<string>();
XmlNodeList nodeList = doc.SelectNodes("/ServerExplorerTree/Node");
foreach (XmlElement item in nodeList)
{
retElements.Add(item.GetAttribute("Name"));
foreach (XmlElement child in GetChildren(xmlFile, item.GetAttribute("Name")))
{
retElements.Add(child.GetAttribute("Name"));
}
}
// Adding UniqueTreeNodes
foreach(var name in GetUniqueTreeNodes(xmlFile))
{
retElements.Add(name);
}
// Adding types that are not present anywhere. These types are referred in tests.
retElements.Add("Folder");
var retList = retElements.ToList();
retList.Sort();
return retList;
}
public static List<XmlElement> GetChildren(string xmlFile, string parentName)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/ServerExplorerTree/Node[@Name='{0}']/Child", parentName));
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
public static XmlElement GetNodeElement(string xmlFile, string nodeName)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
return (XmlElement)doc.SelectSingleNode(string.Format("/ServerExplorerTree/Node[@Name='{0}']", nodeName));
}
public static List<string> GetUniqueTreeNodes(string xmlFile)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<string> retElements = new List<string>();
XmlNodeList nodeList = doc.SelectNodes("/ServerExplorerTree/CodeGenOptions/UniqueTreeNode");
foreach (XmlElement item in nodeList)
{
retElements.Add(item.GetAttribute("Name").Replace("TreeNode", string.Empty));
}
return retElements;
}
#>

View File

@@ -1,437 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using Microsoft.SqlTools.ServiceLayer.Metadata.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// Base class for elements in the object explorer tree. Provides common methods for tree navigation
/// and other core functionality
/// </summary>
public class TreeNode : IComparable<TreeNode>
{
private NodeObservableCollection children = new NodeObservableCollection();
private TreeNode parent;
private string nodePath;
private string label;
private string nodePathName;
public const char PathPartSeperator = '/';
/// <summary>
/// Constructor with no required inputs
/// </summary>
public TreeNode()
{
}
/// <summary>
/// Constructor that accepts a label to identify the node
/// </summary>
/// <param name="value">Label identifying the node</param>
public TreeNode(string value)
{
// We intentionally do not valid this being null or empty since
// some nodes may need to set it
NodeValue = value;
}
private object buildingMetadataLock = new object();
/// <summary>
/// Event which tells if MetadataProvider is built fully or not
/// </summary>
public object BuildingMetadataLock
{
get { return this.buildingMetadataLock; }
}
/// <summary>
/// Value describing this node
/// </summary>
public string NodeValue { get; set; }
/// <summary>
/// The name of this object as included in its node path
/// </summary>
public string NodePathName
{
get
{
if (string.IsNullOrEmpty(nodePathName))
{
return NodeValue;
}
return nodePathName;
}
set
{
nodePathName = value;
}
}
/// <summary>
/// Object metadata for smo objects
/// </summary>
public ObjectMetadata ObjectMetadata { get; set; }
/// <summary>
/// The type of the node - for example Server, Database, Folder, Table
/// </summary>
public string NodeType { get; set; }
/// <summary>
// True if the node includes system object
/// </summary>
public bool IsSystemObject { get; set; }
/// <summary>
/// Enum defining the type of the node - for example Server, Database, Folder, Table
/// </summary>
public NodeTypes? NodeTypeId { get; set; }
/// <summary>
/// Node Sub type - for example a key can have type as "Key" and sub type as "PrimaryKey"
/// </summary>
public string NodeSubType { get; set; }
/// <summary>
/// Error message returned from the engine for a object explorer node failure reason, if any.
/// </summary>
public string ErrorMessage { get; set; }
/// <summary>
/// Node status - for example login can be disabled/enabled
/// </summary>
public string NodeStatus { get; set; }
public NodeFilterProperty[] FilterProperties { get; set; }
/// <summary>
/// Label to display to the user, describing this node.
/// If not explicitly set this will fall back to the <see cref="NodeValue"/> but
/// for many nodes such as the server, the display label will be different
/// to the value.
/// </summary>
public string Label
{
get
{
if (label == null)
{
return NodeValue;
}
return label;
}
set
{
label = value;
}
}
/// <summary>
/// Is this a leaf node (in which case no children can be generated) or
/// is it expandable?
/// </summary>
public bool IsAlwaysLeaf { get; set; }
/// <summary>
/// Message to show if this Node is in an error state. This indicates
/// that children could be retrieved
/// </summary>
public string ErrorStateMessage { get; set; }
/// <summary>
/// Parent of this node
/// </summary>
public TreeNode Parent
{
get
{
return parent;
}
set
{
parent = value;
// Reset the node path since it's no longer valid
nodePath = null;
}
}
/// <summary>
/// Path identifying this node: for example a table will be at ["server", "database", "tables", "tableName"].
/// This enables rapid navigation of the tree without the need for a global registry of elements.
/// The path functions as a unique ID and is used to disambiguate the node when sending requests for expansion.
/// A common ID is needed since processes do not share address space and need a unique identifier
/// </summary>
public string GetNodePath()
{
if (nodePath == null)
{
GenerateNodePath();
}
return nodePath;
}
private void GenerateNodePath()
{
string path = "";
ObjectExplorerUtils.VisitChildAndParents(this, node =>
{
if (string.IsNullOrEmpty(node.NodeValue))
{
// Hit a node with no NodeValue. This indicates we need to stop traversing
return false;
}
// Otherwise add this value to the beginning of the path and keep iterating up
path = string.Format(CultureInfo.InvariantCulture,
"{0}{1}{2}", node.NodePathName, string.IsNullOrEmpty(path) ? "" : PathPartSeperator.ToString(), path);
return true;
});
nodePath = path;
}
public TreeNode? FindNodeByPath(string path, bool expandIfNeeded = false)
{
TreeNode? nodeForPath = ObjectExplorerUtils.FindNode(this, node =>
{
return node.GetNodePath() == path;
}, nodeToFilter =>
{
return path.StartsWith(nodeToFilter.GetNodePath());
}, expandIfNeeded);
return nodeForPath;
}
/// <summary>
/// Converts to a <see cref="NodeInfo"/> object for serialization with just the relevant properties
/// needed to identify the node
/// </summary>
/// <returns></returns>
public NodeInfo ToNodeInfo()
{
return new NodeInfo()
{
IsLeaf = this.IsAlwaysLeaf,
Label = this.Label,
NodePath = this.GetNodePath(),
ParentNodePath = this.Parent?.GetNodePath() ?? "",
NodeType = this.NodeType,
Metadata = this.ObjectMetadata,
NodeStatus = this.NodeStatus,
NodeSubType = this.NodeSubType,
ErrorMessage = this.ErrorMessage,
ObjectType = this.NodeTypeId.ToString(),
FilterableProperties = this.FilterProperties
};
}
/// <summary>
/// Expands this node and returns its children
/// </summary>
/// <returns>Children as an IList. This is the raw children collection, not a copy</returns>
public IList<TreeNode> Expand(string name, CancellationToken cancellationToken, string? accessToken = null, IEnumerable<NodeFilter>? filters = null)
{
// TODO consider why solution explorer has separate Children and Items options
if (children.IsInitialized)
{
return children;
}
PopulateChildren(false, name, cancellationToken, accessToken, filters);
return children;
}
/// <summary>
/// Expands this node and returns its children
/// </summary>
/// <returns>Children as an IList. This is the raw children collection, not a copy</returns>
public IList<TreeNode> Expand(CancellationToken cancellationToken, string? accessToken = null, IEnumerable<NodeFilter>? filters = null)
{
return Expand(null, cancellationToken, accessToken, filters);
}
/// <summary>
/// Refresh this node and returns its children
/// </summary>
/// <returns>Children as an IList. This is the raw children collection, not a copy</returns>
public virtual IList<TreeNode> Refresh(CancellationToken cancellationToken, string? accessToken = null, IEnumerable<NodeFilter>? filters = null)
{
// TODO consider why solution explorer has separate Children and Items options
PopulateChildren(true, null, cancellationToken, accessToken, filters);
return children;
}
/// <summary>
/// Gets a readonly view of the currently defined children for this node.
/// This does not expand the node at all
/// Since the tree needs to keep track of parent relationships, directly
/// adding to the list is not supported.
/// </summary>
/// <returns><see cref="IList{TreeNode}"/> containing all children for this node</returns>
public IList<TreeNode> GetChildren()
{
return new ReadOnlyCollection<TreeNode>(children);
}
/// <summary>
/// Adds a child to the list of children under this node
/// </summary>
/// <param name="newChild"><see cref="TreeNode"/></param>
public void AddChild(TreeNode newChild)
{
Validate.IsNotNull(nameof(newChild), newChild);
children.Add(newChild);
newChild.Parent = this;
}
/// <summary>
/// Optional context to help with lookup of children
/// </summary>
public virtual object GetContext()
{
return null;
}
/// <summary>
/// Helper method to convert context to expected format
/// </summary>
/// <typeparam name="T">Type to convert to</typeparam>
/// <returns>context as expected type of null if it doesn't match</returns>
public T GetContextAs<T>()
where T : class
{
return GetContext() as T;
}
public T ParentAs<T>()
where T : TreeNode
{
return Parent as T;
}
protected virtual void PopulateChildren(bool refresh, string name, CancellationToken cancellationToken, string? accessToken = null, IEnumerable<NodeFilter>? filters = null)
{
Logger.Verbose(string.Format(CultureInfo.InvariantCulture, "Populating oe node :{0}", this.GetNodePath()));
Debug.Assert(IsAlwaysLeaf == false);
SmoQueryContext context = this.GetContextAs<SmoQueryContext>();
bool includeSystemObjects = context != null && context.Database != null ? DatabaseUtils.IsSystemDatabaseConnection(context.Database.Name) : true;
if (children.IsPopulating || context == null)
{
return;
}
children.Clear();
BeginChildrenInit();
// Update access token for future queries
context.UpdateAccessToken(accessToken);
try
{
ErrorMessage = null;
IEnumerable<ChildFactory> childFactories = context.GetObjectExplorerService().GetApplicableChildFactories(this);
if (childFactories != null)
{
foreach (var factory in childFactories)
{
cancellationToken.ThrowIfCancellationRequested();
try
{
Logger.Verbose($"Begin populate children for {this.GetNodePath()} using {factory.GetType()} factory");
IEnumerable<TreeNode> items = factory.Expand(this, refresh, name, includeSystemObjects, cancellationToken, filters);
Logger.Verbose($"End populate children for {this.GetNodePath()} using {factory.GetType()} factory");
if (items != null)
{
foreach (TreeNode item in items)
{
children.Add(item);
item.Parent = this;
}
}
}
catch (Exception ex)
{
string error = string.Format(CultureInfo.InvariantCulture, "Failed populating oe children. error:{0} inner:{1} stacktrace:{2}",
ex.Message, ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace);
Logger.Error(error);
ErrorMessage = ex.Message;
}
}
}
}
catch (Exception ex)
{
string error = string.Format(CultureInfo.InvariantCulture, "Failed populating oe children. error:{0} inner:{1} stacktrace:{2}",
ex.Message, ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace);
Logger.Error(error);
ErrorMessage = ex.Message;
}
finally
{
EndChildrenInit();
}
}
public void BeginChildrenInit()
{
children.BeginInit();
}
public void EndChildrenInit()
{
children.EndInit();
// TODO consider use of deferred children and if it's necessary
// children.EndInit(this, ref deferredChildren);
}
/// <summary>
/// Sort Priority to help when ordering elements in the tree
/// </summary>
public int? SortPriority { get; set; }
protected virtual int CompareSamePriorities(TreeNode thisItem, TreeNode otherItem)
{
return string.Compare(thisItem.NodeValue, otherItem.NodeValue, StringComparison.OrdinalIgnoreCase);
}
public int CompareTo(TreeNode other)
{
if (!this.SortPriority.HasValue &&
!other.SortPriority.HasValue)
{
return CompareSamePriorities(this, other);
}
// Higher SortPriority = lower in the list. A couple nodes are defined with SortPriority of Int16.MaxValue
// so they're placed at the bottom of the node list (Dropped Ledger Tables and Dropped Ledger Views folders)
// Individual objects, like tables and views, don't have a SortPriority defined, so their values need
// to be resolved. If a node doesn't have a SortPriority, set it to the second-highest value.
int thisPriority = this.SortPriority ?? Int32.MaxValue - 1;
int otherPriority = other.SortPriority ?? Int32.MaxValue - 1;
// diff > 0 == this below other
// diff < 0 == other below this
return thisPriority - otherPriority;
}
}
}

View File

@@ -1,11 +0,0 @@
//
// 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.ObjectExplorer.Nodes
{
public class TreeNodeWithContext
{
}
}

View File

@@ -23,12 +23,14 @@ using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.TableDesigner;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.ServiceLayer.Workspace;
using Microsoft.SqlTools.SqlCore.Connection;
using Microsoft.SqlTools.SqlCore.ObjectExplorer;
using Microsoft.SqlTools.SqlCore.ObjectExplorer.Nodes;
using Microsoft.SqlTools.SqlCore.ObjectExplorer.SmoModel;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
@@ -46,7 +48,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
private ConnectionService connectionService;
private IProtocolEndpoint serviceHost;
private ConcurrentDictionary<string, ObjectExplorerSession> sessionMap;
private readonly Lazy<Dictionary<string, HashSet<ChildFactory>>> applicableNodeChildFactories;
private IMultiServiceProvider serviceProvider;
private ConnectedBindingQueue bindingQueue = new ConnectedBindingQueue(needsMetadata: false);
private string connectionName = "ObjectExplorer";
@@ -62,7 +63,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
public ObjectExplorerService()
{
sessionMap = new ConcurrentDictionary<string, ObjectExplorerSession>();
applicableNodeChildFactories = new Lazy<Dictionary<string, HashSet<ChildFactory>>>(PopulateFactories);
NodePathGenerator.Initialize();
}
@@ -78,14 +78,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
}
}
private Dictionary<string, HashSet<ChildFactory>> ApplicableNodeChildFactories
{
get
{
return applicableNodeChildFactories.Value;
}
}
/// <summary>
/// Returns the session ids
/// </summary>
@@ -286,7 +278,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
var foundNodes = FindNodes(findNodesParams.SessionId, findNodesParams.Type, findNodesParams.Schema, findNodesParams.Name, findNodesParams.Database, findNodesParams.ParentObjectNames);
foundNodes ??= new List<TreeNode>();
await context.SendResult(new FindNodesResponse { Nodes = foundNodes.Select(node => node.ToNodeInfo()).ToList() });
await context.SendResult(new FindNodesResponse { Nodes = foundNodes.Select(node => new NodeInfo(node)).ToList() });
}
internal void CloseSession(string uri)
@@ -365,7 +357,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
response = new SessionCreatedParameters
{
Success = true,
RootNode = session.Root.ToNodeInfo(),
RootNode = new NodeInfo(session.Root),
SessionId = uri,
ErrorNumber = session.ErrorNumber,
ErrorMessage = session.ErrorMessage
@@ -444,17 +436,30 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
securityToken = null;
}
var filterDefinitions = node.FilterProperties;
var appliedFilters = new List<INodeFilter>();
if (filters != null)
{
foreach (var f in filters)
{
NodeFilterProperty filterProperty = filterDefinitions.FirstOrDefault(x => x.Name == f.Name);
appliedFilters.Add(f.ToINodeFilter(filterProperty));
}
}
if (forceRefresh)
{
Logger.Verbose($"Forcing refresh for {nodePath}");
nodes = node.Refresh(cancelToken, securityToken?.Token, filters).Select(x => x.ToNodeInfo()).ToArray();
nodes = node.Refresh(cancelToken, securityToken?.Token, appliedFilters).Select(x => new NodeInfo(x)).ToArray();
}
else
{
Logger.Verbose($"Expanding {nodePath}");
try
{
nodes = node.Expand(cancelToken, securityToken?.Token, filters).Select(x => x.ToNodeInfo()).ToArray();
nodes = node.Expand(cancelToken, securityToken?.Token, appliedFilters).Select(x => new NodeInfo(x)).ToArray();
}
catch (ConnectionFailureException ex)
{
@@ -534,7 +539,10 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
waitForLockTimeout: timeout,
bindOperation: (bindingContext, cancelToken) =>
{
session = ObjectExplorerSession.CreateSession(connectionResult, serviceProvider, bindingContext.ServerConnection, isDefaultOrSystemDatabase);
session = ObjectExplorerSession.CreateSession(connectionResult, bindingContext.ServerConnection, isDefaultOrSystemDatabase, serviceProvider, () =>
{
return WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.ObjectExplorer.GroupBySchema;
});
session.ConnectionInfo = connectionInfo;
sessionMap.AddOrUpdate(uri, session, (key, oldSession) => session);
@@ -687,39 +695,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
return ConnectedBindingQueue.GetConnectionContextKey(details);
}
public IEnumerable<ChildFactory> GetApplicableChildFactories(TreeNode item)
{
if (ApplicableNodeChildFactories != null)
{
HashSet<ChildFactory> applicableFactories;
if (ApplicableNodeChildFactories.TryGetValue(item.NodeTypeId.ToString(), out applicableFactories))
{
return applicableFactories;
}
}
return null;
}
internal Dictionary<string, HashSet<ChildFactory>> PopulateFactories()
{
VerifyServicesInitialized();
var childFactories = new Dictionary<string, HashSet<ChildFactory>>();
// Create our list of all NodeType to ChildFactory objects so we can expand appropriately
foreach (var factory in serviceProvider.GetServices<ChildFactory>())
{
var parents = factory.ApplicableParents();
if (parents != null)
{
foreach (var parent in parents)
{
AddToApplicableChildFactories(childFactories, factory, parent);
}
}
}
return childFactories;
}
private void VerifyServicesInitialized()
{
if (serviceProvider == null)
@@ -821,27 +796,21 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
return string.Empty;
}
internal class ObjectExplorerSession
internal class ObjectExplorerSession : IObjectExplorerSession
{
private ConnectionService connectionService;
private IMultiServiceProvider serviceProvider;
// TODO decide whether a cache is needed to handle lookups in elements with a large # children
//private const int Cachesize = 10000;
//private Cache<string, NodeMapping> cache;
public ObjectExplorerSession(string uri, TreeNode root, IMultiServiceProvider serviceProvider, ConnectionService connectionService)
public ObjectExplorerSession(string uri, TreeNode root)
{
Validate.IsNotNullOrEmptyString("uri", uri);
Validate.IsNotNull("root", root);
Uri = uri;
Root = root;
this.serviceProvider = serviceProvider;
this.connectionService = connectionService;
}
public string Uri { get; private set; }
public TreeNode Root { get; private set; }
public ConnectionInfo ConnectionInfo { get; set; }
@@ -849,10 +818,21 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
public string ErrorMessage { get; set; }
public static ObjectExplorerSession CreateSession(ConnectionCompleteParams response, IMultiServiceProvider serviceProvider, ServerConnection serverConnection, bool isDefaultOrSystemDatabase)
public static ObjectExplorerSession CreateSession(ConnectionCompleteParams response, ServerConnection serverConnection, bool isDefaultOrSystemDatabase, IMultiServiceProvider serviceProvider, Func<bool> groupBySchemaFlagGetter)
{
ServerNode rootNode = new ServerNode(response, serviceProvider, serverConnection);
var session = new ObjectExplorerSession(response.OwnerUri, rootNode, serviceProvider, serviceProvider.GetService<ConnectionService>());
ServerNode rootNode = new ServerNode(new ObjectExplorerServerInfo()
{
ServerName = response.ConnectionSummary.ServerName,
DatabaseName = response.ConnectionSummary.DatabaseName,
UserName = response.ConnectionSummary.UserName,
ServerVersion = response.ServerInfo.ServerVersion,
EngineEditionId = response.ServerInfo.EngineEditionId,
IsCloud = response.ServerInfo.IsCloud,
}, serverConnection, serviceProvider, () =>
{
return WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.ObjectExplorer.GroupBySchema;
});
var session = new ObjectExplorerSession(response.OwnerUri, rootNode);
if (!isDefaultOrSystemDatabase)
{
// Assuming the databases are in a folder under server node

View File

@@ -7,9 +7,7 @@
using System;
using System.Threading;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using System.Collections.Generic;
using Microsoft.SqlTools.SqlCore.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
{
@@ -53,7 +51,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
/// determines whether to stop going further up the tree</param>
/// <param name="filter">Predicate function to filter the children when traversing</param>
/// <returns>A Tree Node that matches the condition, or null if no matching node could be found</returns>
public static TreeNode? FindNode(TreeNode node, Predicate<TreeNode> condition, Predicate<TreeNode> filter, bool expandIfNeeded = false)
public static TreeNode? FindNode(TreeNode node, Predicate<TreeNode> condition, Predicate<TreeNode> filter, bool expandIfNeeded = false, CancellationToken cancellationToken = new CancellationToken())
{
if (node == null)
{
@@ -64,7 +62,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
{
return node;
}
var children = expandIfNeeded && !node.IsAlwaysLeaf ? node.Expand(new CancellationToken()) : node.GetChildren();
var children = expandIfNeeded && !node.IsAlwaysLeaf ? node.Expand(cancellationToken) : node.GetChildren();
foreach (var child in children)
{
if (filter != null && filter(child))
@@ -78,108 +76,5 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
}
return null;
}
public static INodeFilter ConvertExpandNodeFilterToNodeFilter(NodeFilter filter, NodeFilterProperty filterProperty)
{
Type type = typeof(string);
var IsDateTime = filterProperty.Type == NodeFilterPropertyDataType.Date;
FilterType filterType = FilterType.EQUALS;
bool isNotFilter = false;
object filterValue = null;
switch (filterProperty.Type)
{
case NodeFilterPropertyDataType.String:
case NodeFilterPropertyDataType.Date:
case NodeFilterPropertyDataType.Choice:
type = typeof(string);
filterValue = filter.Value.ToString();
break;
case NodeFilterPropertyDataType.Number:
type = typeof(int);
filterValue = filter.Value.ToObject<int>();
break;
case NodeFilterPropertyDataType.Boolean:
type = typeof(bool);
filterValue = filter.Value.ToObject<bool>() ? 1 : 0;
break;
}
switch (filter.Operator)
{
case NodeFilterOperator.Equals:
filterType = FilterType.EQUALS;
break;
case NodeFilterOperator.NotEquals:
filterType = FilterType.EQUALS;
isNotFilter = true;
break;
case NodeFilterOperator.LessThan:
filterType = FilterType.LESSTHAN;
break;
case NodeFilterOperator.LessThanOrEquals:
filterType = FilterType.LESSTHANOREQUAL;
break;
case NodeFilterOperator.GreaterThan:
filterType = FilterType.GREATERTHAN;
break;
case NodeFilterOperator.GreaterThanOrEquals:
filterType = FilterType.GREATERTHANOREQUAL;
break;
case NodeFilterOperator.Between:
filterType = FilterType.BETWEEN;
break;
case NodeFilterOperator.NotBetween:
filterType = FilterType.NOTBETWEEN;
isNotFilter = true;
break;
case NodeFilterOperator.Contains:
filterType = FilterType.CONTAINS;
break;
case NodeFilterOperator.NotContains:
filterType = FilterType.CONTAINS;
isNotFilter = true;
break;
case NodeFilterOperator.StartsWith:
filterType = FilterType.STARTSWITH;
break;
case NodeFilterOperator.NotStartsWith:
filterType = FilterType.STARTSWITH;
isNotFilter = true;
break;
case NodeFilterOperator.EndsWith:
filterType = FilterType.ENDSWITH;
break;
case NodeFilterOperator.NotEndsWith:
filterType = FilterType.ENDSWITH;
isNotFilter = true;
break;
}
if (filter.Operator == NodeFilterOperator.Between || filter.Operator == NodeFilterOperator.NotBetween)
{
if (filterProperty.Type == NodeFilterPropertyDataType.Number)
{
filterValue = filter.Value.ToObject<int[]>();
}
else if (filterProperty.Type == NodeFilterPropertyDataType.Date)
{
filterValue = filter.Value.ToObject<string[]>();
}
}
return new NodePropertyFilter
{
Property = filterProperty.Name,
Type = type,
Values = new List<object> { filterValue },
IsNotFilter = isNotFilter,
FilterType = filterType,
IsDateTime = IsDateTime
};
}
}
}

View File

@@ -1,116 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
internal partial class DatabaseTreeNode
{
public DatabaseTreeNode(ServerNode serverNode, string databaseName) : this()
{
Parent = serverNode;
NodeValue = databaseName;
var db = new Database(serverNode.GetContextAs<SmoQueryContext>().Server, this.NodeValue);
db.Refresh();
// If we got this far, the connection is valid. However, it's possible
// the user connected directly to the master of a readable secondary
// In that case, the name in the connection string won't be found in sys.databases
// We detect that here and fall back to master
if (db.State == SqlSmoState.Creating && !IsDWGen3(db))
{
Logger.Information($"Database {databaseName} is in Creating state after initialization, defaulting to master for Object Explorer connections. This is expected when connecting to an Availability Group readable secondary");
db = new Database(serverNode.GetContextAs<SmoQueryContext>().Server, "master");
db.Refresh();
}
CacheInfoFromModel(db);
}
/// <summary>
/// Initializes the context and sets its ValidFor property
/// </summary>
protected override void EnsureContextInitialized()
{
if (context == null)
{
base.EnsureContextInitialized();
var db = SmoObject as Database;
if (db != null)
{
context.Database = db;
}
context.ValidFor = ServerVersionHelper.GetValidForFlag(context.SqlServerType, db);
}
}
protected override void PopulateChildren(bool refresh, string name, CancellationToken cancellationToken, string? accessToken = null, IEnumerable<NodeFilter>? filters = null)
{
var smoQueryContext = this.GetContextAs<SmoQueryContext>();
if (IsAccessible(smoQueryContext))
{
base.PopulateChildren(refresh, name, cancellationToken, accessToken, filters);
}
else
{
if (string.IsNullOrEmpty(ErrorMessage))
{
// Write error message if it wasn't already set during IsAccessible check
ErrorMessage = string.Format(CultureInfo.InvariantCulture, SR.DatabaseNotAccessible, this.NodeValue);
}
}
}
public bool IsAccessible(SmoQueryContext context)
{
try
{
return context?.Database == null || context.Database.IsAccessible;
}
catch (Exception ex)
{
// IsAccessible is not set of DW Gen3 and Dataverse so exception is expected in this case
// Incase of dataverses and other TDS endpoints isAccessible creates a temp table to check if the database
// is accessible, however these endpoints may not support ddl statements and therefore the check fails.
if (IsDWGen3(context?.Database) || isUnknownDatabaseEdition(context?.Database))
{
return true;
}
else
{
var error = string.Format(CultureInfo.InvariantCulture, "Failed to get IsAccessible. error:{0} inner:{1} stacktrace:{2}",
ex.Message, ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace);
Logger.Error(error);
ErrorMessage = ex.Message;
return false;
}
}
}
private bool IsDWGen3(Database db)
{
return db != null
&& db.DatabaseEngineEdition == DatabaseEngineEdition.SqlDataWarehouse
&& db.ServerVersion.Major == 12;
}
private bool isUnknownDatabaseEdition(Database db)
{
// If the database engine edition is not defined in the enum, it is an unknown edition
return db != null
&& !Enum.IsDefined(typeof(DatabaseEngineEdition), db.DatabaseEngineEdition);
}
}
}

View File

@@ -1,41 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Represents a folder node in the tree
/// </summary>
public class FolderNode : SmoTreeNode
{
public FolderNode()
{
this.NodeType = nameof(NodeTypes.Folder);
}
/// <summary>
/// For folders, this copies the context of its parent if available
/// </summary>
/// <returns></returns>
public override object GetContext()
{
return Parent?.GetContext();
}
/// <summary>
/// For folders, searches for its parent's SMO object rather than copying for itself
/// </summary>
/// <returns><see cref="NamedSmoObject"/> from this parent's parent, or null if not found</returns>
public override NamedSmoObject GetParentSmoObject()
{
return ParentAs<SmoTreeNode>()?.GetParentSmoObject();
}
}
}

View File

@@ -1,267 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
public class NodePathGenerator
{
private static ServerExplorerTree TreeRoot { get; set; }
private static Dictionary<string, HashSet<Node>> NodeTypeDictionary { get; set; }
internal static void Initialize()
{
if (TreeRoot != null)
{
return;
}
var assembly = typeof(ObjectExplorerService).Assembly;
var resource = assembly.GetManifestResourceStream("Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel.SmoTreeNodesDefinition.xml");
var serializer = new XmlSerializer(typeof(ServerExplorerTree));
NodeTypeDictionary = new Dictionary<string, HashSet<Node>>();
using (var reader = new StreamReader(resource))
{
TreeRoot = (ServerExplorerTree)serializer.Deserialize(reader);
}
foreach (var node in TreeRoot.Nodes)
{
var containedType = node.ContainedType();
if (containedType != null && node.Label() != string.Empty)
{
if (!NodeTypeDictionary.ContainsKey(containedType))
{
NodeTypeDictionary.Add(containedType, new HashSet<Node>());
}
NodeTypeDictionary.GetValueOrDefault(containedType).Add(node);
}
}
var serverNode = TreeRoot.Nodes.FirstOrDefault(node => node.Name == "Server");
var serverSet = new HashSet<Node>();
serverSet.Add(serverNode);
NodeTypeDictionary.Add("Server", serverSet);
}
internal static HashSet<string> FindNodePaths(ObjectExplorerService.ObjectExplorerSession objectExplorerSession, string typeName, string schema, string name, string databaseName, List<string> parentNames = null)
{
if (TreeRoot == null)
{
Initialize();
}
var returnSet = new HashSet<string>();
var matchingNodes = NodeTypeDictionary.GetValueOrDefault(typeName);
if (matchingNodes == null)
{
return returnSet;
}
var path = name;
if (schema != null)
{
path = schema + "." + path;
}
path ??= "";
foreach (var matchingNode in matchingNodes)
{
var paths = GenerateNodePath(objectExplorerSession, matchingNode, databaseName, parentNames, path);
foreach (var newPath in paths)
{
returnSet.Add(newPath);
}
}
return returnSet;
}
private static HashSet<string> GenerateNodePath(ObjectExplorerService.ObjectExplorerSession objectExplorerSession, Node currentNode, string databaseName, List<string> parentNames, string path)
{
if (parentNames != null)
{
parentNames = parentNames.ToList();
}
if (currentNode.Name == "Server" || (currentNode.Name == "Database" && objectExplorerSession.Root.NodeType == "Database"))
{
var serverRoot = objectExplorerSession.Root;
if (objectExplorerSession.Root.NodeType == "Database")
{
serverRoot = objectExplorerSession.Root.Parent;
path = objectExplorerSession.Root.NodeValue + (path.Length > 0 ? ("/" + path) : "");
}
path = serverRoot.NodeValue + (path.Length > 0 ? ("/" + path) : "");
var returnSet = new HashSet<string>();
returnSet.Add(path);
return returnSet;
}
var currentLabel = currentNode.Label();
if (currentLabel != string.Empty)
{
path = currentLabel + "/" + path;
var returnSet = new HashSet<string>();
foreach (var parent in currentNode.ParentNodes())
{
var paths = GenerateNodePath(objectExplorerSession, parent, databaseName, parentNames, path);
foreach (var newPath in paths)
{
returnSet.Add(newPath);
}
}
return returnSet;
}
else
{
var returnSet = new HashSet<string>();
if (currentNode.ContainedType() == "Database" || currentNode.ContainedType() == "ExpandableSchema")
{
path = databaseName + "/" + path;
}
else if (parentNames != null && parentNames.Count > 0)
{
var parentName = parentNames.Last();
parentNames.RemoveAt(parentNames.Count - 1);
path = parentName + "/" + path;
}
else
{
return returnSet;
}
foreach (var parentNode in currentNode.ParentNodes())
{
var newPaths = GenerateNodePath(objectExplorerSession, parentNode, databaseName, parentNames, path);
foreach (var newPath in newPaths)
{
returnSet.Add(newPath);
}
}
return returnSet;
}
}
[XmlRoot("ServerExplorerTree")]
public class ServerExplorerTree
{
[XmlElement("Node", typeof(Node))]
public List<Node> Nodes { get; set; }
public Node GetNode(string name)
{
foreach (var node in this.Nodes)
{
if (node.Name == name)
{
return node;
}
}
return null;
}
}
public class Node
{
[XmlAttribute]
public string Name { get; set; }
[XmlAttribute]
public string LocLabel { get; set; }
[XmlAttribute]
public string TreeNode { get; set; }
[XmlAttribute]
public string NodeType { get; set; }
[XmlElement("Child", typeof(Child))]
public List<Child> Children { get; set; }
public HashSet<Node> ChildFolders()
{
var childSet = new HashSet<Node>();
foreach (var child in this.Children)
{
var node = TreeRoot.GetNode(child.Name);
if (node != null)
{
childSet.Add(node);
}
}
return childSet;
}
public string ContainedType()
{
if (this.TreeNode != null)
{
return this.TreeNode.Replace("TreeNode", "");
}
else if (this.NodeType != null)
{
return this.NodeType;
}
return null;
}
public Node ContainedObject()
{
var containedType = this.ContainedType();
if (containedType == null)
{
return null;
}
var containedNode = TreeRoot.GetNode(containedType);
if (containedNode == this)
{
return null;
}
return containedNode;
}
public string Label()
{
if (this.LocLabel.StartsWith("SR."))
{
return SR.Keys.GetString(this.LocLabel.Remove(0, 3));
}
return string.Empty;
}
public HashSet<Node> ParentNodes()
{
var parentNodes = new HashSet<Node>();
foreach (var node in TreeRoot.Nodes)
{
if (this != node && (node.ContainedType() == this.Name || node.Children.Any(child => child.Name == this.Name)))
{
parentNodes.Add(node);
}
}
return parentNodes;
}
}
public class Child
{
[XmlAttribute]
public string Name { get; set; }
}
}
}

View File

@@ -1,160 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Globalization;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Server node implementation
/// </summary>
public class ServerNode : TreeNode
{
private ConnectionSummary connectionSummary;
private ServerInfo serverInfo;
private Lazy<SmoQueryContext> context;
private SmoWrapper smoWrapper;
private SqlServerType sqlServerType;
private ServerConnection serverConnection;
public ServerNode(ConnectionCompleteParams connInfo, IMultiServiceProvider serviceProvider, ServerConnection serverConnection)
: base()
{
Validate.IsNotNull(nameof(connInfo), connInfo);
Validate.IsNotNull("connInfo.ConnectionSummary", connInfo.ConnectionSummary);
Validate.IsNotNull(nameof(serviceProvider), serviceProvider);
this.connectionSummary = connInfo.ConnectionSummary;
this.serverInfo = connInfo.ServerInfo;
this.sqlServerType = ServerVersionHelper.CalculateServerType(this.serverInfo);
this.context = new Lazy<SmoQueryContext>(() => CreateContext(serviceProvider));
this.serverConnection = serverConnection;
NodeValue = connectionSummary.ServerName;
IsAlwaysLeaf = false;
NodeType = NodeTypes.Server.ToString();
NodeTypeId = NodeTypes.Server;
Label = GetConnectionLabel();
}
internal SmoWrapper SmoWrapper
{
get
{
smoWrapper ??= new SmoWrapper();
return smoWrapper;
}
set
{
this.smoWrapper = value;
}
}
/// <summary>
/// Returns the label to display to the user.
/// </summary>
internal string GetConnectionLabel()
{
string userName = connectionSummary.UserName;
// TODO Domain and username is not yet supported on .Net Core.
// Consider passing as an input from the extension where this can be queried
//if (string.IsNullOrWhiteSpace(userName))
//{
// userName = Environment.UserDomainName + @"\" + Environment.UserName;
//}
// TODO Consider adding IsAuthenticatingDatabaseMaster check in the code and
// referencing result here
if (!DatabaseUtils.IsSystemDatabaseConnection(connectionSummary.DatabaseName))
{
// We either have an azure with a database specified or a Denali database using a contained user
if (string.IsNullOrWhiteSpace(userName))
{
userName = connectionSummary.DatabaseName;
}
else
{
userName += ", " + connectionSummary.DatabaseName;
}
}
string label;
if (string.IsNullOrWhiteSpace(userName))
{
label = string.Format(
CultureInfo.InvariantCulture,
"{0} ({1} {2})",
connectionSummary.ServerName,
"SQL Server",
serverInfo.ServerVersion);
}
else
{
label = string.Format(
CultureInfo.InvariantCulture,
"{0} ({1} {2} - {3})",
connectionSummary.ServerName,
"SQL Server",
serverInfo.ServerVersion,
userName);
}
return label;
}
private SmoQueryContext CreateContext(IMultiServiceProvider serviceProvider)
{
string exceptionMessage;
try
{
Server server = SmoWrapper.CreateServer(this.serverConnection);
if (server != null)
{
return new SmoQueryContext(server, serviceProvider, SmoWrapper)
{
Parent = server,
SqlServerType = this.sqlServerType
};
}
else
{
return null;
}
}
catch (ConnectionFailureException cfe)
{
exceptionMessage = cfe.Message;
}
catch (Exception ex)
{
exceptionMessage = ex.Message;
}
Logger.Error("Exception at ServerNode.CreateContext() : " + exceptionMessage);
this.ErrorStateMessage = string.Format(SR.TreeNodeError, exceptionMessage);
return null;
}
public override object GetContext()
{
return context.Value;
}
}
}

View File

@@ -1,356 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
public class SmoChildFactoryBase : ChildFactory
{
private IEnumerable<NodeSmoProperty> smoProperties;
public override IEnumerable<string> ApplicableParents()
{
return null;
}
public override IEnumerable<TreeNode> Expand(TreeNode parent, bool refresh, string name, bool includeSystemObjects, CancellationToken cancellationToken, IEnumerable<NodeFilter>? filters = null)
{
List<TreeNode> allChildren = new List<TreeNode>();
try
{
if (this.PutFoldersAfterNodes)
{
OnExpandPopulateNonFolders(allChildren, parent, refresh, name, cancellationToken, filters);
OnExpandPopulateFoldersAndFilter(allChildren, parent, includeSystemObjects);
RemoveFoldersFromInvalidSqlServerVersions(allChildren, parent);
}
else
{
OnExpandPopulateFoldersAndFilter(allChildren, parent, includeSystemObjects);
RemoveFoldersFromInvalidSqlServerVersions(allChildren, parent);
OnExpandPopulateNonFolders(allChildren, parent, refresh, name, cancellationToken, filters);
}
OnBeginAsyncOperations(parent);
}
catch (Exception ex)
{
string error = string.Format(CultureInfo.InvariantCulture, "Failed expanding oe children. parent:{0} error:{1} inner:{2} stacktrace:{3}",
parent != null ? parent.GetNodePath() : "", ex.Message, ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace);
Logger.Error(error);
throw;
}
return allChildren;
}
private void OnExpandPopulateFoldersAndFilter(List<TreeNode> allChildren, TreeNode parent, bool includeSystemObjects)
{
SmoQueryContext context = parent.GetContextAs<SmoQueryContext>();
OnExpandPopulateFolders(allChildren, parent);
if (!includeSystemObjects)
{
allChildren.RemoveAll(x => x.IsSystemObject);
}
if (context != null && context.ValidFor != 0 && context.ValidFor != ValidForFlag.All)
{
allChildren.RemoveAll(x =>
{
FolderNode folderNode = x as FolderNode;
if (folderNode != null && !ServerVersionHelper.IsValidFor(context.ValidFor, folderNode.ValidFor))
{
return true;
}
return false;
});
// Remove the Dropped Ledger Columns folder if this isn't under a ledger table
allChildren.RemoveAll(x =>
{
if (x.NodeTypeId == NodeTypes.DroppedLedgerColumns)
{
Table? parentTable = context.Parent as Table;
if (parentTable == null ||
!(parentTable.LedgerType == LedgerTableType.UpdatableLedgerTable ||
parentTable.LedgerType == LedgerTableType.AppendOnlyLedgerTable))
{
return true;
}
}
return false;
});
}
}
/// <summary>
/// Populates any folders for a given parent node
/// </summary>
/// <param name="allChildren">List to which nodes should be added</param>
/// <param name="parent">Parent the nodes are being added to</param>
protected virtual void OnExpandPopulateFolders(IList<TreeNode> allChildren, TreeNode parent)
{
}
/// <summary>
/// Populates any non-folder nodes such as specific items in the tree.
/// </summary>
/// <param name="allChildren">List to which nodes should be added</param>
/// <param name="parent">Parent the nodes are being added to</param>
protected virtual void OnExpandPopulateNonFolders(IList<TreeNode> allChildren, TreeNode parent, bool refresh, string name, CancellationToken cancellationToken, IEnumerable<NodeFilter>? appliedFilters = null)
{
Logger.Verbose(string.Format(CultureInfo.InvariantCulture, "child factory parent :{0}", parent.GetNodePath()));
if (ChildQuerierTypes == null)
{
// This node does not support non-folder children
return;
}
SmoQueryContext context = parent.GetContextAs<SmoQueryContext>();
Validate.IsNotNull(nameof(context), context);
var serverValidFor = context.ValidFor;
if (ShouldFilterNode(parent, serverValidFor))
{
return;
}
IEnumerable<SmoQuerier> queriers = context.ServiceProvider.GetServices<SmoQuerier>(IsCompatibleQuerier);
var filters = this.Filters.ToList();
var smoProperties = this.SmoProperties.Where(p => ServerVersionHelper.IsValidFor(serverValidFor, p.ValidFor)).Select(x => x.Name);
var filterDefinitions = parent.FilterProperties;
if (!string.IsNullOrEmpty(name))
{
filters.Add(new NodePropertyFilter
{
Property = "Name",
Type = typeof(string),
Values = new List<object> { name },
});
}
if (appliedFilters != null)
{
foreach (var f in appliedFilters)
{
NodeFilterProperty filterProperty = filterDefinitions.FirstOrDefault(x => x.Name == f.Name);
filters.Add(ObjectExplorerUtils.ConvertExpandNodeFilterToNodeFilter(f, filterProperty));
}
}
foreach (var querier in queriers)
{
cancellationToken.ThrowIfCancellationRequested();
if (!querier.IsValidFor(serverValidFor))
{
continue;
}
string propertyFilter = INodeFilter.GetPropertyFilter(filters, querier.GetType(), serverValidFor);
try
{
var smoObjectList = querier.Query(context, propertyFilter, refresh, smoProperties).ToList();
foreach (var smoObject in smoObjectList)
{
cancellationToken.ThrowIfCancellationRequested();
if (smoObject == null)
{
Logger.Error("smoObject should not be null");
}
TreeNode childNode = CreateChild(parent, smoObject);
if (childNode != null && PassesFinalFilters(childNode, smoObject) && !ShouldFilterNode(childNode, serverValidFor))
{
allChildren.Add(childNode);
}
}
}
catch (Exception ex)
{
string error = string.Format(CultureInfo.InvariantCulture, "Failed getting smo objects. parent:{0} querier: {1} error:{2} inner:{3} stacktrace:{4}",
parent != null ? parent.GetNodePath() : "", querier.GetType(), ex.Message, ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace);
Logger.Error(error);
throw;
}
}
}
private bool ShouldFilterNode(TreeNode childNode, ValidForFlag validForFlag)
{
bool filterTheNode = false;
SmoTreeNode smoTreeNode = childNode as SmoTreeNode;
if (smoTreeNode != null)
{
if (!ServerVersionHelper.IsValidFor(validForFlag, smoTreeNode.ValidFor))
{
filterTheNode = true;
}
}
return filterTheNode;
}
private bool IsCompatibleQuerier(SmoQuerier querier)
{
if (ChildQuerierTypes == null)
{
return false;
}
Type actualType = querier.GetType();
foreach (Type childType in ChildQuerierTypes)
{
// We will accept any querier that is compatible with the listed querier type
if (childType.IsAssignableFrom(actualType))
{
return true;
}
}
return false;
}
/// <summary>
/// Filters out invalid folders if they cannot be displayed for the current server version
/// </summary>
/// <param name="allChildren">List to which nodes should be added</param>
/// <param name="parent">Parent the nodes are being added to</param>
protected virtual void RemoveFoldersFromInvalidSqlServerVersions(IList<TreeNode> allChildren, TreeNode parent)
{
}
// TODO Assess whether async operations node is required
protected virtual void OnBeginAsyncOperations(TreeNode parent)
{
}
public override bool CanCreateChild(TreeNode parent, object context)
{
return false;
}
public override TreeNode CreateChild(TreeNode parent, object context)
{
throw new NotImplementedException();
}
protected virtual void InitializeChild(TreeNode parent, TreeNode child, object context)
{
NamedSmoObject smoObj = context as NamedSmoObject;
if (smoObj == null)
{
Debug.WriteLine("context is not a NamedSmoObject. type: " + context.GetType());
}
else
{
smoProperties = SmoProperties;
SmoTreeNode childAsMeItem = (SmoTreeNode)child;
childAsMeItem.CacheInfoFromModel(smoObj);
SmoQueryContext smoContext = parent.GetContextAs<SmoQueryContext>();
// If node has custom name, replaced it with the name already set
string customizedName = GetNodeCustomName(context, smoContext);
if (!string.IsNullOrEmpty(customizedName))
{
childAsMeItem.NodeValue = customizedName;
childAsMeItem.NodePathName = GetNodePathName(context);
}
childAsMeItem.NodeSubType = GetNodeSubType(context, smoContext);
childAsMeItem.NodeStatus = GetNodeStatus(context, smoContext);
}
}
internal virtual Type[] ChildQuerierTypes
{
get
{
return null;
}
}
public override IEnumerable<INodeFilter> Filters
{
get
{
return Enumerable.Empty<INodeFilter>();
}
}
public override IEnumerable<NodeSmoProperty> SmoProperties
{
get
{
return Enumerable.Empty<NodeSmoProperty>();
}
}
internal IEnumerable<NodeSmoProperty> CachedSmoProperties
{
get
{
return smoProperties == null ? SmoProperties : smoProperties;
}
}
/// <summary>
/// Returns true if any final validation of the object to be added passes, and false
/// if validation fails. This provides a chance to filter specific items out of a list
/// </summary>
/// <param name="parent"></param>
/// <param name="contextObject"></param>
/// <returns>boolean</returns>
public virtual bool PassesFinalFilters(TreeNode parent, object context)
{
return true;
}
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
return string.Empty;
}
public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
return string.Empty;
}
public static bool IsPropertySupported(string propertyName, SmoQueryContext context, NamedSmoObject smoObj, IEnumerable<NodeSmoProperty> supportedProperties)
{
var property = supportedProperties.FirstOrDefault(x => string.Compare(x.Name, propertyName, StringComparison.InvariantCultureIgnoreCase) == 0);
if (property != null)
{
return ServerVersionHelper.IsValidFor(context.ValidFor, property.ValidFor);
}
else
{
// Return true if cannot find the proeprty, SMO still tries to get that property but adding the property to supported list can make loading the nodes faster
Logger.Verbose($"Smo property name {propertyName} for Smo type {smoObj.GetType()} is not added as supported properties. This can cause the performance of loading the OE nodes");
return true;
}
}
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
return string.Empty;
}
public override string GetNodePathName(object smoObject)
{
return (smoObject as NamedSmoObject).Name;
}
}
}

View File

@@ -1,59 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Wrapper to convert non-generic Smo enumerables to generic enumerable types for easier use in
/// </summary>
/// <typeparam name="T"></typeparam>
public class SmoCollectionWrapper<T> : IEnumerable<T>
where T : SqlSmoObject
{
private SmoCollectionBase collection;
/// <summary>
/// Constructor which accepts a <see cref="SmoCollectionBase"/> containing the objects
/// to wrap
/// </summary>
/// <param name="collection"><see cref="SmoCollectionBase"/> or null if none were set</param>
public SmoCollectionWrapper(SmoCollectionBase collection)
{
this.collection = collection;
}
/// <summary>
/// <see cref="IEnumerable{T}.GetEnumerator"/>
/// </summary>
/// <returns></returns>
public IEnumerator<T> GetEnumerator()
{
if (collection == null)
{
yield break;
}
foreach(Object obj in collection)
{
yield return (T)obj;
}
}
/// <summary>
/// <see cref="IEnumerable.GetEnumerator"/>
/// </summary>
/// <returns></returns>
IEnumerator IEnumerable.GetEnumerator()
{
return collection?.GetEnumerator();
}
}
}

View File

@@ -1,366 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Custom name for Columns
/// </summary>
internal partial class ColumnsChildFactory : SmoChildFactoryBase
{
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
return SmoColumnCustomNodeHelper.CalculateCustomLabel(smoObject, smoContext);
}
private readonly Lazy<List<NodeSmoProperty>> smoPropertiesLazy = new Lazy<List<NodeSmoProperty>>(() => new List<NodeSmoProperty>
{
new NodeSmoProperty
{
Name = "Computed",
ValidFor = ValidForFlag.All
},
new NodeSmoProperty
{
Name = "IsColumnSet",
ValidFor = ValidForFlag.All
},
new NodeSmoProperty
{
Name = "Nullable",
ValidFor = ValidForFlag.All
},
new NodeSmoProperty
{
Name = "DataType",
ValidFor = ValidForFlag.All
},
new NodeSmoProperty
{
Name = "InPrimaryKey",
ValidFor = ValidForFlag.All
},
new NodeSmoProperty
{
Name = "IsForeignKey",
ValidFor = ValidForFlag.All
},
new NodeSmoProperty
{
Name = "SystemType",
ValidFor = ValidForFlag.All
},
new NodeSmoProperty
{
Name = "Length",
ValidFor = ValidForFlag.All
},
new NodeSmoProperty
{
Name = "NumericPrecision",
ValidFor = ValidForFlag.All
},
new NodeSmoProperty
{
Name = "NumericScale",
ValidFor = ValidForFlag.All
},
new NodeSmoProperty
{
Name = "XmlSchemaNamespaceSchema",
ValidFor = ValidForFlag.NotSqlDw
},
new NodeSmoProperty
{
Name = "XmlSchemaNamespace",
ValidFor = ValidForFlag.NotSqlDw
},
new NodeSmoProperty
{
Name = "XmlDocumentConstraint",
ValidFor = ValidForFlag.NotSqlDw
},
new NodeSmoProperty
{
Name = "IsDroppedLedgerColumn",
ValidFor = ValidForFlag.Sql2022|ValidForFlag.AzureV12
}
});
public override IEnumerable<NodeSmoProperty> SmoProperties => smoPropertiesLazy.Value;
}
/// <summary>
/// Custom name for UserDefinedTableTypeColumn
/// </summary>
internal partial class UserDefinedTableTypeColumnsChildFactory : SmoChildFactoryBase
{
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
return SmoColumnCustomNodeHelper.CalculateCustomLabel(smoObject, smoContext);
}
}
static class SmoColumnCustomNodeHelper
{
private const string SimpleColumnLabelWithType = "{0} ({1}{2}, {3})";
private const string SimpleColumnLabelWithoutType = "{0} ({1})";
private const string SimpleColumnLabelWithTypeAndKeyString = "{0} ({1}, {2}, {3})";
internal static string CalculateCustomLabel(object context, SmoQueryContext smoContext)
{
UserDefinedDataTypeCollection uddts = null;
if (smoContext != null)
{
uddts = smoContext.Database.UserDefinedDataTypes;
}
Column column = context as Column;
if(column != null)
{
return GetCustomizedLabel(column, uddts);
}
return string.Empty;
}
private static string GetCustomizedLabel(Column column, UserDefinedDataTypeCollection uddts)
{
try
{
if (column.Computed)
{
return GetComputedColumnLabel(column, uddts);
}
else if (column.IsColumnSet)
{
return GetColumnSetLabel(column, uddts);
}
else
{
return GetSimpleColumnLabel(column, uddts);
}
}
catch(Exception ex)
{
Logger.Error($"Failed to get customized column name. error:{ex.Message}");
}
return string.Empty;
}
private static string GetTypeSpecifierLabel(DataType dataType, UserDefinedDataTypeCollection uddts)
{
string typeName = string.Empty;
if (dataType != null)
{
// typeSpecifier might still be in a resolve candidate status. If so then the
// name might be null. Don't ask for the type specifier name in this case.
typeName = dataType.Name;
// This may return [dbo].[MyType], but for the purposes of display we only want MyType
if (!string.IsNullOrWhiteSpace(typeName) &&
typeName.EndsWith("]", StringComparison.Ordinal))
{
int nameStart = typeName.LastIndexOf('[');
typeName = typeName.Substring(nameStart + 1, typeName.Length - nameStart - 2);
}
if(dataType.SqlDataType == SqlDataType.UserDefinedDataType && uddts != null)
{
foreach (UserDefinedDataType item in uddts)
{
if(item.Name == dataType.Name)
{
typeName += $"({item.SystemType})";
break;
}
}
}
// These types supports detailed information
switch (dataType.SqlDataType)
{
case SqlDataType.Char:
case SqlDataType.NChar:
case SqlDataType.Binary:
case SqlDataType.VarChar:
case SqlDataType.NVarChar:
case SqlDataType.VarBinary:
typeName += $"({dataType.MaximumLength})";
break;
case SqlDataType.Numeric:
case SqlDataType.Decimal:
typeName += $"({dataType.NumericPrecision},{dataType.NumericScale})";
break;
case SqlDataType.DateTime2:
case SqlDataType.Time:
case SqlDataType.DateTimeOffset:
typeName += $"({dataType.NumericScale})";
break;
case SqlDataType.VarBinaryMax:
case SqlDataType.NVarCharMax:
case SqlDataType.VarCharMax:
typeName += "(max)";
break;
}
}
return typeName;
}
private static string GetKeyString(Column column)
{
// Get if it's a PK or FK (or both)
// Here's how it could be both...notice t2c1 is both a primary and foreign key
//
// Create table t1 (t1c1 int, t1c2 int not null primary key)
// Create table t2 (t2c1 int primary key, t2c2 int not null)
// Alter table t2 add FOREIGN KEY(t2c1) references t1(t1c2)
//
string keyString = null;
if (column.InPrimaryKey)
keyString = "PK";
if (column.IsForeignKey)
{
keyString = (keyString == null) ? "FK" :
"PK, FK";
}
return keyString;
}
private static string GetColumnSetLabel(Column column, UserDefinedDataTypeCollection uddts)
{
// This is the simple name
string label = column.Name;
// Get the column type
string columnType = GetTypeSpecifierLabel(column.DataType, uddts);
string keyString = GetKeyString(column);
if (keyString != null && !string.IsNullOrWhiteSpace(columnType))
{
return string.Format(CultureInfo.InvariantCulture,
SR.SchemaHierarchy_ColumnSetLabelWithTypeAndKeyString,
label,
keyString,
columnType,
SR.SchemaHierarchy_NullColumn_Label);
}
if (!string.IsNullOrWhiteSpace(columnType))
{
return string.Format(CultureInfo.InvariantCulture,
SR.SchemaHierarchy_ColumnSetLabelWithType,
label,
keyString,
columnType,
SR.SchemaHierarchy_NullColumn_Label);
}
return string.Format(CultureInfo.InvariantCulture,
SR.SchemaHierarchy_ColumnSetLabelWithoutType,
label,
SR.SchemaHierarchy_NullColumn_Label);
}
private static string GetSimpleColumnLabel(Column column, UserDefinedDataTypeCollection uddts)
{
// This is the simple name
string label = column.Name;
// Get the nullability
string isNullable = column.Nullable ? SR.SchemaHierarchy_NullColumn_Label : SR.SchemaHierarchy_NotNullColumn_Label;
// Get the column type
string columnType = GetTypeSpecifierLabel(column.DataType, uddts);
string keyString = GetKeyString(column);
if (keyString != null && !string.IsNullOrWhiteSpace(columnType))
{
return string.Format(CultureInfo.InvariantCulture,
SimpleColumnLabelWithTypeAndKeyString,
label,
keyString,
columnType,
isNullable);
}
if (!string.IsNullOrWhiteSpace(columnType))
{
return string.Format(CultureInfo.InvariantCulture,
SimpleColumnLabelWithType,
label,
keyString,
columnType,
isNullable);
}
return string.Format(CultureInfo.InvariantCulture,
SimpleColumnLabelWithoutType,
label,
isNullable);
}
private static string GetComputedColumnLabel(Column column, UserDefinedDataTypeCollection uddts)
{
string columnType = null;
// Display the type name as fully qualified
string label = column.Name;
// Get the nullability
string isNullable = column.Nullable ? SR.SchemaHierarchy_NullColumn_Label : SR.SchemaHierarchy_NotNullColumn_Label;
string keyString = GetKeyString(column);
// Get the column type
columnType = GetTypeSpecifierLabel(column.DataType, uddts);
if (!string.IsNullOrWhiteSpace(columnType))
{
if (column.Parent is View)
{
// View columns are always computed, but SSMS shows then as never computed, so
// treat them as simple columns
return string.Format(CultureInfo.InvariantCulture,
SimpleColumnLabelWithType,
label,
keyString,
columnType,
isNullable);
}
return string.Format(CultureInfo.InvariantCulture,
SR.SchemaHierarchy_ComputedColumnLabelWithType,
label,
keyString,
columnType,
isNullable);
}
if (column.Parent is View)
{
return string.Format(CultureInfo.InvariantCulture,
SimpleColumnLabelWithoutType,
label,
keyString);
}
return string.Format(CultureInfo.InvariantCulture,
SR.SchemaHierarchy_ComputedColumnLabelWithoutType,
label,
keyString);
}
}
}

View File

@@ -1,150 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System.Collections.Generic;
using Microsoft.SqlTools.Utility;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using System;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Status for databases
/// </summary>
internal partial class DatabasesChildFactory : SmoChildFactoryBase
{
public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
return DatabasesCustomNodeHelper.GetStatus(smoObject, smoContext, CachedSmoProperties);
}
protected override void InitializeChild(TreeNode parent, TreeNode child, object context)
{
base.InitializeChild(parent, child, context);
var smoTreeNode = child as SmoTreeNode;
if (smoTreeNode != null && smoTreeNode.SmoObject != null
&& DatabasesCustomNodeHelper.GetDatabaseIsUnavailable(smoTreeNode.SmoObject, parent.GetContextAs<SmoQueryContext>(), CachedSmoProperties))
{
child.IsAlwaysLeaf = true;
}
}
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
try
{
Database? db = smoObject as Database;
if (db != null && IsPropertySupported(nameof(db.IsLedger), smoContext, db, CachedSmoProperties) && db.IsLedger)
{
return "Ledger";
}
}
catch (Exception e)
{
//Ignore the exception and just not change create custom name
Logger.Warning($"Error ignored when reading databases node subtype: {e.Message}");
}
return string.Empty;
}
}
internal static class DatabasesCustomNodeHelper
{
private static readonly DatabaseStatus[] UnavailableDatabaseStatuses = { DatabaseStatus.Inaccessible, DatabaseStatus.Offline, DatabaseStatus.Recovering,
DatabaseStatus.RecoveryPending, DatabaseStatus.Restoring, DatabaseStatus.Suspect, DatabaseStatus.Shutdown };
internal static bool GetDatabaseIsUnavailable(object smoObject, SmoQueryContext smoContext, IEnumerable<NodeSmoProperty> supportedProperties)
{
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)
{
// We get into this situation with DW Nodes which are paused.
return true;
}
foreach (DatabaseStatus unavailableStatus in DatabasesCustomNodeHelper.UnavailableDatabaseStatuses)
{
if (status.HasFlag(unavailableStatus))
{
return true;
}
}
}
return false;
}
internal static string GetStatus(object smoObject, SmoQueryContext smoContext, IEnumerable<NodeSmoProperty> supportedProperties)
{
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)
{
// We get into this situation with DW Nodes which are paused.
return "Unknown";
}
if ((status & DatabaseStatus.Offline) == DatabaseStatus.Offline)
{
return "Offline";
}
else if ((status & DatabaseStatus.Recovering) == DatabaseStatus.Recovering)
{
return "Recovering";
}
else if ((status & DatabaseStatus.RecoveryPending) == DatabaseStatus.RecoveryPending)
{
return "Recovery Pending";
}
else if ((status & DatabaseStatus.Restoring) == DatabaseStatus.Restoring)
{
return "Restoring";
}
else if ((status & DatabaseStatus.EmergencyMode) == DatabaseStatus.EmergencyMode)
{
return "Emergency Mode";
}
else if ((status & DatabaseStatus.Inaccessible) == DatabaseStatus.Inaccessible)
{
return "Inaccessible";
}
else if ((status & DatabaseStatus.Shutdown) == DatabaseStatus.Shutdown)
{
return "Shutdown";
}
else if ((status & DatabaseStatus.Standby) == DatabaseStatus.Standby)
{
return "Standby";
}
else if ((status & DatabaseStatus.Suspect) == DatabaseStatus.Suspect)
{
return "Suspect";
}
else if ((status & DatabaseStatus.AutoClosed) == DatabaseStatus.AutoClosed)
{
return "Auto Closed";
}
}
return string.Empty;
}
}
}

View File

@@ -1,29 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Connection;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
internal static class SmoExtensions
{
/// <summary>
/// Updates access token on the connection context of <paramref name="sqlObj"/> instance.
/// </summary>
/// <param name="sqlObj">(this) SMO SQL Object containing connection context.</param>
/// <param name="accessToken">Access token</param>
public static void UpdateAccessToken(this SqlSmoObject sqlObj, string accessToken)
{
if (sqlObj != null && !string.IsNullOrEmpty(accessToken)
&& sqlObj.ExecutionManager != null
&& sqlObj.ExecutionManager.ConnectionContext != null)
{
sqlObj.ExecutionManager.ConnectionContext.AccessToken = new AzureAccessToken(accessToken);
}
}
}
}

View File

@@ -1,117 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections.Generic;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Index = Microsoft.SqlServer.Management.Smo.Index;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Subtye for keys
/// </summary>
internal partial class KeysChildFactory : SmoChildFactoryBase
{
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
return IndexCustomeNodeHelper.GetSubType(smoObject);
}
}
/// <summary>
/// Sub types and custom name for indexes
/// </summary>
internal partial class IndexesChildFactory : SmoChildFactoryBase
{
private readonly Lazy<List<NodeSmoProperty>> smoPropertiesLazy = new Lazy<List<NodeSmoProperty>>(() => new List<NodeSmoProperty>
{
new NodeSmoProperty
{
Name = "IsUnique",
ValidFor = ValidForFlag.All
},
new NodeSmoProperty
{
Name = "IsClustered",
ValidFor = ValidForFlag.All
},
new NodeSmoProperty
{
Name = "IndexKeyType",
ValidFor = ValidForFlag.All
}
});
public override IEnumerable<NodeSmoProperty> SmoProperties => smoPropertiesLazy.Value;
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
return IndexCustomeNodeHelper.GetSubType(smoObject);
}
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
return IndexCustomeNodeHelper.GetCustomLabel(smoObject);
}
}
/// <summary>
/// sub type for UserDefinedTableTypeKeys
/// </summary>
internal partial class UserDefinedTableTypeKeysChildFactory : SmoChildFactoryBase
{
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
return IndexCustomeNodeHelper.GetSubType(smoObject);
}
}
internal static class IndexCustomeNodeHelper
{
internal static string GetCustomLabel(object context)
{
Index index = context as Index;
if (index != null)
{
string name = index.Name;
string unique = index.IsUnique ? SR.UniqueIndex_LabelPart : SR.NonUniqueIndex_LabelPart;
string clustered = index.IsClustered ? SR.ClusteredIndex_LabelPart : SR.NonClusteredIndex_LabelPart;
name = name + $" ({unique}, {clustered})";
return name;
}
return string.Empty;
}
internal static string GetSubType(object context)
{
Index index = context as Index;
if (index != null)
{
switch (index.IndexKeyType)
{
case IndexKeyType.DriPrimaryKey:
return "PrimaryKey";
case IndexKeyType.DriUniqueKey:
return "UniqueKey";
}
}
ForeignKey foreignKey = context as ForeignKey;
if (foreignKey != null)
{
return "ForeignKey";
}
return string.Empty;
}
}
}

View File

@@ -1,54 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections.Generic;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Status for logins
/// </summary>
internal partial class ServerLevelLoginsChildFactory : SmoChildFactoryBase
{
public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
return LoginCustomNodeHelper.GetStatus(smoObject);
}
private readonly Lazy<List<NodeSmoProperty>> smoPropertiesLazy = new Lazy<List<NodeSmoProperty>>(() => new List<NodeSmoProperty>
{
new NodeSmoProperty
{
Name = "IsDisabled",
ValidFor = ValidForFlag.All
}
});
public override IEnumerable<NodeSmoProperty> SmoProperties => smoPropertiesLazy.Value;
}
internal static class LoginCustomNodeHelper
{
internal static string GetStatus(object context)
{
Login login = context as Login;
if (login != null)
{
if (login.IsDisabled)
{
return "Disabled";
}
}
return string.Empty;
}
}
}

View File

@@ -1,139 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System.Globalization;
using Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Custom name for parameters
/// </summary>
internal partial class TableValuedFunctionParametersChildFactory : SmoChildFactoryBase
{
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
return ParameterCustomeNodeHelper.GetCustomLabel(smoObject, smoContext);
}
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
return ParameterCustomeNodeHelper.GetSubType(smoObject);
}
}
/// <summary>
/// Custom name for parameters
/// </summary>
internal partial class ScalarValuedFunctionParametersChildFactory : SmoChildFactoryBase
{
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
return ParameterCustomeNodeHelper.GetCustomLabel(smoObject, smoContext);
}
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
return ParameterCustomeNodeHelper.GetSubType(smoObject);
}
}
/// <summary>
/// Custom name for parameters
/// </summary>
internal partial class AggregateFunctionParametersChildFactory : SmoChildFactoryBase
{
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
return ParameterCustomeNodeHelper.GetCustomLabel(smoObject, smoContext);
}
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
return ParameterCustomeNodeHelper.GetSubType(smoObject);
}
}
/// <summary>
/// Custom name for parameters
/// </summary>
internal partial class StoredProcedureParametersChildFactory : SmoChildFactoryBase
{
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
return ParameterCustomeNodeHelper.GetCustomLabel(smoObject, smoContext);
}
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
return ParameterCustomeNodeHelper.GetSubType(smoObject);
}
}
static class ParameterCustomeNodeHelper
{
internal static string GetSubType(object context)
{
Parameter parameter = context as Parameter;
if (parameter != null)
{
StoredProcedureParameter stordProcedureParameter = parameter as StoredProcedureParameter;
if (stordProcedureParameter != null && stordProcedureParameter.IsOutputParameter)
{
return "Output";
}
return "Input";
//TODO return parameters
}
return string.Empty;
}
internal static string GetCustomLabel(object context, SmoQueryContext smoContext)
{
Parameter parameter = context as Parameter;
if (parameter != null)
{
return GetParameterCustomLabel(parameter);
}
return string.Empty;
}
internal static string GetParameterCustomLabel(Parameter parameter)
{
string label = parameter.Name;
string defaultString = SR.SchemaHierarchy_SubroutineParameterNoDefaultLabel;
string inputOutputString = SR.SchemaHierarchy_SubroutineParameterInputLabel;
string typeName = parameter.DataType.ToString();
if (parameter.DefaultValue != null &&
!string.IsNullOrEmpty(parameter.DefaultValue))
{
defaultString = SR.SchemaHierarchy_SubroutineParameterDefaultLabel;
}
StoredProcedureParameter stordProcedureParameter = parameter as StoredProcedureParameter;
if (stordProcedureParameter != null && stordProcedureParameter.IsOutputParameter)
{
inputOutputString = SR.SchemaHierarchy_SubroutineParameterInputOutputLabel;
if (parameter.IsReadOnly)
{
inputOutputString = SR.SchemaHierarchy_SubroutineParameterInputOutputReadOnlyLabel;
}
}
else if (parameter.IsReadOnly)
{
inputOutputString = SR.SchemaHierarchy_SubroutineParameterInputReadOnlyLabel;
}
return string.Format(CultureInfo.InvariantCulture,
SR.SchemaHierarchy_SubroutineParameterLabelFormatString,
label,
typeName,
inputOutputString,
defaultString);
}
}
}

View File

@@ -1,98 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections.Generic;
using System.Data;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Extensibility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// A <see cref="SmoQuerier"/> handles SMO queries for one or more SMO object types.
/// The <see cref="SupportedObjectTypes"/> property defines which types can be queried.
///
/// To query multiple
/// </summary>
public abstract class SmoQuerier : IComposableService
{
public abstract Type[] SupportedObjectTypes { get; }
private static object lockObject = new object();
/// <summary>
/// Queries SMO for a collection of objects using the <see cref="SmoQueryContext"/>
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public abstract IEnumerable<SqlSmoObject> Query(SmoQueryContext context, string filter, bool refresh, IEnumerable<string> extraProperties);
internal IMultiServiceProvider ServiceProvider
{
get;
private set;
}
public void SetServiceProvider(IMultiServiceProvider provider)
{
ServiceProvider = provider;
}
/// <summary>
/// Convert the data to data reader is possible
/// </summary>
protected IDataReader GetDataReader(object data)
{
IDataReader reader = null;
if (data is IDataReader)
{
reader = data as IDataReader;
}
else if(data is DataTable)
{
reader = ((DataTable)data).CreateDataReader();
}
else if (data is DataSet)
{
reader = ((DataSet)data).Tables[0].CreateDataReader();
}
return reader;
}
/// <summary>
/// Mthod used to do custom filtering on smo objects if cannot be implemented using the filters
/// </summary>
protected virtual bool PassesFinalFilters(SqlSmoObject parent, SqlSmoObject smoObject)
{
return true;
}
/// <summary>
/// Returns true if the querier is valid for the given server version
/// </summary>
/// <param name="serverValidFor"></param>
/// <returns></returns>
public bool IsValidFor(ValidForFlag serverValidFor)
{
return ServerVersionHelper.IsValidFor(serverValidFor, ValidFor);
}
/// <summary>
/// Indicates which platforms the querier is valid for
/// </summary>
public virtual ValidForFlag ValidFor
{
get
{
return ValidForFlag.All;
}
}
}
}

View File

@@ -1,212 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Context object containing key properties needed to query for SMO objects
/// </summary>
public class SmoQueryContext
{
private Server server;
private Database database;
private SmoObjectBase parent;
private SmoWrapper smoWrapper;
private ValidForFlag validFor = 0;
/// <summary>
/// Creates a context object with a server to use as the basis for any queries
/// </summary>
/// <param name="server"></param>
public SmoQueryContext(Server server, IMultiServiceProvider serviceProvider)
: this(server, serviceProvider, null)
{
}
internal SmoQueryContext(Server server, IMultiServiceProvider serviceProvider, SmoWrapper serverManager)
{
this.server = server;
ServiceProvider = serviceProvider;
this.smoWrapper = serverManager ?? new SmoWrapper();
}
/// <summary>
/// The server type
/// </summary>
public SqlServerType SqlServerType { get; set; }
/// <summary>
/// The server SMO will query against
/// </summary>
public Server Server
{
get
{
return GetObjectWithOpenedConnection(server);
}
}
/// <summary>
/// Optional Database context object to query against
/// </summary>
public Database Database
{
get
{
return GetObjectWithOpenedConnection(database);
}
set
{
database = value;
}
}
/// <summary>
/// Parent of a give node to use for queries
/// </summary>
public SmoObjectBase Parent
{
get
{
return GetObjectWithOpenedConnection(parent);
}
set
{
parent = value;
}
}
/// <summary>
/// A query loader that can be used to find <see cref="SmoQuerier"/> objects
/// for specific SMO types
/// </summary>
public IMultiServiceProvider ServiceProvider { get; private set; }
/// <summary>
/// Helper method to cast a parent to a specific type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T ParentAs<T>()
where T : TreeNode
{
return Parent as T;
}
/// <summary>
/// Gets the <see cref="ObjectExplorerService"/> if available, by looking it up
/// from the <see cref="ServiceProvider"/>
/// </summary>
/// <returns></returns>
/// <exception cref="InvalidOperationException">
/// Thrown if the <see cref="ServiceProvider"/> is not set or the <see cref="ObjectExplorerService"/>
/// isn't available from that provider
/// </exception>
public ObjectExplorerService GetObjectExplorerService()
{
if (ServiceProvider == null)
{
throw new InvalidOperationException(SR.ServiceProviderNotSet);
}
return ServiceProvider.GetService<ObjectExplorerService>()
?? throw new InvalidOperationException(SR.ServiceNotFound(nameof(ObjectExplorerService)));
}
/// <summary>
/// Copies the context for use by another node
/// </summary>
/// <param name="parent">New Parent to set</param>
/// <returns>new <see cref="SmoQueryContext"/> with all fields except <see cref="Parent"/> the same</returns>
public SmoQueryContext CopyWithParent(SmoObjectBase parent)
{
SmoQueryContext context = new SmoQueryContext(this.Server, this.ServiceProvider, this.smoWrapper)
{
database = this.Database,
Parent = parent,
SqlServerType = this.SqlServerType,
ValidFor = ValidFor
};
return context;
}
/// <summary>
/// Indicates which platforms the server and database is valid for
/// </summary>
public ValidForFlag ValidFor
{
get
{
if (validFor == 0)
{
validFor = ServerVersionHelper.GetValidForFlag(SqlServerType, Database);
}
return validFor;
}
set
{
validFor = value;
}
}
private T GetObjectWithOpenedConnection<T>(T smoObj)
where T : SmoObjectBase
{
if (smoObj != null)
{
EnsureConnectionOpen(smoObj);
}
return smoObj;
}
/// <summary>
/// Updates access token on parent connection context.
/// </summary>
/// <param name="accessToken">Acquired access token</param>
public void UpdateAccessToken(string? accessToken)
{
if (!string.IsNullOrEmpty(accessToken))
{
// Update all applicable nodes that could contain access token
// to prevent stale token from being re-used.
if (server != null)
{
(server as SqlSmoObject).UpdateAccessToken(accessToken);
}
if (database != null)
{
(database as SqlSmoObject).UpdateAccessToken(accessToken);
}
if (parent != null)
{
(parent as SqlSmoObject).UpdateAccessToken(accessToken);
}
}
}
/// <summary>
/// Ensures the server objects connection context is open. This is used by all child objects, and
/// the only way to easily access is via the server object. This should be called during access of
/// any of the object properties
/// </summary>
public void EnsureConnectionOpen(SmoObjectBase smoObj)
{
if (!smoWrapper.IsConnectionOpen(smoObj))
{
// We have a closed server connection. Reopen this
// Note: not currently catching connection exceptions. Expect this to bubble
// up to calling methods and be logged there as this would be happening there in any case
smoWrapper.OpenConnection(smoObj);
}
}
}
}

View File

@@ -1,377 +0,0 @@
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Xml.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
// This file was generated by a T4 Template. Do not modify directly, instead update the SmoQueryModelDefinition.xml file
// and re-run the T4 template. This can be done in Visual Studio by right-click in and choosing "Run Custom Tool",
// or from the command-line on any platform by running "build.cmd -Target=CodeGen" or "build.sh -Target=CodeGen".
using System;
using System.Collections.Generic;
using System.Composition;
using System.Linq;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Broker;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.Utility;
using Index = Microsoft.SqlServer.Management.Smo.Index;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
<#
var directory = Path.GetDirectoryName(Host.TemplateFile);
string xmlFile = Path.Combine(directory, "SmoQueryModelDefinition.xml");
/////////
// Now generate all the Query methods
/////////
var allNodes = GetNodes(xmlFile);
var indent = " ";
foreach (var nodeName in allNodes)
{
XmlElement nodeElement = GetNodeElement(xmlFile, nodeName);
IList<string> parents = GetParents(nodeElement, xmlFile, nodeName);
string nodeType = GetNodeType(nodeElement, nodeName);
var validFor = nodeElement.GetAttribute("ValidFor");
string queryBaseClass = "SmoQuerier";
PushIndent(indent);
WriteLine("");
WriteLine("[Export(typeof({0}))]", queryBaseClass);
WriteLine("internal partial class {0}Querier: {1}", nodeName, queryBaseClass);
WriteLine("{");
PushIndent(indent);
// Supported Types
WriteLine("Type[] supportedTypes = new Type[] { typeof("+ nodeType + ") };");
if (!string.IsNullOrWhiteSpace(validFor))
{
WriteLine("");
WriteLine("public override ValidForFlag ValidFor {{ get {{ return {0}; }} }}", GetValidForFlags(validFor));
WriteLine("");
}
WriteLine("");
WriteLine("public override Type[] SupportedObjectTypes { get { return supportedTypes; } }");
WriteLine("");
// Query impl
WriteLine("public override IEnumerable<SqlSmoObject> Query(SmoQueryContext context, string filter, bool refresh, IEnumerable<string> extraProperties)");
WriteLine("{");
PushIndent(indent);
WriteLine("Logger.Verbose(\"Begin query {0}\");", nodeType);
// TODO Allow override of the navigation path
foreach(var parentType in parents)
{
string parentVar = string.Format("parent{0}", parentType);
WriteLine("{0} {1} = context.Parent as {0};", parentType, parentVar);
WriteLine("if ({0} != null)", parentVar);
WriteLine("{");
PushIndent(indent);
WriteLine("Logger.Verbose(\"Parent of type `{0}` found\");",parentType);
XmlElement navPathElement = GetNavPathElement(xmlFile, nodeName, parentType);
string navigationPath = GetNavigationPath(nodeElement, nodeName, navPathElement);
string subField = GetNavPathAttribute(navPathElement, "SubField");
string fieldType = GetNavPathAttribute(navPathElement, "FieldType");
if(navPathElement != null){
/**
Adding runtime filters to the querier based on the property values available in the context.
The code below will go through all the filters in the navPath element and add them to the filter string
recieved by the querier.
**/
XmlNodeList runtimeFilters = navPathElement.GetElementsByTagName("Filter");
if(runtimeFilters.Count > 0)
{
WriteLine("List<NodePropertyFilter> filters = new List<NodePropertyFilter>();");
foreach(XmlElement filter in runtimeFilters)
{
string filterName = filter.GetAttribute("Property");
string filterField = filter.GetAttribute("Field");
string filterType = filter.GetAttribute("Type");
string filterValidFor = filter.GetAttribute("ValidFor");
WriteLine("filters.Add(new NodePropertyFilter()");
WriteLine("{");
PushIndent(indent);
WriteLine("Property = nameof({0}),", filterName);
WriteLine("Type = typeof({0}),", filterType);
WriteLine("Values = new List<object> {{ {0}.{1} }},", parentVar, filterField);
if(!string.IsNullOrWhiteSpace(filterValidFor))
{
WriteLine("ValidFor = {0},", GetValidForFlags(filterValidFor));
}
else
{
WriteLine("ValidFor = ValidForFlag.All ");
}
PopIndent();
WriteLine("});");
}
WriteLine("filter = INodeFilter.AddPropertyFilterToFilterString(filter, filters, this.GetType(), context.ValidFor);");
}
}
WriteLine("var retValue = {0}.{1};", parentVar, navigationPath);
WriteLine("if (retValue != null)");
WriteLine("{");
PushIndent(indent);
if (IsCollection(nodeElement))
{
WriteLine("retValue.ClearAndInitialize(filter, extraProperties);");
if (string.IsNullOrEmpty(subField) )
{
WriteLine("var ret = new SmoCollectionWrapper<{0}>(retValue).Where(c => PassesFinalFilters({1}, c));", nodeType, parentVar);
WriteLine("Logger.Verbose(\"End query {0}\");", nodeType);
WriteLine("return ret;");
}
else
{
WriteLine("List<{0}> subFieldResult = new List<{0}>();", nodeType);
WriteLine("foreach({0} field in retValue)", fieldType);
WriteLine("{");
PushIndent(indent);
WriteLine("{0} subField = field.{1};", nodeType, subField);
WriteLine("if (subField != null)");
WriteLine("{");
PushIndent(indent);
WriteLine("subFieldResult.Add(subField);");
PopIndent();
WriteLine("}");
PopIndent();
WriteLine("}");
WriteLine("var ret = subFieldResult.Where(c => PassesFinalFilters({1}, c));", nodeType, parentVar);
WriteLine("Logger.Verbose(\"End query {0}\");", nodeType);
WriteLine("return ret;");
}
}
else
{
WriteLine("if (refresh)");
WriteLine("{");
PushIndent(indent);
WriteLine("{0}.{1}.Refresh();", parentVar, navigationPath);
PopIndent();
WriteLine("}");
WriteLine("return new SqlSmoObject[] { retValue };");
}
PopIndent();
WriteLine("}");
PopIndent();
WriteLine("}"); // close If
}
WriteLine("return Enumerable.Empty<SqlSmoObject>();");
PopIndent();
WriteLine("}"); // close Query method
PopIndent();
WriteLine("}"); // close Class
PopIndent();
}
#>
}
<#+
public static string[] GetNodes(string xmlFile)
{
List<string> typesList = new List<string>();
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList treeTypes = doc.SelectNodes("/SmoQueryModel/Node");
if (treeTypes != null)
{
foreach (var type in treeTypes)
{
XmlElement element = type as XmlElement;
if (element != null)
{
typesList.Add(element.GetAttribute("Name"));
}
}
}
return typesList.ToArray();
}
public static XmlElement GetNodeElement(string xmlFile, string nodeName)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
return (XmlElement)doc.SelectSingleNode(string.Format("/SmoQueryModel/Node[@Name='{0}']", nodeName));
}
public static XmlElement GetNavPathElement(string xmlFile, string nodeName, string parent)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlElement navPathElement = (XmlElement)doc.SelectSingleNode(string.Format("/SmoQueryModel/Node[@Name='{0}']/NavigationPath[@Parent='{1}']", nodeName, parent));
return navPathElement;
}
public static string GetNavPathAttribute(XmlElement navPathElement, string attributeName)
{
return navPathElement == null ? null : navPathElement.GetAttribute(attributeName);
}
public static string GetNavigationPath(XmlElement nodeElement, string nodeName, XmlElement navPathElement)
{
string navPathField = GetNavPathAttribute(navPathElement, "Field");
if (!string.IsNullOrEmpty(navPathField))
{
return navPathField;
}
// else use pluralized type as this is the most common scenario
string nodeType = GetNodeType(nodeElement, nodeName);
string nodeTypeAccessor = IsCollection(nodeElement) ? string.Format("{0}s", nodeType) : nodeType;
return nodeTypeAccessor;
}
public static string GetNodeType(XmlElement nodeElement, string nodeName)
{
var type = nodeElement.GetAttribute("Type");
if (!string.IsNullOrEmpty(type))
{
return type;
}
// Otherwise assume the type is the node name without "Sql" at the start
var prefix = "Sql";
return nodeName.IndexOf(prefix) == 0 ? nodeName.Substring(prefix.Length) : nodeName;
}
public static bool IsCollection(XmlElement nodeElement)
{
var collection = nodeElement.GetAttribute("Collection");
bool result;
if (bool.TryParse(collection, out result))
{
return result;
}
// Default is true
return true;
}
public static IList<string> GetParents(XmlElement nodeElement, string xmlFile, string parentName)
{
var parentAttr = nodeElement.GetAttribute("Parent");
if (!string.IsNullOrEmpty(parentAttr))
{
return new string[] { parentAttr };
}
var parentNodes = GetChildren(xmlFile, parentName, "Parent");
if (parentNodes != null && parentNodes.Count > 0)
{
List<string> parents = new List<string>();
foreach(var node in parentNodes)
{
parents.Add(node.InnerText);
}
return parents;
}
// default to assuming a type is under Database
return new string[] { "Database" };
}
public static List<XmlElement> GetChildren(string xmlFile, string parentName, string childNode)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/SmoQueryModel/Node[@Name='{0}']/{1}", parentName, childNode));
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
public static string GetValidForFlags(string validForStr)
{
List<string> flags = new List<string>();
if (validForStr.Contains("Sql2005"))
{
flags.Add("ValidForFlag.Sql2005");
}
if (validForStr.Contains("Sql2008"))
{
flags.Add("ValidForFlag.Sql2008");
}
if (validForStr.Contains("Sql2012"))
{
flags.Add("ValidForFlag.Sql2012");
}
if (validForStr.Contains("Sql2014"))
{
flags.Add("ValidForFlag.Sql2014");
}
if (validForStr.Contains("Sql2016"))
{
flags.Add("ValidForFlag.Sql2016");
}
if (validForStr.Contains("Sql2017"))
{
flags.Add("ValidForFlag.Sql2017");
}
if (validForStr.Contains("AzureV12"))
{
flags.Add("ValidForFlag.AzureV12");
}
if (validForStr.Contains("AllOnPrem"))
{
flags.Add("ValidForFlag.AllOnPrem");
}
if (validForStr.Contains("AllAzure"))
{
flags.Add("ValidForFlag.AllAzure");
}
if (validForStr.Contains("NotSqlDw"))
{
flags.Add("ValidForFlag.NotSqlDw");
}
if (validForStr.Contains("SqlOnDemand"))
{
flags.Add("ValidForFlag.SqlOnDemand");
}
if (validForStr == "NotSqlDemand")
{
flags.Add("ValidForFlag.NotSqlDemand");
}
if (validForStr == "All")
{
flags.Add("ValidForFlag.All");
}
return string.Join("|", flags);
}
#>

View File

@@ -1,253 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
This XML file defines how to query for a given SMO type based on a parent/child or
XPath relationship. From this file, the paths to query each type should be buildable
into code using a T4 template.
Key properties:
attr.Name: This maps
attr.Type: Optional SMO type. If not specified, the Name without the Sql prefix is used
attr.Parent: Expected parent type. Needed to codegen the response.
Parent: In case a node has multiple parents, chilren of type parents need to be added.
Each parent should have corresponding navigation path.
NavigationPath: For types whose access path differs based on parent or needs custom navigation
this can be used.
attr.Parent: The parent type that this navigation path is valid for
attr.Field: The field to use to navigate to the child type
Filter: Optional filter to apply to the navigation path. This is used to filter out
results that are not of the expected type. For example, the SqlTable type has a
filter on the Schema field to ensure that the table is in the expected schema.
attr.Property: The property to filter on
attr.Field: The field to use from the parent to filter on the property
attr.Type: The type of the field.
-->
<SmoQueryModel>
<!--<Node Name="SqlServer"/> -->
<Node Name="SqlDatabase" Type="Database" Parent="Server" />
<Node Name="SqlLinkedServerLogin" Type="LinkedServer" Parent="Server"/>
<Node Name="SqlLogin" Type="Login" Parent="Server" />
<Node Name="SqlServerRole" Type="" Parent="Server" >
<NavigationPath Parent="Server" Field="Roles" />
</Node>
<Node Name="SqlCredential" Parent="Server" />
<Node Name="SqlCryptographicProvider" Parent="Server" />
<Node Name="SqlServerAudit" Type="Audit" Parent="Server" />
<Node Name="SqlServerAuditSpecification" Type="ServerAuditSpecification" Parent="Server"/>
<Node Name="SqlEndpoint" Parent="Server"/>
<Node Name="SqlLinkedServer" Parent="Server" />
<Node Name="SqlServerDdlTrigger" Parent="Server" ValidFor="NotSqlDw" >
<NavigationPath Parent="Server" Field="Triggers" />
</Node>
<Node Name="SqlErrorMessage" Type="UserDefinedMessage" Parent="Server" />
<Node Name="SqlTable">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="Tables" />
<NavigationPath Parent="Schema" Field="Parent.Tables">
<Filter Property="Schema" Field="Name" Type="string" />
</NavigationPath>
</Node>
<Node Name="SqlHistoryTable" Type="Table" Parent="Table" >
<NavigationPath Parent="Table" Type="Table" Field="Parent.Tables" />
</Node>
<Node Name="SqlView">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="Views" />
<NavigationPath Parent="Schema" Field="Parent.Views">
<Filter Property="Schema" Field="Name" Type="string" />
</NavigationPath>
</Node>
<Node Name="SqlSynonym" ValidFor="NotSqlDw">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="Synonyms" />
<NavigationPath Parent="Schema" Field="Parent.Synonyms">
<Filter Property="Schema" Field="Name" Type="string" />
</NavigationPath>
</Node>
<Node Name="SqlColumn" Parent="TableViewTableTypeBase"/>
<Node Name="SqlIndex" Parent="TableViewTableTypeBase">
<NavigationPath Parent="TableViewTableTypeBase" Field="Indexes" />
</Node>
<Node Name="SqlCheck" Parent="Table"/>
<Node Name="SqlForeignKeyConstraint" Type="ForeignKey" Parent="Table" />
<Node Name="SqlDefaultConstraint" Collection="True" >
<Parent>Table</Parent>
<Parent>UserDefinedTableType</Parent>
<NavigationPath Parent="Table" Field="Columns" SubField="DefaultConstraint" FieldType="Column" />
<NavigationPath Parent="UserDefinedTableType" Field="Columns" SubField="DefaultConstraint" FieldType="Column" />
</Node>
<Node Name="SqlDmlTrigger" Type="Trigger" ValidFor="NotSqlDw">
<Parent>Table</Parent>
<Parent>View</Parent>
</Node>
<Node Name="SqlFullTextIndex" Parent="Table" Collection="False" ValidFor="NotSqlDw" />
<Node Name="SqlStatistic" Parent="TableViewBase"/>
<Node Name="SqlDatabaseDdlTrigger" Type="DatabaseDdlTrigger" Parent="Database" ValidFor="NotSqlDw">
<NavigationPath Parent="Database" Field="Triggers" />
</Node>
<Node Name="SqlAssembly" Type="SqlAssembly" Parent="Database" >
<NavigationPath Parent="Database" Field="Assemblies" />
</Node>
<!-- Deprecated
<Node Name="SqlRule" Parent="Database" />
<Node Name="SqlDefault" Parent="Database" />
-->
<Node Name="SqlSequence">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="Sequences" />
<NavigationPath Parent="Schema" Field="Parent.Sequences">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlUserDefinedDataType" ValidFor="NotSqlDw">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="UserDefinedDataTypes" />
<NavigationPath Parent="Schema" Field="Parent.UserDefinedDataTypes">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlUserDefinedTableType">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="UserDefinedTableTypes" />
<NavigationPath Parent="Schema" Field="Parent.UserDefinedTableTypes">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlXmlSchemaCollection">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="XmlSchemaCollections" />
<NavigationPath Parent="Schema" Field="Parent.XmlSchemaCollections">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlUserDefinedType">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="UserDefinedTypes" />
<NavigationPath Parent="Schema" Field="Parent.UserDefinedTypes">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlUserDefinedFunction">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<Navigation Path="Database" Field="UserDefinedFunctions" />
<NavigationPath Parent="Schema" Field="Parent.UserDefinedFunctions">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlUserDefinedAggregate">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="UserDefinedAggregates" />
<NavigationPath Parent="Schema" Field="Parent.UserDefinedAggregates">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlFileGroup" />
<Node Name="SqlFile" Type="DataFile" Parent="FileGroup" >
<NavigationPath Parent="FileGroup" Field="Files" />
</Node>
<Node Name="SqlFullTextCatalog"/>
<Node Name="SqlFullTextStopList" />
<Node Name="SqlPartitionFunction"/>
<Node Name="SqlPartitionScheme"/>
<Node Name="SqlSearchPropertyList" />
<Node Name="SqlUser"/>
<Node Name="SqlSchema"/>
<Node Name="SqlAsymmetricKey" />
<Node Name="SqlCertificate" />
<Node Name="SqlSymmetricKey" />
<Node Name="SqlDatabaseEncryptionKey" Collection="False" />
<Node Name="SqlMasterKey" Collection="False" />
<Node Name="SqlDatabaseAuditSpecification" />
<Node Name="SqlSecurityPolicy" >
<NavigationPath Parent="Database" Field="SecurityPolicies" />
</Node>
<Node Name="SqlDatabaseCredential" Type="DatabaseScopedCredential"/>
<Node Name="SqlRole" Type="DatabaseRole" >
<NavigationPath Parent="Database" Field="Roles" />
</Node>
<Node Name="SqlApplicationRole" />
<Node Name="SqlColumnMasterKey" />
<Node Name="SqlColumnEncryptionKey" />
<Node Name="SqlServiceBroker" Type="ServiceBroker" Collection="False" />
<Node Name="SqlService" Type="BrokerService" Parent="ServiceBroker" >
<NavigationPath Parent="ServiceBroker" Field="Services" />
</Node>
-
<Node Name="SqlContract" Type="ServiceContract" Parent="ServiceBroker" />
<Node Name="SqlQueue" Type="ServiceQueue" Parent="ServiceBroker" >
<NavigationPath Parent="ServiceBroker" Field="Queues" />
</Node>
<Node Name="SqlRemoteServiceBinding" Parent="ServiceBroker" />
<Node Name="SqlBrokerPriority" Parent="ServiceBroker" >
<NavigationPath Parent="ServiceBroker" Field="Priorities" />
</Node>
<Node Name="SqlMessageType" Parent="ServiceBroker"/>
<Node Name="SqlExternalDataSource" />
<Node Name="SqlExternalFileFormat" />
<Node Name="SqlProcedure" Type="StoredProcedure">
<Parent>Database</Parent>
<Parent>Schema</Parent>
<NavigationPath Parent="Database" Field="StoredProcedures" />
<NavigationPath Parent="Schema" Field="Parent.StoredProcedures">
<Filter Property="Schema" Field="Name" Type="string"/>
</NavigationPath>
</Node>
<Node Name="SqlExtendedStoredProcedure" />
<Node Name="SqlSubroutineParameter" Type="Parameter" >
<Parent>StoredProcedure</Parent>
<Parent>UserDefinedAggregate</Parent>
<Parent>UserDefinedFunction</Parent>
</Node>
<Node Name="SqlPartitionFunctionParameter" Parent="PartitionFunction" />
<Node Name="SqlBuiltInType" Type="SystemDataType" Parent="Database">
<NavigationPath Parent="Database" Field="Parent.SystemDataTypes" FieldForUrn="Parent" />
</Node>
<!-- TODO Enable all types
<Node Name="SqlRoute"/>
-->
<!-- Signatures appear to be missing entirely from SMO and SSMS object explorer...
<Node Name="SqlSignature" />
-->
<!-- TODO find mapping - exists in SSDT but not SSMS / SMO?
<Node Name="SqlEventNotification" Parent="ServiceBroker" />
-->
<!-- TODO Requires XEvents SMO DLL in .Net Core
<Node Name="SqlEventSession" Type="Session" />
<Node Name="SqlServerEventNotification" Type="Event" Parent="Server" />
-->
</SmoQueryModel>

View File

@@ -1,197 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Custom name for table
/// </summary>
internal partial class TablesChildFactory : SmoChildFactoryBase
{
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
try
{
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})";
}
else if (table != null && IsPropertySupported("IsExternal", smoContext, table, CachedSmoProperties) && table.IsExternal)
{
return $"{table.Schema}.{table.Name} ({SR.External_LabelPart})";
}
else if (table != null && IsPropertySupported("IsFileTable", smoContext, table, CachedSmoProperties) && table.IsFileTable)
{
return $"{table.Schema}.{table.Name} ({SR.FileTable_LabelPart})";
}
}
catch
{
//Ignore the exception and just not change create custom name
}
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))
{
if (table.LedgerType == LedgerTableType.AppendOnlyLedgerTable)
{
return "LedgerAppendOnly";
}
if (table.LedgerType == LedgerTableType.UpdatableLedgerTable)
{
return "LedgerUpdatable";
}
}
if (table != null && IsPropertySupported("TemporalType", smoContext, table, CachedSmoProperties) && table.TemporalType != TableTemporalType.None)
{
return "Temporal";
}
if (table != null && IsPropertySupported("IsEdge", smoContext, table, CachedSmoProperties) && table.IsEdge)
{
return "GraphEdge";
}
if (table != null && IsPropertySupported("IsNode", smoContext, table, CachedSmoProperties) && table.IsNode)
{
return "GraphNode";
}
// TODO carbon issue 3125 enable "External" subtype once icon is ready. Otherwise will get missing icon here.
// else if (table != null && IsPropertySupported("IsExternal", smoContext, table, CachedSmoProperties) && table.IsExternal)
// {
// return "External";
// }
// return string.Empty;
}
catch
{
//Ignore the exception and just not change create custom name
}
return string.Empty;
}
public override string GetNodePathName(object smoObject)
{
return TableCustomNodeHelper.GetPathName(smoObject);
}
}
/// <summary>
/// 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;
if (table != null)
{
return $"{table.Schema}.{table.Name} ({SR.History_LabelPart})";
}
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);
}
}
internal static class TableCustomNodeHelper
{
internal static string GetPathName(object smoObject)
{
Table? table = smoObject as Table;
if (table != null)
{
return $"{table.Schema}.{table.Name}";
}
return string.Empty;
}
}
/// <summary>
/// Custom name and icon for dropped ledger tables
/// </summary>
internal partial class DroppedLedgerTablesChildFactory : SmoChildFactoryBase
{
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
try
{
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})";
}
}
}
catch
{
//Ignore the exception and just not change create custom name
}
return string.Empty;
}
public override string GetNodeSubType(object smoObject, SmoQueryContext smoContext)
{
return "LedgerDropped";
}
public override string GetNodePathName(object smoObject)
{
return TableCustomNodeHelper.GetPathName(smoObject);
}
}
}

View File

@@ -1,127 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// A Node in the tree representing a SMO-based object
/// </summary>
public class SmoTreeNode : TreeNode
{
public static int FolderSortPriority = 0;
private static int _nextSortPriority = FolderSortPriority + 1; // 0 is reserved for folders
protected SmoQueryContext context;
public SmoTreeNode() : base()
{
}
protected virtual void OnInitialize()
{
// TODO setup initialization
}
/// <summary>
/// Is this a system (MSShipped) object?
/// </summary>
public bool IsMsShippedOwned { get; set; }
/// <summary>
/// Indicates which platforms a node is valid for
/// </summary>
public ValidForFlag ValidFor { get; set; }
/// <summary>
/// Gets an incrementing sort priority value to assist in automatically sorting
/// elements in a tree
/// </summary>
public static int NextSortPriority
{
get
{
return System.Threading.Interlocked.Increment(ref _nextSortPriority);
}
}
public NamedSmoObject SmoObject { get; private set; }
public virtual void CacheInfoFromModel(NamedSmoObject smoObject)
{
SmoObject = smoObject;
NodeValue = smoObject.Name;
ScriptSchemaObjectBase schemaBaseObject = smoObject as ScriptSchemaObjectBase;
ObjectMetadata = new Metadata.Contracts.ObjectMetadata();
ObjectMetadata.Name = smoObject.Name;
try
{
if (smoObject.Urn != null)
{
ObjectMetadata.Urn = smoObject.Urn.Value;
ObjectMetadata.MetadataTypeName = smoObject.Urn.Type;
}
}
catch
{
//Ignore the exception, sometimes the urn returns exception and I' not sure why
}
if (schemaBaseObject != null)
{
ObjectMetadata.Schema = schemaBaseObject.Schema;
if (!string.IsNullOrEmpty(ObjectMetadata.Schema))
{
NodeValue = $"{ObjectMetadata.Schema}.{smoObject.Name}";
}
}
else
{
// Try to read the schema from the parent object
var parent = smoObject?.ParentCollection?.ParentInstance as ScriptSchemaObjectBase;
if (parent != null)
{
ObjectMetadata.Schema = parent.Schema;
ObjectMetadata.ParentName = parent.Name;
ObjectMetadata.ParentTypeName = parent.Urn.Type;
}
}
}
public virtual NamedSmoObject GetParentSmoObject()
{
if (SmoObject != null)
{
return SmoObject;
}
// Return the parent's object, or null if it's not set / not a SmoTreeNode
return ParentAs<SmoTreeNode>()?.GetParentSmoObject();
}
public override object GetContext()
{
EnsureContextInitialized();
return context;
}
protected virtual void EnsureContextInitialized()
{
if (context == null)
{
SmoObjectBase smoParent = GetParentSmoObject();
SmoQueryContext parentContext = Parent?.GetContextAs<SmoQueryContext>();
if (smoParent != null && parentContext != null)
{
context = parentContext.CopyWithParent(smoParent);
}
}
}
}
}

View File

@@ -1,854 +0,0 @@
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Xml.dll" #>
<#@ assembly name="System.Core.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq"#>
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
// This file was generated by a T4 Template. Do not modify directly, instead update the SmoTreeNodesDefinition.xml file
// and re-run the T4 template. This can be done in Visual Studio by right-click in and choosing "Run Custom Tool",
// or from the command-line on any platform by running "build.cmd -Target=CodeGen" or "build.sh -Target=CodeGen".
using System;
using System.Collections.Generic;
using System.Composition;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.Workspace;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
<#
var directory = Path.GetDirectoryName(Host.TemplateFile);
string xmlFile = Path.Combine(directory, "SmoTreeNodesDefinition.xml");
var indent = " ";
/////////
// TODO - is Generate all the ReverseDependencies needed?
/////////
// var allReverseDependencies = GetReverseDependencies(xmlFile);
// WriteLine(" internal static class TreeNodeRules");
// WriteLine(" {");
// WriteLine(" internal static Dictionary<Type, IList<Type>> TypeReverseDependencyMap = new Dictionary<Type, IList<Type>>()");
// WriteLine(" {");
// foreach (var reverseDependencyKey in allReverseDependencies.Keys)
// {
// bool isFirstDependentType = true;
// StringBuilder dependentListBuilder = new StringBuilder("{");
// foreach (var dependentType in allReverseDependencies[reverseDependencyKey])
// {
// if (isFirstDependentType)
// {
// isFirstDependentType = false;
// }
// else
// {
// dependentListBuilder.Append(",");
// }
//
// dependentListBuilder.Append(string.Format(CultureInfo.InvariantCulture, " typeof({0})", dependentType));
// }
// dependentListBuilder.Append(" }");
//
// WriteLine(string.Format(CultureInfo.InvariantCulture, " {{ typeof({0}), new List<Type> {1} }}", reverseDependencyKey, dependentListBuilder.ToString()));
// }
// WriteLine(" };");
// WriteLine(" }");
// WriteLine("");
/////////
// First generate all the TreeNodes
/////////
var allTreeNodes = GetUniqueTreeNodes(xmlFile);
foreach (var TreeNode in allTreeNodes)
{
var name = TreeNode.GetAttribute("Name");
var type = !string.IsNullOrWhiteSpace(TreeNode.GetAttribute("Type")) ? TreeNode.GetAttribute("Type") : TreeNode.GetAttribute("Name");
WriteLine(" internal sealed partial class {0} : SmoTreeNode", name);
WriteLine(" {");
WriteLine(" public {0}() : base()", name);
WriteLine(" {");
WriteLine(" NodeValue = string.Empty;");
WriteLine(" this.NodeType = \"{0}\";", type.Replace("TreeNode", string.Empty));
WriteLine(" this.NodeTypeId = NodeTypes.{0};", name.Replace("TreeNode", string.Empty));
List<XmlElement> filterProperties = GetFilterProperties(xmlFile, type.Replace("TreeNode", string.Empty));
string settingsFlag = GetFilterSettingsFlag(xmlFile, type.Replace("TreeNode", string.Empty));
if(!String.IsNullOrEmpty(settingsFlag))
{
WriteLine(" if({0})", GetSettingsString(settingsFlag));
WriteLine(" {");
}
if(filterProperties.Count > 0){
WriteLine(" this.FilterProperties = new NodeFilterProperty[]");
WriteLine(" {");
foreach (var filterDef in filterProperties)
{
var filterName = filterDef.GetAttribute("Name");
var filterDisplayName = filterDef.GetAttribute("LocLabel");
var filterType = filterDef.GetAttribute("Type");
var enumString = "NodeFilterPropertyDataType";
switch (filterType)
{
case "string":
enumString += ".String";
break;
case "bool":
enumString += ".Boolean";
break;
case "date":
enumString += ".Date";
break;
case "choice":
enumString += ".Choice";
break;
}
var filterDescription = filterDef.GetAttribute("Description");
WriteLine(" new NodeFilterProperty");
WriteLine(" {");
WriteLine(" Name = \"{0}\",", filterName);
WriteLine(" DisplayName = {0},", filterDisplayName);
WriteLine(" Type = {0},", enumString);
WriteLine(" Description = {0},", filterDescription);
if(filterType == "choice")
{
var choiceValues = filterDef.ChildNodes;
WriteLine(" Choices = new NodeFilterPropertyChoice[] {");
foreach (XmlElement choice in choiceValues)
{
var choiceName = choice.GetAttribute("LocLabel");
var choiceValue = choice.GetAttribute("Value");
WriteLine(" new NodeFilterPropertyChoice {");
WriteLine(" DisplayName = {0},", choiceName);
WriteLine(" Value = \"{0}\",", choiceValue);
WriteLine(" },");
}
WriteLine(" }");
}
WriteLine(" },");
}
WriteLine(" };");
}
if(!String.IsNullOrEmpty(settingsFlag))
{
WriteLine(" }");
}
WriteLine(" OnInitialize();");
WriteLine(" }");
WriteLine(" }");
WriteLine("");
}
/////////
// Now generate all the ChildFactories
/////////
var allNodes = GetNodes(xmlFile);
foreach (var type in allNodes)
{
XmlElement nodeElement = GetNodeElement(xmlFile, type);
var imageAttr = nodeElement.GetAttribute("Image");
var isAlwaysLeaf = nodeElement.GetAttributeNode("IsAlwaysLeaf");
var baseClass = nodeElement.GetAttribute("BaseClass");
var strategy = nodeElement.GetAttribute("Strategy");
var nodeType = nodeElement.GetAttribute("NodeType");
var ChildQuerierTypes = nodeElement.GetAttribute("ChildQuerierTypes");
var ConditionalChildQuerierTypes = nodeElement.GetElementsByTagName("ConditionalChildQuerierType");
var TreeNode = nodeElement.GetAttribute("TreeNode");
var isAsync = nodeElement.GetAttributeNode("IsAsyncLoad");
var disableSort = nodeElement.GetAttributeNode("DisableSort");
string childFactoryBaseClass = "SmoChildFactoryBase";
// TODO Will we need alternative child factories? If so, add code here to support this
if (isAlwaysLeaf == null)
{
WriteLine(" [Export(typeof(ChildFactory))]");
WriteLine(" [Shared]");
WriteLine(" internal partial class {0}ChildFactory : {1}", type, childFactoryBaseClass);
WriteLine(" {");
if(!string.IsNullOrEmpty(nodeElement.GetAttribute("PutFoldersAfterNodes")))
{
WriteLine(" public override bool PutFoldersAfterNodes => {0};", nodeElement.GetAttribute("PutFoldersAfterNodes"));
}
WriteLine(" public override IEnumerable<string> ApplicableParents() {{ return new[] {{ nameof(NodeTypes.{0}) }}; }}", type);
List<XmlElement> children = GetChildren(xmlFile, type);
List<XmlElement> smoProperties = GetNodeSmoProperties(xmlFile, type);
// Load and parse Filters node
// A <Filters> node is comprised of <Or> and <Filter> nodes
// - A <Filter> node defines the properties to construct a NodePropertyFilter object
// - An <Or> node defines a list of <Filter> nodes that are or'ed in the resulting URN Query
// <Filters> can have an arbitrary number of top-level <Or> and <Filter> nodes.
// All filters defined at the top-level are and'ed in the resulting URN Query.
// This is generated into the IEnumerable<INodeFilter> Filters object for a particular SMO object.
// Currently there is not support for nested <Or> nodes
XmlNode filtersNode = GetFiltersNode(xmlFile, type);
if (filtersNode != null)
{
// Get the children nodes for the Filters
XmlNodeList childNodes = filtersNode.ChildNodes;
if (childNodes.Count > 0)
{
// Write initial declarator for the filters object
WriteLine("");
WriteLine(" public override IEnumerable<INodeFilter> Filters");
WriteLine(" {");
WriteLine(" get");
WriteLine(" {");
WriteLine(" var filters = new List<INodeFilter>();");
// Parse each of the <Or> nodes in <Filters>
foreach (var orNode in filtersNode.SelectNodes("Or"))
{
XmlElement or = orNode as XmlElement;
if (or == null)
{
continue;
}
// Write initial declarator for the <Or> object, which is just a list of NodePropertyFilters
WriteLine(" filters.Add(new NodeOrFilter");
WriteLine(" {");
WriteLine(" FilterList = new List<NodePropertyFilter> {");
foreach(var orFilterNode in or.GetElementsByTagName("Filter"))
{
XmlElement orFilter = orFilterNode as XmlElement;
if (orFilter == null)
{
continue;
}
// Declaration of Filter node
WriteLine(" new NodePropertyFilter");
// Parse the elements in the <Filter> node into a string, and write
ParseAndWriteFilterNode(xmlFile, type, orFilter, true /*orFilter*/);
// Close out filter object definition
WriteLine(" },");
}
// Close out declaration of the NodeOrFilter
WriteLine(" }");
WriteLine(" });");
}
// Parse each of the top-level <Filter> nodes in <Filters>
foreach (var filterNode in filtersNode.SelectNodes("Filter"))
{
XmlElement filter = filterNode as XmlElement;
if (filter == null)
{
continue;
}
// Start declaration of Filter node
WriteLine(" filters.Add(new NodePropertyFilter");
// Parse the elements in the <Filter> node into a string, and write
ParseAndWriteFilterNode(xmlFile, type, filter);
// Close out filter object definition
WriteLine(" });");
}
// Close out declaration of the Filters object
WriteLine(" return filters;");
WriteLine(" }");
WriteLine(" }");
}
}
if (smoProperties.Count > 0)
{
WriteLine("");
WriteLine(" public override IEnumerable<NodeSmoProperty> SmoProperties");
WriteLine(" {");
WriteLine(" get");
WriteLine(" {");
WriteLine(" var properties = new List<NodeSmoProperty>();");
foreach (var smoPropertiy in smoProperties)
{
var propertyName = smoPropertiy.GetAttribute("Name");
var validFor = smoPropertiy.GetAttribute("ValidFor");
WriteLine(" properties.Add(new NodeSmoProperty");
WriteLine(" {");
WriteLine(" Name = \"{0}\",", propertyName);
if (!string.IsNullOrWhiteSpace(validFor))
{
WriteLine(" ValidFor = {0}", GetValidForFlags(validFor));
}
WriteLine(" });");
}
WriteLine(" return properties;");
WriteLine(" }");
WriteLine(" }");
}
if (children.Count > 0)
{
WriteLine("");
WriteLine(" protected override void OnExpandPopulateFolders(IList<TreeNode> currentChildren, TreeNode parent)");
WriteLine(" {");
foreach (var child in children)
{
var childName = child.GetAttribute("Name");
var settingsFlag = child.GetAttribute("SettingsFlag");
XmlElement childAsXmlElement = GetNodeElement(xmlFile, childName);
if (childAsXmlElement == null)
{
// TODO SHould we error with clear message that this needs to be fixed?
continue;
}
string childImage = childAsXmlElement.GetAttribute("Image");
var msShippedOwned = childAsXmlElement.GetAttributeNode("IsMsShippedOwned");
var validFor = childAsXmlElement.GetAttribute("ValidFor");
var sortPriority = childAsXmlElement.GetAttribute("SortPriority");
if (sortPriority == string.Empty)
{
sortPriority = "SmoTreeNode.NextSortPriority";
}
var doesSettingsFlagExist = !string.IsNullOrEmpty(settingsFlag);
if(doesSettingsFlagExist){
WriteLine(" if ({0})", GetSettingsString(settingsFlag));
WriteLine(" {");
PushIndent(indent);
}
if (TreeNodeExists(xmlFile, childName + "TreeNode"))
{
WriteLine(" currentChildren.Add(new {0}TreeNode {{ SortPriority = {1} }} );", childName, sortPriority);
}
else
{
WriteLine(" currentChildren.Add(new FolderNode {");
WriteLine(" NodeValue = {0},", childAsXmlElement.GetAttribute("LocLabel"));
WriteLine(" NodeTypeId = NodeTypes.{0},", childName);
WriteLine(" IsSystemObject = {0},", child.GetAttribute("IsSystemObject") == "1" ? "true" : "false");
if (msShippedOwned != null)
{
WriteLine(" IsMsShippedOwned = true,");
}
if (!string.IsNullOrWhiteSpace(validFor))
{
WriteLine(" ValidFor = {0},", GetValidForFlags(validFor));
}
WriteLine(" SortPriority = {0},", sortPriority);
List<XmlElement> filterProperties = GetFilterProperties(xmlFile, childName);
if(filterProperties.Count > 0)
{
WriteLine(" FilterProperties = new NodeFilterProperty[]");
WriteLine(" {");
foreach (var filterDef in filterProperties)
{
var filterName = filterDef.GetAttribute("Name");
var filterDisplayName = filterDef.GetAttribute("LocLabel");
var filterType = filterDef.GetAttribute("Type");
var enumString = "NodeFilterPropertyDataType";
switch (filterType)
{
case "string":
enumString += ".String";
break;
case "bool":
enumString += ".Boolean";
break;
case "date":
enumString += ".Date";
break;
case "choice":
enumString += ".Choice";
break;
}
var filterDescription = filterDef.GetAttribute("Description");
WriteLine(" new NodeFilterProperty");
WriteLine(" {");
WriteLine(" Name = \"{0}\",", filterName);
WriteLine(" DisplayName = {0},", filterDisplayName);
WriteLine(" Type = {0},", enumString);
WriteLine(" Description = {0},", filterDescription);
if(filterType == "choice")
{
var choiceValues = filterDef.ChildNodes;
WriteLine(" Choices = new NodeFilterPropertyChoice[] {");
foreach (XmlElement choice in choiceValues)
{
var choiceName = choice.GetAttribute("LocLabel");
var choiceValue = choice.GetAttribute("Value");
WriteLine(" new NodeFilterPropertyChoice {");
WriteLine(" DisplayName = {0},", choiceName);
WriteLine(" Value = \"{0}\",", choiceValue);
WriteLine(" },");
}
WriteLine(" }");
}
WriteLine(" },");
}
WriteLine(" }");
}
WriteLine(" });");
}
if(doesSettingsFlagExist){
PopIndent();
WriteLine(" }");
}
}
WriteLine(" }");
}
if (!string.IsNullOrWhiteSpace(strategy))
{
if(ConditionalChildQuerierTypes.Count > 0)
{
WriteLine("");
WriteLine(" internal override Type[] ChildQuerierTypes");
WriteLine(" {");
WriteLine(" get");
WriteLine(" {");
WriteLine(" List<Type> conditionalTypesList = new List<Type>();");
foreach(XmlElement Querier in ConditionalChildQuerierTypes)
{
var settingsFlag = Querier.GetAttribute("SettingsFlag");
var QuerierName = Querier.GetAttribute("Name");
if(!string.IsNullOrEmpty(settingsFlag))
{
WriteLine(" if ({0})", GetSettingsString(settingsFlag));
WriteLine(" {");
WriteLine(" conditionalTypesList.Add(typeof({0}Querier));", QuerierName);
WriteLine(" }");
}
else
{
WriteLine(" conditionalTypesList.Add(typeof({0}Querier));", QuerierName);
}
}
WriteLine(" return conditionalTypesList.ToArray();");
WriteLine(" }");
WriteLine(" }");
}
else
{
string[] allTypes = ChildQuerierTypes.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
WriteLine("");
WriteLine(" internal override Type[] ChildQuerierTypes");
WriteLine(" {");
WriteLine(" get");
WriteLine(" {");
if (!string.IsNullOrWhiteSpace(ChildQuerierTypes))
{
Write(" return new [] {");
foreach (var typeToRe in allTypes)
{
Write(" typeof({0}Querier),", typeToRe);
}
WriteLine(" };");
}
else
{
WriteLine(" return new Type[0];");
}
WriteLine(" }");
WriteLine(" }");
}
WriteLine("");
WriteLine(" public override TreeNode CreateChild(TreeNode parent, object context)");
WriteLine(" {");
if (string.IsNullOrWhiteSpace(TreeNode))
{
WriteLine(" var child = new SmoTreeNode();");
WriteLine(" child.IsAlwaysLeaf = true;");
if (!string.IsNullOrEmpty(nodeType))
{
WriteLine(" child.NodeType = \"{0}\";", nodeType);
}
}
else
{
var modelNodeChildren = GetNodeElement(xmlFile, TreeNode.Replace("TreeNode",string.Empty));
WriteLine(" var child = new {0}();", TreeNode);
if (modelNodeChildren.ChildNodes.Count == 0)
{
WriteLine(" child.IsAlwaysLeaf = true;");
}
}
if (disableSort != null)
{
WriteLine(" child.SortPriority = SmoTreeNode.NextSortPriority;");
}
WriteLine(" InitializeChild(parent, child, context);");
WriteLine(" return child;");
WriteLine(" }");
}
else if (baseClass == "ModelBased")
{
WriteLine("");
WriteLine(" internal override Type[] ChildQuerierTypes { get {return null;} }");
WriteLine("");
// TODO Is reverse engineering strategy every needed?
// WriteLine(" protected override ReverseEngineeringStrategy Strategy { get {return ReverseEngineeringStrategy.None;} }");
WriteLine("");
WriteLine(" public override TreeNode CreateChild(TreeNode parent, object context)");
WriteLine(" {");
WriteLine(" return null;");
WriteLine(" }");
}
WriteLine(" }");
WriteLine("");
}
}
#>
}
<#+
public static string GetValidForFlags(string validForStr)
{
var flags = validForStr.Split('|').Select(validForFlag => "ValidForFlag." + validForFlag);
return string.Join("|", flags);
}
public static string[] GetNodes(string xmlFile)
{
List<string> typesList = new List<string>();
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList treeTypes = doc.SelectNodes("/ServerExplorerTree/Node");
if (treeTypes != null)
{
foreach (var type in treeTypes)
{
XmlElement element = type as XmlElement;
if (element != null)
{
typesList.Add(element.GetAttribute("Name"));
}
}
}
return typesList.ToArray();
}
public static Dictionary<string, List<string>> GetReverseDependencies(string xmlFile)
{
Dictionary<string, List<string>> dependencyMap = new Dictionary<string, List<string>>();
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList treeTypes = doc.SelectNodes("/ServerExplorerTree/ReverseDependencyList/ReverseDependency");
if (treeTypes != null)
{
foreach (var type in treeTypes)
{
XmlElement element = type as XmlElement;
if (element != null)
{
string typeName = element.GetAttribute("Type");
string dependency = element.GetAttribute("DependsOn");
List<string> dependenciesForType;
if (dependencyMap.TryGetValue(typeName, out dependenciesForType))
{
dependenciesForType.Add(dependency);
}
else
{
string[] allDepedencies = dependency.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
dependenciesForType = new List<string>();
dependenciesForType.AddRange(allDepedencies);
dependencyMap.Add(typeName, dependenciesForType);
}
}
}
}
return dependencyMap;
}
public static XmlElement GetNodeElement(string xmlFile, string nodeName)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
return (XmlElement)doc.SelectSingleNode(string.Format("/ServerExplorerTree/Node[@Name='{0}']", nodeName));
}
public static bool TreeNodeExists(string xmlFile, string TreeNode)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
var found = (XmlElement)doc.SelectSingleNode(string.Format("/ServerExplorerTree/CodeGenOptions/UniqueTreeNode[@Name='{0}']", TreeNode));
return (found != null);
}
public static List<XmlElement> GetUniqueTreeNodes(string xmlFile)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes("/ServerExplorerTree/CodeGenOptions/UniqueTreeNode");
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
public static List<XmlElement> GetChildren(string xmlFile, string parentName)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/ServerExplorerTree/Node[@Name='{0}']/Child", parentName));
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
public static List<XmlElement> GetNodeOrFilters(string xmlFile, string parentName)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/ServerExplorerTree/Node[@Name='{0}']/Filters/Or/Filter", parentName));
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
public static XmlNode GetFiltersNode(string xmlFile, string parentName)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
return doc.SelectSingleNode(string.Format("/ServerExplorerTree/Node[@Name='{0}']/Filters", parentName));
}
public static List<XmlElement> GetNodeSmoProperties(string xmlFile, string parentName)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/ServerExplorerTree/Node[@Name='{0}']/Properties/Property", parentName));
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
public static string GetFilterSettingsFlag(string xmlFile, string nodeType)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList nodeList = doc.SelectNodes(string.Format("/ServerExplorerTree/FilterProperties[@NodeName='{0}']", nodeType));
if(nodeList.Count > 0)
{
return (nodeList[0] as XmlElement).Attributes["SettingsFlag"].Value;
}
return String.Empty;
}
public static List<XmlElement> GetFilterProperties(string xmlFile, string nodeType)
{
XmlElement nodeElement = GetNodeElement(xmlFile, nodeType);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/ServerExplorerTree/FilterProperties[@NodeName='{0}']/Property", nodeType));
foreach (XmlNode item in nodeList)
{
var filterName = item.InnerText;
XmlNodeList filterPropertyList = doc.SelectNodes(string.Format("/ServerExplorerTree/FilterProperty[@Name='{0}']", filterName));
foreach (var filterProperty in filterPropertyList)
{
XmlElement itemAsElement = filterProperty as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
}
return retElements;
}
public static List<XmlElement> GetNodeFilterValues(string xmlFile, string parentName, string filterProperty, bool orFilter = false)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
var xpath = string.Format(
"/ServerExplorerTree/Node[@Name='{0}']/Filters/{1}Filter[@Property='{2}']/Value",
parentName,
orFilter ? "Or/" : string.Empty,
filterProperty);
XmlNodeList nodeList = doc.SelectNodes(xpath);
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
/// <summary>
/// Helper function to parse out and write the contents of a <Filter> node.
/// </summary>
/// <param name="xmlFile">Base xml doc</param>
/// <param name="parentName">name of the parent object in the xml</param>
/// <param name="filter">The filter to be parsed</param>
/// <param name="orFilter">Whether this filter is a sub-node of an <Or> node</param>
public void ParseAndWriteFilterNode(string xmlFile, string parentName, XmlElement filter, bool orFilter = false)
{
// <Or> Filters start at a larger base indentation than <Filter> nodes directly under <Filters>
var indent = orFilter ? " " : " ";
var propertyName = filter.GetAttribute("Property");
var propertyType = filter.GetAttribute("Type");
var propertyValue = filter.GetAttribute("Value");
var validFor = filter.GetAttribute("ValidFor");
var filterType = filter.GetAttribute("FilterType");
var isNotFiler = filter.GetAttribute("IsNotFilter");
var typeToReverse = filter.GetAttribute("TypeToReverse");
List<XmlElement> filterValues = GetNodeFilterValues(xmlFile, parentName, propertyName, orFilter);
// Write out the "meat" of the object definition
WriteLine(indent + "{");
WriteLine(indent + " Property = \"{0}\",", propertyName);
WriteLine(indent + " Type = typeof({0}),", propertyType);
if (!string.IsNullOrWhiteSpace(typeToReverse))
{
WriteLine(indent + " TypeToReverse = typeof({0}Querier),", typeToReverse);
}
if (!string.IsNullOrWhiteSpace(validFor))
{
WriteLine(indent + " ValidFor = {0},", GetValidForFlags(validFor));
}
if (!string.IsNullOrWhiteSpace(filterType))
{
WriteLine(indent + " FilterType = FilterType.{0},", filterType.ToUpper());
}
if (!string.IsNullOrWhiteSpace(isNotFiler))
{
WriteLine(indent + " IsNotFilter = {0},", isNotFiler);
}
if (propertyValue != null && (filterValues == null || filterValues.Count == 0))
{
if (propertyType.Equals("string"))
{
WriteLine(indent + " Values = new List<object> {{ \"{0}\" }},", propertyValue);
}
else
{
WriteLine(indent + " Values = new List<object> {{ {0} }},", propertyValue);
}
}
if (filterValues != null && filterValues.Count > 0)
{
WriteLine(indent + " Values = new List<object>");
WriteLine(indent + " {");
for(int i = 0; i < filterValues.Count; i++)
{
string separator = (i != filterValues.Count - 1) ? "," : "";
var filterValue = filterValues[i];
if(propertyType.Equals("string"))
{
WriteLine(indent + " {{ \"{0}\" }}{1}", filterValue.InnerText, separator);
}
else
{
WriteLine(indent + " {{ {0} }}{1}", filterValue.InnerText, separator);
}
}
WriteLine(indent + " }");
}
}
/// <summary>
/// Helper function to parse out settings Name with not operators and return code to
/// </summary>
public string GetSettingsString(string settingsName)
{
var notOperator = "";
if(settingsName.Substring(0, 1) == "!"){
notOperator = "!";
settingsName = settingsName.Substring(1, settingsName.Length-1);
}
return String.Format("{0}WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.ObjectExplorer.{1}", notOperator, settingsName);
}
#>

View File

@@ -1,680 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<ServerExplorerTree>
<Node Name="Server" LocLabel="SR.SchemaHierarchy_Server" Image="Server">
<Child Name="Databases"/>
<Child Name="ServerLevelSecurity"/>
<Child Name="ServerLevelServerObjects"/>
</Node>
<Node Name="Databases" LocLabel="SR.SchemaHierarchy_Databases" IsAsyncLoad="" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabase" TreeNode="DatabaseTreeNode">
<Filters >
<Filter Property="IsSystemObject" Value="0" Type="bool" />
</Filters>
<Properties>
<Property Name="Status" ValidFor="All"/>
<!--IsLedger property check is disabled on Azure databases to avoid making connections to databases individually
when listing databases in Object Explorer since it's value is not available from 'master' DB for all databases.-->
<Property Name="IsLedger" ValidFor="Sql2022OrHigher"/>
</Properties>
<Child Name="SystemDatabases" IsSystemObject="1"/>
</Node>
<Node Name="ServerLevelSecurity" LocLabel="SR.SchemaHierarchy_Security" BaseClass="ModelBased" ValidFor="All">
<Child Name="ServerLevelLogins"/>
<Child Name="ServerLevelServerRoles"/>
<Child Name="ServerLevelCredentials"/>
<Child Name="ServerLevelCryptographicProviders"/>
<Child Name="ServerLevelServerAudits"/>
<Child Name="ServerLevelServerAuditSpecifications"/>
<!-- TODO Support XEvents in .Net Core SMO
<Child Name="ServerLevelEventSessions"/>
-->
</Node>
<Node Name="ServerLevelServerObjects" LocLabel="SR.SchemaHierarchy_ServerObjects" BaseClass="ModelBased" NodeType="ServerLevelServerObject" ValidFor="AllOnPrem">
<Child Name="ServerLevelEndpoints"/>
<Child Name="ServerLevelLinkedServers"/>
<Child Name="ServerLevelServerTriggers"/>
<Child Name="ServerLevelErrorMessages"/>
<!-- TODO Support XEvents in .Net Core SMO
<Child Name="ServerLevelEventNotifications"/>
-->
</Node>
<Node Name="SystemDatabases" LocLabel="SR.SchemaHierarchy_SystemDatabases" BaseClass="ModelBased" NodeType="SystemDatabase" ChildQuerierTypes="SqlDatabase" Strategy="MultipleElementsOfType" TreeNode="DatabaseTreeNode" ValidFor="All">
<Filters >
<Filter Property="IsSystemObject" Value="1" Type="bool" />
</Filters>
</Node>
<!-- TODO Support XEvents in .Net Core SMO
<Node Name="ServerLevelEventSessions" LocLabel="SR.SchemaHierarchy_EventSessions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlEventSession" ValidFor="Sql2008OrHigher"/>
<Node Name="ServerLevelEventNotifications" LocLabel="SR.SchemaHierarchy_ServerEventNotifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerEventNotification"/>
-->
<Node Name="ServerLevelLogins" LocLabel="SR.SchemaHierarchy_Logins" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="ServerLevelLogin" ChildQuerierTypes="SqlLogin"/>
<Node Name="ServerLevelServerRoles" LocLabel="SR.SchemaHierarchy_ServerRoles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="ServerLevelServerRole" ChildQuerierTypes="SqlServerRole" ValidFor="AllOnPrem"/>
<Node Name="ServerLevelCredentials" LocLabel="SR.SchemaHierarchy_Credentials" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="ServerLevelCredential" ChildQuerierTypes="SqlCredential" ValidFor="AllOnPrem"/>
<Node Name="ServerLevelCryptographicProviders" LocLabel="SR.SchemaHierarchy_CryptographicProviders" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="ServerLevelCryptographicProvider" ChildQuerierTypes="SqlCryptographicProvider" ValidFor="AllOnPrem"/>
<Node Name="ServerLevelServerAudits" LocLabel="SR.SchemaHierarchy_ServerAudits" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="ServerLevelServerAudit" ChildQuerierTypes="SqlServerAudit" ValidFor="AllOnPrem"/>
<Node Name="ServerLevelServerAuditSpecifications" LocLabel="SR.SchemaHierarchy_ServerAuditSpecifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="ServerLevelServerAuditSpecification" ChildQuerierTypes="SqlServerAuditSpecification" ValidFor="AllOnPrem"/>
<Node Name="ServerLevelEndpoints" LocLabel="SR.SchemaHierarchy_Endpoints" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="ServerLevelEndpoint" ChildQuerierTypes="SqlEndpoint" ValidFor="AllOnPrem"/>
<Node Name="ServerLevelLinkedServers" LocLabel="SR.SchemaHierarchy_LinkedServers" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="ServerLevelLinkedServer" ChildQuerierTypes="SqlLinkedServer"/>
<Node Name="ServerLevelServerTriggers" LocLabel="SR.SchemaHierarchy_ServerTriggers" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="ServerLevelServerTrigger" ChildQuerierTypes="SqlServerDdlTrigger"/>
<Node Name="ServerLevelErrorMessages" LocLabel="SR.SchemaHierarchy_ErrorMessages" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="ServerLevelErrorMessage" ChildQuerierTypes="SqlErrorMessage"/>
<Node Name="Database" LocLabel="string.Empty" Image="Database" BaseClass="ModelBased" NodeType="Database" IsAsyncLoad="" Strategy="CreateModel" TreeNode="ExpandableSchemaTreeNode" PutFoldersAfterNodes="true">
<ConditionalChildQuerierType Name="SqlSchema" SettingsFlag="GroupBySchema"/>
<Filters>
<!--
Excluding built-in schemas for backward compatibility from the database node and moving them to legacy schema folder.
The list of schemas was obtained from:
https://learn.microsoft.com/en-us/sql/relational-databases/security/authentication-access/ownership-and-user-schema-separation?view=sql-server-ver16#built-in-schemas-for-backward-compatibility
-->
<Filter Property="Name" Value="db_accessadmin" Type="string" IsNotFilter="true"/>
<Filter Property="Name" Value="db_backupoperator" Type="string" IsNotFilter="true"/>
<Filter Property="Name" Value="db_datareader" Type="string" IsNotFilter="true"/>
<Filter Property="Name" Value="db_datawriter" Type="string" IsNotFilter="true"/>
<Filter Property="Name" Value="db_ddladmin" Type="string" IsNotFilter="true"/>
<Filter Property="Name" Value="db_denydatareader" Type="string" IsNotFilter="true"/>
<Filter Property="Name" Value="db_denydatawriter" Type="string" IsNotFilter="true"/>
<Filter Property="Name" Value="db_owner" Type="string" IsNotFilter="true"/>
<Filter Property="Name" Value="db_securityadmin" Type="string" IsNotFilter="true"/>
</Filters>
<Child Name="Tables" SettingsFlag="!GroupBySchema"/>
<Child Name="Views" SettingsFlag="!GroupBySchema"/>
<Child Name="Synonyms" SettingsFlag="!GroupBySchema"/>
<Child Name="BuiltInSchemas" SettingsFlag="GroupBySchema"/>
<Child Name="Programmability"/>
<Child Name="ExternalResources"/>
<Child Name="ServiceBroker"/>
<Child Name="Storage"/>
<Child Name="Security"/>
</Node>
<Node Name="BuiltInSchemas" LocLabel="SR.SchemaHierarchy_BuiltInSchema" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSchema" TreeNode="ExpandableSchemaTreeNode">
<Filters>
<Or>
<Filter Property="Name" Value="db_accessadmin" Type="string" />
<Filter Property="Name" Value="db_backupoperator" Type="string" />
<Filter Property="Name" Value="db_datareader" Type="string"/>
<Filter Property="Name" Value="db_datawriter" Type="string"/>
<Filter Property="Name" Value="db_ddladmin" Type="string"/>
<Filter Property="Name" Value="db_denydatareader" Type="string"/>
<Filter Property="Name" Value="db_denydatawriter" Type="string"/>
<Filter Property="Name" Value="db_owner" Type="string"/>
<Filter Property="Name" Value="db_securityadmin" Type="string"/>
</Or>
</Filters>
</Node>
<Node Name="ExpandableSchema" LocLabel="string.empty" BaseClass="ModelBased" Strategy="CreateModel">
<Child Name="Tables"/>
<Child Name="Views"/>
<Child Name="Synonyms"/>
<Child Name="ExpandableSchemaProgrammability"/>
</Node>
<Node Name="Tables" LocLabel="SR.SchemaHierarchy_Tables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableTreeNode">
<Filters>
<Filter Property="IsSystemObject" Value="0" Type="bool" />
<Filter Property="TemporalType" Type="Enum" ValidFor="Sql2016OrHigher|AzureV12">
<Value>TableTemporalType.None</Value>
<Value>TableTemporalType.SystemVersioned</Value>
</Filter>
<Filter Property="LedgerType" Type="Enum" ValidFor="Sql2022OrHigher|AzureV12">
<Value>LedgerTableType.None</Value>
<Value>LedgerTableType.AppendOnlyLedgerTable</Value>
<Value>LedgerTableType.UpdatableLedgerTable</Value>
</Filter>
<Filter Property="IsDroppedLedgerTable" Value="0" Type="bool" ValidFor="Sql2022OrHigher|AzureV12" />
</Filters>
<Properties>
<Property Name="IsFileTable" ValidFor="Sql2012OrHigher"/>
<Property Name="IsSystemVersioned" ValidFor="Sql2016OrHigher|AzureV12"/>
<Property Name="TemporalType" ValidFor="Sql2016OrHigher|AzureV12"/>
<Property Name="LedgerType" ValidFor="Sql2022OrHigher|AzureV12"/>
<Property Name="IsExternal" ValidFor="Sql2016OrHigher|AzureV12|SqlOnDemand"/>
<Property Name="IsEdge" ValidFor="Sql2017OrHigher|AzureV12"/>
<Property Name="IsNode" ValidFor="Sql2017OrHigher|AzureV12"/>
</Properties>
<Child Name="SystemTables" IsSystemObject="1"/>
<Child Name="ExternalTables"/>
<Child Name="DroppedLedgerTables"/>
</Node>
<Node Name="Views" LocLabel="SR.SchemaHierarchy_Views" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlView" TreeNode="ViewTreeNode">
<Filters>
<Filter Property="IsSystemObject" Value="0" Type="bool" />
<Filter Property="IsDroppedLedgerView" Value="0" Type="bool" ValidFor="Sql2022OrHigher|AzureV12"/>
</Filters>
<Properties>
<Property Name="LedgerViewType" ValidFor="Sql2022|AzureV12"/>
</Properties>
<Child Name="SystemViews" IsSystemObject="1"/>
<Child Name="DroppedLedgerViews"/>
</Node>
<Node Name="Synonyms" LocLabel="SR.SchemaHierarchy_Synonyms" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="Synonym" ChildQuerierTypes="SqlSynonym" ValidFor="AllOnPrem|AzureV12"/>
<Node Name="Programmability" LocLabel="SR.SchemaHierarchy_Programmability" BaseClass="ModelBased" ValidFor="NotSqlDemand">
<Child Name="StoredProcedures" SettingsFlag="!GroupBySchema"/>
<Child Name="Functions" SettingsFlag="!GroupBySchema"/>
<Child Name="DatabaseTriggers"/>
<Child Name="Assemblies"/>
<Child Name="Types" SettingsFlag="!GroupBySchema"/>
<!--
<Child Name="Rules"/>
<Child Name="Defaults"/>
-->
<Child Name="Sequences" SettingsFlag="!GroupBySchema"/>
</Node>
<Node Name="ExpandableSchemaProgrammability" LocLabel="SR.SchemaHierarchy_Programmability" BaseClass="ModelBased" ValidFor="NotSqlDemand">
<Child Name="StoredProcedures"/>
<Child Name="Functions"/>
<Child Name="Types"/>
<Child Name="Sequences"/>
</Node>
<Node Name="ExternalResources" LocLabel="SR.SchemaHierarchy_ExternalResources" BaseClass="ModelBased" TreeNode="ExternalResourceTreeNode" ValidFor="Sql2016OrHigher|AzureV12|SqlOnDemand">
<Child Name="ExternalDataSources"/>
<Child Name="ExternalFileFormats"/>
</Node>
<Node Name="ServiceBroker" LocLabel="SR.SchemaHierarchy_ServiceBroker" BaseClass="ModelBased" ValidFor="AllOnPrem">
<Child Name="MessageTypes"/>
<Child Name="Contracts"/>
<Child Name="Queues"/>
<Child Name="Services"/>
<!--Child Name="Routes"/-->
<Child Name="DatabaseAndQueueEventNotifications"/>
<Child Name="RemoteServiceBindings"/>
<Child Name="BrokerPriorities"/>
</Node>
<Node Name="Storage" LocLabel="SR.SchemaHierarchy_Storage" BaseClass="ModelBased" ValidFor="AllOnPrem|AzureV12">
<Child Name="FileGroups"/>
<Child Name="FullTextCatalogs"/>
<Child Name="FullTextStopLists"/>
<Child Name="SqlLogFiles"/>
<Child Name="PartitionFunctions"/>
<Child Name="PartitionSchemes"/>
<Child Name="SearchPropertyLists"/>
</Node>
<Node Name="Security" LocLabel="SR.SchemaHierarchy_Security" BaseClass="ModelBased" >
<Child Name="Users"/>
<Child Name="Roles"/>
<Child Name="Schemas"/>
<Child Name="AsymmetricKeys"/>
<Child Name="Certificates"/>
<Child Name="SymmetricKeys"/>
<Child Name="DatabaseScopedCredentials"/>
<Child Name="DatabaseEncryptionKeys"/>
<Child Name="MasterKeys"/>
<Child Name="Signatures"/>
<Child Name="DatabaseAuditSpecifications"/>
<Child Name="SecurityPolicies"/>
<Child Name="AlwaysEncryptedKeys"/>
</Node>
<!-- Childs of Tables -->
<Node Name="SystemTables" LocLabel="SR.SchemaHierarchy_SystemTables" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableTreeNode">
<Filters >
<Filter Property="IsSystemObject" Value="1" Type="bool" />
</Filters>
</Node>
<Node Name="DroppedLedgerTables" LocLabel="SR.SchemaHierarchy_DroppedLedgerTables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableTreeNode" ValidFor="Sql2022OrHigher|AzureV12" SortPriority="Int32.MaxValue">
<Filters >
<Filter Property="IsDroppedLedgerTable" Value="1" Type="bool" />
</Filters>
<Properties>
<Property Name="IsDroppedLedgerTable" ValidFor="Sql2022OrHigher|AzureV12"/>
</Properties>
</Node>
<!--
<Node Name="FileTables" LocLabel="SR.SchemaHierarchy_FileTables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableTreeNode" ValidFor="Sql2012OrHigher">
<Filters >
<Filter Property="IsFileTable" Value="1" Type="bool" />
</Filters>
</Node>
<Node Name="ExternalTables" LocLabel="SR.SchemaHierarchy_ExternalTables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="ExternalTableTreeNode" ValidFor="Sql2016OrHigher|AzureV12">
<Filters >
<Filter Property="IsExternal" Value="1" Type="bool" />
</Filters>
</Node>
-->
<Node Name="Table" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable;SqlHistoryTable" TreeNode="HistoryTableTreeNode">
<Filters>
<Or>
<Filter TypeToReverse="SqlHistoryTable" Property="TemporalType" Type="Enum" ValidFor="Sql2016OrHigher|AzureV12">
<Value>TableTemporalType.HistoryTable</Value>
</Filter>
<Filter TypeToReverse="SqlHistoryTable" Property="LedgerType" Type="Enum" ValidFor="Sql2022OrHigher|AzureV12">
<Value>LedgerTableType.HistoryTable</Value>
</Filter>
</Or>
</Filters>
<Properties>
<Property Name="LedgerType" ValidFor="Sql2022OrHigher|AzureV12"/>
<Property Name="TemporalType" ValidFor="Sql2016OrHigher|AzureV12"/>
</Properties>
<Child Name="Columns"/>
<Child Name="Keys"/>
<Child Name="Constraints"/>
<Child Name="Triggers"/>
<Child Name="Indexes"/>
<Child Name="Statistics"/>
</Node>
<!-- TODO This should use display item not ChildQuerierTypes -->
<Node Name="HistoryTable" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="PopulateDetails" NodeType="Table" ValidFor="Sql2016OrHigher|AzureV12">
<Child Name="Columns"/>
<Child Name="Constraints"/>
<Child Name="Indexes"/>
<Child Name="Statistics"/>
</Node>
<Node Name="ExternalTable" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="PopulateDetails" NodeType="Table" ChildQuerierTypes="SqlTable" ValidFor="Sql2016OrHigher|AzureV12|SqlOnDemand">
<Child Name="Columns"/>
<Child Name="Statistics"/>
</Node>
<Node Name="Columns" LocLabel="SR.SchemaHierarchy_Columns" BaseClass="ModelBased" Strategy="PopulateParentDetails" NodeType="Column" ChildQuerierTypes="SqlColumn" DisableSort="">
<Filters>
<Filter Property="IsDroppedLedgerColumn" Value="0" Type="bool" ValidFor="Sql2022OrHigher|AzureV12" />
</Filters>
<Child Name="DroppedLedgerColumns"/>
</Node>
<Node Name="DroppedLedgerColumns" LocLabel="SR.SchemaHierarchy_DroppedLedgerColumns" BaseClass="ModelBased" Strategy="PopulateParentDetails" NodeType="Column" ChildQuerierTypes="SqlColumn" ValidFor="Sql2022OrHigher|AzureV12" SortPriority="Int32.MaxValue">
<Filters>
<Filter Property="IsDroppedLedgerColumn" Value="1" Type="bool" ValidFor="Sql2022OrHigher|AzureV12" />
</Filters>
</Node>
<Node Name="Keys" LocLabel="SR.SchemaHierarchy_Keys" BaseClass="ModelBased" Strategy="ElementsInRelationship" NodeType="Key" ChildQuerierTypes="SqlIndex;SqlForeignKeyConstraint" ValidFor="NotSqlDw">
<Filters>
<Filter TypeToReverse="SqlIndex" Property="IndexKeyType" Type="Enum" ValidFor="AllOnPrem|AzureV12">
<Value>IndexKeyType.DriPrimaryKey</Value>
<Value>IndexKeyType.DriUniqueKey</Value>
</Filter>
</Filters>
</Node>
<Node Name="Constraints" LocLabel="SR.SchemaHierarchy_Constraints" BaseClass="ModelBased" NodeType="Constraint" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlDefaultConstraint;SqlCheck"/>
<Node Name="Triggers" LocLabel="SR.SchemaHierarchy_Triggers" BaseClass="ModelBased" Strategy="ElementsInRelationship" NodeType="Trigger" ChildQuerierTypes="SqlDmlTrigger" ValidFor="AllOnPrem|AzureV12"/>
<Node Name="Indexes" LocLabel="SR.SchemaHierarchy_Indexes" BaseClass="ModelBased" Strategy="ElementsInRelationship" NodeType="Index" ChildQuerierTypes="SqlIndex;SqlFullTextIndex" ValidFor="NotSqlDemand">
<Filters>
<Filter TypeToReverse="SqlIndex" Property="IndexKeyType" Type="Enum" ValidFor="AllOnPrem|AzureV12">
<Value>IndexKeyType.None</Value>
<Value>IndexKeyType.DriPrimaryKey</Value>
<Value>IndexKeyType.DriUniqueKey</Value>
</Filter>
</Filters>
</Node>
<Node Name="Statistics" LocLabel="SR.SchemaHierarchy_Statistics" BaseClass="ModelBased" Strategy="ElementsInRelationship" NodeType="Statistic" ChildQuerierTypes="SqlStatistic" ValidFor="NotSqlDemand"/>
<Node Name="SystemViews" LocLabel="SR.SchemaHierarchy_SystemViews" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlView" TreeNode="ViewTreeNode">
<Filters>
<Filter Property="IsSystemObject" Value="1" Type="bool" />
</Filters>
</Node>
<Node Name="DroppedLedgerViews" LocLabel="SR.SchemaHierarchy_DroppedLedgerViews" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlView" TreeNode="ViewTreeNode" ValidFor="Sql2022OrHigher|AzureV12" SortPriority="Int32.MaxValue">
<Filters>
<Filter Property="IsDroppedLedgerView" Value="1" Type="bool" ValidFor="Sql2022OrHigher|AzureV12" />
</Filters>
</Node>
<Node Name="View" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" NodeType="View" Strategy="PopulateDetails">
<Child Name="Columns"/>
<Child Name="Triggers"/>
<Child Name="Indexes"/>
<Child Name="Statistics"/>
</Node>
<Node Name="Functions" LocLabel="SR.SchemaHierarchy_Functions" BaseClass="ModelBased" ValidFor="NotSqlDemand">
<Child Name="SystemFunctions" IsSystemObject="1"/>
<Child Name="TableValuedFunctions"/>
<Child Name="ScalarValuedFunctions"/>
<Child Name="AggregateFunctions"/>
</Node>
<Node Name="SystemFunctions" LocLabel="SR.SchemaHierarchy_SystemFunctions" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" TreeNode="TableValuedFunctionTreeNode">
<Child Name="SystemTableValuedFunctions" IsSystemObject="1"/>
<Child Name="SystemScalarValuedFunctions" IsSystemObject="1"/>
</Node>
<Node Name="DatabaseTriggers" LocLabel="SR.SchemaHierarchy_DatabaseTriggers" BaseClass="ModelBased" NodeType="DatabaseTrigger" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseDdlTrigger" ValidFor="AllOnPrem|AzureV12"/>
<Node Name="Assemblies" LocLabel="SR.SchemaHierarchy_Assemblies" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="Assembly" ChildQuerierTypes="SqlAssembly" ValidFor="AllOnPrem|AzureV12"/>
<Node Name="Types" LocLabel="SR.SchemaHierarchy_Types" BaseClass="ModelBased" ValidFor="NotSqlDemand">
<Child Name="SystemDataTypes" IsSystemObject="1"/>
<Child Name="UserDefinedDataTypes"/>
<Child Name="UserDefinedTableTypes"/>
<Child Name="UserDefinedTypes"/>
<Child Name="XmlSchemaCollections"/>
</Node>
<!--==
<Node Name="Rules" LocLabel="SR.SchemaHierarchy_Rules" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="Rule" ChildQuerierTypes="SqlRule" ValidFor="AllOnPrem|AzureV12"/>
<Node Name="Defaults" LocLabel="SR.SchemaHierarchy_Defaults" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="Default" ChildQuerierTypes="SqlDefault" ValidFor="AllOnPrem|AzureV12"/>
-->
<Node Name="Sequences" LocLabel="SR.SchemaHierarchy_Sequences" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="Sequence" ChildQuerierTypes="SqlSequence" ValidFor="Sql2012OrHigher|AzureV12"/>
<Node Name="SystemDataTypes" LocLabel="SR.SchemaHierarchy_SystemDataTypes" BaseClass="ModelBased" >
<Child Name="SystemExactNumerics"/>
<Child Name="SystemApproximateNumerics"/>
<Child Name="SystemDateAndTimes"/>
<Child Name="SystemCharacterStrings"/>
<Child Name="SystemUnicodeCharacterStrings"/>
<Child Name="SystemBinaryStrings"/>
<Child Name="SystemOtherDataTypes"/>
<Child Name="SystemClrDataTypes"/>
<Child Name="SystemSpatialDataTypes"/>
</Node>
<Node Name="UserDefinedDataTypes" LocLabel="SR.SchemaHierarchy_UserDefinedDataTypes" BaseClass="ModelBased" NodeType="UserDefinedDataType" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedDataType" ValidFor="AllOnPrem|AzureV12"/>
<Node Name="UserDefinedTableTypes" LocLabel="SR.SchemaHierarchy_UserDefinedTableTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedTableType" TreeNode="UserDefinedTableTypeTreeNode" ValidFor="Sql2008OrHigher|AzureV12"/>
<Node Name="UserDefinedTypes" LocLabel="SR.SchemaHierarchy_UserDefinedTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="UserDefinedType" ChildQuerierTypes="SqlUserDefinedType" ValidFor="AllOnPrem|AzureV12"/>
<Node Name="XmlSchemaCollections" LocLabel="SR.SchemaHierarchy_XMLSchemaCollections" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="XmlSchemaCollection" ChildQuerierTypes="SqlXmlSchemaCollection" ValidFor="AllOnPrem|AzureV12"/>
<Node Name="UserDefinedTableType" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" NodeType="UserDefinedTableType" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="UserDefinedTableTypeColumns"/>
<Child Name="UserDefinedTableTypeKeys"/>
<Child Name="UserDefinedTableTypeConstraints"/>
</Node>
<Node Name="UserDefinedTableTypeColumns" LocLabel="SR.SchemaHierarchy_Columns" BaseClass="ModelBased" NodeType="UserDefinedTableTypeColumn" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlColumn" DisableSort=""/>
<Node Name="UserDefinedTableTypeKeys" LocLabel="SR.SchemaHierarchy_Keys" BaseClass="ModelBased" NodeType="UserDefinedTableTypeKey" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlIndex">
<Filters>
<Filter TypeToReverse="SqlIndex" Property="IndexKeyType" Type="Enum" ValidFor="Sql2016OrHigher|AzureV12">
<Value>IndexKeyType.DriPrimaryKey</Value>
<Value>IndexKeyType.DriUniqueKey</Value>
</Filter>
</Filters>
</Node>
<Node Name="UserDefinedTableTypeConstraints" LocLabel="SR.SchemaHierarchy_Constraints" BaseClass="ModelBased" NodeType="UserDefinedTableTypeConstraint" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlDefaultConstraint;SqlCheck"/>/>
<Node Name="SystemExactNumerics" LocLabel="SR.SchemaHierarchy_SystemExactNumerics" BaseClass="ModelBased" NodeType="SystemExactNumeric" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemApproximateNumerics" LocLabel="SR.SchemaHierarchy_SystemApproximateNumerics" BaseClass="ModelBased" NodeType="SystemApproximateNumeric" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemDateAndTimes" LocLabel="SR.SchemaHierarchy_SystemDateAndTime" BaseClass="ModelBased" NodeType="SystemDateAndTime" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemCharacterStrings" LocLabel="SR.SchemaHierarchy_SystemCharacterStrings" BaseClass="ModelBased" NodeType="SystemCharacterString" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemUnicodeCharacterStrings" LocLabel="SR.SchemaHierarchy_SystemUnicodeCharacterStrings" BaseClass="ModelBased" NodeType="SystemUnicodeCharacterString" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemBinaryStrings" LocLabel="SR.SchemaHierarchy_SystemBinaryStrings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="SystemBinaryString" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemOtherDataTypes" LocLabel="SR.SchemaHierarchy_SystemOtherDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="SystemOtherDataType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemClrDataTypes" LocLabel="SR.SchemaHierarchy_SystemCLRDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="SystemClrDataType" ChildQuerierTypes="SqlBuiltInType" ValidFor="All"/>
<Node Name="SystemSpatialDataTypes" LocLabel="SR.SchemaHierarchy_SystemSpatialDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="SystemSpatialDataType" ChildQuerierTypes="SqlBuiltInType" ValidFor="Sql2008OrHigher|AzureV12"/>
<!-- Childs of ExternalResources -->
<Node Name="ExternalDataSources" LocLabel="SR.SchemaHierarchy_ExternalDataSources" BaseClass="ModelBased" NodeType="ExternalDataSource" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlExternalDataSource" ValidFor="Sql2016OrHigher|AzureV12|SqlOnDemand"/>
<Node Name="ExternalFileFormats" LocLabel="SR.SchemaHierarchy_ExternalFileFormats" BaseClass="ModelBased" NodeType="ExternalFileFormat" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlExternalFileFormat" ValidFor="Sql2016OrHigher|SqlOnDemand"/>
<Node Name="StoredProcedures" LocLabel="SR.SchemaHierarchy_StoredProcedures" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlProcedure" TreeNode="StoredProcedureTreeNode">
<Filters >
<Filter Property="IsSystemObject" Value="0" Type="bool" />
</Filters>
<Child Name="SystemStoredProcedures" IsSystemObject="1"/>
</Node>
<Node Name="SystemStoredProcedures" LocLabel="SR.SchemaHierarchy_SystemStoredProcedures" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlProcedure" TreeNode="StoredProcedureTreeNode">
<Filters >
<Filter Property="IsSystemObject" Value="1" Type="bool" />
</Filters>
</Node>
<Node Name="StoredProcedure" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" NodeType="StoredProcedure" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="StoredProcedureParameters"/>
</Node>
<Node Name="StoredProcedureParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" NodeType="StoredProcedureParameter" Strategy="StoredProcedureParameters" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
<Node Name="TableValuedFunctions" LocLabel="SR.SchemaHierarchy_TableValuedFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedFunction" TreeNode="TableValuedFunctionTreeNode" ValidFor="NotSqlDw">
<Filters >
<Filter Property="FunctionType" Type="Enum">
<Value>UserDefinedFunctionType.Table</Value>
<Value>UserDefinedFunctionType.Inline</Value>
</Filter>
<Filter Property="IsSystemObject" Value="0" Type="bool" />
</Filters>
</Node>
<Node Name="SystemTableValuedFunctions" LocLabel="SR.SchemaHierarchy_TableValuedFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedFunction" TreeNode="TableValuedFunctionTreeNode" ValidFor="NotSqlDw">
<Filters >
<Filter Property="FunctionType" Type="Enum">
<Value>UserDefinedFunctionType.Table</Value>
<Value>UserDefinedFunctionType.Inline</Value>
</Filter>
<Filter Property="IsSystemObject" Value="1" Type="bool" />
</Filters>
</Node>
<Node Name="TableValuedFunction" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" NodeType="TableValuedFunction" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="TableValuedFunctionParameters"/>
</Node>
<Node Name="TableValuedFunctionParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" NodeType="TableValuedFunctionParameter" Strategy="FunctionParameters" ChildQuerierTypes="SqlSubroutineParameter" DisableSort="">
</Node>
<Node Name="ScalarValuedFunctions" LocLabel="SR.SchemaHierarchy_ScalarValuedFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedFunction" TreeNode="ScalarValuedFunctionTreeNode" >
<Filters>
<Filter Property="FunctionType" Type="Enum" ValidFor="NotSqlDw">
<Value>UserDefinedFunctionType.Scalar</Value>
</Filter>
<Filter Property="IsSystemObject" Value="0" Type="bool" />
</Filters>
</Node>
<Node Name="SystemScalarValuedFunctions" LocLabel="SR.SchemaHierarchy_ScalarValuedFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedFunction" TreeNode="ScalarValuedFunctionTreeNode" >
<Filters>
<Filter Property="FunctionType" Type="Enum" ValidFor="NotSqlDw">
<Value>UserDefinedFunctionType.Scalar</Value>
</Filter>
<Filter Property="IsSystemObject" Value="1" Type="bool" />
</Filters>
</Node>
<Node Name="ScalarValuedFunction" LocLabel="string.Empty" BaseClass="ModelBased" NodeType="ScalarValuedFunction" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="ScalarValuedFunctionParameters"/>
</Node>
<Node Name="ScalarValuedFunctionParameters" LocLabel="SR.SchemaHierarchy_Parameters" NodeType="ScalarValuedFunctionParameter" BaseClass="ModelBased" Strategy="FunctionParameters" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
<Node Name="AggregateFunctions" LocLabel="SR.SchemaHierarchy_AggregateFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedAggregate" TreeNode="AggregateFunctionTreeNode" ValidFor="AllOnPrem|AzureV12">
</Node>
<Node Name="AggregateFunction" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" NodeType="AggregateFunction" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="AggregateFunctionParameters"/>
</Node>
<Node Name="AggregateFunctionParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" NodeType="AggregateFunctionParameter" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
<!-- TODO Support Route in SMO
<Node Name="Routes" LocLabel="SR.SchemaHierarchy_Routes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRoute"/>
-->
<!-- TODO support events
<Node Name="DatabaseAndQueueEventNotifications" LocLabel="SR.SchemaHierarchy_EventNotifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlEventNotification"/>
-->
<Node Name="RemoteServiceBindings" LocLabel="SR.SchemaHierarchy_RemoteServiceBindings" BaseClass="ModelBased" NodeType="RemoteServiceBinding" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRemoteServiceBinding"/>
<Node Name="BrokerPriorities" LocLabel="SR.SchemaHierarchy_BrokerPriorities" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="BrokerPriority" ChildQuerierTypes="SqlBrokerPriority" ValidFor="Sql2008OrHigher"/>
<Node Name="FileGroups" LocLabel="SR.SchemaHierarchy_FileGroups" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFileGroup" TreeNode="FileGroupTreeNode"/>
<Node Name="FullTextCatalogs" LocLabel="SR.SchemaHierarchy_FullTextCatalogs" BaseClass="ModelBased" NodeType="FullTextCatalog" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFullTextCatalog"/>
<Node Name="FullTextStopLists" LocLabel="SR.SchemaHierarchy_FullTextStopLists" BaseClass="ModelBased" NodeType="FullTextStopList" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFullTextStopList" ValidFor="Sql2008OrHigher|AzureV12"/>
<Node Name="SqlLogFiles" LocLabel="SR.SchemaHierarchy_LogFiles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="SqlLogFile" ChildQuerierTypes="SqlFile"/>
<Node Name="PartitionFunctions" LocLabel="SR.SchemaHierarchy_PartitionFunctions" BaseClass="ModelBased" NodeType="PartitionFunction" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlPartitionFunction"/>
<Node Name="PartitionSchemes" LocLabel="SR.SchemaHierarchy_PartitionSchemes" BaseClass="ModelBased" NodeType="PartitionScheme" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlPartitionScheme"/>
<Node Name="SearchPropertyLists" LocLabel="SR.SchemaHierarchy_SearchPropertyLists" BaseClass="ModelBased" NodeType="SearchPropertyList" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSearchPropertyList" ValidFor="Sql2012OrHigher|AzureV12"/>
<Node Name="FileGroup" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="">
<Child Name="FileGroupFiles"/>
</Node>
<Node Name="FileGroupFiles" LocLabel="SR.SchemaHierarchy_FilegroupFiles" BaseClass="ModelBased" NodeType="FileGroupFile" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFile" >
</Node>
<Node Name="Users" LocLabel="SR.SchemaHierarchy_Users" BaseClass="ModelBased" NodeType="User" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUser"/>
<Node Name="Roles" LocLabel="SR.SchemaHierarchy_Roles" NodeType="Role" BaseClass="ModelBased" >
<Child Name="DatabaseRoles"/>
<Child Name="ApplicationRoles"/>
</Node>
<Node Name="Schemas" LocLabel="SR.SchemaHierarchy_Schemas" BaseClass="ModelBased" NodeType="Schema" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSchema"/>
<Node Name="AsymmetricKeys" LocLabel="SR.SchemaHierarchy_AsymmetricKeys" BaseClass="ModelBased" NodeType="AsymmetricKey" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlAsymmetricKey" ValidFor="AllOnPrem"/>
<Node Name="Certificates" LocLabel="SR.SchemaHierarchy_Certificates" BaseClass="ModelBased" NodeType="Certificate" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlCertificate" ValidFor="AllOnPrem"/>
<Node Name="SymmetricKeys" LocLabel="SR.SchemaHierarchy_SymmetricKeys" BaseClass="ModelBased" NodeType="SymmetricKey" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSymmetricKey" ValidFor="AllOnPrem"/>
<Node Name="DatabaseEncryptionKeys" LocLabel="SR.SchemaHierarchy_DatabaseEncryptionKeys" BaseClass="ModelBased" NodeType="DatabaseEncryptionKey" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseEncryptionKey" ValidFor="Sql2008OrHigher"/>
<Node Name="MasterKeys" LocLabel="SR.SchemaHierarchy_MasterKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="MasterKey" ChildQuerierTypes="SqlMasterKey" ValidFor="AllOnPrem"/>
<!-- TODO Support signatures
<Node Name="Signatures" LocLabel="SR.SchemaHierarchy_Signatures" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSignature" ValidFor="AllOnPrem"/>
-->
<Node Name="DatabaseAuditSpecifications" LocLabel="SR.SchemaHierarchy_DatabaseAuditSpecifications" BaseClass="ModelBased" NodeType="DatabaseAuditSpecification" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseAuditSpecification" ValidFor="Sql2008OrHigher"/>
<Node Name="SecurityPolicies" LocLabel="SR.SchemaHierarchy_SecurityPolicies" BaseClass="ModelBased" Strategy="MultipleElementsOfType" NodeType="SecurityPolicy" ChildQuerierTypes="SqlSecurityPolicy" ValidFor="Sql2016OrHigher|AzureV12"/>
<Node Name="DatabaseScopedCredentials" LocLabel="SR.SchemaHierarchy_DatabaseScopedCredentials" BaseClass="ModelBased" NodeType="DatabaseScopedCredential" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseCredential" ValidFor="Sql2016OrHigher|AzureV12"/>
<Node Name="AlwaysEncryptedKeys" LocLabel="SR.SchemaHierarchy_AlwaysEncryptedKeys" BaseClass="ModelBased" ValidFor="Sql2016OrHigher|AzureV12">
<Child Name="ColumnMasterKeys"/>
<Child Name="ColumnEncryptionKeys"/>
</Node>
<Node Name="DatabaseRoles" LocLabel="SR.SchemaHierarchy_DatabaseRoles" BaseClass="ModelBased" NodeType="DatabaseRole" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRole"/>
<Node Name="ApplicationRoles" LocLabel="SR.SchemaHierarchy_ApplicationRoles" BaseClass="ModelBased" NodeType="ApplicationRole" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlApplicationRole" ValidFor="AllOnPrem|AzureV12"/>
<Node Name="ColumnMasterKeys" LocLabel="SR.SchemaHierarchy_ColumnMasterKeys" BaseClass="ModelBased" NodeType="ColumnMasterKey" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlColumnMasterKey" ValidFor="Sql2016OrHigher|AzureV12"/>
<Node Name="ColumnEncryptionKeys" LocLabel="SR.SchemaHierarchy_ColumnEncryptionKeys" BaseClass="ModelBased" NodeType="ColumnEncryptionKey" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlColumnEncryptionKey" ValidFor="Sql2016OrHigher|AzureV12"/>
<Node Name="MessageTypes" LocLabel="SR.SchemaHierarchy_MessageTypes" BaseClass="ModelBased" NodeType="MessageType" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlMessageType">
<Child Name="SystemMessageTypes" IsSystemObject="1"/>
</Node>
<Node Name="SystemMessageTypes" LocLabel="SR.SchemaHierarchy_SystemMessageTypes" BaseClass="ModelBased" NodeType="SystemMessageType" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlMessageType"/>
<Node Name="Contracts" LocLabel="SR.SchemaHierarchy_Contracts" BaseClass="ModelBased" NodeType="Contract" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlContract">
<Child Name="SystemContracts" IsSystemObject="1"/>
</Node>
<Node Name="SystemContracts" LocLabel="SR.SchemaHierarchy_SystemContracts" BaseClass="ModelBased" NodeType="SystemContract" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlContract"/>
<Node Name="Queues" LocLabel="SR.SchemaHierarchy_Queues" BaseClass="ModelBased" NodeType="Queue" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlQueue">
<Child Name="SystemQueues" IsSystemObject="1"/>
</Node>
<Node Name="SystemQueues" LocLabel="SR.SchemaHierarchy_SystemQueues" BaseClass="ModelBased" NodeType="SystemQueue" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlQueue"/>
<Node Name="Services" LocLabel="SR.SchemaHierarchy_Services" BaseClass="ModelBased" NodeType="Service" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlService">
<Child Name="SystemServices" IsSystemObject="1"/>
</Node>
<Node Name="SystemServices" LocLabel="SR.SchemaHierarchy_SystemServices" BaseClass="ModelBased" NodeType="SystemService" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlService"/>
<CodeGenOptions>
<UniqueTreeNode Name="DatabaseTreeNode"/>
<UniqueTreeNode Name="TableTreeNode"/>
<UniqueTreeNode Name="ViewTreeNode"/>
<UniqueTreeNode Name="UserDefinedTableTypeTreeNode"/>
<UniqueTreeNode Name="StoredProcedureTreeNode"/>
<UniqueTreeNode Name="TableValuedFunctionTreeNode"/>
<UniqueTreeNode Name="ScalarValuedFunctionTreeNode"/>
<UniqueTreeNode Name="AggregateFunctionTreeNode"/>
<UniqueTreeNode Name="FileGroupTreeNode"/>
<UniqueTreeNode Name="ExternalTableTreeNode"/>
<UniqueTreeNode Name="ExternalResourceTreeNode"/>
<UniqueTreeNode Name="HistoryTableTreeNode" />
<UniqueTreeNode Name="ExpandableSchemaTreeNode" Type="Schema"/>
</CodeGenOptions>
<!-- WARNING: Specifying reverse dependencies that could load large numbers of objects will be detrimental to performance. -->
<ReverseDependencyList>
<ReverseDependency Type="SqlUser" DependsOn="SqlRole;SqlRoleMembership"/>
</ReverseDependencyList>
<FilterProperties NodeName="Databases">
<Property>Name</Property>
<Property>Owner</Property>
<Property>CreateDate</Property>
</FilterProperties>
<FilterProperties NodeName="Tables">
<Property>Name</Property>
<Property>Schema</Property>
<Property>Owner</Property>
<Property>Durability</Property>
<Property>IsMemoryOptimized</Property>
<Property>CreateDate</Property>
</FilterProperties>
<FilterProperties NodeName="SystemTables">
<Property>Name</Property>
<Property>Schema</Property>
<Property>Owner</Property>
<Property>Durability</Property>
<Property>IsMemoryOptimized</Property>
<Property>CreateDate</Property>
</FilterProperties>
<FilterProperties NodeName="DroppedLedgerTables">
<Property>Name</Property>
<Property>Schema</Property>
<Property>Owner</Property>
<Property>Durability</Property>
<Property>IsMemoryOptimized</Property>
<Property>CreateDate</Property>
</FilterProperties>
<FilterProperties NodeName="Views">
<Property>Name</Property>
<Property>Schema</Property>
<Property>Owner</Property>
<Property>CreateDate</Property>
</FilterProperties>
<FilterProperties NodeName="DroppedLedgerViews">
<Property>Name</Property>
<Property>Schema</Property>
<Property>Owner</Property>
<Property>CreateDate</Property>
</FilterProperties>
<FilterProperties NodeName="StoredProcedures">
<Property>Name</Property>
<Property>Schema</Property>
<Property>Owner</Property>
<Property>IsNativelyCompiled</Property>
<Property>CreateDate</Property>
</FilterProperties>
<FilterProperties NodeName="TableValuedFunctions">
<Property>Name</Property>
<Property>Schema</Property>
<Property>Owner</Property>
<Property>IsNativelyCompiled</Property>
<Property>CreateDate</Property>
</FilterProperties>
<FilterProperties NodeName="ScalarValuedFunctions">
<Property>Name</Property>
<Property>Schema</Property>
<Property>Owner</Property>
<Property>IsNativelyCompiled</Property>
<Property>CreateDate</Property>
</FilterProperties>
<FilterProperties NodeName="AggregateFunctions">
<Property>Name</Property>
<Property>Schema</Property>
<Property>Owner</Property>
<Property>CreateDate</Property>
</FilterProperties>
<FilterProperties NodeName="Sequences">
<Property>Name</Property>
<Property>Schema</Property>
<Property>Owner</Property>
<Property>CreateDate</Property>
</FilterProperties>
<FilterProperties NodeName="Indexes">
<Property>Name</Property>
<Property>IsMemoryOptimized</Property>
</FilterProperties>
<FilterProperties NodeName="Columns">
<Property>Name</Property>
<Property>InPrimaryKey</Property>
</FilterProperties>
<FilterProperties NodeName="Database" SettingsFlag="GroupBySchema">
<Property>Name</Property>
<Property>Owner</Property>
</FilterProperties>
<FilterProperty Name="Name" LocLabel="SR.FilterName" Type="string" Description="SR.FilterNameDescription"/>
<FilterProperty Name="Schema" LocLabel="SR.FilterSchema" Type="string" Description="SR.FilterSchemaDescription"/>
<FilterProperty Name="Owner" LocLabel="SR.FilterOwner" Type="string" Description="SR.FilterOwnerDescription"/>
<FilterProperty Name="Durability" LocLabel="SR.FilterDurabilityType" Type="choice" Description="SR.FilterDurabilityTypeDescription">
<Value LocLabel="SR.FilterDurabilitySchemaAndData" Value="1"/>
<Value LocLabel="SR.FilterDurabilitySchemaOnly" Value="0"/>
</FilterProperty>
<FilterProperty Name="IsMemoryOptimized" LocLabel="SR.FilterIsMemoryOptimized" Type="bool" Description="SR.FilterIsMemoryOptimizedDescription"/>
<FilterProperty Name="CreateDate" LocLabel="SR.FilterCreateDate" Type="date" Description="SR.FilterCreateDateDescription"/>
<FilterProperty Name="IsNativelyCompiled" LocLabel="SR.FilterIsNativelyCompiled" Type="bool" Description="SR.FilterIsNativelyCompiledDescription"/>
<FilterProperty Name="InPrimaryKey" LocLabel="SR.FilterInPrimaryKey" Type="bool" Description="SR.FilterInPrimaryKeyDescription"/>
</ServerExplorerTree>

View File

@@ -1,103 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections.Generic;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Status for triggers
/// </summary>
internal partial class TriggersChildFactory : SmoChildFactoryBase
{
public static readonly Lazy<List<NodeSmoProperty>> SmoPropertiesLazy = new Lazy<List<NodeSmoProperty>>(() => new List<NodeSmoProperty>
{
new NodeSmoProperty
{
Name = "IsEnabled",
ValidFor = ValidForFlag.All
}
});
public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
return TriggersCustomeNodeHelper.GetStatus(smoObject);
}
public override IEnumerable<NodeSmoProperty> SmoProperties => SmoPropertiesLazy.Value;
}
internal partial class ServerLevelServerTriggersChildFactory : SmoChildFactoryBase
{
public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
return TriggersCustomeNodeHelper.GetStatus(smoObject);
}
public override IEnumerable<NodeSmoProperty> SmoProperties
{
get
{
return TriggersChildFactory.SmoPropertiesLazy.Value;
}
}
}
internal partial class DatabaseTriggersChildFactory : SmoChildFactoryBase
{
public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
return TriggersCustomeNodeHelper.GetStatus(smoObject);
}
public override IEnumerable<NodeSmoProperty> SmoProperties
{
get
{
return TriggersChildFactory.SmoPropertiesLazy.Value;
}
}
}
internal static class TriggersCustomeNodeHelper
{
internal static string GetStatus(object context)
{
Trigger trigger = context as Trigger;
if (trigger != null)
{
if (!trigger.IsEnabled)
{
return "Disabled";
}
}
ServerDdlTrigger serverDdlTrigger = context as ServerDdlTrigger;
if (serverDdlTrigger != null)
{
if (!serverDdlTrigger.IsEnabled)
{
return "Disabled";
}
}
DatabaseDdlTrigger databaseDdlTrigger = context as DatabaseDdlTrigger;
if (databaseDdlTrigger != null)
{
if (!databaseDdlTrigger.IsEnabled)
{
return "Disabled";
}
}
return string.Empty;
}
}
}

View File

@@ -1,54 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using System.Collections.Generic;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Status for logins
/// </summary>
internal partial class UsersChildFactory : SmoChildFactoryBase
{
public override string GetNodeStatus(object smoObject, SmoQueryContext smoContext)
{
return UserCustomeNodeHelper.GetStatus(smoObject);
}
private readonly Lazy<List<NodeSmoProperty>> smoPropertiesLazy = new Lazy<List<NodeSmoProperty>>(() => new List<NodeSmoProperty>
{
new NodeSmoProperty
{
Name = "HasDBAccess",
ValidFor = ValidForFlag.All
}
});
public override IEnumerable<NodeSmoProperty> SmoProperties => smoPropertiesLazy.Value;
}
internal static class UserCustomeNodeHelper
{
internal static string GetStatus(object context)
{
User user = context as User;
if (user != null)
{
if (!user.HasDBAccess)
{
return "Disabled";
}
}
return string.Empty;
}
}
}

View File

@@ -1,101 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
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);
}
}
/// <summary>
/// Custom name for dropped ledger views
/// </summary>
internal partial class DroppedLedgerViewsChildFactory : SmoChildFactoryBase
{
public override string GetNodeCustomName(object smoObject, SmoQueryContext smoContext)
{
try
{
View? view = smoObject as View;
if (view != null &&
IsPropertySupported("LedgerViewType", smoContext, view, CachedSmoProperties))
{
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)
{
return "Ledger";
}
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;
}
}
}

View File

@@ -1,58 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Internal for testing purposes only. This class provides wrapper functionality
/// over SMO objects in order to facilitate unit testing
/// </summary>
internal class SmoWrapper
{
/// <summary>
/// Creates instance of <see cref="Server"/> from provided <paramref name="serverConn"/> instance.
/// </summary>
/// <param name="serverConn">Server connection instance.</param>
/// <returns>Server instance.</returns>
public virtual Server CreateServer(ServerConnection serverConn)
{
return serverConn == null ? null : new Server(serverConn);
}
/// <summary>
/// Checks if connection is open on the <paramref name="smoObj"/> instance.
/// </summary>
/// <param name="smoObj">SMO Object containing connection context.</param>
/// <returns>True if connection is open, otherwise false.</returns>
public virtual bool IsConnectionOpen(SmoObjectBase smoObj)
{
SqlSmoObject sqlObj = smoObj as SqlSmoObject;
return sqlObj != null
&& sqlObj.ExecutionManager != null
&& sqlObj.ExecutionManager.ConnectionContext != null
&& sqlObj.ExecutionManager.ConnectionContext.IsOpen;
}
/// <summary>
/// Opens connection on the connection context of <paramref name="smoObj"/> instance.
/// </summary>
/// <param name="smoObj">SMO Object containing connection context.</param>
public virtual void OpenConnection(SmoObjectBase smoObj)
{
SqlSmoObject sqlObj = smoObj as SqlSmoObject;
if (sqlObj != null
&& sqlObj.ExecutionManager != null
&& sqlObj.ExecutionManager.ConnectionContext != null)
{
sqlObj.ExecutionManager.ConnectionContext.Connect();
}
}
}
}

View File

@@ -1,37 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
/// <summary>
/// Filters the history tables to only return ones related to the parent table
/// </summary>
internal partial class SqlHistoryTableQuerier : SmoQuerier
{
protected override bool PassesFinalFilters(SqlSmoObject parent, SqlSmoObject smoObject)
{
Table parentTable = parent as Table;
Table historyTable = smoObject as Table;
if (parentTable != null && historyTable != null)
{
try
{
return (parentTable.HistoryTableID == historyTable.ID);
}
catch(Exception)
{
//TODO: have a better filtering here. HistoryTable is not available for SQL 2014.
//and the property throws exception here
}
}
return false;
}
}
}

View File

@@ -1,210 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System.Collections.Generic;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
internal partial class SystemExactNumericsChildFactory
{
private static readonly HashSet<string> _exactNumerics = new HashSet<string>{
"bit",
"tinyint",
"smallint",
"int",
"bigint",
"numeric",
"decimal",
"smallmoney",
"money"
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _exactNumerics.Contains(name);
}
}
return false;
}
}
internal partial class SystemApproximateNumericsChildFactory
{
private static readonly HashSet<string> _approxNumerics = new HashSet<string>{
"float",
"real"
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _approxNumerics.Contains(name);
}
}
return false;
}
}
internal partial class SystemDateAndTimesChildFactory
{
private static readonly HashSet<string> _dateAndTime = new HashSet<string>{
"datetime",
"smalldatetime",
"date",
"time",
"datetimeoffset",
"datetime2",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _dateAndTime.Contains(name);
}
}
return false;
}
}
internal partial class SystemCharacterStringsChildFactory
{
private static readonly HashSet<string> _characterStrings = new HashSet<string>{
"char",
"varchar",
"text",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _characterStrings.Contains(name);
}
}
return false;
}
}
internal partial class SystemUnicodeCharacterStringsChildFactory
{
private static readonly HashSet<string> _unicodeCharacterStrings = new HashSet<string>
{
"nchar",
"nvarchar",
"ntext",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _unicodeCharacterStrings.Contains(name);
}
}
return false;
}
}
internal partial class SystemBinaryStringsChildFactory
{
private static readonly HashSet<string> _binaryStrings = new HashSet<string>{
"binary",
"varbinary",
"image",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _binaryStrings.Contains(name);
}
}
return false;
}
}
internal partial class SystemOtherDataTypesChildFactory
{
private static readonly HashSet<string> _otherDataTypes = new HashSet<string>{
"sql_variant",
"timestamp",
"uniqueidentifier",
"xml",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _otherDataTypes.Contains(name);
}
}
return false;
}
}
internal partial class SystemClrDataTypesChildFactory
{
private static readonly HashSet<string> _clrDataTypes = new HashSet<string>{
"hierarchyid",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _clrDataTypes.Contains(name);
}
}
return false;
}
}
internal partial class SystemSpatialDataTypesChildFactory
{
private static readonly HashSet<string> _spatialDataTypes = new HashSet<string>{
"geometry",
"geography",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _spatialDataTypes.Contains(name);
}
}
return false;
}
}
}

View File

@@ -1,169 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
{
/// <summary>
/// Server Types
/// </summary>
public enum SqlServerType
{
Unknown,
Sql2005,
Sql2008,
Sql2012,
Sql2014,
Sql2016,
Sql2017,
Sql2019,
Sql2022,
AzureV12,
SqlOnDemand,
AzureSqlDWGen3
}
/// <summary>
/// Includes helper functions for server version and type
/// </summary>
public class ServerVersionHelper
{
/// <summary>
/// Converts a server type to ValidForFlag
/// </summary>
public static ValidForFlag GetValidForFlag(SqlServerType serverType, Database database = null)
{
bool isSqlDw = false;
try
{
// Database could be null here, handle NRE first.
if (database != null)
{
isSqlDw = database.IsSqlDw;
}
}
catch (Exception e)
{
// Incase of dataverses, isSqlDw creates a temp table to check if the database is accessible, however dataverse
// don't support ddl statements and therefore this check fails.
Logger.Information($"This exception is expected when we are trying to access a readonly database. Exception: {e.Message}");
}
return GetValidForFlag(serverType, isSqlDw);
}
/// <summary>
/// Returns true if the given valid for flag is not set or it includes the server version
/// </summary>
/// <param name="serverVersion">Server version</param>
/// <param name="validFor">Valid for flag</param>
/// <returns></returns>
public static bool IsValidFor(ValidForFlag serverVersion, ValidForFlag validFor)
{
// If either the flag is not set or if the serverVersion has a default value of "all", allow the check
// Otherwise, actually do the comparison of the flags
return validFor == ValidForFlag.None || serverVersion == ValidForFlag.All || validFor.HasFlag(serverVersion);
}
/// <summary>
/// Converts a server type to ValidForFlag
/// </summary>
public static ValidForFlag GetValidForFlag(SqlServerType serverType, bool isSqlDw)
{
ValidForFlag validforFlag = ValidForFlag.All;
if (Enum.TryParse<ValidForFlag>(serverType.ToString(), out validforFlag))
{
if ((isSqlDw && serverType == SqlServerType.AzureV12) || serverType == SqlServerType.AzureSqlDWGen3)
{
validforFlag = ValidForFlag.SqlDw;
}
else if (serverType == SqlServerType.SqlOnDemand)
{
validforFlag = ValidForFlag.SqlOnDemand;
}
else
{
//TODO: not supporting SQL DW for on prem
}
return validforFlag;
}
return ValidForFlag.All;
}
/// <summary>
/// Creates a server type from the server version
/// </summary>
public static SqlServerType CalculateServerType(ServerInfo serverInfo)
{
string serverVersion = serverInfo.ServerVersion;
if (serverInfo.EngineEditionId == 11)
{
return SqlServerType.SqlOnDemand;
}
else if (serverInfo.IsCloud)
{
if (serverInfo.EngineEditionId == (int)DatabaseEngineEdition.SqlDataWarehouse
&& serverVersion.StartsWith("12", StringComparison.Ordinal))
{
return SqlServerType.AzureSqlDWGen3;
}
else
{
return SqlServerType.AzureV12;
}
}
else if (!string.IsNullOrWhiteSpace(serverVersion))
{
if (serverVersion.StartsWith("9", StringComparison.Ordinal) ||
serverVersion.StartsWith("09", StringComparison.Ordinal))
{
return SqlServerType.Sql2005;
}
else if (serverVersion.StartsWith("10", StringComparison.Ordinal))
{
return SqlServerType.Sql2008; // and 2008R2
}
else if (serverVersion.StartsWith("11", StringComparison.Ordinal))
{
return SqlServerType.Sql2012;
}
else if (serverVersion.StartsWith("12", StringComparison.Ordinal))
{
return SqlServerType.Sql2014;
}
else if (serverVersion.StartsWith("13", StringComparison.Ordinal))
{
return SqlServerType.Sql2016;
}
else if (serverVersion.StartsWith("14", StringComparison.Ordinal))
{
return SqlServerType.Sql2017;
}
else if (serverVersion.StartsWith("15", StringComparison.Ordinal))
{
return SqlServerType.Sql2019;
}
else if (serverVersion.StartsWith("16", StringComparison.Ordinal))
{
return SqlServerType.Sql2022;
}
else
{
// vNext case - default to latest version
return SqlServerType.Sql2022;
}
}
return SqlServerType.Unknown;
}
}
}

View File

@@ -1,43 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using System;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
{
/// <summary>
/// Indicates which type of server a given node type is valid for
/// </summary>
[Flags]
public enum ValidForFlag
{
None = 0x00,
Sql2005 = 0x01,
Sql2008 = 0x02,
Sql2012 = 0x04,
Sql2014 = 0x08,
AzureV12 = 0x10,
Sql2016 = 0x20,
Sql2017 = 0x40,
SqlDw = 0x80,
SqlOnDemand = 0x100,
AzureSqlDWGen3 = 0x200,
Sql2019 = 0x400,
Sql2022 = 0x800,
Sql2022OrHigher = Sql2022,
Sql2017OrHigher = Sql2017 | Sql2019 | Sql2022OrHigher,
Sql2016OrHigher = Sql2016 | Sql2017OrHigher,
Sql2012OrHigher = Sql2012 | Sql2014 | Sql2016OrHigher,
Sql2008OrHigher = Sql2008 | Sql2012OrHigher,
AllOnPrem = Sql2005 | Sql2008OrHigher,
AllAzure = AzureV12,
All = AllOnPrem | AzureV12 | SqlDw | SqlOnDemand,
NotSqlDw = AllOnPrem | AzureV12 | SqlOnDemand,
NotSqlDemand = AllOnPrem | AzureV12 | SqlDw,
NotSqlDwNotDemand = AllOnPrem | AzureV12,
}
}

View File

@@ -20,6 +20,7 @@ using Microsoft.SqlTools.Utility;
using System.Text;
using System.IO;
using Microsoft.SqlTools.ServiceLayer.Utility.SqlScriptFormatters;
using Microsoft.SqlTools.SqlCore.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
@@ -529,7 +530,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
// Update database file names now that we have a database name
if (viewParams.IsNewObject && !prototype.HideFileSettings)
{
var sanitizedName = DatabaseUtils.SanitizeDatabaseFileName(prototype.Name);
var sanitizedName = Utility.DatabaseUtils.SanitizeDatabaseFileName(prototype.Name);
var dataFile = prototype.Files[0];
if (dataFile.DatabaseFileType != FileType.Data)

View File

@@ -7,18 +7,18 @@
using System;
using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts;
using Microsoft.SqlTools.Utility;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using System.Collections.Specialized;
using System.Text;
using System.Globalization;
using Microsoft.SqlServer.Management.SqlScriptPublish;
using Microsoft.SqlTools.ServiceLayer.Utility;
using System.Text;
using Microsoft.Data.SqlClient;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.SqlScriptPublish;
using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts;
using Microsoft.SqlTools.SqlCore.Connection;
using Microsoft.SqlTools.SqlCore.Utility;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.Scripting
{

View File

@@ -5,14 +5,14 @@
#nullable disable
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts;
using Microsoft.SqlTools.Utility;
using System;
using Microsoft.Data.SqlClient;
using System.IO;
using System.Reflection;
using Microsoft.Data.SqlClient;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts;
using Microsoft.SqlTools.SqlCore.Connection;
using Microsoft.SqlTools.Utility;
using static Microsoft.SqlServer.Management.SqlScriptPublish.SqlScriptOptions;
namespace Microsoft.SqlTools.ServiceLayer.Scripting

View File

@@ -9,9 +9,9 @@ using System;
using System.Globalization;
using System.Text;
using System.Threading;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.ServiceLayer.SqlAssessment.Contracts;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
using Microsoft.SqlTools.SqlCore.Utility;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.SqlAssessment
@@ -129,7 +129,7 @@ INSERT INTO [dbo].[AssessmentResult] ([CheckName],[CheckId],[RulesetName],[Rules
{
sb.Append(
$@"
('{CUtils.EscapeStringSQuote(item.DisplayName)}','{CUtils.EscapeStringSQuote(item.CheckId)}','{CUtils.EscapeStringSQuote(item.RulesetName)}','{item.RulesetVersion}','{item.Level}','{CUtils.EscapeStringSQuote(item.Message)}','{CUtils.EscapeStringSQuote(item.TargetName)}','{item.TargetType}','{CUtils.EscapeStringSQuote(item.HelpLink)}','{item.Timestamp:yyyy-MM-dd hh:mm:ss.fff zzz}'),");
('{StringUtils.EscapeStringSQuote(item.DisplayName)}','{StringUtils.EscapeStringSQuote(item.CheckId)}','{StringUtils.EscapeStringSQuote(item.RulesetName)}','{item.RulesetVersion}','{item.Level}','{StringUtils.EscapeStringSQuote(item.Message)}','{StringUtils.EscapeStringSQuote(item.TargetName)}','{item.TargetType}','{StringUtils.EscapeStringSQuote(item.HelpLink)}','{item.Timestamp:yyyy-MM-dd hh:mm:ss.fff zzz}'),");
}
}

View File

@@ -1,32 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
namespace Microsoft.SqlTools.ServiceLayer.Utility
{
/// <summary>
/// Common Constant values used across multiple services
/// </summary>
public static class CommonConstants
{
public const string MasterDatabaseName = "master";
public const string MsdbDatabaseName = "msdb";
public const string ModelDatabaseName = "model";
public const string TempDbDatabaseName = "tempdb";
public const string DefaultBatchSeperator = "GO";
// Database scoped configurations property values
public const string DatabaseScopedConfigurations_Value_On = "ON";
public const string DatabaseScopedConfigurations_Value_Off = "OFF";
public const string DatabaseScopedConfigurations_Value_Primary = "PRIMARY";
public const string DatabaseScopedConfigurations_Value_When_supported = "WHEN_SUPPORTED";
public const string DatabaseScopedConfigurations_Value_Fail_Unsupported = "FAIL_UNSUPPORTED";
public const string DatabaseScopedConfigurations_Value_Enabled = "ENABLED";
public const string DatabaseScopedConfigurations_Value_Disabled = "DISABLED";
}
}

View File

@@ -10,6 +10,7 @@ using Microsoft.SqlServer.Management.Dmf;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.SqlCore.Utility;
using System;
using System.Collections.Generic;
using System.Data;
@@ -37,13 +38,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
public static string AddStringParameterForInsert(string paramValue)
{
string value = string.IsNullOrWhiteSpace(paramValue) ? paramValue : CUtils.EscapeStringSQuote(paramValue);
string value = string.IsNullOrWhiteSpace(paramValue) ? paramValue : StringUtils.EscapeStringSQuote(paramValue);
return $"'{value}'";
}
public static string AddStringParameterForUpdate(string columnName, string paramValue)
{
string value = string.IsNullOrWhiteSpace(paramValue) ? paramValue : CUtils.EscapeStringSQuote(paramValue);
string value = string.IsNullOrWhiteSpace(paramValue) ? paramValue : StringUtils.EscapeStringSQuote(paramValue);
return $"{columnName} = N'{value}'";
}