mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-22 09:35:38 -05:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#nullable disable
|
||||
|
||||
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
|
||||
using Microsoft.SqlTools.SqlCore.Metadata;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Metadata.Contracts
|
||||
{
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
";
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
#>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
#>
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
#>
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}'),");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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}'";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user