From d903ba56a90743ed71a50149ad0b9fc8f4ceddb5 Mon Sep 17 00:00:00 2001 From: Leila Lali Date: Tue, 11 Apr 2017 15:50:20 -0700 Subject: [PATCH] Object Explorer Service (#311) * moving OE service from an old branch --- .../Hosting/IHostedService.cs | 2 +- .../Connection/ConnectionService.cs | 2 +- .../HostLoader.cs | 2 + .../Localization/sr.cs | 1793 +++++++++ .../Localization/sr.es.resx | 850 ++-- .../Localization/sr.resx | 652 ++++ .../Localization/sr.strings | 330 ++ .../Localization/sr.xlf | 2025 +++++++--- .../Microsoft.SqlTools.ServiceLayer.xproj | 39 +- .../Contracts/CreateSessionRequest.cs | 45 + .../ObjectExplorer/Contracts/ExpandRequest.cs | 56 + .../ObjectExplorer/Contracts/NodeInfo.cs | 40 + .../Contracts/RefreshRequest.cs | 39 + .../ObjectExplorer/Nodes/ChildFactory.cs | 39 + .../Nodes/NodeObservableCollection.cs | 177 + .../ObjectExplorer/Nodes/NodeTypes.cs | 141 + .../ObjectExplorer/Nodes/TreeNode.cs | 329 ++ .../Nodes/TreeNodeWithContext.cs | 11 + .../ObjectExplorer/Nodes/ValidForFlag.cs | 28 + .../ObjectExplorer/ObjectExplorerService.cs | 344 ++ .../ObjectExplorer/ObjectExplorerUtils.cs | 76 + .../SmoModel/DatabaseInstanceTreeNode.cs | 30 + .../ObjectExplorer/SmoModel/FolderNode.cs | 33 + .../ObjectExplorer/SmoModel/ServerNode.cs | 192 + .../SmoModel/SmoChildFactoryBase.cs | 161 + .../SmoModel/SmoCollectionWrapper.cs | 57 + .../ObjectExplorer/SmoModel/SmoQuerier.cs | 42 + .../SmoModel/SmoQueryContext.cs | 102 + .../ObjectExplorer/SmoModel/SmoQueryModel.cs | 1583 ++++++++ .../ObjectExplorer/SmoModel/SmoQueryModel.tt | 215 + .../SmoModel/SmoQueryModelDefinition.xml | 146 + .../ObjectExplorer/SmoModel/SmoTreeNode.cs | 90 + .../SmoModel/SystemDataTypeChildFactories.cs | 208 + .../SmoModel/TreeNodeDefinition.xml | 396 ++ .../SmoModel/TreeNodeGenerator.cs | 3466 +++++++++++++++++ .../SmoModel/TreeNodeGenerator.tt | 387 ++ .../Properties/AssemblyInfo.cs | 3 + .../ServiceHost.cs | 14 + .../Utility/CommonConstants.cs | 19 + .../ObjectExplorerServiceTests.cs | 215 + .../Utility/LiveConnectionHelper.cs | 38 +- .../Scripts/AdventureWorks.sql | Bin 0 -> 1321364 bytes .../Scripts/Scripts.cs | 9 +- .../SqlTestDb.cs | 9 +- .../TestScripts/ColumnstoreindexSql16.sql | 34 + .../TestScripts/FileTableTest.sql | 103 + .../TestScripts/NumberedProcedures.sql | 62 + .../TestScripts/Sql_2016_Additions.sql | 275 ++ .../TestScripts/Sql_Additions.sql | 298 ++ .../TestServiceProvider.cs | 10 + .../project.json | 3 +- .../ObjectExplorer/NodeTests.cs | 369 ++ .../ObjectExplorerServiceTests.cs | 151 + .../ObjectExplorer/ObjectExplorerTestBase.cs | 45 + .../ObjectExplorer/SmoQueryModelTests.cs | 65 + .../ServiceHost/SrTests.cs | 163 + .../Utility/ProtocolEndpointMocks.cs | 33 + .../Utility/TestObjects.cs | 24 + 58 files changed, 15013 insertions(+), 1057 deletions(-) create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/CreateSessionRequest.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/ExpandRequest.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/NodeInfo.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/RefreshRequest.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ChildFactory.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeObservableCollection.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeTypes.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNodeWithContext.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ValidForFlag.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerService.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerUtils.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/DatabaseInstanceTreeNode.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/FolderNode.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/ServerNode.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoCollectionWrapper.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQuerier.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryContext.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.tt create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModelDefinition.xml create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNode.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SystemDataTypeChildFactories.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeDefinition.xml create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.tt create mode 100644 src/Microsoft.SqlTools.ServiceLayer/Utility/CommonConstants.cs create mode 100644 test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectExplorer/ObjectExplorerServiceTests.cs create mode 100644 test/Microsoft.SqlTools.ServiceLayer.Test.Common/Scripts/AdventureWorks.sql create mode 100644 test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/ColumnstoreindexSql16.sql create mode 100644 test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/FileTableTest.sql create mode 100644 test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/NumberedProcedures.sql create mode 100644 test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/Sql_2016_Additions.sql create mode 100644 test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/Sql_Additions.sql create mode 100644 test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/NodeTests.cs create mode 100644 test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs create mode 100644 test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerTestBase.cs create mode 100644 test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/SmoQueryModelTests.cs create mode 100644 test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/ProtocolEndpointMocks.cs diff --git a/src/Microsoft.SqlTools.Hosting/Hosting/IHostedService.cs b/src/Microsoft.SqlTools.Hosting/Hosting/IHostedService.cs index 66d63fdc..25443404 100644 --- a/src/Microsoft.SqlTools.Hosting/Hosting/IHostedService.cs +++ b/src/Microsoft.SqlTools.Hosting/Hosting/IHostedService.cs @@ -52,7 +52,7 @@ namespace Microsoft.SqlTools.Hosting protected IMultiServiceProvider ServiceProvider { get; private set; } - public void SetServiceProvider(IMultiServiceProvider provider) + public virtual void SetServiceProvider(IMultiServiceProvider provider) { ServiceProvider = provider; } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs index 9901952b..cf48aba0 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs @@ -176,7 +176,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection /// /// Open a connection with the specified ConnectParams /// - public async Task Connect(ConnectParams connectionParams) + public virtual async Task Connect(ConnectParams connectionParams) { // Validate parameters ConnectionCompleteParams validationResults = ValidateConnectParams(connectionParams); diff --git a/src/Microsoft.SqlTools.ServiceLayer/HostLoader.cs b/src/Microsoft.SqlTools.ServiceLayer/HostLoader.cs index aa6fac63..a69eec00 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/HostLoader.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/HostLoader.cs @@ -11,6 +11,7 @@ using Microsoft.SqlTools.ServiceLayer.EditData; using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.LanguageServices; using Microsoft.SqlTools.ServiceLayer.Metadata; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; using Microsoft.SqlTools.ServiceLayer.QueryExecution; using Microsoft.SqlTools.ServiceLayer.Scripting; using Microsoft.SqlTools.ServiceLayer.SqlContext; @@ -85,6 +86,7 @@ namespace Microsoft.SqlTools.ServiceLayer serviceProvider.RegisterSingleService(ScriptingService.Instance); InitializeHostedServices(serviceProvider, serviceHost); + serviceHost.ServiceProvider = serviceProvider; serviceHost.InitializeRequestHandlers(); } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs index 049a67af..c8ee4d09 100755 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs @@ -853,6 +853,1310 @@ namespace Microsoft.SqlTools.ServiceLayer } } + public static string TreeNodeError + { + get + { + return Keys.GetString(Keys.TreeNodeError); + } + } + + public static string ServerNodeConnectionError + { + get + { + return Keys.GetString(Keys.ServerNodeConnectionError); + } + } + + public static string SchemaHierarchy_Aggregates + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Aggregates); + } + } + + public static string SchemaHierarchy_ServerRoles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerRoles); + } + } + + public static string SchemaHierarchy_ApplicationRoles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ApplicationRoles); + } + } + + public static string SchemaHierarchy_Assemblies + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Assemblies); + } + } + + public static string SchemaHierarchy_AssemblyFiles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_AssemblyFiles); + } + } + + public static string SchemaHierarchy_AsymmetricKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_AsymmetricKeys); + } + } + + public static string SchemaHierarchy_DatabaseAsymmetricKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseAsymmetricKeys); + } + } + + public static string SchemaHierarchy_DataCompressionOptions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DataCompressionOptions); + } + } + + public static string SchemaHierarchy_Certificates + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Certificates); + } + } + + public static string SchemaHierarchy_FileTables + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_FileTables); + } + } + + public static string SchemaHierarchy_DatabaseCertificates + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseCertificates); + } + } + + public static string SchemaHierarchy_CheckConstraints + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_CheckConstraints); + } + } + + public static string SchemaHierarchy_Columns + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Columns); + } + } + + public static string SchemaHierarchy_Constraints + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Constraints); + } + } + + public static string SchemaHierarchy_Contracts + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Contracts); + } + } + + public static string SchemaHierarchy_Credentials + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Credentials); + } + } + + public static string SchemaHierarchy_ErrorMessages + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ErrorMessages); + } + } + + public static string SchemaHierarchy_ServerRoleMembership + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerRoleMembership); + } + } + + public static string SchemaHierarchy_DatabaseOptions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseOptions); + } + } + + public static string SchemaHierarchy_DatabaseRoles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseRoles); + } + } + + public static string SchemaHierarchy_RoleMemberships + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_RoleMemberships); + } + } + + public static string SchemaHierarchy_DatabaseTriggers + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseTriggers); + } + } + + public static string SchemaHierarchy_DefaultConstraints + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DefaultConstraints); + } + } + + public static string SchemaHierarchy_Defaults + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Defaults); + } + } + + public static string SchemaHierarchy_Sequences + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Sequences); + } + } + + public static string SchemaHierarchy_Endpoints + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Endpoints); + } + } + + public static string SchemaHierarchy_EventNotifications + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_EventNotifications); + } + } + + public static string SchemaHierarchy_ServerEventNotifications + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerEventNotifications); + } + } + + public static string SchemaHierarchy_ExtendedProperties + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ExtendedProperties); + } + } + + public static string SchemaHierarchy_FileGroups + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_FileGroups); + } + } + + public static string SchemaHierarchy_ForeignKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ForeignKeys); + } + } + + public static string SchemaHierarchy_FullTextCatalogs + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_FullTextCatalogs); + } + } + + public static string SchemaHierarchy_FullTextIndexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_FullTextIndexes); + } + } + + public static string SchemaHierarchy_Functions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Functions); + } + } + + public static string SchemaHierarchy_Indexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Indexes); + } + } + + public static string SchemaHierarchy_InlineFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_InlineFunctions); + } + } + + public static string SchemaHierarchy_Keys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Keys); + } + } + + public static string SchemaHierarchy_LinkedServers + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_LinkedServers); + } + } + + public static string SchemaHierarchy_LinkedServerLogins + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_LinkedServerLogins); + } + } + + public static string SchemaHierarchy_Logins + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Logins); + } + } + + public static string SchemaHierarchy_MasterKey + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_MasterKey); + } + } + + public static string SchemaHierarchy_MasterKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_MasterKeys); + } + } + + public static string SchemaHierarchy_MessageTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_MessageTypes); + } + } + + public static string SchemaHierarchy_MultiSelectFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_MultiSelectFunctions); + } + } + + public static string SchemaHierarchy_Parameters + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Parameters); + } + } + + public static string SchemaHierarchy_PartitionFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_PartitionFunctions); + } + } + + public static string SchemaHierarchy_PartitionSchemes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_PartitionSchemes); + } + } + + public static string SchemaHierarchy_Permissions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Permissions); + } + } + + public static string SchemaHierarchy_PrimaryKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_PrimaryKeys); + } + } + + public static string SchemaHierarchy_Programmability + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Programmability); + } + } + + public static string SchemaHierarchy_Queues + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Queues); + } + } + + public static string SchemaHierarchy_RemoteServiceBindings + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_RemoteServiceBindings); + } + } + + public static string SchemaHierarchy_ReturnedColumns + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ReturnedColumns); + } + } + + public static string SchemaHierarchy_Roles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Roles); + } + } + + public static string SchemaHierarchy_Routes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Routes); + } + } + + public static string SchemaHierarchy_Rules + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Rules); + } + } + + public static string SchemaHierarchy_Schemas + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Schemas); + } + } + + public static string SchemaHierarchy_Security + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Security); + } + } + + public static string SchemaHierarchy_ServerObjects + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerObjects); + } + } + + public static string SchemaHierarchy_Management + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Management); + } + } + + public static string SchemaHierarchy_ServerTriggers + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerTriggers); + } + } + + public static string SchemaHierarchy_ServiceBroker + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServiceBroker); + } + } + + public static string SchemaHierarchy_Services + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Services); + } + } + + public static string SchemaHierarchy_Signatures + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Signatures); + } + } + + public static string SchemaHierarchy_LogFiles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_LogFiles); + } + } + + public static string SchemaHierarchy_Statistics + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Statistics); + } + } + + public static string SchemaHierarchy_Storage + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Storage); + } + } + + public static string SchemaHierarchy_StoredProcedures + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_StoredProcedures); + } + } + + public static string SchemaHierarchy_SymmetricKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SymmetricKeys); + } + } + + public static string SchemaHierarchy_Synonyms + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Synonyms); + } + } + + public static string SchemaHierarchy_Tables + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Tables); + } + } + + public static string SchemaHierarchy_Triggers + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Triggers); + } + } + + public static string SchemaHierarchy_Types + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Types); + } + } + + public static string SchemaHierarchy_UniqueKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_UniqueKeys); + } + } + + public static string SchemaHierarchy_UserDefinedDataTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_UserDefinedDataTypes); + } + } + + public static string SchemaHierarchy_UserDefinedTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_UserDefinedTypes); + } + } + + public static string SchemaHierarchy_Users + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Users); + } + } + + public static string SchemaHierarchy_Views + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Views); + } + } + + public static string SchemaHierarchy_XmlIndexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_XmlIndexes); + } + } + + public static string SchemaHierarchy_XMLSchemaCollections + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_XMLSchemaCollections); + } + } + + public static string SchemaHierarchy_UserDefinedTableTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_UserDefinedTableTypes); + } + } + + public static string SchemaHierarchy_FilegroupFiles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_FilegroupFiles); + } + } + + public static string MissingCaption + { + get + { + return Keys.GetString(Keys.MissingCaption); + } + } + + public static string SchemaHierarchy_BrokerPriorities + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_BrokerPriorities); + } + } + + public static string SchemaHierarchy_CryptographicProviders + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_CryptographicProviders); + } + } + + public static string SchemaHierarchy_DatabaseAuditSpecifications + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseAuditSpecifications); + } + } + + public static string SchemaHierarchy_DatabaseEncryptionKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseEncryptionKeys); + } + } + + public static string SchemaHierarchy_EventSessions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_EventSessions); + } + } + + public static string SchemaHierarchy_FullTextStopLists + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_FullTextStopLists); + } + } + + public static string SchemaHierarchy_ResourcePools + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ResourcePools); + } + } + + public static string SchemaHierarchy_ServerAudits + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerAudits); + } + } + + public static string SchemaHierarchy_ServerAuditSpecifications + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerAuditSpecifications); + } + } + + public static string SchemaHierarchy_SpatialIndexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SpatialIndexes); + } + } + + public static string SchemaHierarchy_WorkloadGroups + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_WorkloadGroups); + } + } + + public static string SchemaHierarchy_SqlFiles + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SqlFiles); + } + } + + public static string SchemaHierarchy_ServerFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerFunctions); + } + } + + public static string SchemaHierarchy_SqlType + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SqlType); + } + } + + public static string SchemaHierarchy_ServerOptions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerOptions); + } + } + + public static string SchemaHierarchy_DatabaseDiagrams + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseDiagrams); + } + } + + public static string SchemaHierarchy_SystemTables + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemTables); + } + } + + public static string SchemaHierarchy_Databases + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_Databases); + } + } + + public static string SchemaHierarchy_SystemContracts + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemContracts); + } + } + + public static string SchemaHierarchy_SystemDatabases + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemDatabases); + } + } + + public static string SchemaHierarchy_SystemMessageTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemMessageTypes); + } + } + + public static string SchemaHierarchy_SystemQueues + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemQueues); + } + } + + public static string SchemaHierarchy_SystemServices + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemServices); + } + } + + public static string SchemaHierarchy_SystemStoredProcedures + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemStoredProcedures); + } + } + + public static string SchemaHierarchy_SystemViews + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemViews); + } + } + + public static string SchemaHierarchy_DataTierApplications + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DataTierApplications); + } + } + + public static string SchemaHierarchy_ExtendedStoredProcedures + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ExtendedStoredProcedures); + } + } + + public static string SchemaHierarchy_SystemAggregateFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemAggregateFunctions); + } + } + + public static string SchemaHierarchy_SystemApproximateNumerics + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemApproximateNumerics); + } + } + + public static string SchemaHierarchy_SystemBinaryStrings + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemBinaryStrings); + } + } + + public static string SchemaHierarchy_SystemCharacterStrings + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemCharacterStrings); + } + } + + public static string SchemaHierarchy_SystemCLRDataTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemCLRDataTypes); + } + } + + public static string SchemaHierarchy_SystemConfigurationFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemConfigurationFunctions); + } + } + + public static string SchemaHierarchy_SystemCursorFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemCursorFunctions); + } + } + + public static string SchemaHierarchy_SystemDataTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemDataTypes); + } + } + + public static string SchemaHierarchy_SystemDateAndTime + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemDateAndTime); + } + } + + public static string SchemaHierarchy_SystemDateAndTimeFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemDateAndTimeFunctions); + } + } + + public static string SchemaHierarchy_SystemExactNumerics + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemExactNumerics); + } + } + + public static string SchemaHierarchy_SystemFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemFunctions); + } + } + + public static string SchemaHierarchy_SystemHierarchyIdFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemHierarchyIdFunctions); + } + } + + public static string SchemaHierarchy_SystemMathematicalFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemMathematicalFunctions); + } + } + + public static string SchemaHierarchy_SystemMetadataFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemMetadataFunctions); + } + } + + public static string SchemaHierarchy_SystemOtherDataTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemOtherDataTypes); + } + } + + public static string SchemaHierarchy_SystemOtherFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemOtherFunctions); + } + } + + public static string SchemaHierarchy_SystemRowsetFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemRowsetFunctions); + } + } + + public static string SchemaHierarchy_SystemSecurityFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemSecurityFunctions); + } + } + + public static string SchemaHierarchy_SystemSpatialDataTypes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemSpatialDataTypes); + } + } + + public static string SchemaHierarchy_SystemStringFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemStringFunctions); + } + } + + public static string SchemaHierarchy_SystemSystemStatisticalFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemSystemStatisticalFunctions); + } + } + + public static string SchemaHierarchy_SystemTextAndImageFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemTextAndImageFunctions); + } + } + + public static string SchemaHierarchy_SystemUnicodeCharacterStrings + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemUnicodeCharacterStrings); + } + } + + public static string SchemaHierarchy_AggregateFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_AggregateFunctions); + } + } + + public static string SchemaHierarchy_ScalarValuedFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ScalarValuedFunctions); + } + } + + public static string SchemaHierarchy_TableValuedFunctions + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_TableValuedFunctions); + } + } + + public static string SchemaHierarchy_SystemExtendedStoredProcedures + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SystemExtendedStoredProcedures); + } + } + + public static string SchemaHierarchy_BuiltInType + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_BuiltInType); + } + } + + public static string SchemaHierarchy_BuiltInServerRole + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_BuiltInServerRole); + } + } + + public static string SchemaHierarchy_UserWithPassword + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_UserWithPassword); + } + } + + public static string SchemaHierarchy_SearchPropertyList + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SearchPropertyList); + } + } + + public static string SchemaHierarchy_SecurityPolicies + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SecurityPolicies); + } + } + + public static string SchemaHierarchy_SecurityPredicates + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SecurityPredicates); + } + } + + public static string SchemaHierarchy_ServerRole + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerRole); + } + } + + public static string SchemaHierarchy_SearchPropertyLists + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SearchPropertyLists); + } + } + + public static string SchemaHierarchy_ColumnStoreIndexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ColumnStoreIndexes); + } + } + + public static string SchemaHierarchy_TableTypeIndexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_TableTypeIndexes); + } + } + + public static string SchemaHierarchy_ServerInstance + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ServerInstance); + } + } + + public static string SchemaHierarchy_SelectiveXmlIndexes + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SelectiveXmlIndexes); + } + } + + public static string SchemaHierarchy_XmlNamespaces + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_XmlNamespaces); + } + } + + public static string SchemaHierarchy_XmlTypedPromotedPaths + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_XmlTypedPromotedPaths); + } + } + + public static string SchemaHierarchy_SqlTypedPromotedPaths + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_SqlTypedPromotedPaths); + } + } + + public static string SchemaHierarchy_DatabaseScopedCredentials + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_DatabaseScopedCredentials); + } + } + + public static string SchemaHierarchy_ExternalDataSources + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ExternalDataSources); + } + } + + public static string SchemaHierarchy_ExternalFileFormats + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ExternalFileFormats); + } + } + + public static string SchemaHierarchy_ExternalResources + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ExternalResources); + } + } + + public static string SchemaHierarchy_ExternalTables + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ExternalTables); + } + } + + public static string SchemaHierarchy_AlwaysEncryptedKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_AlwaysEncryptedKeys); + } + } + + public static string SchemaHierarchy_ColumnMasterKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ColumnMasterKeys); + } + } + + public static string SchemaHierarchy_ColumnEncryptionKeys + { + get + { + return Keys.GetString(Keys.SchemaHierarchy_ColumnEncryptionKeys); + } + } + public static string ConnectionServiceListDbErrorNotConnected(string uri) { return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri); @@ -1282,6 +2586,495 @@ namespace Microsoft.SqlTools.ServiceLayer public const string SqlScriptFormatterDecimalMissingPrecision = "SqlScriptFormatterDecimalMissingPrecision"; + public const string TreeNodeError = "TreeNodeError"; + + + public const string ServerNodeConnectionError = "ServerNodeConnectionError"; + + + public const string SchemaHierarchy_Aggregates = "SchemaHierarchy_Aggregates"; + + + public const string SchemaHierarchy_ServerRoles = "SchemaHierarchy_ServerRoles"; + + + public const string SchemaHierarchy_ApplicationRoles = "SchemaHierarchy_ApplicationRoles"; + + + public const string SchemaHierarchy_Assemblies = "SchemaHierarchy_Assemblies"; + + + public const string SchemaHierarchy_AssemblyFiles = "SchemaHierarchy_AssemblyFiles"; + + + public const string SchemaHierarchy_AsymmetricKeys = "SchemaHierarchy_AsymmetricKeys"; + + + public const string SchemaHierarchy_DatabaseAsymmetricKeys = "SchemaHierarchy_DatabaseAsymmetricKeys"; + + + public const string SchemaHierarchy_DataCompressionOptions = "SchemaHierarchy_DataCompressionOptions"; + + + public const string SchemaHierarchy_Certificates = "SchemaHierarchy_Certificates"; + + + public const string SchemaHierarchy_FileTables = "SchemaHierarchy_FileTables"; + + + public const string SchemaHierarchy_DatabaseCertificates = "SchemaHierarchy_DatabaseCertificates"; + + + public const string SchemaHierarchy_CheckConstraints = "SchemaHierarchy_CheckConstraints"; + + + public const string SchemaHierarchy_Columns = "SchemaHierarchy_Columns"; + + + public const string SchemaHierarchy_Constraints = "SchemaHierarchy_Constraints"; + + + public const string SchemaHierarchy_Contracts = "SchemaHierarchy_Contracts"; + + + public const string SchemaHierarchy_Credentials = "SchemaHierarchy_Credentials"; + + + public const string SchemaHierarchy_ErrorMessages = "SchemaHierarchy_ErrorMessages"; + + + public const string SchemaHierarchy_ServerRoleMembership = "SchemaHierarchy_ServerRoleMembership"; + + + public const string SchemaHierarchy_DatabaseOptions = "SchemaHierarchy_DatabaseOptions"; + + + public const string SchemaHierarchy_DatabaseRoles = "SchemaHierarchy_DatabaseRoles"; + + + public const string SchemaHierarchy_RoleMemberships = "SchemaHierarchy_RoleMemberships"; + + + public const string SchemaHierarchy_DatabaseTriggers = "SchemaHierarchy_DatabaseTriggers"; + + + public const string SchemaHierarchy_DefaultConstraints = "SchemaHierarchy_DefaultConstraints"; + + + public const string SchemaHierarchy_Defaults = "SchemaHierarchy_Defaults"; + + + public const string SchemaHierarchy_Sequences = "SchemaHierarchy_Sequences"; + + + public const string SchemaHierarchy_Endpoints = "SchemaHierarchy_Endpoints"; + + + public const string SchemaHierarchy_EventNotifications = "SchemaHierarchy_EventNotifications"; + + + public const string SchemaHierarchy_ServerEventNotifications = "SchemaHierarchy_ServerEventNotifications"; + + + public const string SchemaHierarchy_ExtendedProperties = "SchemaHierarchy_ExtendedProperties"; + + + public const string SchemaHierarchy_FileGroups = "SchemaHierarchy_FileGroups"; + + + public const string SchemaHierarchy_ForeignKeys = "SchemaHierarchy_ForeignKeys"; + + + public const string SchemaHierarchy_FullTextCatalogs = "SchemaHierarchy_FullTextCatalogs"; + + + public const string SchemaHierarchy_FullTextIndexes = "SchemaHierarchy_FullTextIndexes"; + + + public const string SchemaHierarchy_Functions = "SchemaHierarchy_Functions"; + + + public const string SchemaHierarchy_Indexes = "SchemaHierarchy_Indexes"; + + + public const string SchemaHierarchy_InlineFunctions = "SchemaHierarchy_InlineFunctions"; + + + public const string SchemaHierarchy_Keys = "SchemaHierarchy_Keys"; + + + public const string SchemaHierarchy_LinkedServers = "SchemaHierarchy_LinkedServers"; + + + public const string SchemaHierarchy_LinkedServerLogins = "SchemaHierarchy_LinkedServerLogins"; + + + public const string SchemaHierarchy_Logins = "SchemaHierarchy_Logins"; + + + public const string SchemaHierarchy_MasterKey = "SchemaHierarchy_MasterKey"; + + + public const string SchemaHierarchy_MasterKeys = "SchemaHierarchy_MasterKeys"; + + + public const string SchemaHierarchy_MessageTypes = "SchemaHierarchy_MessageTypes"; + + + public const string SchemaHierarchy_MultiSelectFunctions = "SchemaHierarchy_MultiSelectFunctions"; + + + public const string SchemaHierarchy_Parameters = "SchemaHierarchy_Parameters"; + + + public const string SchemaHierarchy_PartitionFunctions = "SchemaHierarchy_PartitionFunctions"; + + + public const string SchemaHierarchy_PartitionSchemes = "SchemaHierarchy_PartitionSchemes"; + + + public const string SchemaHierarchy_Permissions = "SchemaHierarchy_Permissions"; + + + public const string SchemaHierarchy_PrimaryKeys = "SchemaHierarchy_PrimaryKeys"; + + + public const string SchemaHierarchy_Programmability = "SchemaHierarchy_Programmability"; + + + public const string SchemaHierarchy_Queues = "SchemaHierarchy_Queues"; + + + public const string SchemaHierarchy_RemoteServiceBindings = "SchemaHierarchy_RemoteServiceBindings"; + + + public const string SchemaHierarchy_ReturnedColumns = "SchemaHierarchy_ReturnedColumns"; + + + public const string SchemaHierarchy_Roles = "SchemaHierarchy_Roles"; + + + public const string SchemaHierarchy_Routes = "SchemaHierarchy_Routes"; + + + public const string SchemaHierarchy_Rules = "SchemaHierarchy_Rules"; + + + public const string SchemaHierarchy_Schemas = "SchemaHierarchy_Schemas"; + + + public const string SchemaHierarchy_Security = "SchemaHierarchy_Security"; + + + public const string SchemaHierarchy_ServerObjects = "SchemaHierarchy_ServerObjects"; + + + public const string SchemaHierarchy_Management = "SchemaHierarchy_Management"; + + + public const string SchemaHierarchy_ServerTriggers = "SchemaHierarchy_ServerTriggers"; + + + public const string SchemaHierarchy_ServiceBroker = "SchemaHierarchy_ServiceBroker"; + + + public const string SchemaHierarchy_Services = "SchemaHierarchy_Services"; + + + public const string SchemaHierarchy_Signatures = "SchemaHierarchy_Signatures"; + + + public const string SchemaHierarchy_LogFiles = "SchemaHierarchy_LogFiles"; + + + public const string SchemaHierarchy_Statistics = "SchemaHierarchy_Statistics"; + + + public const string SchemaHierarchy_Storage = "SchemaHierarchy_Storage"; + + + public const string SchemaHierarchy_StoredProcedures = "SchemaHierarchy_StoredProcedures"; + + + public const string SchemaHierarchy_SymmetricKeys = "SchemaHierarchy_SymmetricKeys"; + + + public const string SchemaHierarchy_Synonyms = "SchemaHierarchy_Synonyms"; + + + public const string SchemaHierarchy_Tables = "SchemaHierarchy_Tables"; + + + public const string SchemaHierarchy_Triggers = "SchemaHierarchy_Triggers"; + + + public const string SchemaHierarchy_Types = "SchemaHierarchy_Types"; + + + public const string SchemaHierarchy_UniqueKeys = "SchemaHierarchy_UniqueKeys"; + + + public const string SchemaHierarchy_UserDefinedDataTypes = "SchemaHierarchy_UserDefinedDataTypes"; + + + public const string SchemaHierarchy_UserDefinedTypes = "SchemaHierarchy_UserDefinedTypes"; + + + public const string SchemaHierarchy_Users = "SchemaHierarchy_Users"; + + + public const string SchemaHierarchy_Views = "SchemaHierarchy_Views"; + + + public const string SchemaHierarchy_XmlIndexes = "SchemaHierarchy_XmlIndexes"; + + + public const string SchemaHierarchy_XMLSchemaCollections = "SchemaHierarchy_XMLSchemaCollections"; + + + public const string SchemaHierarchy_UserDefinedTableTypes = "SchemaHierarchy_UserDefinedTableTypes"; + + + public const string SchemaHierarchy_FilegroupFiles = "SchemaHierarchy_FilegroupFiles"; + + + public const string MissingCaption = "MissingCaption"; + + + public const string SchemaHierarchy_BrokerPriorities = "SchemaHierarchy_BrokerPriorities"; + + + public const string SchemaHierarchy_CryptographicProviders = "SchemaHierarchy_CryptographicProviders"; + + + public const string SchemaHierarchy_DatabaseAuditSpecifications = "SchemaHierarchy_DatabaseAuditSpecifications"; + + + public const string SchemaHierarchy_DatabaseEncryptionKeys = "SchemaHierarchy_DatabaseEncryptionKeys"; + + + public const string SchemaHierarchy_EventSessions = "SchemaHierarchy_EventSessions"; + + + public const string SchemaHierarchy_FullTextStopLists = "SchemaHierarchy_FullTextStopLists"; + + + public const string SchemaHierarchy_ResourcePools = "SchemaHierarchy_ResourcePools"; + + + public const string SchemaHierarchy_ServerAudits = "SchemaHierarchy_ServerAudits"; + + + public const string SchemaHierarchy_ServerAuditSpecifications = "SchemaHierarchy_ServerAuditSpecifications"; + + + public const string SchemaHierarchy_SpatialIndexes = "SchemaHierarchy_SpatialIndexes"; + + + public const string SchemaHierarchy_WorkloadGroups = "SchemaHierarchy_WorkloadGroups"; + + + public const string SchemaHierarchy_SqlFiles = "SchemaHierarchy_SqlFiles"; + + + public const string SchemaHierarchy_ServerFunctions = "SchemaHierarchy_ServerFunctions"; + + + public const string SchemaHierarchy_SqlType = "SchemaHierarchy_SqlType"; + + + public const string SchemaHierarchy_ServerOptions = "SchemaHierarchy_ServerOptions"; + + + public const string SchemaHierarchy_DatabaseDiagrams = "SchemaHierarchy_DatabaseDiagrams"; + + + public const string SchemaHierarchy_SystemTables = "SchemaHierarchy_SystemTables"; + + + public const string SchemaHierarchy_Databases = "SchemaHierarchy_Databases"; + + + public const string SchemaHierarchy_SystemContracts = "SchemaHierarchy_SystemContracts"; + + + public const string SchemaHierarchy_SystemDatabases = "SchemaHierarchy_SystemDatabases"; + + + public const string SchemaHierarchy_SystemMessageTypes = "SchemaHierarchy_SystemMessageTypes"; + + + public const string SchemaHierarchy_SystemQueues = "SchemaHierarchy_SystemQueues"; + + + public const string SchemaHierarchy_SystemServices = "SchemaHierarchy_SystemServices"; + + + public const string SchemaHierarchy_SystemStoredProcedures = "SchemaHierarchy_SystemStoredProcedures"; + + + public const string SchemaHierarchy_SystemViews = "SchemaHierarchy_SystemViews"; + + + public const string SchemaHierarchy_DataTierApplications = "SchemaHierarchy_DataTierApplications"; + + + public const string SchemaHierarchy_ExtendedStoredProcedures = "SchemaHierarchy_ExtendedStoredProcedures"; + + + public const string SchemaHierarchy_SystemAggregateFunctions = "SchemaHierarchy_SystemAggregateFunctions"; + + + public const string SchemaHierarchy_SystemApproximateNumerics = "SchemaHierarchy_SystemApproximateNumerics"; + + + public const string SchemaHierarchy_SystemBinaryStrings = "SchemaHierarchy_SystemBinaryStrings"; + + + public const string SchemaHierarchy_SystemCharacterStrings = "SchemaHierarchy_SystemCharacterStrings"; + + + public const string SchemaHierarchy_SystemCLRDataTypes = "SchemaHierarchy_SystemCLRDataTypes"; + + + public const string SchemaHierarchy_SystemConfigurationFunctions = "SchemaHierarchy_SystemConfigurationFunctions"; + + + public const string SchemaHierarchy_SystemCursorFunctions = "SchemaHierarchy_SystemCursorFunctions"; + + + public const string SchemaHierarchy_SystemDataTypes = "SchemaHierarchy_SystemDataTypes"; + + + public const string SchemaHierarchy_SystemDateAndTime = "SchemaHierarchy_SystemDateAndTime"; + + + public const string SchemaHierarchy_SystemDateAndTimeFunctions = "SchemaHierarchy_SystemDateAndTimeFunctions"; + + + public const string SchemaHierarchy_SystemExactNumerics = "SchemaHierarchy_SystemExactNumerics"; + + + public const string SchemaHierarchy_SystemFunctions = "SchemaHierarchy_SystemFunctions"; + + + public const string SchemaHierarchy_SystemHierarchyIdFunctions = "SchemaHierarchy_SystemHierarchyIdFunctions"; + + + public const string SchemaHierarchy_SystemMathematicalFunctions = "SchemaHierarchy_SystemMathematicalFunctions"; + + + public const string SchemaHierarchy_SystemMetadataFunctions = "SchemaHierarchy_SystemMetadataFunctions"; + + + public const string SchemaHierarchy_SystemOtherDataTypes = "SchemaHierarchy_SystemOtherDataTypes"; + + + public const string SchemaHierarchy_SystemOtherFunctions = "SchemaHierarchy_SystemOtherFunctions"; + + + public const string SchemaHierarchy_SystemRowsetFunctions = "SchemaHierarchy_SystemRowsetFunctions"; + + + public const string SchemaHierarchy_SystemSecurityFunctions = "SchemaHierarchy_SystemSecurityFunctions"; + + + public const string SchemaHierarchy_SystemSpatialDataTypes = "SchemaHierarchy_SystemSpatialDataTypes"; + + + public const string SchemaHierarchy_SystemStringFunctions = "SchemaHierarchy_SystemStringFunctions"; + + + public const string SchemaHierarchy_SystemSystemStatisticalFunctions = "SchemaHierarchy_SystemSystemStatisticalFunctions"; + + + public const string SchemaHierarchy_SystemTextAndImageFunctions = "SchemaHierarchy_SystemTextAndImageFunctions"; + + + public const string SchemaHierarchy_SystemUnicodeCharacterStrings = "SchemaHierarchy_SystemUnicodeCharacterStrings"; + + + public const string SchemaHierarchy_AggregateFunctions = "SchemaHierarchy_AggregateFunctions"; + + + public const string SchemaHierarchy_ScalarValuedFunctions = "SchemaHierarchy_ScalarValuedFunctions"; + + + public const string SchemaHierarchy_TableValuedFunctions = "SchemaHierarchy_TableValuedFunctions"; + + + public const string SchemaHierarchy_SystemExtendedStoredProcedures = "SchemaHierarchy_SystemExtendedStoredProcedures"; + + + public const string SchemaHierarchy_BuiltInType = "SchemaHierarchy_BuiltInType"; + + + public const string SchemaHierarchy_BuiltInServerRole = "SchemaHierarchy_BuiltInServerRole"; + + + public const string SchemaHierarchy_UserWithPassword = "SchemaHierarchy_UserWithPassword"; + + + public const string SchemaHierarchy_SearchPropertyList = "SchemaHierarchy_SearchPropertyList"; + + + public const string SchemaHierarchy_SecurityPolicies = "SchemaHierarchy_SecurityPolicies"; + + + public const string SchemaHierarchy_SecurityPredicates = "SchemaHierarchy_SecurityPredicates"; + + + public const string SchemaHierarchy_ServerRole = "SchemaHierarchy_ServerRole"; + + + public const string SchemaHierarchy_SearchPropertyLists = "SchemaHierarchy_SearchPropertyLists"; + + + public const string SchemaHierarchy_ColumnStoreIndexes = "SchemaHierarchy_ColumnStoreIndexes"; + + + public const string SchemaHierarchy_TableTypeIndexes = "SchemaHierarchy_TableTypeIndexes"; + + + public const string SchemaHierarchy_ServerInstance = "SchemaHierarchy_ServerInstance"; + + + public const string SchemaHierarchy_SelectiveXmlIndexes = "SchemaHierarchy_SelectiveXmlIndexes"; + + + public const string SchemaHierarchy_XmlNamespaces = "SchemaHierarchy_XmlNamespaces"; + + + public const string SchemaHierarchy_XmlTypedPromotedPaths = "SchemaHierarchy_XmlTypedPromotedPaths"; + + + public const string SchemaHierarchy_SqlTypedPromotedPaths = "SchemaHierarchy_SqlTypedPromotedPaths"; + + + public const string SchemaHierarchy_DatabaseScopedCredentials = "SchemaHierarchy_DatabaseScopedCredentials"; + + + public const string SchemaHierarchy_ExternalDataSources = "SchemaHierarchy_ExternalDataSources"; + + + public const string SchemaHierarchy_ExternalFileFormats = "SchemaHierarchy_ExternalFileFormats"; + + + public const string SchemaHierarchy_ExternalResources = "SchemaHierarchy_ExternalResources"; + + + public const string SchemaHierarchy_ExternalTables = "SchemaHierarchy_ExternalTables"; + + + public const string SchemaHierarchy_AlwaysEncryptedKeys = "SchemaHierarchy_AlwaysEncryptedKeys"; + + + public const string SchemaHierarchy_ColumnMasterKeys = "SchemaHierarchy_ColumnMasterKeys"; + + + public const string SchemaHierarchy_ColumnEncryptionKeys = "SchemaHierarchy_ColumnEncryptionKeys"; + + private Keys() { } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx index c8490030..04bafe16 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx @@ -1,426 +1,426 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Los parámetros de conexión no pueden ser nulos - - - OwnerUri no puede ser nulo ni estar vacío - - - SpecifiedUri '{0}' no tiene una conexión existente - - - El valor '{0}' no es válido para AuthenticationType. Los valores válidos son 'Integrated' y 'SqlLogin'. - - - El valor '{0}' no es válido para ApplicationIntent. Los valores válidos son 'ReadWrite' y 'ReadOnly'. - - - Conexión cancelada - - - OwnerUri no puede ser nulo ni estar vacío - - - El objeto de detalles de conexión no puede ser nulo - - - ServerName no puede ser nulo ni estar vacío - - - {0} no puede ser nulo ni estar vacío cuando se utiliza autenticación SqlLogin - - - Ya se ha completado la consulta, no se puede cancelar - - - La consulta fue cancelada con éxito, pero no se ha podido desechar. No se encontró el URI del propietario. - - - Consulta cancelada por el usuario - - - El lote aún no ha finalizado, - - - Índice de lote no puede ser menor que 0 o mayor que el número de lotes - - - Índice del conjunto de resultados no puede ser menor que 0 o mayor que el número de conjuntos de resultados - - - El número máximo de bytes a devolver debe ser mayor que cero - - - El número máximo de caracteres a devolver debe ser mayor que cero - - - El número máximo de bytes XML a devolver debe ser mayor que cero - - - El método de acceso no puede ser de sólo escritura - - - FileStreamWrapper debe inicializarse antes de realizar operaciones - - - Este FileStreamWrapper no se puede utilizar para escritura. - - - (1 fila afectada) - - - ({0} filas afectadas) - - - Comandos finalizados correctamente. - - - Msg {0}, nivel {1} estado {2}, línea {3} {4} {5} - - - Error en la consulta: {0} - - - (Ningún nombre de columna) - - - La consulta solicitada no existe - - - Este editor no está conectado a una base de datos - - - Una consulta ya está en curso para esta sesión de editor. Por favor, cancelar esta consulta o esperar su finalización. - - - Remitente de eventos de OnInfoMessage debe ser un objeto SqlConnection - - - Lector no puede ser nulo - - - No se puede guardar el resultado hasta que haya finalizado la ejecución de la consulta - - - Error interno al iniciar el guardado de la tarea - - - Una operacion de guardado en la misma ruta se encuentra en curso - - - Error al guardar {0}: {1} - - - No se puede leer el subconjunto, a menos que los resultados se han leído desde el servidor - - - Fila de inicio no puede ser menor que 0 o mayor que el número de filas en el conjunto de resultados - - - La cantidad de filas debe ser un entero positivo - - - No se pudo recuperar el esquema de columna para el conjunto de resultados - - - No se pudo recuperar un plan de ejecución del conjunto de resultados - - - Esta característica actualmente no se admite en la base de datos de SQL Azure y almacén de datos: {0} - - - Se ha producido un error inesperado durante la ejecución de la definición de Peek: {0} - - - No se encontraron resultados. - - - No se pudo obtener ningún objeto asociado a la base de datos. - - - Conéctese a un servidor. - - - Tiempo de espera agotado para esta operación. - - - Esta característica no admite actualmente este tipo de objeto. - - - Posición está fuera del intervalo de la línea de archivo - - - Posición está fuera del intervalo de la columna de la línea {0} - - - Posición de inicio ({0}, {1}) debe preceder o ser igual a la posición final ({2}, {3}) - - - Msg {0}, {1}, nivel de estado {2}, línea {3} - - - Msj {0}, {1}, nivel de estado {2}, procedimiento {3}, línea {4} - - - Msg {0}, nivel {1}, {2} de estado - - - Se produjo un error al procesar el lote. Mensaje de error: {0} - - - ({0} filas afectadas) - - - La ejecución anterior aún no está completa. - - - Se ha producido un error de secuencias de comandos. - - - Se encontró sintaxis incorrecta mientras se estaba analizando {0}. - - - Se ha producido un error grave. - - - La ejecución completó {0} veces... - - - Se canceló la consulta. - - - Se produjo un error mientras se ejecutaba el lote. - - - Se produjo un error mientras se ejecutaba el lote, pero se ha omitido el error. - - - Iniciando bucle de ejecución de {0} veces... - - - No se admite el comando {0}. - - - La variable {0} no se encontró. - - - Error de ejecución de SQL: {0} - - - Ejecución de contenedor del analizador por lotes: {0} se encuentra... en la línea {1}: {2} Descripción: {3} - - - Lote analizador contenedor ejecución motor lote mensaje recibido: mensaje: {0} mensaje detallado: {1} - - - Motor de ejecución de analizador contenedor lote ResultSet procesamiento por lotes: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} - - - Finalizó el elemento ResultSet analizador contenedor ejecución motor los lotes. - - - Cancelando la ejecución por lotes del contenedor del analizador por lotes. - - - Advertencia de scripting. - - - Para obtener más información acerca de este error, vea los temas de solución de problemas en la documentación del producto. - - - El archivo '{0}' se incluyó recursivamente. - - - Falta la marca de final de comentario ' * /'. - - - Sin comilla de cierre después de la cadena de caracteres. - - - Se encontró sintaxis incorrecta al analizar '{0}'. - - - La variable {0} no está definida. - - - prueba - - - No se puede convertir el SqlCodeObject del Tipo {0} al Tipo {1} - - - Sustitución de una cadena vacía por una cadena vacía. - - - Sesión de edición no existe, - - - La consulta no ha finalizado. - - - La consulta no generó un único set de resultados - - - Falló al agregar una nueva fila a la caché de actualización - - - El ID de la fila ingresado, se encuentra fuera del rango de filas de la caché de edición - - - Una actualización está pendiente para esta fila y debe de revertirse primero - - - El ID de la fila ingresado no tiene actualizaciones pendientes - - - La metadata de la tabla o vista no pudo ser encontrada - - - Formato inválido para columna binaria - - - Columnas del tipo boolean deben de ser numéricos 1 o 0, o tipo string true o false - - - Falta un valor requerido de la celda - - - Existe una eliminación pendiente para esta fila, una actualización de celda no puede ser realizada. - - - El ID de la columna debe de estar en el rango de columnas de la consulta. - - - La columna no puede ser editada - - - No se encontró ninguna columna clave - - - Proporcione un nombre de archivo de salida - - - Objeto de base de datos {0} no puede ser usado para modificación. - - - SpecifiedUri '{0}' no tiene alguna conexión por defecto - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Los parámetros de conexión no pueden ser nulos + + + OwnerUri no puede ser nulo ni estar vacío + + + SpecifiedUri '{0}' no tiene una conexión existente + + + El valor '{0}' no es válido para AuthenticationType. Los valores válidos son 'Integrated' y 'SqlLogin'. + + + El valor '{0}' no es válido para ApplicationIntent. Los valores válidos son 'ReadWrite' y 'ReadOnly'. + + + Conexión cancelada + + + OwnerUri no puede ser nulo ni estar vacío + + + El objeto de detalles de conexión no puede ser nulo + + + ServerName no puede ser nulo ni estar vacío + + + {0} no puede ser nulo ni estar vacío cuando se utiliza autenticación SqlLogin + + + Ya se ha completado la consulta, no se puede cancelar + + + La consulta fue cancelada con éxito, pero no se ha podido desechar. No se encontró el URI del propietario. + + + Consulta cancelada por el usuario + + + El lote aún no ha finalizado, + + + Índice de lote no puede ser menor que 0 o mayor que el número de lotes + + + Índice del conjunto de resultados no puede ser menor que 0 o mayor que el número de conjuntos de resultados + + + El número máximo de bytes a devolver debe ser mayor que cero + + + El número máximo de caracteres a devolver debe ser mayor que cero + + + El número máximo de bytes XML a devolver debe ser mayor que cero + + + El método de acceso no puede ser de sólo escritura + + + FileStreamWrapper debe inicializarse antes de realizar operaciones + + + Este FileStreamWrapper no se puede utilizar para escritura. + + + (1 fila afectada) + + + ({0} filas afectadas) + + + Comandos finalizados correctamente. + + + Msg {0}, nivel {1} estado {2}, línea {3} {4} {5} + + + Error en la consulta: {0} + + + (Ningún nombre de columna) + + + La consulta solicitada no existe + + + Este editor no está conectado a una base de datos + + + Una consulta ya está en curso para esta sesión de editor. Por favor, cancelar esta consulta o esperar su finalización. + + + Remitente de eventos de OnInfoMessage debe ser un objeto SqlConnection + + + Lector no puede ser nulo + + + No se puede guardar el resultado hasta que haya finalizado la ejecución de la consulta + + + Error interno al iniciar el guardado de la tarea + + + Una operacion de guardado en la misma ruta se encuentra en curso + + + Error al guardar {0}: {1} + + + No se puede leer el subconjunto, a menos que los resultados se han leído desde el servidor + + + Fila de inicio no puede ser menor que 0 o mayor que el número de filas en el conjunto de resultados + + + La cantidad de filas debe ser un entero positivo + + + No se pudo recuperar el esquema de columna para el conjunto de resultados + + + No se pudo recuperar un plan de ejecución del conjunto de resultados + + + Esta característica actualmente no se admite en la base de datos de SQL Azure y almacén de datos: {0} + + + Se ha producido un error inesperado durante la ejecución de la definición de Peek: {0} + + + No se encontraron resultados. + + + No se pudo obtener ningún objeto asociado a la base de datos. + + + Conéctese a un servidor. + + + Tiempo de espera agotado para esta operación. + + + Esta característica no admite actualmente este tipo de objeto. + + + Posición está fuera del intervalo de la línea de archivo + + + Posición está fuera del intervalo de la columna de la línea {0} + + + Posición de inicio ({0}, {1}) debe preceder o ser igual a la posición final ({2}, {3}) + + + Msg {0}, {1}, nivel de estado {2}, línea {3} + + + Msj {0}, {1}, nivel de estado {2}, procedimiento {3}, línea {4} + + + Msg {0}, nivel {1}, {2} de estado + + + Se produjo un error al procesar el lote. Mensaje de error: {0} + + + ({0} filas afectadas) + + + La ejecución anterior aún no está completa. + + + Se ha producido un error de secuencias de comandos. + + + Se encontró sintaxis incorrecta mientras se estaba analizando {0}. + + + Se ha producido un error grave. + + + La ejecución completó {0} veces... + + + Se canceló la consulta. + + + Se produjo un error mientras se ejecutaba el lote. + + + Se produjo un error mientras se ejecutaba el lote, pero se ha omitido el error. + + + Iniciando bucle de ejecución de {0} veces... + + + No se admite el comando {0}. + + + La variable {0} no se encontró. + + + Error de ejecución de SQL: {0} + + + Ejecución de contenedor del analizador por lotes: {0} se encuentra... en la línea {1}: {2} Descripción: {3} + + + Lote analizador contenedor ejecución motor lote mensaje recibido: mensaje: {0} mensaje detallado: {1} + + + Motor de ejecución de analizador contenedor lote ResultSet procesamiento por lotes: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + Finalizó el elemento ResultSet analizador contenedor ejecución motor los lotes. + + + Cancelando la ejecución por lotes del contenedor del analizador por lotes. + + + Advertencia de scripting. + + + Para obtener más información acerca de este error, vea los temas de solución de problemas en la documentación del producto. + + + El archivo '{0}' se incluyó recursivamente. + + + Falta la marca de final de comentario ' * /'. + + + Sin comilla de cierre después de la cadena de caracteres. + + + Se encontró sintaxis incorrecta al analizar '{0}'. + + + La variable {0} no está definida. + + + prueba + + + No se puede convertir el SqlCodeObject del Tipo {0} al Tipo {1} + + + Sustitución de una cadena vacía por una cadena vacía. + + + Sesión de edición no existe, + + + La consulta no ha finalizado. + + + La consulta no generó un único set de resultados + + + Falló al agregar una nueva fila a la caché de actualización + + + El ID de la fila ingresado, se encuentra fuera del rango de filas de la caché de edición + + + Una actualización está pendiente para esta fila y debe de revertirse primero + + + El ID de la fila ingresado no tiene actualizaciones pendientes + + + La metadata de la tabla o vista no pudo ser encontrada + + + Formato inválido para columna binaria + + + Columnas del tipo boolean deben de ser numéricos 1 o 0, o tipo string true o false + + + Falta un valor requerido de la celda + + + Existe una eliminación pendiente para esta fila, una actualización de celda no puede ser realizada. + + + El ID de la columna debe de estar en el rango de columnas de la consulta. + + + La columna no puede ser editada + + + No se encontró ninguna columna clave + + + Proporcione un nombre de archivo de salida + + + Objeto de base de datos {0} no puede ser usado para modificación. + + + SpecifiedUri '{0}' no tiene alguna conexión por defecto + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx index f7ee389e..76ad3db3 100755 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx @@ -599,4 +599,656 @@ Decimal column is missing numeric precision or numeric scale + + Error expanding: {0} + + + + Error connecting to {0} + + + + Aggregates + + + + Server Roles + + + + Application Roles + + + + Assemblies + + + + Assembly Files + + + + Asymmetric Keys + + + + Asymmetric Keys + + + + Data Compression Options + + + + Certificates + + + + FileTables + + + + Certificates + + + + Check Constraints + + + + Columns + + + + Constraints + + + + Contracts + + + + Credentials + + + + Error Messages + + + + Server Role Membership + + + + Database Options + + + + Database Roles + + + + Role Memberships + + + + Database Triggers + + + + Default Constraints + + + + Defaults + + + + Sequences + + + + Endpoints + + + + Event Notifications + + + + Server Event Notifications + + + + Extended Properties + + + + Filegroups + + + + Foreign Keys + + + + Full-Text Catalogs + + + + Full-Text Indexes + + + + Functions + + + + Indexes + + + + Inline Functions + + + + Keys + + + + Linked Servers + + + + Linked Server Logins + + + + Logins + + + + Master Key + + + + Master Keys + + + + Message Types + + + + Table-Valued Functions + + + + Parameters + + + + Partition Functions + + + + Partition Schemes + + + + Permissions + + + + Primary Keys + + + + Programmability + + + + Queues + + + + Remote Service Bindings + + + + Returned Columns + + + + Roles + + + + Routes + + + + Rules + + + + Schemas + + + + Security + + + + Server Objects + + + + Management + + + + Triggers + + + + Service Broker + + + + Services + + + + Signatures + + + + Log Files + + + + Statistics + + + + Storage + + + + Stored Procedures + + + + Symmetric Keys + + + + Synonyms + + + + Tables + + + + Triggers + + + + Types + + + + Unique Keys + + + + User-Defined Data Types + + + + User-Defined Types (CLR) + + + + Users + + + + Views + + + + XML Indexes + + + + XML Schema Collections + + + + User-Defined Table Types + + + + Files + + + + Missing Caption + + + + Broker Priorities + + + + Cryptographic Providers + + + + Database Audit Specifications + + + + Database Encryption Keys + + + + Event Sessions + + + + Full Text Stoplists + + + + Resource Pools + + + + Audits + + + + Server Audit Specifications + + + + Spatial Indexes + + + + Workload Groups + + + + SQL Files + + + + Server Functions + + + + SQL Type + + + + Server Options + + + + Database Diagrams + + + + System Tables + + + + Databases + + + + System Contracts + + + + System Databases + + + + System Message Types + + + + System Queues + + + + System Services + + + + System Stored Procedures + + + + System Views + + + + Data-tier Applications + + + + Extended Stored Procedures + + + + Aggregate Functions + + + + Approximate Numerics + + + + Binary Strings + + + + Character Strings + + + + CLR Data Types + + + + Configuration Functions + + + + Cursor Functions + + + + System Data Types + + + + Date and Time + + + + Date and Time Functions + + + + Exact Numerics + + + + System Functions + + + + Hierarchy Id Functions + + + + Mathematical Functions + + + + Metadata Functions + + + + Other Data Types + + + + Other Functions + + + + Rowset Functions + + + + Security Functions + + + + Spatial Data Types + + + + String Functions + + + + System Statistical Functions + + + + Text and Image Functions + + + + Unicode Character Strings + + + + Aggregate Functions + + + + Scalar-valued Functions + + + + Table-valued Functions + + + + System Extended Stored Procedures + + + + Built-in Types + + + + Built-in Server Roles + + + + User with Password + + + + Search Property List + + + + Security Policies + + + + Security Predicates + + + + Server Role + + + + Search Property Lists + + + + Column Store Indexes + + + + Table Type Indexes + + + + ServerInstance + + + + Selective XML Indexes + + + + XML Namespaces + + + + XML Typed Promoted Paths + + + + T-SQL Typed Promoted Paths + + + + Database Scoped Credentials + + + + External Data Sources + + + + External File Formats + + + + External Resources + + + + External Tables + + + + Always Encrypted Keys + + + + Column Master Keys + + + + Column Encryption Keys + + diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings index d4917c6b..0bb0b741 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings @@ -293,3 +293,333 @@ TestLocalizationConstant = test # Utilities SqlScriptFormatterDecimalMissingPrecision = Decimal column is missing numeric precision or numeric 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_LinkedServerLogins = Linked Server Logins + +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_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_ServerInstance = ServerInstance + +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_AlwaysEncryptedKeys = Always Encrypted Keys + +SchemaHierarchy_ColumnMasterKeys = Column Master Keys + +SchemaHierarchy_ColumnEncryptionKeys = Column Encryption Keys + diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf index 0936f7a7..de85581c 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf @@ -1,606 +1,1421 @@ - - - - - - Connection parameters cannot be null - Connection parameters cannot be null - - - - OwnerUri cannot be null or empty - OwnerUri cannot be null or empty - - - - SpecifiedUri '{0}' does not have existing connection - SpecifiedUri '{0}' does not have existing connection - . - Parameters: 0 - uri (string) - - - Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. - Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. - . - Parameters: 0 - authType (string) - - - Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. - Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. - . - Parameters: 0 - intent (string) - - - Connection canceled - Connection canceled - - - - OwnerUri cannot be null or empty - OwnerUri cannot be null or empty - - - - Connection details object cannot be null - Connection details object cannot be null - - - - ServerName cannot be null or empty - ServerName cannot be null or empty - - - - {0} cannot be null or empty when using SqlLogin authentication - {0} cannot be null or empty when using SqlLogin authentication - . - Parameters: 0 - component (string) - - - The query has already completed, it cannot be cancelled - The query has already completed, it cannot be cancelled - - - - Query successfully cancelled, failed to dispose query. Owner URI not found. - Query successfully cancelled, failed to dispose query. Owner URI not found. - - - - Query was canceled by user - Query was canceled by user - - - - The batch has not completed, yet - The batch has not completed, yet - - - - Batch index cannot be less than 0 or greater than the number of batches - Batch index cannot be less than 0 or greater than the number of batches - - - - Result set index cannot be less than 0 or greater than the number of result sets - Result set index cannot be less than 0 or greater than the number of result sets - - - - Maximum number of bytes to return must be greater than zero - Maximum number of bytes to return must be greater than zero - - - - Maximum number of chars to return must be greater than zero - Maximum number of chars to return must be greater than zero - - - - Maximum number of XML bytes to return must be greater than zero - Maximum number of XML bytes to return must be greater than zero - - - - Access method cannot be write-only - Access method cannot be write-only - - - - FileStreamWrapper must be initialized before performing operations - FileStreamWrapper must be initialized before performing operations - - - - This FileStreamWrapper cannot be used for writing - This FileStreamWrapper cannot be used for writing - - - - (1 row affected) - (1 row affected) - - - - ({0} rows affected) - ({0} rows affected) - . - Parameters: 0 - rows (long) - - - Commands completed successfully. - Commands completed successfully. - - - - Msg {0}, Level {1}, State {2}, Line {3}{4}{5} - Msg {0}, Level {1}, State {2}, Line {3}{4}{5} - . - Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) - - - Query failed: {0} - Query failed: {0} - . - Parameters: 0 - message (string) - - - (No column name) - (No column name) - - - - The requested query does not exist - The requested query does not exist - - - - This editor is not connected to a database - This editor is not connected to a database - - - - A query is already in progress for this editor session. Please cancel this query or wait for its completion. - A query is already in progress for this editor session. Please cancel this query or wait for its completion. - - - - Sender for OnInfoMessage event must be a SqlConnection - Sender for OnInfoMessage event must be a SqlConnection - - - - Result cannot be saved until query execution has completed - Result cannot be saved until query execution has completed - - - - Internal error occurred while starting save task - Internal error occurred while starting save task - - - - A save request to the same path is in progress - A save request to the same path is in progress - - - - Failed to save {0}: {1} - Failed to save {0}: {1} - . - Parameters: 0 - fileName (string), 1 - message (string) - - - Cannot read subset unless the results have been read from the server - Cannot read subset unless the results have been read from the server - - - - Start row cannot be less than 0 or greater than the number of rows in the result set - Start row cannot be less than 0 or greater than the number of rows in the result set - - - - Row count must be a positive integer - Row count must be a positive integer - - - - Could not retrieve column schema for result set - Could not retrieve column schema for result set - - - - Could not retrieve an execution plan from the result set - Could not retrieve an execution plan from the result set - - - - This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} - This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} - . - Parameters: 0 - errorMessage (string) - - - An unexpected error occurred during Peek Definition execution: {0} - An unexpected error occurred during Peek Definition execution: {0} - . - Parameters: 0 - errorMessage (string) - - - No results were found. - No results were found. - - - - No database object was retrieved. - No database object was retrieved. - - - - Please connect to a server. - Please connect to a server. - - - - Operation timed out. - Operation timed out. - - - - This object type is currently not supported by this feature. - This object type is currently not supported by this feature. - - - - Position is outside of file line range - Position is outside of file line range - - - - Position is outside of column range for line {0} - Position is outside of column range for line {0} - . - Parameters: 0 - line (int) - - - Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) - Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) - . - Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) - - - Msg {0}, Level {1}, State {2}, Line {3} - Msg {0}, Level {1}, State {2}, Line {3} - - - - Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} - Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} - - - - Msg {0}, Level {1}, State {2} - Msg {0}, Level {1}, State {2} - - - - An error occurred while the batch was being processed. The error message is: {0} - An error occurred while the batch was being processed. The error message is: {0} - - - - ({0} row(s) affected) - ({0} row(s) affected) - - - - The previous execution is not yet complete. - The previous execution is not yet complete. - - - - A scripting error occurred. - A scripting error occurred. - - - - Incorrect syntax was encountered while {0} was being parsed. - Incorrect syntax was encountered while {0} was being parsed. - - - - A fatal error occurred. - A fatal error occurred. - - - - Execution completed {0} times... - Execution completed {0} times... - - - - You cancelled the query. - You cancelled the query. - - - - An error occurred while the batch was being executed. - An error occurred while the batch was being executed. - - - - An error occurred while the batch was being executed, but the error has been ignored. - An error occurred while the batch was being executed, but the error has been ignored. - - - - Starting execution loop of {0} times... - Starting execution loop of {0} times... - - - - Command {0} is not supported. - Command {0} is not supported. - - - - The variable {0} could not be found. - The variable {0} could not be found. - - - - SQL Execution error: {0} - SQL Execution error: {0} - - - - Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} - Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} - - - - Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} - Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} - - - - Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} - Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} - - - - Batch parser wrapper execution engine batch ResultSet finished. - Batch parser wrapper execution engine batch ResultSet finished. - - - - Canceling batch parser wrapper batch execution. - Canceling batch parser wrapper batch execution. - - - - Scripting warning. - Scripting warning. - - - - For more information about this error, see the troubleshooting topics in the product documentation. - For more information about this error, see the troubleshooting topics in the product documentation. - - - - File '{0}' recursively included. - File '{0}' recursively included. - - - - Missing end comment mark '*/'. - Missing end comment mark '*/'. - - - - Unclosed quotation mark after the character string. - Unclosed quotation mark after the character string. - - - - Incorrect syntax was encountered while parsing '{0}'. - Incorrect syntax was encountered while parsing '{0}'. - - - - Variable {0} is not defined. - Variable {0} is not defined. - - - - test - EN_LOCALIZATION - - - - Replacement of an empty string by an empty string. - Replacement of an empty string by an empty string. - - - - Edit session does not exist. - Edit session does not exist. - - - - Query has not completed execution - Query has not completed execution - - - - Query did not generate exactly one result set - Query did not generate exactly one result set - - - - Failed to add new row to update cache - Failed to add new row to update cache - - - - Given row ID is outside the range of rows in the edit cache - Given row ID is outside the range of rows in the edit cache - - - - An update is already pending for this row and must be reverted first - An update is already pending for this row and must be reverted first - - - - Given row ID does not have pending update - Given row ID does not have pending updated - - - - Table or view metadata could not be found - Table or view metadata could not be found - - - - Invalid format for binary column - Invalid format for binary column - - - - Allowed values for boolean columns are 0, 1, "true", or "false" - Boolean columns must be numeric 1 or 0, or string true or false - - - - A required cell value is missing - A required cell value is missing - - - - A delete is pending for this row, a cell update cannot be applied. - A delete is pending for this row, a cell update cannot be applied. - - - - Column ID must be in the range of columns for the query - Column ID must be in the range of columns for the query - - - - Column cannot be edited - Column cannot be edited - - - - No key columns were found - No key columns were found - - - - An output filename must be provided - An output filename must be provided - - - - Database object {0} cannot be used for editing. - Database object {0} cannot be used for editing. - . - Parameters: 0 - typeName (string) - - - Specified URI '{0}' does not have a default connection - Specified URI '{0}' does not have a default connection - . - Parameters: 0 - uri (string) - - - A commit task is in progress. Please wait for completion. - A commit task is in progress. Please wait for completion. - - - - Decimal column is missing numeric precision or numeric scale - Decimal column is missing numeric precision or numeric scale - - - - <TBD> - <TBD> - - - - Cannot add row to result buffer, data reader does not contain rows - Cannot add row to result buffer, data reader does not contain rows - - - - TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 - TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 - - - - NULL is not allowed for this column - NULL is not allowed for this column - - - - Edit session already exists. - Edit session already exists. - - - - Edit session has not been initialized - Edit session has not been initialized - - - - Edit session has already been initialized - Edit session has already been initialized - - - - Edit session has already been initialized or is in the process of initializing - Edit session has already been initialized or is in the process of initializing - - - - Query execution failed, see messages for details - Query execution failed, see messages for details - - - - Result limit cannot be negative - Result limit cannot be negative - - - - NULL - NULL - - - - A object name must be provided - A object name must be provided - - - - Explicitly specifying server or database is not supported - Explicitly specifying server or database is not supported - - - - Table metadata does not have extended properties - Table metadata does not have extended properties - - - - Table or view requested for edit could not be found - Table or view requested for edit could not be found - - - - + + + + + + Connection parameters cannot be null + Connection parameters cannot be null + + + + OwnerUri cannot be null or empty + OwnerUri cannot be null or empty + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUri '{0}' does not have existing connection + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + . + Parameters: 0 - intent (string) + + + Connection canceled + Connection canceled + + + + OwnerUri cannot be null or empty + OwnerUri cannot be null or empty + + + + Connection details object cannot be null + Connection details object cannot be null + + + + ServerName cannot be null or empty + ServerName cannot be null or empty + + + + {0} cannot be null or empty when using SqlLogin authentication + {0} cannot be null or empty when using SqlLogin authentication + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + The query has already completed, it cannot be cancelled + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + Query successfully cancelled, failed to dispose query. Owner URI not found. + + + + Query was canceled by user + Query was canceled by user + + + + The batch has not completed, yet + The batch has not completed, yet + + + + Batch index cannot be less than 0 or greater than the number of batches + Batch index cannot be less than 0 or greater than the number of batches + + + + Result set index cannot be less than 0 or greater than the number of result sets + Result set index cannot be less than 0 or greater than the number of result sets + + + + Maximum number of bytes to return must be greater than zero + Maximum number of bytes to return must be greater than zero + + + + Maximum number of chars to return must be greater than zero + Maximum number of chars to return must be greater than zero + + + + Maximum number of XML bytes to return must be greater than zero + Maximum number of XML bytes to return must be greater than zero + + + + Access method cannot be write-only + Access method cannot be write-only + + + + FileStreamWrapper must be initialized before performing operations + FileStreamWrapper must be initialized before performing operations + + + + This FileStreamWrapper cannot be used for writing + This FileStreamWrapper cannot be used for writing + + + + (1 row affected) + (1 row affected) + + + + ({0} rows affected) + ({0} rows affected) + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + Commands completed successfully. + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + Query failed: {0} + . + Parameters: 0 - message (string) + + + (No column name) + (No column name) + + + + The requested query does not exist + The requested query does not exist + + + + This editor is not connected to a database + This editor is not connected to a database + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + + + + Sender for OnInfoMessage event must be a SqlConnection + Sender for OnInfoMessage event must be a SqlConnection + + + + Result cannot be saved until query execution has completed + Result cannot be saved until query execution has completed + + + + Internal error occurred while starting save task + Internal error occurred while starting save task + + + + A save request to the same path is in progress + A save request to the same path is in progress + + + + Failed to save {0}: {1} + Failed to save {0}: {1} + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + Cannot read subset unless the results have been read from the server + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + Start row cannot be less than 0 or greater than the number of rows in the result set + + + + Row count must be a positive integer + Row count must be a positive integer + + + + Could not retrieve column schema for result set + Could not retrieve column schema for result set + + + + Could not retrieve an execution plan from the result set + Could not retrieve an execution plan from the result set + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + An unexpected error occurred during Peek Definition execution: {0} + . + Parameters: 0 - errorMessage (string) + + + No results were found. + No results were found. + + + + No database object was retrieved. + No database object was retrieved. + + + + Please connect to a server. + Please connect to a server. + + + + Operation timed out. + Operation timed out. + + + + This object type is currently not supported by this feature. + This object type is currently not supported by this feature. + + + + Position is outside of file line range + Position is outside of file line range + + + + Position is outside of column range for line {0} + Position is outside of column range for line {0} + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + Msg {0}, Level {1}, State {2}, Line {3} + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + + + + Msg {0}, Level {1}, State {2} + Msg {0}, Level {1}, State {2} + + + + An error occurred while the batch was being processed. The error message is: {0} + An error occurred while the batch was being processed. The error message is: {0} + + + + ({0} row(s) affected) + ({0} row(s) affected) + + + + The previous execution is not yet complete. + The previous execution is not yet complete. + + + + A scripting error occurred. + A scripting error occurred. + + + + Incorrect syntax was encountered while {0} was being parsed. + Incorrect syntax was encountered while {0} was being parsed. + + + + A fatal error occurred. + A fatal error occurred. + + + + Execution completed {0} times... + Execution completed {0} times... + + + + You cancelled the query. + You cancelled the query. + + + + An error occurred while the batch was being executed. + An error occurred while the batch was being executed. + + + + An error occurred while the batch was being executed, but the error has been ignored. + An error occurred while the batch was being executed, but the error has been ignored. + + + + Starting execution loop of {0} times... + Starting execution loop of {0} times... + + + + Command {0} is not supported. + Command {0} is not supported. + + + + The variable {0} could not be found. + The variable {0} could not be found. + + + + SQL Execution error: {0} + SQL Execution error: {0} + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + Batch parser wrapper execution engine batch ResultSet finished. + Batch parser wrapper execution engine batch ResultSet finished. + + + + Canceling batch parser wrapper batch execution. + Canceling batch parser wrapper batch execution. + + + + Scripting warning. + Scripting warning. + + + + For more information about this error, see the troubleshooting topics in the product documentation. + For more information about this error, see the troubleshooting topics in the product documentation. + + + + File '{0}' recursively included. + File '{0}' recursively included. + + + + Missing end comment mark '*/'. + Missing end comment mark '*/'. + + + + Unclosed quotation mark after the character string. + Unclosed quotation mark after the character string. + + + + Incorrect syntax was encountered while parsing '{0}'. + Incorrect syntax was encountered while parsing '{0}'. + + + + Variable {0} is not defined. + Variable {0} is not defined. + + + + test + EN_LOCALIZATION + + + + Replacement of an empty string by an empty string. + Replacement of an empty string by an empty string. + + + + Edit session does not exist. + Edit session does not exist. + + + + Query has not completed execution + Query has not completed execution + + + + Query did not generate exactly one result set + Query did not generate exactly one result set + + + + Failed to add new row to update cache + Failed to add new row to update cache + + + + Given row ID is outside the range of rows in the edit cache + Given row ID is outside the range of rows in the edit cache + + + + An update is already pending for this row and must be reverted first + An update is already pending for this row and must be reverted first + + + + Given row ID does not have pending update + Given row ID does not have pending updated + + + + Table or view metadata could not be found + Table or view metadata could not be found + + + + Invalid format for binary column + Invalid format for binary column + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + Boolean columns must be numeric 1 or 0, or string true or false + + + + A required cell value is missing + A required cell value is missing + + + + A delete is pending for this row, a cell update cannot be applied. + A delete is pending for this row, a cell update cannot be applied. + + + + Column ID must be in the range of columns for the query + Column ID must be in the range of columns for the query + + + + Column cannot be edited + Column cannot be edited + + + + No key columns were found + No key columns were found + + + + An output filename must be provided + An output filename must be provided + + + + Database object {0} cannot be used for editing. + Database object {0} cannot be used for editing. + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + Specified URI '{0}' does not have a default connection + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + A commit task is in progress. Please wait for completion. + + + + Decimal column is missing numeric precision or numeric scale + Decimal column is missing numeric precision or numeric scale + + + + <TBD> + <TBD> + + + + Cannot add row to result buffer, data reader does not contain rows + Cannot add row to result buffer, data reader does not contain rows + + + + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + TIME column values must be between 00:00:00.0000000 and 23:59:59.9999999 + + + + NULL is not allowed for this column + NULL is not allowed for this column + + + + Edit session already exists. + Edit session already exists. + + + + Edit session has not been initialized + Edit session has not been initialized + + + + Edit session has already been initialized + Edit session has already been initialized + + + + Edit session has already been initialized or is in the process of initializing + Edit session has already been initialized or is in the process of initializing + + + + Query execution failed, see messages for details + Query execution failed, see messages for details + + + + Result limit cannot be negative + Result limit cannot be negative + + + + NULL + NULL + + + + A object name must be provided + A object name must be provided + + + + Explicitly specifying server or database is not supported + Explicitly specifying server or database is not supported + + + + Table metadata does not have extended properties + Table metadata does not have extended properties + + + + Table or view requested for edit could not be found + Table or view requested for edit could not be found + + + + Error expanding: {0} + Error expanding: {0} + + + + Error connecting to {0} + Error connecting to {0} + + + + Aggregates + Aggregates + + + + Server Roles + Server Roles + + + + Application Roles + Application Roles + + + + Assemblies + Assemblies + + + + Assembly Files + Assembly Files + + + + Asymmetric Keys + Asymmetric Keys + + + + Asymmetric Keys + Asymmetric Keys + + + + Data Compression Options + Data Compression Options + + + + Certificates + Certificates + + + + FileTables + FileTables + + + + Certificates + Certificates + + + + Check Constraints + Check Constraints + + + + Columns + Columns + + + + Constraints + Constraints + + + + Contracts + Contracts + + + + Credentials + Credentials + + + + Error Messages + Error Messages + + + + Server Role Membership + Server Role Membership + + + + Database Options + Database Options + + + + Database Roles + Database Roles + + + + Role Memberships + Role Memberships + + + + Database Triggers + Database Triggers + + + + Default Constraints + Default Constraints + + + + Defaults + Defaults + + + + Sequences + Sequences + + + + Endpoints + Endpoints + + + + Event Notifications + Event Notifications + + + + Server Event Notifications + Server Event Notifications + + + + Extended Properties + Extended Properties + + + + Filegroups + Filegroups + + + + Foreign Keys + Foreign Keys + + + + Full-Text Catalogs + Full-Text Catalogs + + + + Full-Text Indexes + Full-Text Indexes + + + + Functions + Functions + + + + Indexes + Indexes + + + + Inline Functions + Inline Functions + + + + Keys + Keys + + + + Linked Servers + Linked Servers + + + + Linked Server Logins + Linked Server Logins + + + + Logins + Logins + + + + Master Key + Master Key + + + + Master Keys + Master Keys + + + + Message Types + Message Types + + + + Table-Valued Functions + Table-Valued Functions + + + + Parameters + Parameters + + + + Partition Functions + Partition Functions + + + + Partition Schemes + Partition Schemes + + + + Permissions + Permissions + + + + Primary Keys + Primary Keys + + + + Programmability + Programmability + + + + Queues + Queues + + + + Remote Service Bindings + Remote Service Bindings + + + + Returned Columns + Returned Columns + + + + Roles + Roles + + + + Routes + Routes + + + + Rules + Rules + + + + Schemas + Schemas + + + + Security + Security + + + + Server Objects + Server Objects + + + + Management + Management + + + + Triggers + Triggers + + + + Service Broker + Service Broker + + + + Services + Services + + + + Signatures + Signatures + + + + Log Files + Log Files + + + + Statistics + Statistics + + + + Storage + Storage + + + + Stored Procedures + Stored Procedures + + + + Symmetric Keys + Symmetric Keys + + + + Synonyms + Synonyms + + + + Tables + Tables + + + + Triggers + Triggers + + + + Types + Types + + + + Unique Keys + Unique Keys + + + + User-Defined Data Types + User-Defined Data Types + + + + User-Defined Types (CLR) + User-Defined Types (CLR) + + + + Users + Users + + + + Views + Views + + + + XML Indexes + XML Indexes + + + + XML Schema Collections + XML Schema Collections + + + + User-Defined Table Types + User-Defined Table Types + + + + Files + Files + + + + Missing Caption + Missing Caption + + + + Broker Priorities + Broker Priorities + + + + Cryptographic Providers + Cryptographic Providers + + + + Database Audit Specifications + Database Audit Specifications + + + + Database Encryption Keys + Database Encryption Keys + + + + Event Sessions + Event Sessions + + + + Full Text Stoplists + Full Text Stoplists + + + + Resource Pools + Resource Pools + + + + Audits + Audits + + + + Server Audit Specifications + Server Audit Specifications + + + + Spatial Indexes + Spatial Indexes + + + + Workload Groups + Workload Groups + + + + SQL Files + SQL Files + + + + Server Functions + Server Functions + + + + SQL Type + SQL Type + + + + Server Options + Server Options + + + + Database Diagrams + Database Diagrams + + + + System Tables + System Tables + + + + Databases + Databases + + + + System Contracts + System Contracts + + + + System Databases + System Databases + + + + System Message Types + System Message Types + + + + System Queues + System Queues + + + + System Services + System Services + + + + System Stored Procedures + System Stored Procedures + + + + System Views + System Views + + + + Data-tier Applications + Data-tier Applications + + + + Extended Stored Procedures + Extended Stored Procedures + + + + Aggregate Functions + Aggregate Functions + + + + Approximate Numerics + Approximate Numerics + + + + Binary Strings + Binary Strings + + + + Character Strings + Character Strings + + + + CLR Data Types + CLR Data Types + + + + Configuration Functions + Configuration Functions + + + + Cursor Functions + Cursor Functions + + + + System Data Types + System Data Types + + + + Date and Time + Date and Time + + + + Date and Time Functions + Date and Time Functions + + + + Exact Numerics + Exact Numerics + + + + System Functions + System Functions + + + + Hierarchy Id Functions + Hierarchy Id Functions + + + + Mathematical Functions + Mathematical Functions + + + + Metadata Functions + Metadata Functions + + + + Other Data Types + Other Data Types + + + + Other Functions + Other Functions + + + + Rowset Functions + Rowset Functions + + + + Security Functions + Security Functions + + + + Spatial Data Types + Spatial Data Types + + + + String Functions + String Functions + + + + System Statistical Functions + System Statistical Functions + + + + Text and Image Functions + Text and Image Functions + + + + Unicode Character Strings + Unicode Character Strings + + + + Aggregate Functions + Aggregate Functions + + + + Scalar-valued Functions + Scalar-valued Functions + + + + Table-valued Functions + Table-valued Functions + + + + System Extended Stored Procedures + System Extended Stored Procedures + + + + Built-in Types + Built-in Types + + + + Built-in Server Roles + Built-in Server Roles + + + + User with Password + User with Password + + + + Search Property List + Search Property List + + + + Security Policies + Security Policies + + + + Security Predicates + Security Predicates + + + + Server Role + Server Role + + + + Search Property Lists + Search Property Lists + + + + Column Store Indexes + Column Store Indexes + + + + Table Type Indexes + Table Type Indexes + + + + ServerInstance + ServerInstance + + + + Selective XML Indexes + Selective XML Indexes + + + + XML Namespaces + XML Namespaces + + + + XML Typed Promoted Paths + XML Typed Promoted Paths + + + + T-SQL Typed Promoted Paths + T-SQL Typed Promoted Paths + + + + Database Scoped Credentials + Database Scoped Credentials + + + + External Data Sources + External Data Sources + + + + External File Formats + External File Formats + + + + External Resources + External Resources + + + + External Tables + External Tables + + + + Always Encrypted Keys + Always Encrypted Keys + + + + Column Master Keys + Column Master Keys + + + + Column Encryption Keys + Column Encryption Keys + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.xproj b/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.xproj index 358bb7c3..fa75a6cd 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.xproj +++ b/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.xproj @@ -1,19 +1,22 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - {0D61DC2B-DA66-441D-B9D0-F76C98F780F9} - Microsoft.SqlTools.ServiceLayer - .\obj - .\bin\ - v4.5.2 - - - 2.0 - - + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + {0D61DC2B-DA66-441D-B9D0-F76C98F780F9} + Microsoft.SqlTools.ServiceLayer + .\obj + .\bin\ + v4.5.2 + + + 2.0 + + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/CreateSessionRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/CreateSessionRequest.cs new file mode 100644 index 00000000..51226097 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/CreateSessionRequest.cs @@ -0,0 +1,45 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts +{ + /// + /// Information returned from a . + /// Contains success information, a to be used when + /// requesting expansion of nodes, and a root node to display for this area. + /// + public class CreateSessionResponse + { + /// + /// Boolean indicating if the connection was successful + /// + public bool Success { get; set; } + + /// + /// Unique ID to use when sending any requests for objects in the + /// tree under the node + /// + public string SessionId { get; set; } + + /// + /// Information describing the base node in the tree + /// + public NodeInfo RootNode { get; set; } + } + /// + /// Establishes an Object Explorer tree session for a specific connection. + /// This will create a connection to a specific server or database, register + /// it for use in the + /// + public class CreateSessionRequest + { + public static readonly + RequestType Type = + RequestType.Create("objectexplorer/createsession"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/ExpandRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/ExpandRequest.cs new file mode 100644 index 00000000..a004d172 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/ExpandRequest.cs @@ -0,0 +1,56 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Protocol.Contracts; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts +{ + /// + /// Information returned from a . + /// + public class ExpandResponse + { + /// + /// Unique ID to use when sending any requests for objects in the + /// tree under the node + /// + public string SessionId { get; set; } + + /// + /// Information describing the expanded nodes in the tree + /// + public NodeInfo[] Nodes { get; set; } + } + + /// + /// Parameters to the . + /// + public class ExpandParams + { + /// + /// The Id returned from a . This + /// is used to disambiguate between different trees. + /// + public string SessionId { get; set; } + + /// + /// Path identifying the node to expand. See for details + /// + public string NodePath { get; set; } + } + + /// + /// A request to expand a + /// + public class ExpandRequest + { + /// + /// Returns children of a given node as a array. + /// + public static readonly + RequestType Type = + RequestType.Create("objectexplorer/expand"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/NodeInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/NodeInfo.cs new file mode 100644 index 00000000..b97f647d --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/NodeInfo.cs @@ -0,0 +1,40 @@ +// +// 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.Contracts +{ + /// + /// Information describing a Node in the Object Explorer tree. + /// Contains information required to display the Node to the user and + /// to know whether actions such as expanding children is possible + /// the node + /// + public class NodeInfo + { + /// + /// 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 + /// + public string NodePath { get; set; } + + /// + /// The type of the node - for example Server, Database, Folder, Table + /// + public string NodeType { get; set; } + + /// + /// Label to display to the user, describing this node. + /// + public string Label { get; set; } + + /// + /// Is this a leaf node (in which case no children can be generated) or + /// is it expandable? + /// + public bool IsLeaf { get; set; } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/RefreshRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/RefreshRequest.cs new file mode 100644 index 00000000..74cfc8ed --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/RefreshRequest.cs @@ -0,0 +1,39 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Protocol.Contracts; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts +{ + /// + /// Parameters to the . + /// + public class RefreshParams + { + /// + /// The Id returned from a . This + /// is used to disambiguate between different trees. + /// + public string SessionId { get; set; } + + /// + /// Path identifying the node to expand. See for details + /// + public string[] NodePath { get; set; } + } + + /// + /// A request to expand a + /// + public class RefreshRequest + { + /// + /// Returns children of a given node as a array. + /// + public static readonly + RequestType Type = + RequestType.Create("objectexplorer/refresh"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ChildFactory.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ChildFactory.cs new file mode 100644 index 00000000..cb412d79 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ChildFactory.cs @@ -0,0 +1,39 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Collections.Generic; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes +{ + /// + /// A supports creation of children + /// for a class of objects in the tree. The + /// + public abstract class ChildFactory + { + /// + /// The set of applicable parents for which the factory can create children. + /// + /// + /// the string names for each that + /// this factory can create children for + /// + public abstract IEnumerable ApplicableParents(); + + /// + /// Expands an element in the + /// + /// + /// + public abstract IEnumerable Expand(TreeNode parent); + + 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); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeObservableCollection.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeObservableCollection.cs new file mode 100644 index 00000000..b7d8fad5 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeObservableCollection.cs @@ -0,0 +1,177 @@ +// +// 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.Collections.ObjectModel; +using System.Linq; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes +{ + /// + /// A collection class for + /// + public sealed class NodeObservableCollection : ObservableCollection + { + 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 void BeginInit() + { + if (!numInits.HasValue) + { + numInits = 1; + } + else + { + numInits = numInits + 1; + } + } + + public void EndInit() + { + IList empty = null; + EndInit(null, ref empty); + } + + public void EndInit(TreeNode parent, ref IList deferredChildren) + { + if (numInits.HasValue && + numInits.Value == 1) + { + try + { + 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; + } + } + + + /// + /// Repositions this child in the list + /// + public void ReSortChild(TreeNode child) + { + if (child == null) + return; + + List 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 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); + } + } + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeTypes.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeTypes.cs new file mode 100644 index 00000000..2305cb7f --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeTypes.cs @@ -0,0 +1,141 @@ +// +// 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 +{ + /// + /// Enum listing possible node types in the object explorer tree + /// + // TODO Consider replacing this with an auto-gen'd version + public enum NodeTypes + { + None, + SqlServersRoot, + DatabaseInstance, + DacInstance, + ServerInstance, + ScalarValuedFunctionInstance, + TableValuedFunctionInstance, + AggregateFunctionInstance, + FileGroupInstance, + StoredProcedureInstance, + UserDefinedTableTypeInstance, + ViewInstance, + TableInstance, + HistoryTableInstance, + Databases, + ExternalResources, + ServerLevelSecurity, + ServerLevelServerObjects, + ServerLevelManagement, + SystemDatabases, + ServerLevelLinkedServerLogins, + ServerLevelServerAudits, + ServerLevelCryptographicProviders, + ServerLevelCredentials, + ServerLevelServerRoles, + ServerLevelLogins, + ServerLevelEventSessions, + ServerLevelServerAuditSpecifications, + ServerLevelEventNotifications, + ServerLevelErrorMessages, + ServerLevelServerTriggers, + ServerLevelLinkedServers, + ServerLevelEndpoints, + DacInstancesFolder, + Tables, + Views, + Synonyms, + Programmability, + ServiceBroker, + Storage, + Security, + SystemTables, + FileTables, + SystemViews, + StoredProcedures, + Functions, + ExtendedStoredProcedures, + DatabaseTriggers, + Defaults, + Rules, + Types, + Assemblies, + MessageTypes, + Contracts, + Queues, + Services, + Routes, + DatabaseAndQueueEventNotifications, + RemoteServiceBindings, + BrokerPriorities, + FileGroups, + FullTextCatalogs, + FullTextStopLists, + SqlLogFiles, + PartitionFunctions, + PartitionSchemes, + SearchPropertyLists, + Users, + Roles, + Schemas, + AsymmetricKeys, + Certificates, + SymmetricKeys, + DatabaseEncryptionKeys, + MasterKeys, + Signatures, + DatabaseAuditSpecifications, + Columns, + Keys, + Constraints, + Triggers, + Indexes, + Statistics, + TableValuedFunctions, + ScalarValuedFunctions, + AggregateFunctions, + SystemDataTypes, + UserDefinedDataTypes, + UserDefinedTableTypes, + UserDefinedTypes, + XmlSchemaCollections, + SystemExactNumerics, + SystemApproximateNumerics, + SystemDateAndTimes, + SystemCharacterStrings, + SystemUnicodeCharacterStrings, + SystemBinaryStrings, + SystemOtherDataTypes, + SystemClrDataTypes, + SystemSpatialDataTypes, + UserDefinedTableTypeColumns, + UserDefinedTableTypeKeys, + UserDefinedTableTypeConstraints, + SystemStoredProcedures, + StoredProcedureParameters, + TableValuedFunctionParameters, + ScalarValuedFunctionParameters, + AggregateFunctionParameters, + DatabaseRoles, + ApplicationRoles, + FileGroupFiles, + SystemMessageTypes, + SystemContracts, + SystemServices, + SystemQueues, + Sequences, + SecurityPolicies, + DatabaseScopedCredentials, + ExternalTables, + ExternalResourceInstance, + ExternalDataSources, + ExternalFileFormats, + ExternalTableInstance, + AlwaysEncryptedKeys, + ColumnMasterKeys, + ColumnEncryptionKeys + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs new file mode 100644 index 00000000..11b5e74b --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs @@ -0,0 +1,329 @@ +// +// 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.Collections.ObjectModel; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel; +using Microsoft.SqlTools.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes +{ + /// + /// Base class for elements in the object explorer tree. Provides common methods for tree navigation + /// and other core functionality + /// + public class TreeNode : IComparable + { + private NodeObservableCollection children = new NodeObservableCollection(); + private TreeNode parent; + private string nodePath; + private string label; + private ObjectExplorerService objectExplorerService; + public const char PathPartSeperator = '/'; + + /// + /// Constructor with no required inputs + /// + public TreeNode() + { + + } + + /// + /// Constructor that accepts a label to identify the node + /// + /// Label identifying the node + public TreeNode(string value) + { + // We intentionally do not valid this being null or empty since + // some nodes may need to set it + NodeValue = value; + } + + /// + /// Value describing this node + /// + public string NodeValue { get; set; } + + /// + /// The type of the node - for example Server, Database, Folder, Table + /// + public string NodeType { get; set; } + + /// + /// Enum defining the type of the node - for example Server, Database, Folder, Table + /// + public NodeTypes NodeTypeId { get; set; } + + /// + /// Label to display to the user, describing this node. + /// If not explicitly set this will fall back to the but + /// for many nodes such as the server, the display label will be different + /// to the value. + /// + public string Label { + get + { + if(label == null) + { + return NodeValue; + } + return label; + } + set + { + label = value; + } + } + + /// + /// Is this a leaf node (in which case no children can be generated) or + /// is it expandable? + /// + public bool IsAlwaysLeaf { get; set; } + + /// + /// Message to show if this Node is in an error state. This indicates + /// that children could be retrieved + /// + public string ErrorStateMessage { get; set; } + + /// + /// Parent of this node + /// + public TreeNode Parent + { + get + { + return parent; + } + set + { + parent = value; + // Reset the node path since it's no longer valid + nodePath = null; + } + } + + /// + /// 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 + /// + 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.NodeValue, string.IsNullOrEmpty(path) ? "" : PathPartSeperator.ToString(), path); + return true; + }); + nodePath = path; + } + + public TreeNode FindNodeByPath(string path) + { + TreeNode nodeForPath = ObjectExplorerUtils.FindNode(this, node => + { + return node.GetNodePath() == path; + }, nodeToFilter => + { + return path.StartsWith(nodeToFilter.GetNodePath()); + }); + + return nodeForPath; + } + + /// + /// Converts to a object for serialization with just the relevant properties + /// needed to identify the node + /// + /// + public NodeInfo ToNodeInfo() + { + return new NodeInfo() + { + IsLeaf = this.IsAlwaysLeaf, + Label = this.Label, + NodePath = this.GetNodePath(), + NodeType = this.NodeType + }; + } + + /// + /// Expands this node and returns its children + /// + /// Children as an IList. This is the raw children collection, not a copy + public IList Expand() + { + // TODO consider why solution explorer has separate Children and Items options + if (children.IsInitialized) + { + return children; + } + PopulateChildren(); + return children; + } + + /// + /// 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. + /// + /// containing all children for this node + public IList GetChildren() + { + return new ReadOnlyCollection(children); + } + + /// + /// Adds a child to the list of children under this node + /// + /// + public void AddChild(TreeNode newChild) + { + Validate.IsNotNull(nameof(newChild), newChild); + children.Add(newChild); + newChild.Parent = this; + } + + /// + /// Optional context to help with lookup of children + /// + public virtual object GetContext() + { + return null; + } + + /// + /// Helper method to convert context to expected format + /// + /// Type to convert to + /// context as expected type of null if it doesn't match + public T GetContextAs() + where T : class + { + return GetContext() as T; + } + + public T ParentAs() + where T : TreeNode + { + return Parent as T; + } + + protected void PopulateChildren() + { + Debug.Assert(IsAlwaysLeaf == false); + + SmoQueryContext context = this.GetContextAs(); + + if (children.IsPopulating || context == null) + return; + + children.Clear(); + BeginChildrenInit(); + + try + { + IEnumerable childFactories = context.GetObjectExplorerService().GetApplicableChildFactories(this); + if (childFactories != null) + { + foreach (var factory in childFactories) + { + IEnumerable items = factory.Expand(this); + if (items != null) + { + foreach (TreeNode item in items) + { + children.Add(item); + item.Parent = this; + + } + } + } + } + } + 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); + } + + + /// + /// Sort Priority to help when ordering elements in the tree + /// + 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); + } + + if (this.SortPriority.HasValue && + !other.SortPriority.HasValue) + { + return -1; // this is above other + } + if (!this.SortPriority.HasValue) + { + return 1; // this is below other + } + + // Both have sort priority + int priDiff = this.SortPriority.Value - other.SortPriority.Value; + if (priDiff < 0) + return -1; // this is below other + if (priDiff == 0) + return 0; + return 1; + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNodeWithContext.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNodeWithContext.cs new file mode 100644 index 00000000..0ff80faa --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNodeWithContext.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes +{ + public class TreeNodeWithContext + { + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ValidForFlag.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ValidForFlag.cs new file mode 100644 index 00000000..8b10051b --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ValidForFlag.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes +{ + /// + /// Indicates which type of server a given node type is valid for + /// + [Flags] + public enum ValidForFlag + { + Sql2005 = 0x01, + Sql2008 = 0x02, + Sql2012 = 0x04, + Sql2014 = 0x08, + Azure = 0x10, + NotDebugInstance = 0x20, + NotContainedUser = 0x40, + AzureV12 = 0x80, + Sql2016 = 0x100, + CanConnectToMaster = 0x200, + CanViewSecurity = 0x400, + SqlvNext = 0x800, + All = Sql2005 | Sql2008 | Sql2012 | Sql2014 | Sql2016 | SqlvNext | Azure | AzureV12 + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerService.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerService.cs new file mode 100644 index 00000000..bedad392 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerService.cs @@ -0,0 +1,344 @@ +// +// 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.Globalization; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.SqlTools.Extensibility; +using Microsoft.SqlTools.Hosting; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel; +using Microsoft.SqlTools.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer +{ + /// + /// A Service to support querying server and database information as an Object Explorer tree. + /// The APIs used for this are modeled closely on the VSCode TreeExplorerNodeProvider API. + /// + public class ObjectExplorerService : HostedService, IComposableService + { + internal const string uriPrefix = "objectexplorer://"; + + // Instance of the connection service, used to get the connection info for a given owner URI + private ConnectionService connectionService; + private IProtocolEndpoint serviceHost; + private Dictionary sessionMap; + private readonly Lazy>> applicableNodeChildFactories; + private IMultiServiceProvider serviceProvider; + + /// + /// Singleton constructor + /// + public ObjectExplorerService() + { + sessionMap = new Dictionary(); + applicableNodeChildFactories = new Lazy>>(() => PopulateFactories()); + } + + /// + /// Internal for testing only + /// + internal ObjectExplorerService(ExtensionServiceProvider serviceProvider) + : this() + { + SetServiceProvider(serviceProvider); + } + + private Dictionary> ApplicableNodeChildFactories + { + get + { + return applicableNodeChildFactories.Value; + } + } + + /// + /// As an , this will be set whenever the service is initialized + /// via an + /// + /// + public override void SetServiceProvider(IMultiServiceProvider provider) + { + Validate.IsNotNull(nameof(provider), provider); + serviceProvider = provider; + connectionService = provider.GetService(); + } + + /// + /// Initializes the service with the service host and registers request handlers. + /// + /// The service host instance to register with + public override void InitializeService(IProtocolEndpoint serviceHost) + { + this.serviceHost = serviceHost; + // Register handlers for requests + serviceHost.SetRequestHandler(CreateSessionRequest.Type, HandleCreateSessionRequest); + serviceHost.SetRequestHandler(ExpandRequest.Type, HandleExpandRequest); + } + + internal async Task HandleCreateSessionRequest(ConnectionDetails connectionDetails, RequestContext context) + { + Logger.Write(LogLevel.Verbose, "HandleCreateSessionRequest"); + Func> doCreateSession = async () => + { + Validate.IsNotNull(nameof(connectionDetails), connectionDetails); + Validate.IsNotNull(nameof(context), context); + + string uri = GenerateUri(connectionDetails); + + ObjectExplorerSession session; + if (!sessionMap.TryGetValue(uri, out session)) + { + // Establish a connection to the specified server/database + session = await DoCreateSession(connectionDetails, uri); + } + + CreateSessionResponse response; + if (session == null) + { + response = new CreateSessionResponse() { Success = false }; + } + else + { + // Else we have a session available, response with existing session information + response = new CreateSessionResponse() + { + Success = true, + RootNode = session.Root.ToNodeInfo(), + SessionId = session.Uri + }; + } + return response; + }; + + await HandleRequestAsync(doCreateSession, context, "HandleCreateSessionRequest"); + } + + internal async Task ExpandNode(ObjectExplorerSession session, string nodePath) + { + return await Task.Factory.StartNew(() => + { + NodeInfo[] nodes = null; + TreeNode node = session.Root.FindNodeByPath(nodePath); + if(node != null) + { + nodes = node.Expand().Select(x => x.ToNodeInfo()).ToArray(); + } + return nodes; + }); + } + + /// + /// Establishes a new session and stores its information + /// + /// object if successful, null if unsuccessful + internal async Task DoCreateSession(ConnectionDetails connectionDetails, string uri) + { + ObjectExplorerSession session; + + ConnectParams connectParams = new ConnectParams() { OwnerUri = uri, Connection = connectionDetails }; + + ConnectionCompleteParams connectionResult = await Connect(connectParams); + if (connectionResult == null) + { + return null; + } + + session = ObjectExplorerSession.CreateSession(connectionResult, serviceProvider); + sessionMap[uri] = session; + return session; + } + + + private async Task Connect(ConnectParams connectParams) + { + try + { + // open connection based on request details + ConnectionCompleteParams result = await connectionService.Connect(connectParams); + return result; + } + catch (Exception ex) + { + // Send a connection failed error message in this case. + ConnectionCompleteParams result = new ConnectionCompleteParams() + { + Messages = ex.ToString() + }; + await serviceHost.SendEvent(ConnectionCompleteNotification.Type, result); + return null; + } + } + + internal async Task HandleExpandRequest(ExpandParams expandParams, RequestContext context) + { + Logger.Write(LogLevel.Verbose, "HandleExpandRequest"); + Func> expandNode = async () => + { + Validate.IsNotNull(nameof(expandParams), expandParams); + Validate.IsNotNull(nameof(context), context); + + string uri = expandParams.SessionId; + ObjectExplorerSession session = null; + NodeInfo[] nodes = null; + if (sessionMap.ContainsKey(uri)) + { + session = sessionMap[uri]; + } + else + { + //TODO: error + } + + + if (session != null) + { + // Establish a connection to the specified server/database + nodes = await ExpandNode(session, expandParams.NodePath); + } + + ExpandResponse response; + response = new ExpandResponse() { Nodes = nodes, SessionId = uri }; + return response; + }; + + await HandleRequestAsync(expandNode, context, "HandleExpandRequest"); + } + + private async Task HandleRequestAsync(Func> handler, RequestContext requestContext, string requestType) + { + Logger.Write(LogLevel.Verbose, requestType); + + try + { + T result = await handler(); + await requestContext.SendResult(result); + } + catch (Exception ex) + { + await requestContext.SendError(ex.ToString()); + } + } + + /// + /// Generates a URI for object explorer using a similar pattern to Mongo DB (which has URI-based database definition) + /// as this should ensure uniqueness + /// + /// + /// string representing a URI + /// Internal for testing purposes only + internal static string GenerateUri(ConnectionDetails details) + { + Validate.IsNotNull("details", details); + string uri = string.Format(CultureInfo.InvariantCulture, "{0}{1}", uriPrefix, Uri.EscapeUriString(details.ServerName)); + uri = AppendIfExists(uri, "databaseName", details.DatabaseName); + uri = AppendIfExists(uri, "user", details.UserName); + return uri; + } + + private static string AppendIfExists(string uri, string propertyName, string propertyValue) + { + if (!string.IsNullOrEmpty(propertyValue)) + { + uri += string.Format(CultureInfo.InvariantCulture, ";{0}={1}", propertyName, Uri.EscapeUriString(propertyValue)); + } + return uri; + } + + public IEnumerable GetApplicableChildFactories(TreeNode item) + { + if (ApplicableNodeChildFactories != null) + { + HashSet applicableFactories; + if (ApplicableNodeChildFactories.TryGetValue(item.NodeTypeId.ToString(), out applicableFactories)) + { + return applicableFactories; + } + } + return null; + } + + internal Dictionary> PopulateFactories() + { + VerifyServicesInitialized(); + + var childFactories = new Dictionary>(); + // Create our list of all NodeType to ChildFactory objects so we can expand appropriately + foreach (var factory in serviceProvider.GetServices()) + { + var parents = factory.ApplicableParents(); + if (parents != null) + { + foreach (var parent in parents) + { + AddToApplicableChildFactories(childFactories, factory, parent); + } + } + } + return childFactories; + } + + private void VerifyServicesInitialized() + { + if (serviceProvider == null) + { + throw new InvalidOperationException(SqlTools.Hosting.Localization.sr.ServiceProviderNotSet); + } + if (connectionService == null) + { + throw new InvalidOperationException(SqlTools.Hosting.Localization.sr.ServiceProviderNotSet); + } + } + + private static void AddToApplicableChildFactories(Dictionary> childFactories, ChildFactory factory, string parent) + { + HashSet applicableFactories; + if (!childFactories.TryGetValue(parent, out applicableFactories)) + { + applicableFactories = new HashSet(); + childFactories[parent] = applicableFactories; + } + applicableFactories.Add(factory); + } + + internal class ObjectExplorerSession + { + 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 cache; + + public ObjectExplorerSession(string uri, TreeNode root, IMultiServiceProvider serviceProvider, ConnectionService connectionService) + { + 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 static ObjectExplorerSession CreateSession(ConnectionCompleteParams response, IMultiServiceProvider serviceProvider) + { + TreeNode serverNode = new ServerNode(response, serviceProvider); + return new ObjectExplorerSession(response.OwnerUri, serverNode, serviceProvider, serviceProvider.GetService()); + } + + } + } + +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerUtils.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerUtils.cs new file mode 100644 index 00000000..443c93a3 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerUtils.cs @@ -0,0 +1,76 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer +{ + /// + /// Utility class for Object Explorer related operations + /// + public static class ObjectExplorerUtils + { + /// + /// Visitor that walks all nodes from the child to the root node, unless the + /// function indicates that this should stop traversing + /// + /// node to start traversing at + /// Predicate function that accesses the tree and + /// determines whether to stop going further up the tree + /// + /// boolean - true to continue navigating up the tree, false to end the loop + /// and return early + /// + public static bool VisitChildAndParents(TreeNode child, Predicate visitor) + { + if (child == null) + { + // End case: all nodes have been visited + return true; + } + + // Visit the child first, then go up the parents + if (!visitor(child)) + { + return false; + } + return VisitChildAndParents(child.Parent, visitor); + } + + /// + /// Finds a node by traversing the tree starting from the given node through all the children + /// + /// node to start traversing at + /// Predicate function that accesses the tree and + /// determines whether to stop going further up the tree + /// Predicate function to filter the children when traversing + /// A Tree Node that matches the condition + public static TreeNode FindNode(TreeNode node, Predicate condition, Predicate filter) + { + if(node == null) + { + return null; + } + + if (condition(node)) + { + return node; + } + foreach (var child in node.GetChildren()) + { + if (filter != null && filter(child)) + { + TreeNode childNode = FindNode(child, condition, filter); + if (childNode != null) + { + return childNode; + } + } + } + return null; + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/DatabaseInstanceTreeNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/DatabaseInstanceTreeNode.cs new file mode 100644 index 00000000..cf375376 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/DatabaseInstanceTreeNode.cs @@ -0,0 +1,30 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + + +using Microsoft.SqlServer.Management.Smo; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ + internal partial class DatabaseInstanceTreeNode + { + + /// + /// Initializes the context and ensures that + /// + protected override void EnsureContextInitialized() + { + if (context == null) + { + base.EnsureContextInitialized(); + Database db = SmoObject as Database; + if (context != null && db != null) + { + context.Database = db; + } + } + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/FolderNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/FolderNode.cs new file mode 100644 index 00000000..1ee4f221 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/FolderNode.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlServer.Management.Smo; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ + /// + /// Represents a folder node in the tree + /// + public class FolderNode : SmoTreeNode + { + /// + /// For folders, this copies the context of its parent if available + /// + /// + public override object GetContext() + { + return Parent?.GetContext(); + } + + /// + /// For folders, searches for its parent's SMO object rather than copying for itself + /// + /// from this parent's parent, or null if not found + public override NamedSmoObject GetParentSmoObject() + { + return ParentAs()?.GetParentSmoObject(); + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/ServerNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/ServerNode.cs new file mode 100644 index 00000000..3703f7b7 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/ServerNode.cs @@ -0,0 +1,192 @@ +// +// 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.Data.Common; +using System.Data.SqlClient; +using System.Globalization; +using System.Linq; +using Microsoft.SqlServer.Management.Common; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlTools.Extensibility; +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; +using Microsoft.SqlTools.ServiceLayer.Utility; +using Microsoft.SqlTools.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ + /// + /// Server node implementation + /// + public class ServerNode : TreeNode + { + private ConnectionSummary connectionSummary; + private ServerInfo serverInfo; + private string connectionUri; + private Lazy context; + private ConnectionService connectionService; + private SmoServerCreator serverCreator; + + public ServerNode(ConnectionCompleteParams connInfo, IMultiServiceProvider serviceProvider) + : 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.connectionUri = connInfo.OwnerUri; + + this.connectionService = serviceProvider.GetService(); + + this.context = new Lazy(() => CreateContext(serviceProvider)); + + NodeValue = connectionSummary.ServerName; + IsAlwaysLeaf = false; + NodeType = NodeTypes.ServerInstance.ToString(); + NodeTypeId = NodeTypes.ServerInstance; + Label = GetConnectionLabel(); + } + + internal SmoServerCreator ServerCreator + { + get + { + if (serverCreator == null) + { + ServerCreator = new SmoServerCreator(); + } + return serverCreator; + } + set + { + this.serverCreator = value; + } + } + + /// + /// Returns the label to display to the user. + /// + 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 (!string.IsNullOrWhiteSpace(connectionSummary.DatabaseName) && + string.Compare(connectionSummary.DatabaseName, CommonConstants.MasterDatabaseName, StringComparison.OrdinalIgnoreCase) != 0 && + (serverInfo.IsCloud /* || !ci.IsAuthenticatingDatabaseMaster */)) + { + // We either have an azure with a database specified or a Denali database using a contained user + 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; + ConnectionInfo connectionInfo; + SqlConnection connection = null; + // Get server object from connection + if (!connectionService.TryFindConnection(this.connectionUri, out connectionInfo) || + connectionInfo.AllConnections == null || connectionInfo.AllConnections.Count == 0) + { + ErrorStateMessage = string.Format(CultureInfo.CurrentCulture, + SR.ServerNodeConnectionError, connectionSummary.ServerName); + return null; + } + //TODO: figure out how to use existing connections + DbConnection dbConnection = connectionInfo.AllConnections.First(); + ReliableSqlConnection reliableSqlConnection = dbConnection as ReliableSqlConnection; + SqlConnection sqlConnection = dbConnection as SqlConnection; + if (reliableSqlConnection != null) + { + connection = reliableSqlConnection.GetUnderlyingConnection(); + } + else if (sqlConnection != null) + { + connection = sqlConnection; + } + else + { + ErrorStateMessage = string.Format(CultureInfo.CurrentCulture, + SR.ServerNodeConnectionError, connectionSummary.ServerName); + return null; + } + + try + { + Server server = ServerCreator.Create(connection); + return new SmoQueryContext(server, serviceProvider) + { + Parent = server + }; + } + catch (ConnectionFailureException cfe) + { + exceptionMessage = cfe.Message; + } + catch (Exception ex) + { + exceptionMessage = ex.Message; + } + + Logger.Write(LogLevel.Error, "Exception at ServerNode.CreateContext() : " + exceptionMessage); + this.ErrorStateMessage = string.Format(SR.TreeNodeError, exceptionMessage); + return null; + } + + public override object GetContext() + { + return context.Value; + } + } + + /// + /// Internal for testing purposes only + /// + internal class SmoServerCreator + { + public virtual Server Create(SqlConnection connection) + { + ServerConnection serverConn = new ServerConnection(connection); + return new Server(serverConn); + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs new file mode 100644 index 00000000..6aa7a072 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs @@ -0,0 +1,161 @@ +// +// 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.Diagnostics; +using System.Linq; +using System.Reflection; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; +using Microsoft.SqlTools.ServiceLayer.Utility; +using Microsoft.SqlTools.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ + public class SmoChildFactoryBase : ChildFactory + { + public override IEnumerable ApplicableParents() + { + return null; + } + + public override IEnumerable Expand(TreeNode parent) + { + //parent.BeginChildrenInit(); + try + { + List allChildren = new List(); + OnExpandPopulateFolders(allChildren, parent); + RemoveFoldersFromInvalidSqlServerVersions(allChildren, parent); + OnExpandPopulateNonFolders(allChildren, parent); + OnBeginAsyncOperations(parent); + return allChildren; + } + finally + { + //parent.EndChildrenInit(); + } + } + + /// + /// Populates any folders for a given parent node + /// + /// List to which nodes should be added + /// Parent the nodes are being added to + protected virtual void OnExpandPopulateFolders(IList allChildren, TreeNode parent) + { + } + + /// + /// Populates any non-folder nodes such as specific items in the tree. + /// + /// List to which nodes should be added + /// Parent the nodes are being added to + protected virtual void OnExpandPopulateNonFolders(IList allChildren, TreeNode parent) + { + if (ChildQuerierTypes == null) + { + // This node does not support non-folder children + return; + } + SmoQueryContext context = parent.GetContextAs(); + Validate.IsNotNull(nameof(context), context); + IEnumerable queriers = context.ServiceProvider.GetServices(q => IsCompatibleQuerier(q)); + foreach (var querier in queriers) + { + foreach(var smoObject in querier.Query(context)) + { + if (smoObject == null) + { + Console.WriteLine("smoObject should not be null"); + } + TreeNode childNode = CreateChild(parent, smoObject); + if (childNode != null) + { + allChildren.Add(childNode); + } + } + } + } + + 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; + + } + + /// + /// Filters out invalid folders if they cannot be displayed for the current server version + /// + /// List to which nodes should be added + /// Parent the nodes are being added to + protected virtual void RemoveFoldersFromInvalidSqlServerVersions(IList 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 child, object context) + { + NamedSmoObject smoObj = context as NamedSmoObject; + if (smoObj == null) + { + Debug.WriteLine("context is not a NamedSmoObject. type: " + context.GetType()); + } + else + { + SmoTreeNode childAsMeItem = (SmoTreeNode)child; + childAsMeItem.CacheInfoFromModel(smoObj); + } + } + + internal virtual Type[] ChildQuerierTypes { + get + { + return null; + } + } + + /// + /// 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 + /// + /// + /// + /// boolean + public virtual bool PassesFinalFilters(TreeNode parent, object context) + { + return true; + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoCollectionWrapper.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoCollectionWrapper.cs new file mode 100644 index 00000000..13122300 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoCollectionWrapper.cs @@ -0,0 +1,57 @@ +// +// 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; +using System.Collections.Generic; +using Microsoft.SqlServer.Management.Smo; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ + /// + /// Wrapper to convert non-generic Smo enumerables to generic enumerable types for easier use in + /// + /// + public class SmoCollectionWrapper : IEnumerable + where T : SqlSmoObject + { + private SmoCollectionBase collection; + + /// + /// Constructor which accepts a containing the objects + /// to wrap + /// + /// or null if none were set + public SmoCollectionWrapper(SmoCollectionBase collection) + { + this.collection = collection; + } + + /// + /// + /// + /// + public IEnumerator GetEnumerator() + { + if (collection == null) + { + yield break; + } + foreach(Object obj in collection) + { + yield return (T)obj; + } + } + + /// + /// + /// + /// + IEnumerator IEnumerable.GetEnumerator() + { + return collection?.GetEnumerator(); + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQuerier.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQuerier.cs new file mode 100644 index 00000000..87373258 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQuerier.cs @@ -0,0 +1,42 @@ +// +// 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 Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlTools.Extensibility; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ + /// + /// A handles SMO queries for one or more SMO object types. + /// The property defines which types can be queried. + /// + /// To query multiple + /// + public abstract class SmoQuerier : IComposableService + { + public abstract Type[] SupportedObjectTypes { get; } + + /// + /// Queries SMO for a collection of objects using the + /// + /// + /// + public abstract IEnumerable Query(SmoQueryContext context); + + internal IMultiServiceProvider ServiceProvider + { + get; + private set; + } + + public void SetServiceProvider(IMultiServiceProvider provider) + { + ServiceProvider = provider; + } + } + +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryContext.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryContext.cs new file mode 100644 index 00000000..d933c5f9 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryContext.cs @@ -0,0 +1,102 @@ +// +// 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; +using System.Collections.Generic; +using System.Globalization; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlTools.Extensibility; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ + /// + /// Context object containing key properties needed to query for SMO objects + /// + public class SmoQueryContext + { + /// + /// Creates a context object with a server to use as the basis for any queries + /// + /// + public SmoQueryContext(Server server, IMultiServiceProvider serviceProvider) + { + Server = server; + ServiceProvider = serviceProvider; + } + + /// + /// The server SMO will query against + /// + public Server Server { get; private set; } + + /// + /// Optional Database context object to query against + /// + public Database Database { get; set; } + + /// + /// Parent of a give node to use for queries + /// + public SmoObjectBase Parent { get; set; } + + /// + /// A query loader that can be used to find objects + /// for specific SMO types + /// + public IMultiServiceProvider ServiceProvider { get; private set; } + + /// + /// Helper method to cast a parent to a specific type + /// + /// + /// + public T ParentAs() + where T : TreeNode + { + return Parent as T; + } + + /// + /// Gets the if available, by looking it up + /// from the + /// + /// + /// + /// Thrown if the is not set or the + /// isn't available from that provider + /// + public ObjectExplorerService GetObjectExplorerService() + { + if (ServiceProvider == null) + { + throw new InvalidOperationException(SqlTools.Hosting.Localization.sr.ServiceProviderNotSet); + } + ObjectExplorerService service = ServiceProvider.GetService(); + if (service == null) + { + throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, + SqlTools.Hosting.Localization.sr.ServiceNotFound, nameof(ObjectExplorerService))); + } + + return service; + } + /// + /// Copies the context for use by another node + /// + /// New Parent to set + /// new with all fields except the same + public SmoQueryContext CopyWithParent(SmoObjectBase parent) + { + SmoQueryContext context = new SmoQueryContext(this.Server, this.ServiceProvider) + { + Database = this.Database, + Parent = parent + }; + return context; + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs new file mode 100644 index 00000000..a87a1dc4 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs @@ -0,0 +1,1583 @@ + + + + + + + + + +// 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; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ + + [Export(typeof(SmoQuerier))] + internal partial class SqlDatabaseQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Database) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.Databases; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlLinkedServerLoginQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(LinkedServer) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.LinkedServers; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlLoginQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Login) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.Logins; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlServerRoleQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ServerRole) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.Roles; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlCredentialQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Credential) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.Credentials; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlCryptographicProviderQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(CryptographicProvider) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.CryptographicProviders; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlServerAuditQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Audit) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.Audits; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlServerAuditSpecificationQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ServerAuditSpecification) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.ServerAuditSpecifications; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlEndpointQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Endpoint) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.Endpoints; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlLinkedServerQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(LinkedServer) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.LinkedServers; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlServerDdlTriggerQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ServerDdlTrigger) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.Triggers; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlErrorMessageQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(UserDefinedMessage) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.UserDefinedMessages; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlTableQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Table) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.Tables; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlViewQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(View) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.Views; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlSynonymQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Synonym) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.Synonyms; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlColumnQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Column) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + TableViewTableTypeBase parentTableViewTableTypeBase = context.Parent as TableViewTableTypeBase; + if (parentTableViewTableTypeBase != null) + { + var retValue = parentTableViewTableTypeBase.Columns; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlIndexQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Index) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + TableViewTableTypeBase parentTableViewTableTypeBase = context.Parent as TableViewTableTypeBase; + if (parentTableViewTableTypeBase != null) + { + var retValue = parentTableViewTableTypeBase.Indexes; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlCheckQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Check) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Table parentTable = context.Parent as Table; + if (parentTable != null) + { + var retValue = parentTable.Checks; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlForeignKeyConstraintQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ForeignKey) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Table parentTable = context.Parent as Table; + if (parentTable != null) + { + var retValue = parentTable.ForeignKeys; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlDefaultConstraintQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(DefaultConstraint) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Column parentColumn = context.Parent as Column; + if (parentColumn != null) + { + var retValue = parentColumn.DefaultConstraint; + if(retValue != null) + { + return new SqlSmoObject[] { retValue }; + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlDmlTriggerQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Trigger) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Table parentTable = context.Parent as Table; + if (parentTable != null) + { + var retValue = parentTable.Triggers; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlFullTextIndexQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(FullTextIndex) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Table parentTable = context.Parent as Table; + if (parentTable != null) + { + var retValue = parentTable.FullTextIndex; + if(retValue != null) + { + return new SqlSmoObject[] { retValue }; + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlStatisticQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Statistic) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + TableViewBase parentTableViewBase = context.Parent as TableViewBase; + if (parentTableViewBase != null) + { + var retValue = parentTableViewBase.Statistics; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlDatabaseDdlTriggerQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Trigger) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.Triggers; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlAssemblyQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(SqlAssembly) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.Assemblies; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlRuleQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Rule) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.Rules; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlDefaultQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Default) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.Defaults; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlSequenceQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Sequence) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.Sequences; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlSystemDataTypeQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(SystemDataType) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.SystemDataTypes; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlUserDefinedDataTypeQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(UserDefinedDataType) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.UserDefinedDataTypes; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlUserDefinedTableTypeQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(UserDefinedTableType) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.UserDefinedTableTypes; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlXmlSchemaCollectionQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(XmlSchemaCollection) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.XmlSchemaCollections; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlUserDefinedTypeQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(UserDefinedType) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.UserDefinedTypes; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlUserDefinedFunctionQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(UserDefinedFunction) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.UserDefinedFunctions; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlUserDefinedAggregateQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(UserDefinedAggregate) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.UserDefinedAggregates; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlFileGroupQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(FileGroup) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.FileGroups; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlFileQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(DataFile) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + FileGroup parentFileGroup = context.Parent as FileGroup; + if (parentFileGroup != null) + { + var retValue = parentFileGroup.Files; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlFullTextCatalogQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(FullTextCatalog) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.FullTextCatalogs; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlFullTextStopListQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(FullTextStopList) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.FullTextStopLists; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlPartitionFunctionQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(PartitionFunction) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.PartitionFunctions; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlPartitionSchemeQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(PartitionScheme) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.PartitionSchemes; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlSearchPropertyListQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(SearchPropertyList) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.SearchPropertyLists; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlUserQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(User) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.Users; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlSchemaQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Schema) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.Schemas; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlAsymmetricKeyQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(AsymmetricKey) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.AsymmetricKeys; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlCertificateQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Certificate) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.Certificates; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlSymmetricKeyQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(SymmetricKey) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.SymmetricKeys; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlDatabaseEncryptionKeyQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(DatabaseEncryptionKey) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.DatabaseEncryptionKey; + if(retValue != null) + { + return new SqlSmoObject[] { retValue }; + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlMasterKeyQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(MasterKey) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.MasterKey; + if(retValue != null) + { + return new SqlSmoObject[] { retValue }; + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlDatabaseAuditSpecificationQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(DatabaseAuditSpecification) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.DatabaseAuditSpecifications; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlSecurityPolicyQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(SecurityPolicy) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.SecurityPolicies; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlDatabaseCredentialQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(DatabaseScopedCredential) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.DatabaseScopedCredentials; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlRoleQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(DatabaseRole) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.Roles; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlApplicationRoleQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ApplicationRole) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.ApplicationRoles; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlColumnMasterKeyQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ColumnMasterKey) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.ColumnMasterKeys; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlColumnEncryptionKeyQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ColumnEncryptionKey) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.ColumnEncryptionKeys; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlServiceBrokerQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ServiceBroker) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.ServiceBroker; + if(retValue != null) + { + return new SqlSmoObject[] { retValue }; + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlServiceQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(BrokerService) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + ServiceBroker parentServiceBroker = context.Parent as ServiceBroker; + if (parentServiceBroker != null) + { + var retValue = parentServiceBroker.Services; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlContractQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ServiceContract) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + ServiceBroker parentServiceBroker = context.Parent as ServiceBroker; + if (parentServiceBroker != null) + { + var retValue = parentServiceBroker.ServiceContracts; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlQueueQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ServiceQueue) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + ServiceBroker parentServiceBroker = context.Parent as ServiceBroker; + if (parentServiceBroker != null) + { + var retValue = parentServiceBroker.Queues; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlRemoteServiceBindingQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(RemoteServiceBinding) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + ServiceBroker parentServiceBroker = context.Parent as ServiceBroker; + if (parentServiceBroker != null) + { + var retValue = parentServiceBroker.RemoteServiceBindings; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlBrokerPriorityQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(BrokerPriority) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + ServiceBroker parentServiceBroker = context.Parent as ServiceBroker; + if (parentServiceBroker != null) + { + var retValue = parentServiceBroker.Priorities; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlMessageTypeQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(MessageType) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + ServiceBroker parentServiceBroker = context.Parent as ServiceBroker; + if (parentServiceBroker != null) + { + var retValue = parentServiceBroker.MessageTypes; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlExternalDataSourceQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ExternalDataSource) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.ExternalDataSources; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlExternalFileFormatQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ExternalFileFormat) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.ExternalFileFormats; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlProcedureQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(StoredProcedure) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.StoredProcedures; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlExtendedStoredProcedureQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(ExtendedStoredProcedure) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Database parentDatabase = context.Parent as Database; + if (parentDatabase != null) + { + var retValue = parentDatabase.ExtendedStoredProcedures; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlSubroutineParameterQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(Parameter) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + StoredProcedure parentStoredProcedure = context.Parent as StoredProcedure; + if (parentStoredProcedure != null) + { + var retValue = parentStoredProcedure.Parameters; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + UserDefinedAggregate parentUserDefinedAggregate = context.Parent as UserDefinedAggregate; + if (parentUserDefinedAggregate != null) + { + var retValue = parentUserDefinedAggregate.Parameters; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + UserDefinedFunction parentUserDefinedFunction = context.Parent as UserDefinedFunction; + if (parentUserDefinedFunction != null) + { + var retValue = parentUserDefinedFunction.Parameters; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlPartitionFunctionParameterQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(PartitionFunctionParameter) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + PartitionFunction parentPartitionFunction = context.Parent as PartitionFunction; + if (parentPartitionFunction != null) + { + var retValue = parentPartitionFunction.PartitionFunctionParameters; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + + [Export(typeof(SmoQuerier))] + internal partial class SqlBuiltInTypeQuerier: SmoQuerier + { + Type[] supportedTypes = new Type[] { typeof(SystemDataType) }; + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } + + public override IEnumerable Query(SmoQueryContext context) + { + Server parentServer = context.Parent as Server; + if (parentServer != null) + { + var retValue = parentServer.SystemDataTypes; + if(retValue != null) + { + return new SmoCollectionWrapper(retValue); + } + } + return Enumerable.Empty(); + } + } + +} + diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.tt b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.tt new file mode 100644 index 00000000..99fe3fcd --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.tt @@ -0,0 +1,215 @@ +<#@ 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" #> +// 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; + +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 parents = GetParents(nodeElement, xmlFile, nodeName); + string nodeType = GetNodeType(nodeElement, nodeName); + + string queryBaseClass = "SmoQuerier"; + PushIndent(indent); + WriteLine(""); + WriteLine(string.Format("[Export(typeof({0}))]", queryBaseClass)); + WriteLine(string.Format("internal partial class {0}Querier: {1}", nodeName, queryBaseClass)); + WriteLine("{"); + PushIndent(indent); + + // Supported Types + WriteLine("Type[] supportedTypes = new Type[] { typeof("+ nodeType + ") };"); + WriteLine(""); + WriteLine("public override Type[] SupportedObjectTypes { get { return supportedTypes; } }"); + WriteLine(""); + + // Query impl + WriteLine("public override IEnumerable Query(SmoQueryContext context)"); + WriteLine("{"); + PushIndent(indent); + + // TODO Allow override of the navigation path + foreach(var parentType in parents) + { + string parentVar = string.Format("parent{0}", parentType); + WriteLine(string.Format("{0} {1} = context.Parent as {0};", parentType, parentVar)); + WriteLine(string.Format("if ({0} != null)", parentVar)); + WriteLine("{"); + PushIndent(indent); + + string navigationPath = GetNavigationPath(nodeElement, xmlFile, nodeName, parentType); + WriteLine(string.Format("var retValue = {0}.{1};", parentVar, navigationPath)); + WriteLine("if(retValue != null)"); + WriteLine("{"); + PushIndent(indent); + if (IsCollection(nodeElement)) + { + WriteLine(string.Format("return new SmoCollectionWrapper<{0}>(retValue);", nodeType)); + } + else + { + WriteLine("return new SqlSmoObject[] { retValue };"); + } + PopIndent(); + WriteLine("}"); + PopIndent(); + WriteLine("}"); // close If + } + + WriteLine("return Enumerable.Empty();"); + + PopIndent(); + WriteLine("}"); // close Query method + PopIndent(); + WriteLine("}"); // close Class + PopIndent(); + } +#> +} + +<#+ + + public static string[] GetNodes(string xmlFile) + { + List typesList = new List(); + 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 string GetNavPathField(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?.GetAttribute("Field"); + } + + public static string GetNavigationPath(XmlElement nodeElement, string xmlFile, string nodeName, string parentName) + { + string navPathField = GetNavPathField(xmlFile, nodeName, parentName); + 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 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 parents = new List(); + int i = 0; + 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 GetChildren(string xmlFile, string parentName, string childNode) + { + XmlElement nodeElement = GetNodeElement(xmlFile, parentName); + XmlDocument doc = new XmlDocument(); + doc.Load(xmlFile); + + List retElements = new List(); + 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; + } + +#> \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModelDefinition.xml b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModelDefinition.xml new file mode 100644 index 00000000..fd1a5960 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModelDefinition.xml @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + StoredProcedure + UserDefinedAggregate + UserDefinedFunction + + + + + + + + + + diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNode.cs new file mode 100644 index 00000000..d732cd47 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoTreeNode.cs @@ -0,0 +1,90 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ + /// + /// A Node in the tree representing a SMO-based object + /// + 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 + } + + /// + /// Is this a system (MSShipped) object? + /// + public bool IsMsShippedOwned { get; set; } + + /// + /// Indicates which platforms a node is valid for + /// + public ValidForFlag ValidFor { get; set; } + + /// + /// Gets an incrementing sort priority value to assist in automatically sorting + /// elements in a tree + /// + 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; + } + + 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()?.GetParentSmoObject(); + } + + public override object GetContext() + { + EnsureContextInitialized(); + return context; + } + + protected virtual void EnsureContextInitialized() + { + if (context == null) + { + SmoObjectBase smoParent = GetParentSmoObject(); + SmoQueryContext parentContext = Parent?.GetContextAs(); + if (smoParent != null && parentContext != null) + { + context = parentContext.CopyWithParent(smoParent); + } + } + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SystemDataTypeChildFactories.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SystemDataTypeChildFactories.cs new file mode 100644 index 00000000..5f860c40 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SystemDataTypeChildFactories.cs @@ -0,0 +1,208 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +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 _exactNumerics = new HashSet{ + "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 _approxNumerics = new HashSet{ + "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 _dateAndTime = new HashSet{ + "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 _characterStrings = new HashSet{ + "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 _unicodeCharacterStrings = new HashSet + { + "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 _binaryStrings = new HashSet{ + "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 _otherDataTypes = new HashSet{ + "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 _clrDataTypes = new HashSet{ + "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 _spatialDataTypes = new HashSet{ + "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; + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeDefinition.xml b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeDefinition.xml new file mode 100644 index 00000000..ea347cb9 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeDefinition.xml @@ -0,0 +1,396 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TemporalTableType.None + TemporalTableType.SystemVersioned + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TemporalTableType.History + + + + + + + + + + + + + + + + + + + + + + + + + + + + IndexKeyType.DriPrimaryKey + IndexKeyType.DriUniqueKey + + + + + + + + + IndexKeyType.None + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IndexKeyType.DriPrimaryKey + IndexKeyType.DriUniqueKey + + + + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + UserDefinedFunctionType.Table + + + + + + + + + + + + UserDefinedFunctionType.Table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.cs new file mode 100644 index 00000000..fc994563 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.cs @@ -0,0 +1,3466 @@ + + + + + + + + + +using System; +using System.Collections.Generic; +using System.Composition; +using Microsoft.SqlTools.ServiceLayer; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ + + internal sealed partial class DatabaseInstanceTreeNode : SmoTreeNode + { + public DatabaseInstanceTreeNode() : base() + { + NodeValue = string.Empty; + this.NodeType = "DatabaseInstance"; + this.NodeTypeId = NodeTypes.DatabaseInstance; + OnInitialize(); + } + } + + internal sealed partial class TableInstanceTreeNode : SmoTreeNode + { + public TableInstanceTreeNode() : base() + { + NodeValue = string.Empty; + this.NodeType = "TableInstance"; + this.NodeTypeId = NodeTypes.TableInstance; + OnInitialize(); + } + } + + internal sealed partial class ViewInstanceTreeNode : SmoTreeNode + { + public ViewInstanceTreeNode() : base() + { + NodeValue = string.Empty; + this.NodeType = "ViewInstance"; + this.NodeTypeId = NodeTypes.ViewInstance; + OnInitialize(); + } + } + + internal sealed partial class UserDefinedTableTypeInstanceTreeNode : SmoTreeNode + { + public UserDefinedTableTypeInstanceTreeNode() : base() + { + NodeValue = string.Empty; + this.NodeType = "UserDefinedTableTypeInstance"; + this.NodeTypeId = NodeTypes.UserDefinedTableTypeInstance; + OnInitialize(); + } + } + + internal sealed partial class StoredProcedureInstanceTreeNode : SmoTreeNode + { + public StoredProcedureInstanceTreeNode() : base() + { + NodeValue = string.Empty; + this.NodeType = "StoredProcedureInstance"; + this.NodeTypeId = NodeTypes.StoredProcedureInstance; + OnInitialize(); + } + } + + internal sealed partial class TableValuedFunctionInstanceTreeNode : SmoTreeNode + { + public TableValuedFunctionInstanceTreeNode() : base() + { + NodeValue = string.Empty; + this.NodeType = "TableValuedFunctionInstance"; + this.NodeTypeId = NodeTypes.TableValuedFunctionInstance; + OnInitialize(); + } + } + + internal sealed partial class ScalarValuedFunctionInstanceTreeNode : SmoTreeNode + { + public ScalarValuedFunctionInstanceTreeNode() : base() + { + NodeValue = string.Empty; + this.NodeType = "ScalarValuedFunctionInstance"; + this.NodeTypeId = NodeTypes.ScalarValuedFunctionInstance; + OnInitialize(); + } + } + + internal sealed partial class AggregateFunctionInstanceTreeNode : SmoTreeNode + { + public AggregateFunctionInstanceTreeNode() : base() + { + NodeValue = string.Empty; + this.NodeType = "AggregateFunctionInstance"; + this.NodeTypeId = NodeTypes.AggregateFunctionInstance; + OnInitialize(); + } + } + + internal sealed partial class FileGroupInstanceTreeNode : SmoTreeNode + { + public FileGroupInstanceTreeNode() : base() + { + NodeValue = string.Empty; + this.NodeType = "FileGroupInstance"; + this.NodeTypeId = NodeTypes.FileGroupInstance; + OnInitialize(); + } + } + + internal sealed partial class ExternalTableInstanceTreeNode : SmoTreeNode + { + public ExternalTableInstanceTreeNode() : base() + { + NodeValue = string.Empty; + this.NodeType = "ExternalTableInstance"; + this.NodeTypeId = NodeTypes.ExternalTableInstance; + OnInitialize(); + } + } + + internal sealed partial class ExternalResourceInstanceTreeNode : SmoTreeNode + { + public ExternalResourceInstanceTreeNode() : base() + { + NodeValue = string.Empty; + this.NodeType = "ExternalResourceInstance"; + this.NodeTypeId = NodeTypes.ExternalResourceInstance; + OnInitialize(); + } + } + + internal sealed partial class HistoryTableInstanceTreeNode : SmoTreeNode + { + public HistoryTableInstanceTreeNode() : base() + { + NodeValue = string.Empty; + this.NodeType = "HistoryTableInstance"; + this.NodeTypeId = NodeTypes.HistoryTableInstance; + OnInitialize(); + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerInstanceChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerInstance" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Databases, + NodeType = "Folder", + NodeTypeId = NodeTypes.Databases, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Security, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelSecurity, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.Azure|ValidForFlag.AzureV12|ValidForFlag.NotContainedUser|ValidForFlag.CanViewSecurity, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ServerObjects, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelServerObjects, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.NotContainedUser, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class DatabasesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Databases" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemDatabases, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemDatabases, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.Azure|ValidForFlag.AzureV12|ValidForFlag.NotContainedUser|ValidForFlag.CanConnectToMaster, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlDatabaseQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new DatabaseInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelSecurityChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelSecurity" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_LinkedServerLogins, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelLinkedServerLogins, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Logins, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelLogins, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ServerRoles, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelServerRoles, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Credentials, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelCredentials, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_CryptographicProviders, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelCryptographicProviders, + ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.NotDebugInstance, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ServerAudits, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelServerAudits, + ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ServerAuditSpecifications, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelServerAuditSpecifications, + ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelServerObjectsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelServerObjects" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Endpoints, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelEndpoints, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_LinkedServers, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelLinkedServers, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ServerTriggers, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelServerTriggers, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ErrorMessages, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServerLevelErrorMessages, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemDatabasesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemDatabases" }; } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelLinkedServerLoginsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelLinkedServerLogins" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlLinkedServerLoginQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelLoginsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelLogins" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlLoginQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelServerRolesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelServerRoles" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlServerRoleQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelCredentialsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelCredentials" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlCredentialQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelCryptographicProvidersChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelCryptographicProviders" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlCryptographicProviderQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelServerAuditsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelServerAudits" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlServerAuditQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelServerAuditSpecificationsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelServerAuditSpecifications" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlServerAuditSpecificationQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelEndpointsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelEndpoints" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlEndpointQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelLinkedServersChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelLinkedServers" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlLinkedServerQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelServerTriggersChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelServerTriggers" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlServerDdlTriggerQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServerLevelErrorMessagesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServerLevelErrorMessages" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlErrorMessageQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class DatabaseInstanceChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "DatabaseInstance" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Tables, + NodeType = "Folder", + NodeTypeId = NodeTypes.Tables, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Views, + NodeType = "Folder", + NodeTypeId = NodeTypes.Views, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Synonyms, + NodeType = "Folder", + NodeTypeId = NodeTypes.Synonyms, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Programmability, + NodeType = "Folder", + NodeTypeId = NodeTypes.Programmability, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ExternalResources, + NodeType = "Folder", + NodeTypeId = NodeTypes.ExternalResources, + ValidFor = ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ServiceBroker, + NodeType = "Folder", + NodeTypeId = NodeTypes.ServiceBroker, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Storage, + NodeType = "Folder", + NodeTypeId = NodeTypes.Storage, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Security, + NodeType = "Folder", + NodeTypeId = NodeTypes.Security, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new Type[0]; } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class TablesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Tables" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemTables, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemTables, + IsMsShippedOwned = true, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_FileTables, + NodeType = "Folder", + NodeTypeId = NodeTypes.FileTables, + ValidFor = ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.NotDebugInstance, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ExternalTables, + NodeType = "Folder", + NodeTypeId = NodeTypes.ExternalTables, + ValidFor = ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlTableQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new TableInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ViewsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Views" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemViews, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemViews, + IsMsShippedOwned = true, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlViewQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new ViewInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SynonymsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Synonyms" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlSynonymQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ProgrammabilityChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Programmability" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_StoredProcedures, + NodeType = "Folder", + NodeTypeId = NodeTypes.StoredProcedures, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Functions, + NodeType = "Folder", + NodeTypeId = NodeTypes.Functions, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_DatabaseTriggers, + NodeType = "Folder", + NodeTypeId = NodeTypes.DatabaseTriggers, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Assemblies, + NodeType = "Folder", + NodeTypeId = NodeTypes.Assemblies, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Types, + NodeType = "Folder", + NodeTypeId = NodeTypes.Types, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Rules, + NodeType = "Folder", + NodeTypeId = NodeTypes.Rules, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Defaults, + NodeType = "Folder", + NodeTypeId = NodeTypes.Defaults, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Sequences, + NodeType = "Folder", + NodeTypeId = NodeTypes.Sequences, + ValidFor = ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ExternalResourcesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ExternalResources" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ExternalDataSources, + NodeType = "Folder", + NodeTypeId = NodeTypes.ExternalDataSources, + ValidFor = ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ExternalFileFormats, + NodeType = "Folder", + NodeTypeId = NodeTypes.ExternalFileFormats, + ValidFor = ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServiceBrokerChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ServiceBroker" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_MessageTypes, + NodeType = "Folder", + NodeTypeId = NodeTypes.MessageTypes, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Contracts, + NodeType = "Folder", + NodeTypeId = NodeTypes.Contracts, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Queues, + NodeType = "Folder", + NodeTypeId = NodeTypes.Queues, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Services, + NodeType = "Folder", + NodeTypeId = NodeTypes.Services, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_RemoteServiceBindings, + NodeType = "Folder", + NodeTypeId = NodeTypes.RemoteServiceBindings, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_BrokerPriorities, + NodeType = "Folder", + NodeTypeId = NodeTypes.BrokerPriorities, + ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class StorageChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Storage" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_FileGroups, + NodeType = "Folder", + NodeTypeId = NodeTypes.FileGroups, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_FullTextCatalogs, + NodeType = "Folder", + NodeTypeId = NodeTypes.FullTextCatalogs, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_FullTextStopLists, + NodeType = "Folder", + NodeTypeId = NodeTypes.FullTextStopLists, + ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_LogFiles, + NodeType = "Folder", + NodeTypeId = NodeTypes.SqlLogFiles, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_PartitionFunctions, + NodeType = "Folder", + NodeTypeId = NodeTypes.PartitionFunctions, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_PartitionSchemes, + NodeType = "Folder", + NodeTypeId = NodeTypes.PartitionSchemes, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SearchPropertyLists, + NodeType = "Folder", + NodeTypeId = NodeTypes.SearchPropertyLists, + ValidFor = ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SecurityChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Security" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Users, + NodeType = "Folder", + NodeTypeId = NodeTypes.Users, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Roles, + NodeType = "Folder", + NodeTypeId = NodeTypes.Roles, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Schemas, + NodeType = "Folder", + NodeTypeId = NodeTypes.Schemas, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_AsymmetricKeys, + NodeType = "Folder", + NodeTypeId = NodeTypes.AsymmetricKeys, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Certificates, + NodeType = "Folder", + NodeTypeId = NodeTypes.Certificates, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SymmetricKeys, + NodeType = "Folder", + NodeTypeId = NodeTypes.SymmetricKeys, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_DatabaseScopedCredentials, + NodeType = "Folder", + NodeTypeId = NodeTypes.DatabaseScopedCredentials, + ValidFor = ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_DatabaseEncryptionKeys, + NodeType = "Folder", + NodeTypeId = NodeTypes.DatabaseEncryptionKeys, + ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_MasterKeys, + NodeType = "Folder", + NodeTypeId = NodeTypes.MasterKeys, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_DatabaseAuditSpecifications, + NodeType = "Folder", + NodeTypeId = NodeTypes.DatabaseAuditSpecifications, + ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SecurityPolicies, + NodeType = "Folder", + NodeTypeId = NodeTypes.SecurityPolicies, + ValidFor = ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_AlwaysEncryptedKeys, + NodeType = "Folder", + NodeTypeId = NodeTypes.AlwaysEncryptedKeys, + ValidFor = ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemTablesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemTables" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlTableQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new TableInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class FileTablesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "FileTables" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlTableQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new TableInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ExternalTablesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ExternalTables" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlTableQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new ExternalTableInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class TableInstanceChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "TableInstance" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Columns, + NodeType = "Folder", + NodeTypeId = NodeTypes.Columns, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Keys, + NodeType = "Folder", + NodeTypeId = NodeTypes.Keys, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Constraints, + NodeType = "Folder", + NodeTypeId = NodeTypes.Constraints, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Triggers, + NodeType = "Folder", + NodeTypeId = NodeTypes.Triggers, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Indexes, + NodeType = "Folder", + NodeTypeId = NodeTypes.Indexes, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Statistics, + NodeType = "Folder", + NodeTypeId = NodeTypes.Statistics, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlTableQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new HistoryTableInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class HistoryTableInstanceChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "HistoryTableInstance" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Columns, + NodeType = "Folder", + NodeTypeId = NodeTypes.Columns, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Indexes, + NodeType = "Folder", + NodeTypeId = NodeTypes.Indexes, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Statistics, + NodeType = "Folder", + NodeTypeId = NodeTypes.Statistics, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlTableQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ExternalTableInstanceChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ExternalTableInstance" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Columns, + NodeType = "Folder", + NodeTypeId = NodeTypes.Columns, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Statistics, + NodeType = "Folder", + NodeTypeId = NodeTypes.Statistics, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlTableQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ColumnsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Columns" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlColumnQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + child.SortPriority = SmoTreeNode.NextSortPriority; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class KeysChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Keys" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlIndexQuerier), typeof(SqlForeignKeyConstraintQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ConstraintsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Constraints" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlDefaultConstraintQuerier), typeof(SqlCheckQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class TriggersChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Triggers" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlDmlTriggerQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class IndexesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Indexes" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlIndexQuerier), typeof(SqlFullTextIndexQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class StatisticsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Statistics" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlStatisticQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemViewsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemViews" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlViewQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new ViewInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ViewInstanceChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ViewInstance" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Columns, + NodeType = "Folder", + NodeTypeId = NodeTypes.Columns, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Triggers, + NodeType = "Folder", + NodeTypeId = NodeTypes.Triggers, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Indexes, + NodeType = "Folder", + NodeTypeId = NodeTypes.Indexes, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Statistics, + NodeType = "Folder", + NodeTypeId = NodeTypes.Statistics, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new Type[0]; } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class FunctionsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Functions" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_TableValuedFunctions, + NodeType = "Folder", + NodeTypeId = NodeTypes.TableValuedFunctions, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ScalarValuedFunctions, + NodeType = "Folder", + NodeTypeId = NodeTypes.ScalarValuedFunctions, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_AggregateFunctions, + NodeType = "Folder", + NodeTypeId = NodeTypes.AggregateFunctions, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class DatabaseTriggersChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "DatabaseTriggers" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlDatabaseDdlTriggerQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class AssembliesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Assemblies" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlAssemblyQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class TypesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Types" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemDataTypes, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemDataTypes, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_UserDefinedDataTypes, + NodeType = "Folder", + NodeTypeId = NodeTypes.UserDefinedDataTypes, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_UserDefinedTableTypes, + NodeType = "Folder", + NodeTypeId = NodeTypes.UserDefinedTableTypes, + ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.Azure|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_UserDefinedTypes, + NodeType = "Folder", + NodeTypeId = NodeTypes.UserDefinedTypes, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_XMLSchemaCollections, + NodeType = "Folder", + NodeTypeId = NodeTypes.XmlSchemaCollections, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class RulesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Rules" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlRuleQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class DefaultsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Defaults" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlDefaultQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SequencesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Sequences" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlSequenceQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemDataTypesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemDataTypes" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemExactNumerics, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemExactNumerics, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemApproximateNumerics, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemApproximateNumerics, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemDateAndTime, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemDateAndTimes, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemCharacterStrings, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemCharacterStrings, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemUnicodeCharacterStrings, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemUnicodeCharacterStrings, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemBinaryStrings, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemBinaryStrings, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemOtherDataTypes, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemOtherDataTypes, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemCLRDataTypes, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemClrDataTypes, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.Azure|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemSpatialDataTypes, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemSpatialDataTypes, + ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.Azure|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class UserDefinedDataTypesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "UserDefinedDataTypes" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlUserDefinedDataTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class UserDefinedTableTypesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "UserDefinedTableTypes" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlUserDefinedTableTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new UserDefinedTableTypeInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class UserDefinedTypesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "UserDefinedTypes" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlUserDefinedTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class XmlSchemaCollectionsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "XmlSchemaCollections" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlXmlSchemaCollectionQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class UserDefinedTableTypeInstanceChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "UserDefinedTableTypeInstance" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Columns, + NodeType = "Folder", + NodeTypeId = NodeTypes.UserDefinedTableTypeColumns, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Keys, + NodeType = "Folder", + NodeTypeId = NodeTypes.UserDefinedTableTypeKeys, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Constraints, + NodeType = "Folder", + NodeTypeId = NodeTypes.UserDefinedTableTypeConstraints, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new Type[0]; } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class UserDefinedTableTypeColumnsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "UserDefinedTableTypeColumns" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlColumnQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + child.SortPriority = SmoTreeNode.NextSortPriority; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class UserDefinedTableTypeKeysChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "UserDefinedTableTypeKeys" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlIndexQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class UserDefinedTableTypeConstraintsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "UserDefinedTableTypeConstraints" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlDefaultConstraintQuerier), typeof(SqlCheckQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemExactNumericsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemExactNumerics" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlBuiltInTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemApproximateNumericsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemApproximateNumerics" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlBuiltInTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemDateAndTimesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemDateAndTimes" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlBuiltInTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemCharacterStringsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemCharacterStrings" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlBuiltInTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemUnicodeCharacterStringsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemUnicodeCharacterStrings" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlBuiltInTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemBinaryStringsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemBinaryStrings" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlBuiltInTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemOtherDataTypesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemOtherDataTypes" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlBuiltInTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemClrDataTypesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemClrDataTypes" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlUserDefinedTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemSpatialDataTypesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemSpatialDataTypes" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlUserDefinedTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ExternalDataSourcesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ExternalDataSources" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlExternalDataSourceQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ExternalFileFormatsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ExternalFileFormats" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlExternalFileFormatQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class StoredProceduresChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "StoredProcedures" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemStoredProcedures, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemStoredProcedures, + IsMsShippedOwned = true, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlProcedureQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new StoredProcedureInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemStoredProceduresChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemStoredProcedures" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlProcedureQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new StoredProcedureInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class StoredProcedureInstanceChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "StoredProcedureInstance" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Parameters, + NodeType = "Folder", + NodeTypeId = NodeTypes.StoredProcedureParameters, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new Type[0]; } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class StoredProcedureParametersChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "StoredProcedureParameters" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlSubroutineParameterQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + child.SortPriority = SmoTreeNode.NextSortPriority; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class TableValuedFunctionsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "TableValuedFunctions" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlUserDefinedFunctionQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new TableValuedFunctionInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class TableValuedFunctionInstanceChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "TableValuedFunctionInstance" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Parameters, + NodeType = "Folder", + NodeTypeId = NodeTypes.TableValuedFunctionParameters, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new Type[0]; } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class TableValuedFunctionParametersChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "TableValuedFunctionParameters" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlSubroutineParameterQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + child.SortPriority = SmoTreeNode.NextSortPriority; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ScalarValuedFunctionsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ScalarValuedFunctions" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlUserDefinedFunctionQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new ScalarValuedFunctionInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ScalarValuedFunctionInstanceChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ScalarValuedFunctionInstance" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Parameters, + NodeType = "Folder", + NodeTypeId = NodeTypes.ScalarValuedFunctionParameters, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new Type[0]; } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ScalarValuedFunctionParametersChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ScalarValuedFunctionParameters" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlSubroutineParameterQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + child.SortPriority = SmoTreeNode.NextSortPriority; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class AggregateFunctionsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "AggregateFunctions" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlUserDefinedAggregateQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new AggregateFunctionInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class AggregateFunctionInstanceChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "AggregateFunctionInstance" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_Parameters, + NodeType = "Folder", + NodeTypeId = NodeTypes.AggregateFunctionParameters, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new Type[0]; } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class AggregateFunctionParametersChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "AggregateFunctionParameters" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlSubroutineParameterQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + child.SortPriority = SmoTreeNode.NextSortPriority; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class RemoteServiceBindingsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "RemoteServiceBindings" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlRemoteServiceBindingQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class BrokerPrioritiesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "BrokerPriorities" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlBrokerPriorityQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class FileGroupsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "FileGroups" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlFileGroupQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new FileGroupInstanceTreeNode(); + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class FullTextCatalogsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "FullTextCatalogs" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlFullTextCatalogQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class FullTextStopListsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "FullTextStopLists" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlFullTextStopListQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SqlLogFilesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SqlLogFiles" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlFileQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class PartitionFunctionsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "PartitionFunctions" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlPartitionFunctionQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class PartitionSchemesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "PartitionSchemes" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlPartitionSchemeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SearchPropertyListsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SearchPropertyLists" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlSearchPropertyListQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class FileGroupInstanceChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "FileGroupInstance" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_FilegroupFiles, + NodeType = "Folder", + NodeTypeId = NodeTypes.FileGroupFiles, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class FileGroupFilesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "FileGroupFiles" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlFileQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class UsersChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Users" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlUserQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class RolesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Roles" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_DatabaseRoles, + NodeType = "Folder", + NodeTypeId = NodeTypes.DatabaseRoles, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ApplicationRoles, + NodeType = "Folder", + NodeTypeId = NodeTypes.ApplicationRoles, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SchemasChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Schemas" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlSchemaQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class AsymmetricKeysChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "AsymmetricKeys" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlAsymmetricKeyQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class CertificatesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Certificates" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlCertificateQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SymmetricKeysChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SymmetricKeys" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlSymmetricKeyQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class DatabaseEncryptionKeysChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "DatabaseEncryptionKeys" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlDatabaseEncryptionKeyQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class MasterKeysChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "MasterKeys" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlMasterKeyQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class DatabaseAuditSpecificationsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "DatabaseAuditSpecifications" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlDatabaseAuditSpecificationQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SecurityPoliciesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SecurityPolicies" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlSecurityPolicyQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class DatabaseScopedCredentialsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "DatabaseScopedCredentials" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlDatabaseCredentialQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class AlwaysEncryptedKeysChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "AlwaysEncryptedKeys" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ColumnMasterKeys, + NodeType = "Folder", + NodeTypeId = NodeTypes.ColumnMasterKeys, + ValidFor = ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_ColumnEncryptionKeys, + NodeType = "Folder", + NodeTypeId = NodeTypes.ColumnEncryptionKeys, + ValidFor = ValidForFlag.Sql2016|ValidForFlag.AzureV12, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes { get {return null;} } + + + public override TreeNode CreateChild(TreeNode parent, object context) + { + return null; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class DatabaseRolesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "DatabaseRoles" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlRoleQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ApplicationRolesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ApplicationRoles" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlApplicationRoleQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ColumnMasterKeysChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ColumnMasterKeys" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlColumnMasterKeyQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ColumnEncryptionKeysChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "ColumnEncryptionKeys" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlColumnEncryptionKeyQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class MessageTypesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "MessageTypes" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemMessageTypes, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemMessageTypes, + IsMsShippedOwned = true, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlMessageTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemMessageTypesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemMessageTypes" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlMessageTypeQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ContractsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Contracts" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemContracts, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemContracts, + IsMsShippedOwned = true, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlContractQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemContractsChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemContracts" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlContractQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class QueuesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Queues" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemQueues, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemQueues, + IsMsShippedOwned = true, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlQueueQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemQueuesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemQueues" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlQueueQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class ServicesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "Services" }; } + + protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent) + { + currentChildren.Add(new FolderNode { + NodeValue = SR.SchemaHierarchy_SystemServices, + NodeType = "Folder", + NodeTypeId = NodeTypes.SystemServices, + IsMsShippedOwned = true, + SortPriority = SmoTreeNode.NextSortPriority, + }); + } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlServiceQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + [Export(typeof(ChildFactory))] + [Shared] + internal partial class SystemServicesChildFactory : SmoChildFactoryBase + { + public override IEnumerable ApplicableParents() { return new[] { "SystemServices" }; } + + internal override Type[] ChildQuerierTypes + { + get + { + return new [] { typeof(SqlServiceQuerier), }; + } + } + + public override TreeNode CreateChild(TreeNode parent, object context) + { + var child = new SmoTreeNode(); + child.IsAlwaysLeaf = true; + InitializeChild(child, context); + return child; + } + } + + +} + diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.tt b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.tt new file mode 100644 index 00000000..f51dc887 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.tt @@ -0,0 +1,387 @@ +<#@ 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" #> +using System; +using System.Collections.Generic; +using System.Composition; +using Microsoft.SqlTools.ServiceLayer; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ + +<# + var directory = Path.GetDirectoryName(Host.TemplateFile); + string xmlFile = Path.Combine(directory, "TreeNodeDefinition.xml"); + + ///////// + // TODO - is Generate all the ReverseDependencies needed? + ///////// + // var allReverseDependencies = GetReverseDependencies(xmlFile); + // WriteLine(" internal static class TreeNodeRules"); + // WriteLine(" {"); + // WriteLine(" internal static Dictionary> TypeReverseDependencyMap = new Dictionary>()"); + // 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 {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"); + WriteLine(string.Format(" internal sealed partial class {0} : SmoTreeNode", name)); + WriteLine(" {"); + WriteLine(string.Format(" public {0}() : base()", name)); + WriteLine(" {"); + WriteLine(" NodeValue = string.Empty;"); + WriteLine(string.Format(" this.NodeType = \"{0}\";", name.Replace("TreeNode", string.Empty))); + WriteLine(string.Format(" this.NodeTypeId = NodeTypes.{0};", name.Replace("TreeNode", string.Empty))); + 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 ChildQuerierTypes = nodeElement.GetAttribute("ChildQuerierTypes"); + 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(string.Format(" internal partial class {0}ChildFactory : {1}", type, childFactoryBaseClass)); + + WriteLine(" {"); + WriteLine(string.Format(" public override IEnumerable ApplicableParents() {{ return new[] {{ \"{0}\" }}; }}", type)); + + List children = GetChildren(xmlFile, type); + if (children.Count > 0) + { + WriteLine(""); + WriteLine(" protected override void OnExpandPopulateFolders(IList currentChildren, TreeNode parent)"); + WriteLine(" {"); + foreach (var child in children) + { + XmlElement childAsXmlElement = GetNodeElement(xmlFile, child.GetAttribute("Name")); + 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"); + + if (TreeNodeExists(xmlFile, child.GetAttribute("Name") + "TreeNode")) + { + WriteLine(string.Format(" currentChildren.Add(new {0}TreeNode {{ SortPriority = SmoTreeNode.NextSortPriority }} );", child.GetAttribute("Name"))); + } + else + { + WriteLine(" currentChildren.Add(new FolderNode {"); + WriteLine(string.Format(" NodeValue = {0},", childAsXmlElement.GetAttribute("LocLabel"))); + WriteLine(string.Format(" NodeType = \"{0}\",", "Folder")); + WriteLine(string.Format(" NodeTypeId = NodeTypes.{0},", child.GetAttribute("Name"))); + + if (msShippedOwned != null) + { + WriteLine(" IsMsShippedOwned = true,"); + } + if (!string.IsNullOrWhiteSpace(validFor)) + { + WriteLine(string.Format(" ValidFor = {0},", GetValidForFlags(validFor))); + } + WriteLine(" SortPriority = SmoTreeNode.NextSortPriority,"); + WriteLine(" });"); + } + } + WriteLine(" }"); + } + + if (!string.IsNullOrWhiteSpace(strategy)) + { + 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(string.Format(" typeof({0}Querier),", typeToRe)); + } + WriteLine(" };"); + } + else + { + Write(" 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;"); + } + else + { + var modelNodeChildren = GetNodeElement(xmlFile, TreeNode.Replace("TreeNode",string.Empty)); + WriteLine(string.Format(" var child = new {0}();", TreeNode)); + if (modelNodeChildren.ChildNodes.Count == 0) + { + WriteLine(" child.IsAlwaysLeaf = true;"); + } + } + if (disableSort != null) + { + WriteLine(" child.SortPriority = SmoTreeNode.NextSortPriority;"); + } + WriteLine(" InitializeChild(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) + { + List flags = new List(); + 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("AzureV11")) + { + flags.Add("ValidForFlag.Azure"); + } + + if (validForStr.Contains("AzureV12")) + { + flags.Add("ValidForFlag.AzureV12"); + } + + if (validForStr.Contains("NotDebugInstance")) + { + flags.Add("ValidForFlag.NotDebugInstance"); + } + + if (validForStr.Contains("NotContainedUser")) + { + flags.Add("ValidForFlag.NotContainedUser"); + } + + if (validForStr.Contains("CanConnectToMaster")) + { + flags.Add("ValidForFlag.CanConnectToMaster"); + } + + if (validForStr.Contains("CanViewSecurity")) + { + flags.Add("ValidForFlag.CanViewSecurity"); + } + + return string.Join("|", flags); + } + public static string[] GetNodes(string xmlFile) + { + List typesList = new List(); + 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> GetReverseDependencies(string xmlFile) + { + Dictionary> dependencyMap = new Dictionary>(); + 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 dependenciesForType; + if (dependencyMap.TryGetValue(typeName, out dependenciesForType)) + { + dependenciesForType.Add(dependency); + } + else + { + string[] allDepedencies = dependency.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries); + dependenciesForType = new List(); + 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 GetUniqueTreeNodes(string xmlFile) + { + XmlDocument doc = new XmlDocument(); + doc.Load(xmlFile); + + List retElements = new List(); + 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 GetChildren(string xmlFile, string parentName) + { + XmlElement nodeElement = GetNodeElement(xmlFile, parentName); + XmlDocument doc = new XmlDocument(); + doc.Load(xmlFile); + + List retElements = new List(); + 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; + } +#> \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Properties/AssemblyInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/Properties/AssemblyInfo.cs index 05de5fec..38a47f7c 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Properties/AssemblyInfo.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Properties/AssemblyInfo.cs @@ -44,3 +44,6 @@ using System.Runtime.InteropServices; [assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.UnitTests")] [assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.IntegrationTests")] [assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.Test.Common")] + +// Allowing internals visible access to Moq library to help testing +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] diff --git a/src/Microsoft.SqlTools.ServiceLayer/ServiceHost.cs b/src/Microsoft.SqlTools.ServiceLayer/ServiceHost.cs index bfe0fbb2..c042a023 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ServiceHost.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ServiceHost.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; +using Microsoft.SqlTools.Extensibility; using Microsoft.SqlTools.Hosting; using Microsoft.SqlTools.Hosting.Contracts; using Microsoft.SqlTools.Hosting.Protocol; @@ -29,6 +30,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting /// private const int ShutdownTimeoutInSeconds = 120; public static readonly string[] CompletionTriggerCharacters = new string[] { ".", "-", ":", "\\", "[", "\"" }; + private IMultiServiceProvider serviceProvider; #region Singleton Instance Code @@ -54,6 +56,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting // Initialize the shutdown activities shutdownCallbacks = new List(); initializeCallbacks = new List(); + } + + public IMultiServiceProvider ServiceProvider + { + get + { + return serviceProvider; + } + internal set + { + serviceProvider = value; + } } /// diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/CommonConstants.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/CommonConstants.cs new file mode 100644 index 00000000..d98f75ee --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/CommonConstants.cs @@ -0,0 +1,19 @@ +// +// 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.Utility +{ + /// + /// Common Constant values used across multiple services + /// + public static class CommonConstants + { + public const string MasterDatabaseName = "master"; + public const string MsdbDatabaseName = "msdb"; + public const string ModelDatabaseName = "model"; + public const string TempDbDatabaseName = "tempdb"; + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectExplorer/ObjectExplorerServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectExplorer/ObjectExplorerServiceTests.cs new file mode 100644 index 00000000..fd288334 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectExplorer/ObjectExplorerServiceTests.cs @@ -0,0 +1,215 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; +using Microsoft.SqlTools.ServiceLayer.Test.Common; +using Xunit; +using static Microsoft.SqlTools.ServiceLayer.ObjectExplorer.ObjectExplorerService; + +namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer +{ + public class ObjectExplorerServiceTests + { + private ObjectExplorerService _service = TestServiceProvider.Instance.ObjectExplorerService; + + [Fact] + public async void CreateSessionAndExpandOnTheServerShouldReturnTheDatabases() + { + var query = ""; + string uri = "CreateSessionAndExpand"; + string databaseName = null; + using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri)) + { + var session = await CreateSession(testDb.DatabaseName, uri); + await CreateSessionAndDatabaseNode(testDb.DatabaseName, session); + CancelConnection(uri); + } + } + + private async Task CreateSession(string databaseName, string uri) + { + ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName); + ConnectionDetails details = connectParams.Connection; + + return await _service.DoCreateSession(details, uri); + } + + private async Task CreateSessionAndDatabaseNode(string databaseName, ObjectExplorerSession session) + { + Assert.NotNull(session); + Assert.NotNull(session.Root); + NodeInfo nodeInfo = session.Root.ToNodeInfo(); + Assert.Equal(nodeInfo.IsLeaf, false); + Assert.Equal(nodeInfo.NodeType, NodeTypes.ServerInstance.ToString()); + var children = session.Root.Expand(); + + //All server children should be folder nodes + foreach (var item in children) + { + Assert.Equal(item.NodeType, "Folder"); + } + + var databasesRoot = children.FirstOrDefault(x => x.NodeTypeId == NodeTypes.Databases); + var databasesChildren = await _service.ExpandNode(session, databasesRoot.GetNodePath()); + var databases = databasesChildren.Where(x => x.NodeType == NodeTypes.DatabaseInstance.ToString()); + + //Verify the test databases is in the list + Assert.NotNull(databases); + var databaseNode = databases.FirstOrDefault(d => d.Label == databaseName); + Assert.NotNull(databaseNode); + return databaseNode; + } + + private void CancelConnection(string uri) + { + //ConnectionService.Instance.CancelConnect(new CancelConnectParams + //{ + // OwnerUri = uri, + // Type = ConnectionType.Default + //}); + } + + private async Task ExpandTree(NodeInfo node, ObjectExplorerSession session) + { + if(node != null && !node.IsLeaf) + { + var children = await _service.ExpandNode(session, node.NodePath); + Assert.NotNull(children); + if(children.Count() == 0 && !node.NodePath.Contains("System") && + !node.NodePath.Contains("FileTables") && !node.NodePath.Contains("External Tables")) + { + var labaleToUpper = node.Label.ToUpper(); + if (labaleToUpper.Contains("TABLE") || labaleToUpper.Contains("StoredProcedure") + || labaleToUpper.Contains("VIEW")) + { + //TOOD: Add a better validation. For now at least check tables not to be empty + //Assert.True(false, "The list of tables, procedure and views cannot be empty"); + } + } + foreach (var child in children) + { + //Console.WriteLine(child.Label); + await ExpandTree(child, session); + } + } + } + + [Fact] + public async void VerifyAdventureWorksDatabaseObjects() + { + var query = Scripts.AdventureWorksScript; + string uri = "VerifyAdventureWorksDatabaseObjects"; + string databaseName = null; + + using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri)) + { + var session = await CreateSession(testDb.DatabaseName, uri); + var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session); + await ExpandTree(databaseNodeInfo, session); + CancelConnection(uri); + } + } + + // [Fact] + public async void VerifySql2016Objects() + { + var query = LoadScript("Sql_2016_Additions.sql"); + string uri = "VerifySql2016Objects"; + string databaseName = null; + + using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri)) + { + var session = await CreateSession(testDb.DatabaseName, uri); + var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session); + await ExpandTree(databaseNodeInfo, session); + CancelConnection(uri); + } + } + + // [Fact] + public async void VerifySqlObjects() + { + var query = LoadScript("Sql_Additions.sql"); + string uri = "VerifySqlObjects"; + string databaseName = null; + + using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri)) + { + var session = await CreateSession(testDb.DatabaseName, uri); + var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session); + await ExpandTree(databaseNodeInfo, session); + CancelConnection(uri); + } + } + + // [Fact] + public async void VerifyFileTableTest() + { + var query = LoadScript("FileTableTest.sql"); + string uri = "VerifyFileTableTest"; + string databaseName = null; + + using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri)) + { + var session = await CreateSession(testDb.DatabaseName, uri); + var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session); + await ExpandTree(databaseNodeInfo, session); + CancelConnection(uri); + } + } + + //[Fact] + public async void VerifyColumnstoreindexSql16() + { + var query = LoadScript("ColumnstoreindexSql16.sql"); + string uri = "VerifyColumnstoreindexSql16"; + string databaseName = null; + + using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri)) + { + var session = await CreateSession(testDb.DatabaseName, uri); + var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session); + await ExpandTree(databaseNodeInfo, session); + CancelConnection(uri); + } + } + + private static string TestLocationDirectory + { + get + { + return Path.Combine(RunEnvironmentInfo.GetTestDataLocation(), "ObjectExplorer"); + } + } + + public DirectoryInfo InputFileDirectory + { + get + { + string d = Path.Combine(TestLocationDirectory, "TestScripts"); + return new DirectoryInfo(d); + } + } + + public FileInfo GetInputFile(string fileName) + { + return new FileInfo(Path.Combine(InputFileDirectory.FullName, fileName)); + } + + private string LoadScript(string fileName) + { + FileInfo inputFile = GetInputFile(fileName); + return TestUtilities.ReadTextAndNormalizeLineEndings(inputFile.FullName); + } + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Utility/LiveConnectionHelper.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Utility/LiveConnectionHelper.cs index c07b121d..c634c079 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Utility/LiveConnectionHelper.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Utility/LiveConnectionHelper.cs @@ -1,7 +1,10 @@ -using System.Data.SqlClient; +using System; +using System.Data.SqlClient; using System.Globalization; using System.IO; using System.Reflection; +using System.Threading; +using System.Threading.Tasks; using Microsoft.SqlServer.Management.Common; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; @@ -27,11 +30,11 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility } - public static TestConnectionResult InitLiveConnectionInfo() + public static TestConnectionResult InitLiveConnectionInfo(string databaseName = null) { string sqlFilePath = GetTestSqlFile(); ScriptFile scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(sqlFilePath); - ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem); + ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName); string ownerUri = scriptFile.ClientFilePath; var connectionService = GetLiveTestConnectionService(); @@ -50,6 +53,35 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility return new TestConnectionResult() { ConnectionInfo = connInfo, ScriptFile = scriptFile }; } + public static async Task InitLiveConnectionInfoAsync(string databaseName = null, string ownerUri = null) + { + ScriptFile scriptFile = null; + if (string.IsNullOrEmpty(ownerUri)) + { + string sqlFilePath = GetTestSqlFile(); + scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(sqlFilePath); + ownerUri = scriptFile.ClientFilePath; + } + ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName); + + var connectionService = GetLiveTestConnectionService(); + var connectionResult = + await connectionService + .Connect(new ConnectParams + { + OwnerUri = ownerUri, + Connection = connectParams.Connection + }); + if (!string.IsNullOrEmpty(connectionResult.ErrorMessage)) + { + Console.WriteLine(connectionResult.ErrorMessage); + } + + ConnectionInfo connInfo = null; + connectionService.TryFindConnection(ownerUri, out connInfo); + return new TestConnectionResult() { ConnectionInfo = connInfo, ScriptFile = scriptFile }; + } + public static ConnectionInfo InitLiveConnectionInfoForDefinition(string databaseName = null) { ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName); diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/Scripts/AdventureWorks.sql b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/Scripts/AdventureWorks.sql new file mode 100644 index 0000000000000000000000000000000000000000..4697adc4cca73cbf3650e9bfba630a00499d2e98 GIT binary patch literal 1321364 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 rS CreateDatabaseObjectsQueryInstance = new Lazy(() => { @@ -58,6 +60,11 @@ END private static readonly Lazy TestDbSelectQueriesInstance = new Lazy(() => { return GetScriptFileContent(ResourceNameRefix + "TestDbTableQueries.sql"); + }); + + private static readonly Lazy AdventureWorksScriptInstance = new Lazy(() => + { + return GetScriptFileContent(ResourceNameRefix + "AdventureWorks.sql"); }); private static string GetScriptFileContent(string fileName) diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/SqlTestDb.cs b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/SqlTestDb.cs index 99d3df96..c20a1f08 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/SqlTestDb.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/SqlTestDb.cs @@ -27,13 +27,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common /// /// Create the test db if not already exists /// - public static SqlTestDb CreateNew(TestServerType serverType, bool doNotCleanupDb = false, string databaseName = null, string query = null) + public static SqlTestDb CreateNew( + TestServerType serverType, + bool doNotCleanupDb = false, + string databaseName = null, + string query = null, + string dbNamePrefix = null) { SqlTestDb testDb = new SqlTestDb(); using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) { - databaseName = databaseName ?? GetUniqueDBName(""); + databaseName = databaseName ?? GetUniqueDBName(dbNamePrefix); string createDatabaseQuery = Scripts.CreateDatabaseQuery.Replace("#DatabaseName#", databaseName); TestServiceProvider.Instance.RunQuery(serverType, MasterDatabaseName, createDatabaseQuery); Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Test database '{0}' is created", databaseName)); diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/ColumnstoreindexSql16.sql b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/ColumnstoreindexSql16.sql new file mode 100644 index 00000000..c8086c63 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/ColumnstoreindexSql16.sql @@ -0,0 +1,34 @@ +CREATE TABLE CS_Delay_Table1 +(ProductKey [int] NOT NULL, +OrderDateKey [int] NOT NULL, +DueDateKey [int] NOT NULL, +ShipDateKey [int] NOT NULL); +GO + +CREATE CLUSTERED COLUMNSTORE INDEX CSI_1 ON CS_Delay_Table1 +WITH (COMPRESSION_DELAY = 100 minutes); +GO + +CREATE TABLE CS_Delay_Table2 +(ProductKey [int] NOT NULL, +OrderDateKey [int] NOT NULL, +DueDateKey [int] NOT NULL, +ShipDateKey [int] NOT NULL); +GO + +CREATE CLUSTERED INDEX CI_Table2 ON CS_Delay_Table2 (ProductKey); +GO + +CREATE NONCLUSTERED COLUMNSTORE INDEX CSI_2 +ON CS_Delay_Table2 +(OrderDateKey, DueDateKey, ShipDateKey) +WITH (COMPRESSION_DELAY = 200); +GO + +CREATE TABLE CS_Delay_Table3 +(ProductKey [int] NOT NULL, +OrderDateKey [int] NOT NULL, +DueDateKey [int] NOT NULL, +ShipDateKey [int] NOT NULL, +INDEX CSI_3 CLUSTERED COLUMNSTORE WITH(COMPRESSION_DELAY = 50 minute)); +GO \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/FileTableTest.sql b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/FileTableTest.sql new file mode 100644 index 00000000..2f689c79 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/FileTableTest.sql @@ -0,0 +1,103 @@ + +CREATE DATABASE [$(DatabaseName)] + +GO +ALTER DATABASE [$(DatabaseName)] SET TARGET_RECOVERY_TIME = 1 MINUTES +GO +USE [$(DatabaseName)] + +GO +ALTER DATABASE [$(DatabaseName)] +SET FILESTREAM( + NON_TRANSACTED_ACCESS = FULL, + DIRECTORY_NAME = N'$(DatabaseName)' + ) WITH NO_WAIT + +GO + +ALTER DATABASE $(DatabaseName) + ADD FILEGROUP [FileGroup1] + CONTAINS FILESTREAM + +GO + +ALTER DATABASE $(DatabaseName) +ADD FILE + (NAME = 'FileTableFile' + , FILENAME = '$(DefaultDataPath)$(DatabaseName)_FT' + ) +TO FILEGROUP [FileGroup1] + +GO + + + +CREATE TABLE [dbo].[FileTablePass] AS FILETABLE WITH( +FileTable_Directory = 'docs', +FILETABLE_PRIMARY_KEY_CONSTRAINT_NAME=MyPk, +FILETABLE_STREAMID_UNIQUE_CONSTRAINT_NAME=MyStreamUQ, +FILETABLE_FULLPATH_UNIQUE_CONSTRAINT_NAME=MyPathUQ) + +GO +ALTER TABLE [dbo].[FileTablePass] WITH CHECK ADD CONSTRAINT [MyCheck] CHECK ((stream_id IS NOT NULL)) +GO +ALTER TABLE [dbo].[FileTablePass] ADD CONSTRAINT [MyDefault] DEFAULT ((NULL)) FOR [name] +GO +ALTER TABLE [dbo].[FileTablePass] ADD CONSTRAINT [MyQU] UNIQUE NONCLUSTERED ([name] ASC) +GO +ALTER TABLE [dbo].[FileTablePass] WITH CHECK ADD CONSTRAINT [MyFk] FOREIGN KEY([parent_path_locator]) +REFERENCES [dbo].[FileTablePass] ([path_locator]) +GO +CREATE TABLE [dbo].[t2] ( + [c1] INT NOT NULL, + [c2] INT DEFAULT ((1)) NULL, + [c3] INT DEFAULT ((1)) NOT NULL, + [path_locator] hierarchyid, + PRIMARY KEY CLUSTERED ([c1] ASC), + UNIQUE NONCLUSTERED ([c2] ASC), + CHECK ([c2] > (0)) +); + +GO +CREATE STATISTICS stat1 + ON dbo.[FileTablePass](stream_id) +WITH SAMPLE 50 PERCENT; +GO +CREATE INDEX IX_FileTablePass_Stream_id + ON dbo.FileTablePass(stream_id); +GO + +CREATE TRIGGER FileTableTrigger +ON dbo.FileTablePass +AFTER INSERT +AS RAISERROR ('Block insert', 16, 10); +GO +CREATE INDEX IX_T2_C3 + ON [dbo].[t2](c3); + +GO + +CREATE TRIGGER reminder2 +ON dbo.t2 +AFTER INSERT, UPDATE, DELETE +AS +PRINT 'reminder trigger'; + +GO + +ALTER TABLE dbo.t2 +ADD CONSTRAINT FK_TO_FILETABLE FOREIGN KEY (path_locator) + REFERENCES FileTablePass (path_locator) ; +GO +exec sp_addextendedproperty 'prop_ex', 'FileTable', 'SCHEMA', 'dbo', 'TABLE', 'FileTablePass' +exec sp_addextendedproperty 'prop_ex', 'MyPk', 'SCHEMA', 'dbo', 'TABLE', 'FileTablePass', 'CONSTRAINT', 'MyPk' +exec sp_addextendedproperty 'prop_ex', 'MyStreamUQ', 'SCHEMA', 'dbo', 'TABLE', 'FileTablePass', 'CONSTRAINT', 'MyStreamUQ' +exec sp_addextendedproperty 'prop_ex', 'MyPathUQ', 'SCHEMA', 'dbo', 'TABLE', 'FileTablePass', 'CONSTRAINT', 'MyPathUQ' + +GO + +CREATE USER test_user WITHOUT LOGIN +GO + +GRANT SELECT ON dbo.FileTablePass TO test_user +GO \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/NumberedProcedures.sql b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/NumberedProcedures.sql new file mode 100644 index 00000000..0c6f4534 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/NumberedProcedures.sql @@ -0,0 +1,62 @@ +CREATE PROCEDURE [dbo].[Encrypted_Additional_Numbered_Procedure] +( @param1 int) +WITH ENCRYPTION +AS +SELECT 1 AS Col1 + +GO + + +CREATE PROCEDURE [dbo].[Encrypted_Additional_Numbered_Procedure];2 +( @param1 int) +WITH ENCRYPTION +AS +SELECT 2 AS Col1 + + +GO + +CREATE PROCEDURE [dbo].[Encrypted_Additional_Numbered_Procedure];3 +( @param1 int) +WITH ENCRYPTION +AS +SELECT 3 AS Col1 + + +GO + +CREATE PROCEDURE [dbo].[Encrypted_Additional_Numbered_Procedure];4 +( @param1 int) +WITH ENCRYPTION +AS +SELECT 4 AS Col1 + +GO + +CREATE PROCEDURE [dbo].[Additional_Numbered_Procedure] +(@param1 int) +AS +SELECT 1 AS Col1 + +GO + +CREATE PROCEDURE [dbo].[Additional_Numbered_Procedure];2 +(@param1 int) +AS +SELECT 2 AS Col1 + +GO + +CREATE PROCEDURE [dbo].[Additional_Numbered_Procedure];3 +(@param1 int) +AS +SELECT 3 AS Col1 + +GO + +CREATE PROCEDURE [dbo].[Additional_Numbered_Procedure];4 +(@param1 int) +AS +SELECT 4 AS Col1 + + diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/Sql_2016_Additions.sql b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/Sql_2016_Additions.sql new file mode 100644 index 00000000..c68e4de7 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/Sql_2016_Additions.sql @@ -0,0 +1,275 @@ +ALTER DATABASE current SET COMPATIBILITY_LEVEL=130 +GO + +/* Dropping previous master key in master db that could have been created from other runs */ +IF ( EXISTS(SELECT name FROM sys.symmetric_keys WHERE name = '##MS_DatabaseMasterKey##')) DROP MASTER KEY + +CREATE MASTER KEY ENCRYPTION BY PASSWORD= 'Password01!'; + +OPEN MASTER KEY DECRYPTION BY PASSWORD = 'Password01!'; + + +CREATE DATABASE SCOPED CREDENTIAL AlterEgo WITH IDENTITY = 'RettigB', + SECRET = 'sdrlk8$40-dksli87nNN8'; + +GO + +-- Row-Level Security +CREATE TABLE [dbo].[Sales1] +( + OrderID INT, + SalesRep SYSNAME NOT NULL, + Product VARCHAR(10), + Qty INT +); + +GO + +CREATE TABLE [dbo].[Sales2] +( + OrderID INT, + SalesRep SYSNAME NOT NULL, + Product VARCHAR(10), + Qty INT +); + +GO + +CREATE FUNCTION [dbo].[fn_securitypredicate](@SalesRep AS SYSNAME) + RETURNS TABLE +WITH SCHEMABINDING +AS + RETURN SELECT 1 AS fn_securitypredicate_result +WHERE @SalesRep = USER_NAME() OR USER_NAME() = 'Manager'; + + +GO + +CREATE SECURITY POLICY [dbo].[SalesFilter] +ADD FILTER PREDICATE [dbo].[fn_securitypredicate]([SalesRep]) ON [dbo].[Sales1], +ADD FILTER PREDICATE [dbo].[fn_securitypredicate]([SalesRep]) ON [dbo].[Sales2], +ADD BLOCK PREDICATE [dbo].[fn_securitypredicate]([SalesRep]) ON [dbo].[Sales1], +ADD BLOCK PREDICATE [dbo].[fn_securitypredicate]([SalesRep]) ON [dbo].[Sales2] AFTER UPDATE +WITH (STATE = OFF) +NOT FOR REPLICATION + +GO + +CREATE COLUMN MASTER KEY CMK1 +WITH ( + KEY_STORE_PROVIDER_NAME = 'MSSQL_CERTIFICATE_STORE', + KEY_PATH = 'Current User/Personal/f2260f28d909d21c642a3d8e0b45a830e79a1420' + ); + +GO + +CREATE COLUMN MASTER KEY CMK2 +WITH ( + KEY_STORE_PROVIDER_NAME = 'MSSQL_CERTIFICATE_STORE', + KEY_PATH = 'Current User/Personal/f2260f28d909d21c642a3d8e0b45a830e79a1420' + ); + +GO + +CREATE COLUMN ENCRYPTION KEY TwoValueCEK +WITH VALUES +( + COLUMN_MASTER_KEY = CMK1, + ALGORITHM = 'RSA_OAEP', + ENCRYPTED_VALUE = 0x016E000001630075007200720065006E00740075007300650072002F006D0079002F0037006300380061003100310033003400320037003800620037003000630038003100390062003900630039003400360061006600340039006500610030003200650038006200650038003400340065006C33A82ECF04A7185824B4545457AC5244CD9C219E64067B9520C0081B8399B58C2863F7494ABE3694BD87D55FFD7576FFDC47C28F94ECC99577DF4FB8FA19AA95764FEF889CDE0F176DA5897B74382FBB22756CE2921050A09201A0EB6AF3D6091014C30146EA62635EE8CBF0A8074DEDFF125CEA80D1C0F5E8C58750A07D270E2A8BF824EE4C0C156366BF26D38CCE49EBDD5639A2DF029A7DBAE5A5D111F2F2FA3246DF8C2FA83C1E542C10570FADA98F6B29478DC58CE5CBDD407CCEFCDB97814525F6F32BECA266014AC346AC39C4F185C6C0F0A24FEC4DFA015649624692DE7865B9827BA22C3B574C9FD169F822B609F902288C5880EB25F14BD990D871B1BC4BA3A5B237AF76D26354773FA2A25CF4511AF58C911E601CFCB1905128C997844EED056C2AE7F0B48700AB41307E470FF9520997D0EB0D887DE11AFE574FFE845B7DC6C03FEEE8D467236368FC0CB2FDBD54DADC65B10B3DE6C80DF8B7B3F8F3CE5BE914713EE7B1FA5B7A578359592B8A5FDFDDE5FF9F392BC87C3CD02FBA94582AC063BBB9FFAC803FD489E16BEB28C4E3374A8478C737236A0B232F5A9DDE4D119573F1AEAE94B2192B81575AD6F57E670C1B2AB91045124DFDAEC2898F3F0112026DFC93BF9391D667D1AD7ED7D4E6BB119BBCEF1D1ADA589DD3E1082C3DAD13223BE438EB9574DA04E9D8A06320CAC6D3EC21D5D1C2A0AA484C7C +), +( + COLUMN_MASTER_KEY = CMK2, + ALGORITHM = 'RSA_OAEP', + ENCRYPTED_VALUE = 0x016E000001630075007200720065006E00740075007300650072002F006D0079002F0064006500650063006200660034006100340031003000380034006200350033003200360066003200630062006200350030003600380065003900620061003000320030003600610037003800310066001DDA6134C3B73A90D349C8905782DD819B428162CF5B051639BA46EC69A7C8C8F81591A92C395711493B25DCBCCC57836E5B9F17A0713E840721D098F3F8E023ABCDFE2F6D8CC4339FC8F88630ED9EBADA5CA8EEAFA84164C1095B12AE161EABC1DF778C07F07D413AF1ED900F578FC00894BEE705EAC60F4A5090BBE09885D2EFE1C915F7B4C581D9CE3FDAB78ACF4829F85752E9FC985DEB8773889EE4A1945BD554724803A6F5DC0A2CD5EFE001ABED8D61E8449E4FAA9E4DD392DA8D292ECC6EB149E843E395CDE0F98D04940A28C4B05F747149B34A0BAEC04FFF3E304C84AF1FF81225E615B5F94E334378A0A888EF88F4E79F66CB377E3C21964AACB5049C08435FE84EEEF39D20A665C17E04898914A85B3DE23D56575EBC682D154F4F15C37723E04974DB370180A9A579BC84F6BC9B5E7C223E5CBEE721E57EE07EFDCC0A3257BBEBF9ADFFB00DBF7EF682EC1C4C47451438F90B4CF8DA709940F72CFDC91C6EB4E37B4ED7E2385B1FF71B28A1D2669FBEB18EA89F9D391D2FDDEA0ED362E6A591AC64EF4AE31CA8766C259ECB77D01A7F5C36B8418F91C1BEADDD4491C80F0016B66421B4B788C55127135DA2FA625FB7FD195FB40D90A6C67328602ECAF3EC4F5894BFD84A99EB4753BE0D22E0D4DE6A0ADFEDC80EB1B556749B4A8AD00E73B329C95827AB91C0256347E85E3C5FD6726D0E1FE82C925D3DF4A9 +); + +GO + +CREATE TABLE Customers ( + CustName nvarchar(60), + SSN varchar(11) + COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = TwoValueCEK, + ENCRYPTION_TYPE = DETERMINISTIC , + ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'), + Age int NULL, + ACTNO varchar(11) + ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = TwoValueCEK, + ENCRYPTION_TYPE = RANDOMIZED, + ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') +); + +GO + +USE [$(DatabaseName)] + +GO + +DBCC TRACEON(4631,-1) + +GO + +OPEN MASTER KEY DECRYPTION BY PASSWORD = 'Password01!'; + +CREATE DATABASE SCOPED CREDENTIAL cred1 WITH IDENTITY = 'test_user', SECRET = '$(Secret)'; + +CREATE EXTERNAL DATA SOURCE eds1 + WITH ( + TYPE = HADOOP, + LOCATION = '$(DataSourceLocation)', + CREDENTIAL = cred1 + ); + +CREATE EXTERNAL DATA SOURCE eds2 + WITH ( + TYPE = HADOOP, + LOCATION = '$(DataSourceLocation)' + ); + +CREATE EXTERNAL FILE FORMAT eff1 + WITH ( + FORMAT_TYPE = DELIMITEDTEXT + ); + +CREATE EXTERNAL FILE FORMAT eff2 + WITH ( + FORMAT_TYPE = ORC + ); + +CREATE EXTERNAL FILE FORMAT eff3 + WITH ( + FORMAT_TYPE = PARQUET + ); + +CREATE EXTERNAL FILE FORMAT eff4 + WITH ( + FORMAT_TYPE = RCFILE, + SERDE_METHOD = 'org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe' + ); + +CREATE EXTERNAL FILE FORMAT eff5 + WITH ( + FORMAT_TYPE = DELIMITEDTEXT, + FORMAT_OPTIONS (FIELD_TERMINATOR = '|', STRING_DELIMITER = ';', DATE_FORMAT = 'MM-dd-yyyy', USE_TYPE_DEFAULT = FALSE) + ); + +CREATE EXTERNAL FILE FORMAT eff6 + WITH ( + FORMAT_TYPE = DELIMITEDTEXT, + FORMAT_OPTIONS (FIELD_TERMINATOR = '|') + ); + +CREATE EXTERNAL FILE FORMAT eff7 + WITH ( + FORMAT_TYPE = DELIMITEDTEXT, + FORMAT_OPTIONS (DATE_FORMAT = 'MM-dd-yyyy', FIELD_TERMINATOR = '|') + ); + +CREATE EXTERNAL FILE FORMAT eff8 + WITH ( + FORMAT_TYPE = DELIMITEDTEXT, + FORMAT_OPTIONS (DATE_FORMAT = 'MM-dd-yyyy', FIELD_TERMINATOR = '|', STRING_DELIMITER = ';') + ); + +CREATE EXTERNAL FILE FORMAT eff9 + WITH ( + FORMAT_TYPE = DELIMITEDTEXT, + FORMAT_OPTIONS (DATE_FORMAT = 'MM-dd-yyyy', FIELD_TERMINATOR = '|', STRING_DELIMITER = ';'), + DATA_COMPRESSION = 'org.apache.hadoop.io.compress.GzipCodec' + ); + +CREATE EXTERNAL FILE FORMAT eff10 + WITH ( + FORMAT_TYPE = RCFILE, + SERDE_METHOD = 'org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe', + DATA_COMPRESSION = 'org.apache.hadoop.io.compress.DefaultCodec' + ); + +CREATE EXTERNAL FILE FORMAT eff11 + WITH ( + FORMAT_TYPE = ORC, + DATA_COMPRESSION = 'org.apache.hadoop.io.compress.SnappyCodec' + ); + +CREATE EXTERNAL FILE FORMAT eff12 + WITH ( + FORMAT_TYPE = PARQUET, + DATA_COMPRESSION = 'org.apache.hadoop.io.compress.SnappyCodec' + ); + +CREATE EXTERNAL TABLE bands1 +( + id INTEGER NOT NULL, + name VARCHAR(50) NOT NULL, + origin CHAR(3), + rate FLOAT, + experience SMALLINT + ) + WITH ( + LOCATION = '/bands.dat', + DATA_SOURCE = eds1, + FILE_FORMAT = eff1 + ); + +CREATE EXTERNAL TABLE bands2 +( + id INTEGER NOT NULL, + name VARCHAR(50) NOT NULL, + origin CHAR(3), + rate FLOAT, + experience SMALLINT + ) + WITH ( + LOCATION = '/bands.dat', + DATA_SOURCE = eds2, + FILE_FORMAT = eff1 + ); + +CREATE EXTERNAL TABLE bands3 +( + id INTEGER NOT NULL, + name VARCHAR(50) NOT NULL, + origin CHAR(3), + rate FLOAT, + experience SMALLINT + ) + WITH ( + LOCATION = '/bands.dat', + DATA_SOURCE = eds2, + FILE_FORMAT = eff1, + REJECT_TYPE = VALUE, + REJECT_VALUE = 0 + ); + +CREATE EXTERNAL TABLE bands4 +( + id INTEGER NOT NULL, + name VARCHAR(50) NOT NULL, + origin CHAR(3), + rate FLOAT, + experience SMALLINT + ) + WITH ( + LOCATION = '/bands.dat', + DATA_SOURCE = eds1, + FILE_FORMAT = eff1, + REJECT_TYPE = PERCENTAGE, + REJECT_VALUE = 30.5, + REJECT_SAMPLE_VALUE = 10 + ); + +CREATE EXTERNAL TABLE bands5 +( + id INTEGER NOT NULL, + name VARCHAR(50) NOT NULL, + origin CHAR(3), + rate FLOAT, + experience SMALLINT + ) + WITH ( + LOCATION = '/bands.dat', + DATA_SOURCE = eds1, + FILE_FORMAT = eff1, + REJECT_TYPE = VALUE, + REJECT_VALUE = 30 + ); \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/Sql_Additions.sql b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/Sql_Additions.sql new file mode 100644 index 00000000..dea7fcbf --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestData/ObjectExplorer/TestScripts/Sql_Additions.sql @@ -0,0 +1,298 @@ +-- create signature +ADD SIGNATURE TO [Procedure1] + BY CERTIFICATE [Certificate1] + WITH PASSWORD = 'pGFD4bb925DGvbd2439587y' ; +GO +--Create a queue to receive messages. +CREATE QUEUE NotifyQueue ; +GO +--Create a service on the queue that references +--the event notifications contract. +CREATE SERVICE NotifyService +ON QUEUE NotifyQueue +([http://schemas.microsoft.com/SQL/Notifications/PostEventNotification]); +GO +--Create the event notification on queue. +CREATE EVENT NOTIFICATION Notify_ALTER_T1 +ON QUEUE notifyqueue +FOR QUEUE_ACTIVATION +TO SERVICE 'NotifyService', +'8140a771-3c4b-4479-8ac0-81008ab17984'; +GO +--Create the event notification on database +CREATE EVENT NOTIFICATION Notify_ALTER_T1 +ON DATABASE +FOR ALTER_TABLE +TO SERVICE 'NotifyService', + '8140a771-3c4b-4479-8ac0-81008ab17984'; +GO + +CREATE FUNCTION [dbo].[TableFunctionWithComputedColumns] +( + -- Add the parameters for the function here + @p1 int = 2, + @p2 nchar(10) = NUll +) +RETURNS +@Table_Var TABLE +( + -- Add the column definitions for the TABLE variable here + c1 int, + c2 nchar(10), + c3 AS 1 * 3 +) +AS +BEGIN + -- Fill the table variable with the rows for your result set + INSERT INTO @Table_Var + SELECT a.column_1, a.column_2 + FROM Table_1 a + WHERE a.column_1 > 5 + + INSERT INTO @Table_Var + SELECT column_1, 'From 2' + FROM Table_2 + WHERE @p1 > column_1 + + RETURN +END +GO + +CREATE FUNCTION [dbo].[TableFunctionWithComputedColumnsEncrypted] +( + -- Add the parameters for the function here + @p1 int = 2, + @p2 nchar(10) +) +RETURNS +@Table_Var TABLE +( + -- Add the column definitions for the TABLE variable here + c1 int, + c2 nchar(10), + c3 AS 1 * 3 +) +WITH ENCRYPTION +AS +BEGIN + -- Fill the table variable with the rows for your result set + INSERT INTO @Table_Var + SELECT a.column_1, a.column_2 + FROM Table_1 a + WHERE a.column_1 > 5 + + INSERT INTO @Table_Var + SELECT column_1, 'From 2' + FROM Table_2 + WHERE @p1 > column_1 + + RETURN +END +GO + +Create table [dbo].[referenced_table] (C1 int, C2 int); + +GO + +CREATE PROCEDURE GetReferenedTable +AS +BEGIN +SELECT * from [dbo].[referenced_table]; +END +GO +exec sp_addextendedproperty N'microsoft_database_tools_support', 'GetReferenedTable', N'SCHEMA', 'dbo', N'PROCEDURE' ,'GetReferenedTable' +GO +DISABLE TRIGGER [Trigger_1] + ON DATABASE; +GO + +CREATE VIEW [dbo].[View_2] (c1) +AS +SELECT column_1 as c1 +FROM dbo.Table_1 + +GO + +exec sp_addextendedproperty 'prop_ex', 'Table_1', 'SCHEMA', 'dbo', 'TABLE', 'Table_1' + +GO + +exec sp_addextendedproperty 'prop_ex', 'column_1', 'SCHEMA', 'dbo', 'TABLE', 'Table_1', 'COLUMN', 'column_1' +GO + +CREATE TABLE dbo.MultipleIndexTable +( [c1] INT NOT NULL CHECK (c1 > 0), +[c2] int default 10 null, +PRIMARY KEY NONCLUSTERED (c1 ASC), +UNIQUE CLUSTERED (c1 ASC, c2 DESC) +) + +GO + +CREATE TRIGGER [Trigger_2] +ON DATABASE +FOR DROP_TABLE +AS + SELECT COUNT(column_1) from dbo.Table_1 + RAISERROR ('You must disable Trigger "Trigger_1" to drop synonyms!',10, 1) + ROLLBACK + +GO + +SET ANSI_NULLS OFF +GO + +SET QUOTED_IDENTIFIER OFF +GO + +DISABLE TRIGGER [Trigger_1] ON DATABASE +GO + +GO + +CREATE TABLE dbo.Table_3 +( + c1 int, + c2 int, +) ON PartitionScheme(c1) + +GO +CREATE TABLE [dbo].[Different_WithAppend_Table]( +[Id] [int] IDENTITY(1,1) NOT NULL, +[Col] [char](1) NULL +) ON [PRIMARY] + +GO + +CREATE FUNCTION [dbo].[EncryptedFunctionWithConstraints] +(@p1 INT) +RETURNS + @GeneratedTableName TABLE ( + [c0] INT NOT NULL PRIMARY KEY, + [c1] INT DEFAULT ((1)) NULL, + [c2] NCHAR (10) NULL, + [c3] INT UNIQUE , + CHECK ([c1]>(0))) +WITH ENCRYPTION +AS +BEGIN + insert into @GeneratedTableName values (1,1, 'abc',1); + RETURN +END +GO +CREATE TABLE [[] (c1 int) +GO +CREATE TABLE []]] (c1 int) +GO +CREATE TABLE [asdf'[] (c1 int) +GO +CREATE TABLE [噂構申表5] (c1 int) +GO +-- Casing of NULL is explicit 'NUll' +CREATE PROC CasingOnDefaultValue @param1 int = NUll, @param2 nvarchar(123) = N'abc' +AS +BEGIN + select 1 as a +END +-- permissions +GO +CREATE USER nologon4 without login +GO +GRANT VIEW DEFINITION ON CasingOnDefaultValue to nologon4 +GO +CREATE USER granter without login +GO +GRANT CONNECT TO granter WITH GRANT OPTION; +GO +DENY CONNECT TO nologon4 CASCADE AS granter; +GO +GRANT VIEW DEFINITION ON [噂構申表5] to nologon4 +GO +GRANT VIEW DEFINITION ON [[] TO nologon4 +GO +GRANT VIEW DEFINITION ON []]] TO nologon4 +GO +GRANT VIEW DEFINITION ON [asdf'[] TO nologon4 +GO +GRANT SELECT ON dbo.Table_1 to nologon4 +GO +GRANT SELECT ON dbo.Table_2 to nologon4 +GO +REVOKE SELECT ON dbo.Table_2(column_2) TO nologon4 +GO +GRANT SELECT ON dbo.View_1 to nologon4 +GO +GRANT SELECT ON dbo.EncryptedView(A) to nologon4 +GO +GRANT EXECUTE ON dbo.Procedure1 TO nologon4 +GO +GRANT EXECUTE ON dbo.CLR_SimpleResultsetProcedure TO nologon4 +GO +GRANT EXECUTE ON dbo.EncryptedProcedure TO nologon4 +GO +GRANT VIEW DEFINITION ON CERTIFICATE :: Certificate1 TO nologon4 +GO +GRANT EXECUTE ON dbo.ScalarFunction1 TO nologon4 +GO +GRANT EXECUTE ON dbo.EncryptedFunction TO nologon4 +GO +GRANT SELECT ON dbo.InlineFunction_1 TO nologon4 +GO +GRANT SELECT ON dbo.TableFunction1 TO nologon4 +GO +GRANT SELECT ON dbo.CLRTableValueFunction TO nologon4 +GO +GRANT VIEW DEFINITION ON TYPE::dbo.dataType To nologon4 +GO +GRANT VIEW DEFINITION ON FULLTEXT CATALOG ::FullTextCatalog1 To nologon4 +GO +GRANT VIEW DEFINITION ON XML SCHEMA COLLECTION :: dbo.XmlSchemaCollection To nologon4 +GO +GRANT VIEW DEFINITION ON ASSEMBLY :: [Geometry] To nologon4 +GO +GRANT VIEW DEFINITION ON TYPE:: dbo.Angle To nologon4 +GO +GRANT VIEW DEFINITION ON dbo.[Concat] To nologon4 +GO +GRANT VIEW DEFINITION ON dbo.Synonym_1 To nologon4 +GO +GRANT VIEW DEFINITION ON SCHEMA :: Schema1 To nologon4 +GO +GRANT VIEW DEFINITION ON SYMMETRIC KEY :: SymKey1 To nologon4 +GO +GRANT VIEW DEFINITION ON ASYMMETRIC KEY :: AsmKey1 To nologon4 +GO +GRANT VIEW DEFINITION ON dbo.Queue1 To nologon4 +GO +GRANT VIEW DEFINITION ON dbo.NotifyQueue To nologon4 +GO +GRANT VIEW DEFINITION ON SERVICE :: Service1 To nologon4 +GO +GRANT VIEW DEFINITION ON SERVICE :: NotifyService To nologon4 +GO +GRANT VIEW DEFINITION ON CONTRACT :: Contract1 To nologon4 +GO +GRANT VIEW DEFINITION ON MESSAGE TYPE :: MessageType1 To nologon4 +GO +GRANT VIEW DEFINITION ON ROUTE :: AutoCreatedLocal To nologon4 +GO +GRANT VIEW DEFINITION ON ROUTE :: Route1 To nologon4 +GO +GRANT VIEW DEFINITION ON REMOTE SERVICE BINDING :: ServiceBinding1 To nologon4 +GO +GRANT SELECT ON dbo.referenced_table To nologon4 +GO +GRANT SELECT ON dbo.TableFunctionWithComputedColumns To nologon4 +GO +GRANT SELECT ON dbo.TableFunctionWithComputedColumnsEncrypted To nologon4 +GO +GRANT SELECT ON dbo.View_2 TO nologon4 +GO +GRANT SELECT ON dbo.MultipleIndexTable TO nologon4 +GO +GRANT SELECT ON dbo.Table_3 TO nologon4 +GO +GRANT SELECT ON dbo.Different_WithAppend_Table TO nologon4 +GO +GRANT SELECT ON dbo.[EncryptedFunctionWithConstraints] TO nologon4 +GO \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestServiceProvider.cs b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestServiceProvider.cs index 00f3146b..1f8a7607 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestServiceProvider.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestServiceProvider.cs @@ -8,6 +8,7 @@ using Microsoft.SqlTools.Credentials; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; using Microsoft.SqlTools.ServiceLayer.Hosting; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; using Microsoft.SqlTools.ServiceLayer.QueryExecution; using Microsoft.SqlTools.ServiceLayer.SqlContext; using Microsoft.SqlTools.ServiceLayer.Workspace; @@ -43,6 +44,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common { return CredentialService.Instance; } + } + + public ObjectExplorerService ObjectExplorerService + { + get + { + var serviceProvider = ServiceHost.Instance.ServiceProvider; + return serviceProvider.GetService(); + } } public TestConnectionProfileService ConnectionProfileService diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/project.json b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/project.json index 1b200970..b3070af8 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/project.json +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/project.json @@ -6,7 +6,8 @@ "includeFiles": [ "Scripts/CreateTestDatabaseObjects.sql", "Scripts/CreateTestDatabase.sql", - "Scripts/TestDbTableQueries.sql" + "Scripts/TestDbTableQueries.sql", + "Scripts/AdventureWorks.sql" ] } }, diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/NodeTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/NodeTests.cs new file mode 100644 index 00000000..a37babf6 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/NodeTests.cs @@ -0,0 +1,369 @@ +// +// 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.Data.SqlClient; +using System.Globalization; +using Microsoft.SqlServer.Management.Common; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlTools.Extensibility; +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel; +using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility; +using Moq; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer +{ + /// + /// Tests covering basic operation of Node based classes + /// + public class NodeTests : ObjectExplorerTestBase + { + private string defaultOwnerUri = "objectexplorer://myserver"; + private ServerInfo defaultServerInfo; + private ConnectionDetails defaultConnectionDetails; + private ConnectionCompleteParams defaultConnParams; + private string fakeConnectionString = "Data Source=server;Initial Catalog=database;Integrated Security=False;User Id=user"; + + public NodeTests() + { + defaultServerInfo = TestObjects.GetTestServerInfo(); + + defaultConnectionDetails = new ConnectionDetails() + { + DatabaseName = "master", + ServerName = "localhost", + UserName = "serverAdmin", + Password = "..." + }; + defaultConnParams = new ConnectionCompleteParams() + { + ServerInfo = defaultServerInfo, + ConnectionSummary = defaultConnectionDetails, + OwnerUri = defaultOwnerUri + }; + + // TODO can all tests use the standard service provider? + ServiceProvider = ExtensionServiceProvider.CreateDefaultServiceProvider(); + } + + [Fact] + public void ServerNodeConstructorValidatesFields() + { + Assert.Throws(() => new ServerNode(null, ServiceProvider)); + Assert.Throws(() => new ServerNode(defaultConnParams, null)); + } + + [Fact] + public void ServerNodeConstructorShouldSetValuesCorrectly() + { + // Given a server node with valid inputs + ServerNode node = new ServerNode(defaultConnParams, ServiceProvider); + // Then expect all fields set correctly + Assert.False(node.IsAlwaysLeaf, "Server node should never be a leaf"); + Assert.Equal(defaultConnectionDetails.ServerName, node.NodeValue); + + string expectedLabel = defaultConnectionDetails.ServerName + " (SQL Server " + defaultServerInfo.ServerVersion + " - " + + defaultConnectionDetails.UserName + ")"; + Assert.Equal(expectedLabel, node.Label); + + Assert.Equal(NodeTypes.ServerInstance.ToString(), node.NodeType); + string[] nodePath = node.GetNodePath().Split(TreeNode.PathPartSeperator); + Assert.Equal(1, nodePath.Length); + Assert.Equal(defaultConnectionDetails.ServerName, nodePath[0]); + } + + [Fact] + public void ServerNodeLabelShouldIgnoreUserNameIfEmptyOrNull() + { + // Given no username set + ConnectionSummary integratedAuthSummary = new ConnectionSummary() + { + DatabaseName = defaultConnectionDetails.DatabaseName, + ServerName = defaultConnectionDetails.ServerName, + UserName = null + }; + ConnectionCompleteParams connParams = new ConnectionCompleteParams() + { + ConnectionSummary = integratedAuthSummary, + ServerInfo = defaultServerInfo, + OwnerUri = defaultOwnerUri + }; + // When querying label + string label = new ServerNode(connParams, ServiceProvider).Label; + // Then only server name and version shown + string expectedLabel = defaultConnectionDetails.ServerName + " (SQL Server " + defaultServerInfo.ServerVersion + ")"; + Assert.Equal(expectedLabel, label); + } + + [Fact] + public void ServerNodeConstructorShouldShowDbNameForCloud() + { + defaultServerInfo.IsCloud = true; + + // Given a server node for a cloud DB, with master name + ServerNode node = new ServerNode(defaultConnParams, ServiceProvider); + // Then expect label to not include db name + string expectedLabel = defaultConnectionDetails.ServerName + " (SQL Server " + defaultServerInfo.ServerVersion + " - " + + defaultConnectionDetails.UserName + ")"; + Assert.Equal(expectedLabel, node.Label); + + // But given a server node for a cloud DB that's not master + defaultConnectionDetails.DatabaseName = "NotMaster"; + node = new ServerNode(defaultConnParams, ServiceProvider); + + // Then expect label to include db name + expectedLabel = defaultConnectionDetails.ServerName + " (SQL Server " + defaultServerInfo.ServerVersion + " - " + + defaultConnectionDetails.UserName + ", " + defaultConnectionDetails.DatabaseName + ")"; + Assert.Equal(expectedLabel, node.Label); + } + + [Fact] + public void ToNodeInfoIncludeAllFields() + { + // Given a server connection + ServerNode node = new ServerNode(defaultConnParams, ServiceProvider); + // When converting to NodeInfo + NodeInfo info = node.ToNodeInfo(); + // Then all fields should match + Assert.Equal(node.IsAlwaysLeaf, info.IsLeaf); + Assert.Equal(node.Label, info.Label); + Assert.Equal(node.NodeType, info.NodeType); + string[] nodePath = node.GetNodePath().Split(TreeNode.PathPartSeperator); + string[] nodeInfoPathParts = info.NodePath.Split(TreeNode.PathPartSeperator); + Assert.Equal(nodePath.Length, nodeInfoPathParts.Length); + for (int i = 0; i < nodePath.Length; i++) + { + Assert.Equal(nodePath[i], nodeInfoPathParts[i]); + } + } + + [Fact] + public void AddChildShouldSetParent() + { + TreeNode parent = new TreeNode("parent"); + TreeNode child = new TreeNode("child"); + Assert.Null(child.Parent); + parent.AddChild(child); + Assert.Equal(parent, child.Parent); + } + + [Fact] + public void GetChildrenShouldReturnReadonlyList() + { + TreeNode node = new TreeNode("parent"); + IList children = node.GetChildren(); + Assert.Throws(() => children.Add(new TreeNode("child"))); + } + + [Fact] + public void GetChildrenShouldReturnAddedNodesInOrder() + { + TreeNode parent = new TreeNode("parent"); + TreeNode[] expectedKids = new TreeNode[] { new TreeNode("1"), new TreeNode("2") }; + foreach (TreeNode child in expectedKids) + { + parent.AddChild(child); + } + IList children = parent.GetChildren(); + Assert.Equal(expectedKids.Length, children.Count); + for (int i = 0; i < expectedKids.Length; i++) + { + Assert.Equal(expectedKids[i], children[i]); + } + } + + public void MultiLevelTreeShouldFormatPath() + { + TreeNode root = new TreeNode("root"); + Assert.Equal("/root" , root.GetNodePath()); + + TreeNode level1Child1 = new TreeNode("L1C1"); + TreeNode level1Child2 = new TreeNode("L1C2"); + root.AddChild(level1Child1); + root.AddChild(level1Child2); + Assert.Equal("/root/L1C1" , level1Child1.GetNodePath()); + Assert.Equal("/root/L1C2", level1Child2.GetNodePath()); + + TreeNode level2Child1 = new TreeNode("L2C2"); + level1Child1.AddChild(level2Child1); + Assert.Equal("/root/L1C1/L2C2", level2Child1.GetNodePath()); + } + + [Fact] + public void ServerNodeContextShouldIncludeServer() + { + // given a successful Server creation + SetupAndRegisterTestConnectionService(); + Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString))); + ServerNode node = SetupServerNodeWithServer(smoServer); + + // When I get the context for a ServerNode + var context = node.GetContextAs(); + + // Then I expect it to contain the server I created + Assert.NotNull(context); + Assert.Equal(smoServer, context.Server); + // And the server should be the parent + Assert.Equal(smoServer, context.Parent); + Assert.Null(context.Database); + } + + [Fact] + public void ServerNodeContextShouldSetErrorMessageIfSqlConnectionIsNull() + { + // given a connectionInfo with no SqlConnection to use for queries + ConnectionService connService = SetupAndRegisterTestConnectionService(); + connService.OwnerToConnectionMap.Remove(defaultOwnerUri); + + Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString))); + ServerNode node = SetupServerNodeWithServer(smoServer); + + // When I get the context for a ServerNode + var context = node.GetContextAs(); + + // Then I expect it to be in an error state + Assert.Null(context); + Assert.Equal( + string.Format(CultureInfo.CurrentCulture, SR.ServerNodeConnectionError, defaultConnectionDetails.ServerName), + node.ErrorStateMessage); + } + + [Fact] + public void ServerNodeContextShouldSetErrorMessageIfConnFailureExceptionThrown() + { + // given a connectionInfo with no SqlConnection to use for queries + SetupAndRegisterTestConnectionService(); + + Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString))); + string expectedMsg = "ConnFailed!"; + ServerNode node = SetupServerNodeWithExceptionCreator(new ConnectionFailureException(expectedMsg)); + + // When I get the context for a ServerNode + var context = node.GetContextAs(); + + // Then I expect it to be in an error state + Assert.Null(context); + Assert.Equal( + string.Format(CultureInfo.CurrentCulture, SR.TreeNodeError, expectedMsg), + node.ErrorStateMessage); + } + + [Fact] + public void ServerNodeContextShouldSetErrorMessageIfExceptionThrown() + { + // given a connectionInfo with no SqlConnection to use for queries + SetupAndRegisterTestConnectionService(); + + Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString))); + string expectedMsg = "Failed!"; + ServerNode node = SetupServerNodeWithExceptionCreator(new Exception(expectedMsg)); + + // When I get the context for a ServerNode + var context = node.GetContextAs(); + + // Then I expect it to be in an error state + Assert.Null(context); + Assert.Equal( + string.Format(CultureInfo.CurrentCulture, SR.TreeNodeError, expectedMsg), + node.ErrorStateMessage); + } + + private ConnectionService SetupAndRegisterTestConnectionService() + { + ConnectionService connService = TestObjects.GetTestConnectionService(); + ConnectionInfo connectionInfo = new ConnectionInfo(TestObjects.GetTestSqlConnectionFactory(), + defaultOwnerUri, defaultConnectionDetails); + connectionInfo.AddConnection("Default", new SqlConnection()); + + connService.OwnerToConnectionMap.Add(defaultOwnerUri, connectionInfo); + ServiceProvider.RegisterSingleService(connService); + return connService; + } + + private ServerNode SetupServerNodeWithServer(Server smoServer) + { + Mock creator = new Mock(); + creator.Setup(c => c.Create(It.IsAny())) + .Returns(() => smoServer); + ServerNode node = SetupServerNodeWithCreator(creator.Object); + return node; + } + + private ServerNode SetupServerNodeWithExceptionCreator(Exception ex) + { + Mock creator = new Mock(); + creator.Setup(c => c.Create(It.IsAny())) + .Throws(ex); + + ServerNode node = SetupServerNodeWithCreator(creator.Object); + return node; + } + + private ServerNode SetupServerNodeWithCreator(SmoServerCreator creator) + { + ServerNode node = new ServerNode(defaultConnParams, ServiceProvider); + node.ServerCreator = creator; + return node; + } + + [Fact] + public void ServerNodeChildrenShouldIncludeFoldersAndDatabases() + { + // Given a server with 1 database + SetupAndRegisterTestConnectionService(); + ServiceProvider.RegisterSingleService(new ObjectExplorerService()); + + string dbName = "DB1"; + Mock smoObjectMock = new Mock(); + smoObjectMock.SetupGet(s => s.Name).Returns(dbName); + + Mock querierMock = new Mock(); + querierMock.Setup(q => q.Query(It.IsAny())) + .Returns(smoObjectMock.Object.SingleItemAsEnumerable()); + + ServiceProvider.Register(() => new[] { querierMock.Object }); + + Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString))); + ServerNode node = SetupServerNodeWithServer(smoServer); + + // When I populate its children + IList children = node.Expand(); + + // Then I expect it to contain server-level folders + Assert.Equal(3, children.Count); + VerifyTreeNode(children[0], "Folder", SR.SchemaHierarchy_Databases); + VerifyTreeNode(children[1], "Folder", SR.SchemaHierarchy_Security); + VerifyTreeNode(children[2], "Folder", SR.SchemaHierarchy_ServerObjects); + // And the database is contained under it + TreeNode databases = children[0]; + IList dbChildren = databases.Expand(); + Assert.Equal(2, dbChildren.Count); + Assert.Equal("System Databases", dbChildren[0].NodeValue); + + TreeNode dbNode = dbChildren[1]; + Assert.Equal(dbName, dbNode.NodeValue); + Assert.Equal(dbName, dbNode.Label); + Assert.False(dbNode.IsAlwaysLeaf); + + // Note: would like to verify Database in the context, but cannot since it's a Sealed class and isn't easily mockable + } + + private void VerifyTreeNode(TreeNode node, string nodeType, string folderValue) + where T : TreeNode + { + T nodeAsT = node as T; + Assert.NotNull(nodeAsT); + Assert.Equal(nodeType, nodeAsT.NodeType); + Assert.Equal(folderValue, nodeAsT.NodeValue); + } + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs new file mode 100644 index 00000000..a357dfd3 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs @@ -0,0 +1,151 @@ +// +// 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.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; +using Microsoft.SqlTools.ServiceLayer.Test.Common; +using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility; +using Moq; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer +{ + + public class ObjectExplorerServiceTests : ObjectExplorerTestBase + { + private ObjectExplorerService service; + private Mock connectionServiceMock; + private Mock serviceHostMock; + public ObjectExplorerServiceTests() + { + connectionServiceMock = new Mock(); + serviceHostMock = new Mock(); + service = CreateOEService(connectionServiceMock.Object); + service.InitializeService(serviceHostMock.Object); + } + + [Fact] + public async Task CreateSessionRequestErrorsIfConnectionDetailsIsNull() + { + object errorResponse = null; + var contextMock = RequestContextMocks.Create(null) + .AddErrorHandling((errorMessage, errorCode, obj) => errorResponse = errorMessage); + + await service.HandleCreateSessionRequest(null, contextMock.Object); + VerifyErrorSent(contextMock); + Assert.True(((string)errorResponse).Contains("ArgumentNullException")); + } + + [Fact] + public async Task CreateSessionRequestReturnsFalseOnConnectionFailure() + { + // Given the connection service fails to connect + ConnectionDetails details = TestObjects.GetTestConnectionDetails(); + ConnectionCompleteParams completeParams = null; + serviceHostMock.AddEventHandling(ConnectionCompleteNotification.Type, (et, p) => completeParams = p); + + string expectedExceptionText = "Error!!!"; + connectionServiceMock.Setup(c => c.Connect(It.IsAny())) + .Throws(new Exception(expectedExceptionText)); + + // when creating a new session + // then expect the create session request to return false + await RunAndVerify( + test: (requestContext) => service.HandleCreateSessionRequest(details, requestContext), + verify: (actual => + { + Assert.False(actual.Success); + Assert.Null(actual.SessionId); + Assert.Null(actual.RootNode); + })); + + // And expect error notification to be sent + serviceHostMock.Verify(x => x.SendEvent(ConnectionCompleteNotification.Type, It.IsAny()), Times.Once()); + Assert.NotNull(completeParams); + Assert.True(completeParams.Messages.Contains(expectedExceptionText)); + } + + + [Fact] + public async Task CreateSessionRequestReturnsSuccessAndNodeInfo() + { + // Given the connection service fails to connect + ConnectionDetails details = TestObjects.GetTestConnectionDetails(); + serviceHostMock.AddEventHandling(ConnectionCompleteNotification.Type, null); + + connectionServiceMock.Setup(c => c.Connect(It.IsAny())) + .Returns((ConnectParams connectParams) => Task.FromResult(GetCompleteParamsForConnection(connectParams.OwnerUri, details))); + + // when creating a new session + // then expect the create session request to return false + await RunAndVerify( + test: (requestContext) => service.HandleCreateSessionRequest(details, requestContext), + verify: (actual => + { + Assert.True(actual.Success); + Assert.NotNull(actual.SessionId); + VerifyServerNode(actual.RootNode, details); + })); + + // And expect no error notification to be sent + serviceHostMock.Verify(x => x.SendEvent(ConnectionCompleteNotification.Type, + It.IsAny()), Times.Never()); + } + + private void VerifyServerNode(NodeInfo serverNode, ConnectionDetails details) + { + Assert.NotNull(serverNode); + Assert.Equal(NodeTypes.ServerInstance.ToString(), serverNode.NodeType); + string[] pathParts = serverNode.NodePath.Split(TreeNode.PathPartSeperator); + Assert.Equal(1, pathParts.Length); + Assert.Equal(details.ServerName, pathParts[0]); + Assert.True(serverNode.Label.Contains(details.ServerName)); + Assert.False(serverNode.IsLeaf); + } + + private static ConnectionCompleteParams GetCompleteParamsForConnection(string uri, ConnectionDetails details) + { + return new ConnectionCompleteParams() + { + OwnerUri = uri, + ConnectionSummary = new ConnectionSummary() + { + ServerName = details.ServerName, + DatabaseName = details.DatabaseName, + UserName = details.UserName + }, + ServerInfo = TestObjects.GetTestServerInfo() + }; + } + + private async Task RunAndVerify(Func, Task> test, Action verify) + { + T result = default(T); + var contextMock = RequestContextMocks.Create(r => result = r).AddErrorHandling(null); + await test(contextMock.Object); + VerifyResult(contextMock, verify, result); + } + + private void VerifyResult(Mock> contextMock, Action verify, T actual) + { + contextMock.Verify(c => c.SendResult(It.IsAny()), Times.Once); + contextMock.Verify(c => c.SendError(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + verify(actual); + } + + private void VerifyErrorSent(Mock> contextMock) + { + contextMock.Verify(c => c.SendResult(It.IsAny()), Times.Never); + contextMock.Verify(c => c.SendError(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + } + + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerTestBase.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerTestBase.cs new file mode 100644 index 00000000..2020ed7f --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerTestBase.cs @@ -0,0 +1,45 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Extensibility; +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; + +namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer +{ + // Base class providing common test functionality for OE tests + public abstract class ObjectExplorerTestBase + { + protected RegisteredServiceProvider ServiceProvider + { + get; + set; + } + + protected RegisteredServiceProvider CreateServiceProviderWithMinServices() + { + return CreateProvider() + .RegisterSingleService(new ConnectionService()) + .RegisterSingleService(new ObjectExplorerService()); + } + + protected RegisteredServiceProvider CreateProvider() + { + ServiceProvider = new RegisteredServiceProvider(); + return ServiceProvider; + } + + protected ObjectExplorerService CreateOEService(ConnectionService connService) + { + CreateProvider() + .RegisterSingleService(connService) + .RegisterSingleService(new ObjectExplorerService()); + + // Create the service using the service provider, which will initialize dependencies + return ServiceProvider.GetService(); + } + + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/SmoQueryModelTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/SmoQueryModelTests.cs new file mode 100644 index 00000000..c6f46554 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/SmoQueryModelTests.cs @@ -0,0 +1,65 @@ +// +// 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.Linq; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlTools.Extensibility; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer +{ + public class SmoQueryModelTests + { + + [Fact] + public void ShouldFindDatabaseQuerierFromRealPath() + { + // Given the extension type loader is set to find SmoCollectionQuerier objects + IMultiServiceProvider serviceProvider = ExtensionServiceProvider.CreateDefaultServiceProvider(); + // When I request a database compatible querier + SmoQuerier querier = serviceProvider.GetService(q => q.SupportedObjectTypes.Contains(typeof(Database))); + // Then I expect to get back the SqlDatabaseQuerier + Assert.NotNull(querier); + Assert.Equal(typeof(SqlDatabaseQuerier), querier.GetType()); + + // And I expect the service provider to have been set by the extension code + Assert.NotNull(querier.ServiceProvider); + } + + [Fact] + public void ShouldFindQuerierIfInExtensionList() + { + VerifyQuerierLookup(typeof(Table), typeof(SqlTableQuerier), expectExists: true); + } + + [Fact] + public void ShouldNotFindQuerierIfNotInExtensionList() + { + VerifyQuerierLookup(typeof(Database), null, expectExists: false); + } + + private static void VerifyQuerierLookup(Type smoType, Type querierType, bool expectExists) + { + ExtensionServiceProvider serviceProvider = ExtensionServiceProvider.Create(new Type[] { + typeof(SqlTableQuerier), + typeof(SqlLinkedServerQuerier) + }); + SmoQuerier querier = serviceProvider.GetService(q => q.SupportedObjectTypes.Contains(smoType)); + if (expectExists) + { + Assert.NotNull(querier); + Assert.Equal(querierType, querier.GetType()); + Assert.NotNull(querier.ServiceProvider); + } + else + { + Assert.Null(querier); + } + } + + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/SrTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/SrTests.cs index 0b9a9aa4..9925e566 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/SrTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/SrTests.cs @@ -43,6 +43,169 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ServiceHost var queryServiceErrorFormat = SR.QueryServiceErrorFormat(1, 1, 1, 1, "\n", ".."); var queryServiceQueryFailed = SR.QueryServiceQueryFailed(".."); var workspaceServiceBufferPositionOutOfOrder = SR.WorkspaceServiceBufferPositionOutOfOrder(1, 2, 3, 4); + var treeNodeError = SR.TreeNodeError; + var serverNodeConnectionError = SR.ServerNodeConnectionError; + var schemaHierarchyAggregates = SR.SchemaHierarchy_Aggregates; + var SchemaHierarchy_ServerRoles = SR.SchemaHierarchy_ServerRoles; + var SchemaHierarchy_ApplicationRoles = SR.SchemaHierarchy_ApplicationRoles; + var SchemaHierarchy_Assemblies = SR.SchemaHierarchy_Assemblies; + var SchemaHierarchy_AssemblyFiles = SR.SchemaHierarchy_AssemblyFiles; + var SchemaHierarchy_AsymmetricKeys = SR.SchemaHierarchy_AsymmetricKeys; + var SchemaHierarchy_DatabaseAsymmetricKeys = SR.SchemaHierarchy_DatabaseAsymmetricKeys; + var SchemaHierarchy_DataCompressionOptions = SR.SchemaHierarchy_DataCompressionOptions; + var SchemaHierarchy_Certificates = SR.SchemaHierarchy_Certificates; + var SchemaHierarchy_FileTables = SR.SchemaHierarchy_FileTables; + var SchemaHierarchy_DatabaseCertificates = SR.SchemaHierarchy_DatabaseCertificates; + var SchemaHierarchy_CheckConstraints = SR.SchemaHierarchy_CheckConstraints; + var SchemaHierarchy_Columns = SR.SchemaHierarchy_Columns; + var SchemaHierarchy_Constraints = SR.SchemaHierarchy_Constraints; + var SchemaHierarchy_Contracts = SR.SchemaHierarchy_Contracts; + var SchemaHierarchy_Credentials = SR.SchemaHierarchy_Credentials; + var SchemaHierarchy_ErrorMessages = SR.SchemaHierarchy_ErrorMessages; + var SchemaHierarchy_ServerRoleMembership = SR.SchemaHierarchy_ServerRoleMembership; + var SchemaHierarchy_DatabaseOptions = SR.SchemaHierarchy_DatabaseOptions; + var SchemaHierarchy_DatabaseRoles = SR.SchemaHierarchy_DatabaseRoles; + var SchemaHierarchy_RoleMemberships = SR.SchemaHierarchy_RoleMemberships; + var SchemaHierarchy_DatabaseTriggers = SR.SchemaHierarchy_DatabaseTriggers; + var SchemaHierarchy_DefaultConstraints = SR.SchemaHierarchy_DefaultConstraints; + var SchemaHierarchy_Defaults = SR.SchemaHierarchy_Defaults; + var SchemaHierarchy_Sequences = SR.SchemaHierarchy_Sequences; + var SchemaHierarchy_Endpoints = SR.SchemaHierarchy_Endpoints; + var SchemaHierarchy_EventNotifications = SR.SchemaHierarchy_EventNotifications; + var SchemaHierarchy_ServerEventNotifications = SR.SchemaHierarchy_ServerEventNotifications; + var SchemaHierarchy_ExtendedProperties = SR.SchemaHierarchy_ExtendedProperties; + var SchemaHierarchy_FileGroups = SR.SchemaHierarchy_FileGroups; + var SchemaHierarchy_ForeignKeys = SR.SchemaHierarchy_ForeignKeys; + var SchemaHierarchy_FullTextCatalogs = SR.SchemaHierarchy_FullTextCatalogs; + var SchemaHierarchy_FullTextIndexes = SR.SchemaHierarchy_FullTextIndexes; + var SchemaHierarchy_Functions = SR.SchemaHierarchy_Functions; + var SchemaHierarchy_Indexes = SR.SchemaHierarchy_Indexes; + var SchemaHierarchy_InlineFunctions = SR.SchemaHierarchy_InlineFunctions; + var SchemaHierarchy_Keys = SR.SchemaHierarchy_Keys; + var SchemaHierarchy_LinkedServers = SR.SchemaHierarchy_LinkedServers; + var SchemaHierarchy_LinkedServerLogins = SR.SchemaHierarchy_LinkedServerLogins; + var SchemaHierarchy_Logins = SR.SchemaHierarchy_Logins; + var SchemaHierarchy_MasterKey = SR.SchemaHierarchy_MasterKey; + var SchemaHierarchy_MasterKeys = SR.SchemaHierarchy_MasterKeys; + var SchemaHierarchy_MessageTypes = SR.SchemaHierarchy_MessageTypes; + var SchemaHierarchy_MultiSelectFunctions = SR.SchemaHierarchy_MultiSelectFunctions; + var SchemaHierarchy_Parameters = SR.SchemaHierarchy_Parameters; + var SchemaHierarchy_PartitionFunctions = SR.SchemaHierarchy_PartitionFunctions; + var SchemaHierarchy_PartitionSchemes = SR.SchemaHierarchy_PartitionSchemes; + var SchemaHierarchy_Permissions = SR.SchemaHierarchy_Permissions; + var SchemaHierarchy_PrimaryKeys = SR.SchemaHierarchy_PrimaryKeys; + var schemaHierarchyPrimaryKeys = SR.SchemaHierarchy_PrimaryKeys; + var schemaHierarchyProgrammability = SR.SchemaHierarchy_Programmability; + var schemaHierarchyQueues = SR.SchemaHierarchy_Queues; + var schemaHierarchyRemoteServiceBindings = SR.SchemaHierarchy_RemoteServiceBindings; + var schemaHierarchyReturnedColumns = SR.SchemaHierarchy_ReturnedColumns; + var schemaHierarchyRoles = SR.SchemaHierarchy_Roles; + var schemaHierarchyRoutes = SR.SchemaHierarchy_Routes; + var schemaHierarchyRules = SR.SchemaHierarchy_Rules; + var schemaHierarchySchemas = SR.SchemaHierarchy_Schemas; + var schemaHierarchySecurity = SR.SchemaHierarchy_Security; + var schemaHierarchyServerObjects = SR.SchemaHierarchy_ServerObjects; + var schemaHierarchyManagement = SR.SchemaHierarchy_Management; + var schemaHierarchyServerTriggers = SR.SchemaHierarchy_ServerTriggers; + var schemaHierarchyServiceBroker = SR.SchemaHierarchy_ServiceBroker; + var schemaHierarchyServices = SR.SchemaHierarchy_Services; + var schemaHierarchySignatures = SR.SchemaHierarchy_LogFiles; + var schemaHierarchyStatistics = SR.SchemaHierarchy_Statistics; + var schemaHierarchyStorage = SR.SchemaHierarchy_Storage; + var schemaHierarchyStoredProcedures = SR.SchemaHierarchy_StoredProcedures; + var schemaHierarchySymmetricKeys = SR.SchemaHierarchy_SymmetricKeys; + var schemaHierarchySynonyms = SR.SchemaHierarchy_Synonyms; + var schemaHierarchyTables = SR.SchemaHierarchy_Tables; + var schemaHierarchyTriggers = SR.SchemaHierarchy_Triggers; + var schemaHierarchyTypes = SR.SchemaHierarchy_Types; + var schemaHierarchyUniqueKeys = SR.SchemaHierarchy_UniqueKeys; + var schemaHierarchyUserDefinedDataTypes = SR.SchemaHierarchy_UserDefinedDataTypes; + var schemaHierarchyUserDefinedTypes = SR.SchemaHierarchy_UserDefinedTypes; + var schemaHierarchyUsers = SR.SchemaHierarchy_Users; + var schemaHierarchyViews = SR.SchemaHierarchy_Views; + var schemaHierarchyXmlIndexes = SR.SchemaHierarchy_XmlIndexes; + var schemaHierarchyXMLSchemaCollections = SR.SchemaHierarchy_XMLSchemaCollections; + var schemaHierarchyUserDefinedTableTypes = SR.SchemaHierarchy_UserDefinedTableTypes; + var schemaHierarchyFilegroupFiles = SR.SchemaHierarchy_FilegroupFiles; + var missingCaption = SR.MissingCaption; + var schemaHierarchyBrokerPriorities = SR.SchemaHierarchy_BrokerPriorities; + var schemaHierarchyCryptographicProviders = SR.SchemaHierarchy_CryptographicProviders; + var schemaHierarchyDatabaseAuditSpecifications = SR.SchemaHierarchy_DatabaseAuditSpecifications; + var schemaHierarchyDatabaseEncryptionKeys = SR.SchemaHierarchy_DatabaseEncryptionKeys; + var schemaHierarchyEventSessions = SR.SchemaHierarchy_EventSessions; + var schemaHierarchyFullTextStopLists = SR.SchemaHierarchy_FullTextStopLists; + var schemaHierarchyResourcePools = SR.SchemaHierarchy_ResourcePools; + var schemaHierarchyServerAudits = SR.SchemaHierarchy_ServerAudits; + var schemaHierarchyServerAuditSpecifications = SR.SchemaHierarchy_ServerAuditSpecifications; + var schemaHierarchySpatialIndexes = SR.SchemaHierarchy_SpatialIndexes; + var schemaHierarchyWorkloadGroups = SR.SchemaHierarchy_WorkloadGroups; + var schemaHierarchySqlFiles = SR.SchemaHierarchy_SqlFiles; + var schemaHierarchyServerFunctions = SR.SchemaHierarchy_ServerFunctions; + var schemaHierarchySqlType = SR.SchemaHierarchy_SqlType; + var schemaHierarchyServerOptions = SR.SchemaHierarchy_ServerOptions; + var schemaHierarchyDatabaseDiagrams = SR.SchemaHierarchy_DatabaseDiagrams; + var schemaHierarchySystemTables = SR.SchemaHierarchy_SystemTables; + var schemaHierarchyDatabases = SR.SchemaHierarchy_Databases; + var schemaHierarchySystemContracts = SR.SchemaHierarchy_SystemContracts; + var schemaHierarchySystemDatabases = SR.SchemaHierarchy_SystemDatabases; + var schemaHierarchySystemMessageTypes = SR.SchemaHierarchy_SystemMessageTypes; + var schemaHierarchySystemQueues = SR.SchemaHierarchy_SystemQueues; + var schemaHierarchySystemServices = SR.SchemaHierarchy_SystemServices; + var schemaHierarchySystemStoredProcedures = SR.SchemaHierarchy_SystemStoredProcedures; + var schemaHierarchySystemViews = SR.SchemaHierarchy_SystemViews; + var schemaHierarchyDataTierApplications = SR.SchemaHierarchy_DataTierApplications; + var schemaHierarchyExtendedStoredProcedures = SR.SchemaHierarchy_ExtendedStoredProcedures; + var schemaHierarchySystemAggregateFunctions = SR.SchemaHierarchy_SystemAggregateFunctions; + var schemaHierarchySystemApproximateNumerics = SR.SchemaHierarchy_SystemApproximateNumerics; + var schemaHierarchySystemBinaryStrings = SR.SchemaHierarchy_SystemBinaryStrings; + var schemaHierarchySystemCharacterStrings = SR.SchemaHierarchy_SystemCharacterStrings; + var schemaHierarchySystemCLRDataTypes = SR.SchemaHierarchy_SystemCLRDataTypes; + var schemaHierarchySystemConfigurationFunctions = SR.SchemaHierarchy_SystemConfigurationFunctions; + var schemaHierarchySystemCursorFunctions = SR.SchemaHierarchy_SystemCursorFunctions; + var schemaHierarchySystemDataTypes = SR.SchemaHierarchy_SystemDataTypes; + var schemaHierarchySystemDateAndTime = SR.SchemaHierarchy_SystemDateAndTime; + var schemaHierarchySystemDateAndTimeFunctions = SR.SchemaHierarchy_SystemDateAndTimeFunctions; + var schemaHierarchySystemExactNumerics = SR.SchemaHierarchy_SystemExactNumerics; + var schemaHierarchySystemFunctions = SR.SchemaHierarchy_SystemFunctions; + var schemaHierarchySystemHierarchyIdFunctions = SR.SchemaHierarchy_SystemHierarchyIdFunctions; + var schemaHierarchySystemMathematicalFunctions = SR.SchemaHierarchy_SystemMathematicalFunctions; + var schemaHierarchySystemMetadataFunctionions = SR.SchemaHierarchy_SystemMetadataFunctions; + var schemaHierarchySystemOtherDataTypes = SR.SchemaHierarchy_SystemOtherDataTypes; + var schemaHierarchySystemOtherFunctions = SR.SchemaHierarchy_SystemOtherFunctions; + var schemaHierarchySystemRowsetFunctions = SR.SchemaHierarchy_SystemRowsetFunctions; + var schemaHierarchySystemSecurityFunctions = SR.SchemaHierarchy_SystemSecurityFunctions; + var schemaHierarchySystemSpatialDataTypes = SR.SchemaHierarchy_SystemSpatialDataTypes; + var schemaHierarchySystemStringFunctions = SR.SchemaHierarchy_SystemStringFunctions; + var schemaHierarchySystemSystemStatisticalFunctions = SR.SchemaHierarchy_SystemSystemStatisticalFunctions; + var schemaHierarchySystemTextAndImageFunctions = SR.SchemaHierarchy_SystemTextAndImageFunctions; + var schemaHierarchySystemUnicodeCharacterStrings = SR.SchemaHierarchy_SystemUnicodeCharacterStrings; + var schemaHierarchyAggregateFunctions = SR.SchemaHierarchy_AggregateFunctions; + var schemaHierarchyScalarValuedFunctions = SR.SchemaHierarchy_ScalarValuedFunctions; + var schemaHierarchyTableValuedFunctions = SR.SchemaHierarchy_TableValuedFunctions; + var schemaHierarchySystemExtendedStoredProcedures = SR.SchemaHierarchy_SystemExtendedStoredProcedures; + var schemaHierarchyBuiltInType = SR.SchemaHierarchy_BuiltInType; + var schemaHierarchyBuiltInServerRole = SR.SchemaHierarchy_BuiltInServerRole; + var schemaHierarchyUserWithPassword = SR.SchemaHierarchy_UserWithPassword; + var schemaHierarchySearchPropertyList = SR.SchemaHierarchy_SearchPropertyList; + var schemaHierarchySecurityPolicies = SR.SchemaHierarchy_SecurityPolicies; + var schemaHierarchySecurityPredicates = SR.SchemaHierarchy_SecurityPredicates; + var schemaHierarchyServerRole = SR.SchemaHierarchy_ServerRole; + var schemaHierarchySearchPropertyLists = SR.SchemaHierarchy_SearchPropertyLists; + var schemaHierarchyColumnStoreIndexes = SR.SchemaHierarchy_ColumnStoreIndexes; + var schemaHierarchyTableTypeIndexes = SR.SchemaHierarchy_TableTypeIndexes; + var schemaHierarchyServerInstance = SR.SchemaHierarchy_ServerInstance; + var schemaHierarchySelectiveXmlIndexes = SR.SchemaHierarchy_SelectiveXmlIndexes; + var schemaHierarchyXmlNamespaces = SR.SchemaHierarchy_XmlNamespaces; + var schemaHierarchyXmlTypedPromotedPaths = SR.SchemaHierarchy_XmlTypedPromotedPaths; + var schemaHierarchySqlTypedPromotedPaths = SR.SchemaHierarchy_SqlTypedPromotedPaths; + var schemaHierarchyDatabaseScopedCredentials = SR.SchemaHierarchy_DatabaseScopedCredentials; + var schemaHierarchyExternalDataSources = SR.SchemaHierarchy_ExternalDataSources; + var schemaHierarchyExternalFileFormats = SR.SchemaHierarchy_ExternalFileFormats; + var schemaHierarchyExternalResources = SR.SchemaHierarchy_ExternalResources; + var schemaHierarchyExternalTables = SR.SchemaHierarchy_ExternalTables; + var schemaHierarchyAlwaysEncryptedKeys = SR.SchemaHierarchy_AlwaysEncryptedKeys; + var schemaHierarchyColumnMasterKeys = SR.SchemaHierarchy_ColumnMasterKeys; + var schemaHierarchyColumnEncryptionKeys = SR.SchemaHierarchy_ColumnEncryptionKeys; } [Fact] diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/ProtocolEndpointMocks.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/ProtocolEndpointMocks.cs new file mode 100644 index 00000000..eb8005c1 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/ProtocolEndpointMocks.cs @@ -0,0 +1,33 @@ +// +// 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.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.Hosting.Protocol.Contracts; +using Moq; + +namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility +{ + public static class ProtocolEndpointMocks + { + public static Mock AddEventHandling( + this Mock mock, + EventType expectedEvent, + Action, TParams> eventCallback) + { + var flow = mock.Setup(h => h.SendEvent( + It.Is>(m => m == expectedEvent), + It.IsAny())) + .Returns(Task.FromResult(0)); + if (eventCallback != null) + { + flow.Callback(eventCallback); + } + + return mock; + } + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/TestObjects.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/TestObjects.cs index a8d5b429..240877e2 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/TestObjects.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/TestObjects.cs @@ -53,6 +53,30 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility }; } + public static ServerInfo GetTestServerInfo() + { + return new ServerInfo() + { + ServerVersion = "14.0.1.0", + ServerMajorVersion = 14, + ServerMinorVersion = 0, + EngineEditionId = 3, + OsVersion = "Linux (Ubuntu 15.10)", + IsCloud = false, + ServerEdition = "Developer Edition", + ServerLevel = "" + }; + } + + /// + /// Creates a test sql connection factory instance + /// + public static ISqlConnectionFactory GetTestSqlConnectionFactory() + { + // use mock database connection + return new TestSqlConnectionFactory(); + } + /// /// Creates a test connection details object ///