Object Explorer Service (#311)

* moving OE service from an old branch
This commit is contained in:
Leila Lali
2017-04-11 15:50:20 -07:00
committed by GitHub
parent 90861b7d9e
commit d903ba56a9
58 changed files with 24577 additions and 1057 deletions

View File

@@ -52,7 +52,7 @@ namespace Microsoft.SqlTools.Hosting
protected IMultiServiceProvider ServiceProvider { get; private set; } protected IMultiServiceProvider ServiceProvider { get; private set; }
public void SetServiceProvider(IMultiServiceProvider provider) public virtual void SetServiceProvider(IMultiServiceProvider provider)
{ {
ServiceProvider = provider; ServiceProvider = provider;
} }

View File

@@ -176,7 +176,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
/// <summary> /// <summary>
/// Open a connection with the specified ConnectParams /// Open a connection with the specified ConnectParams
/// </summary> /// </summary>
public async Task<ConnectionCompleteParams> Connect(ConnectParams connectionParams) public virtual async Task<ConnectionCompleteParams> Connect(ConnectParams connectionParams)
{ {
// Validate parameters // Validate parameters
ConnectionCompleteParams validationResults = ValidateConnectParams(connectionParams); ConnectionCompleteParams validationResults = ValidateConnectParams(connectionParams);

View File

@@ -11,6 +11,7 @@ using Microsoft.SqlTools.ServiceLayer.EditData;
using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.LanguageServices; using Microsoft.SqlTools.ServiceLayer.LanguageServices;
using Microsoft.SqlTools.ServiceLayer.Metadata; using Microsoft.SqlTools.ServiceLayer.Metadata;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.QueryExecution; using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.Scripting; using Microsoft.SqlTools.ServiceLayer.Scripting;
using Microsoft.SqlTools.ServiceLayer.SqlContext; using Microsoft.SqlTools.ServiceLayer.SqlContext;
@@ -85,6 +86,7 @@ namespace Microsoft.SqlTools.ServiceLayer
serviceProvider.RegisterSingleService(ScriptingService.Instance); serviceProvider.RegisterSingleService(ScriptingService.Instance);
InitializeHostedServices(serviceProvider, serviceHost); InitializeHostedServices(serviceProvider, serviceHost);
serviceHost.ServiceProvider = serviceProvider;
serviceHost.InitializeRequestHandlers(); serviceHost.InitializeRequestHandlers();
} }

File diff suppressed because it is too large Load Diff

View File

@@ -599,4 +599,656 @@
<value>Decimal column is missing numeric precision or numeric scale</value> <value>Decimal column is missing numeric precision or numeric scale</value>
<comment></comment> <comment></comment>
</data> </data>
<data name="TreeNodeError" xml:space="preserve">
<value>Error expanding: {0}</value>
<comment></comment>
</data>
<data name="ServerNodeConnectionError" xml:space="preserve">
<value>Error connecting to {0}</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Aggregates" xml:space="preserve">
<value>Aggregates</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerRoles" xml:space="preserve">
<value>Server Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ApplicationRoles" xml:space="preserve">
<value>Application Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Assemblies" xml:space="preserve">
<value>Assemblies</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_AssemblyFiles" xml:space="preserve">
<value>Assembly Files</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_AsymmetricKeys" xml:space="preserve">
<value>Asymmetric Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseAsymmetricKeys" xml:space="preserve">
<value>Asymmetric Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DataCompressionOptions" xml:space="preserve">
<value>Data Compression Options</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Certificates" xml:space="preserve">
<value>Certificates</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FileTables" xml:space="preserve">
<value>FileTables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseCertificates" xml:space="preserve">
<value>Certificates</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_CheckConstraints" xml:space="preserve">
<value>Check Constraints</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Columns" xml:space="preserve">
<value>Columns</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Constraints" xml:space="preserve">
<value>Constraints</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Contracts" xml:space="preserve">
<value>Contracts</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Credentials" xml:space="preserve">
<value>Credentials</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ErrorMessages" xml:space="preserve">
<value>Error Messages</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerRoleMembership" xml:space="preserve">
<value>Server Role Membership</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseOptions" xml:space="preserve">
<value>Database Options</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseRoles" xml:space="preserve">
<value>Database Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_RoleMemberships" xml:space="preserve">
<value>Role Memberships</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseTriggers" xml:space="preserve">
<value>Database Triggers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DefaultConstraints" xml:space="preserve">
<value>Default Constraints</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Defaults" xml:space="preserve">
<value>Defaults</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Sequences" xml:space="preserve">
<value>Sequences</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Endpoints" xml:space="preserve">
<value>Endpoints</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_EventNotifications" xml:space="preserve">
<value>Event Notifications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerEventNotifications" xml:space="preserve">
<value>Server Event Notifications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExtendedProperties" xml:space="preserve">
<value>Extended Properties</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FileGroups" xml:space="preserve">
<value>Filegroups</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ForeignKeys" xml:space="preserve">
<value>Foreign Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FullTextCatalogs" xml:space="preserve">
<value>Full-Text Catalogs</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FullTextIndexes" xml:space="preserve">
<value>Full-Text Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Functions" xml:space="preserve">
<value>Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Indexes" xml:space="preserve">
<value>Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_InlineFunctions" xml:space="preserve">
<value>Inline Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Keys" xml:space="preserve">
<value>Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_LinkedServers" xml:space="preserve">
<value>Linked Servers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_LinkedServerLogins" xml:space="preserve">
<value>Linked Server Logins</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Logins" xml:space="preserve">
<value>Logins</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_MasterKey" xml:space="preserve">
<value>Master Key</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_MasterKeys" xml:space="preserve">
<value>Master Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_MessageTypes" xml:space="preserve">
<value>Message Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_MultiSelectFunctions" xml:space="preserve">
<value>Table-Valued Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Parameters" xml:space="preserve">
<value>Parameters</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_PartitionFunctions" xml:space="preserve">
<value>Partition Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_PartitionSchemes" xml:space="preserve">
<value>Partition Schemes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Permissions" xml:space="preserve">
<value>Permissions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_PrimaryKeys" xml:space="preserve">
<value>Primary Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Programmability" xml:space="preserve">
<value>Programmability</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Queues" xml:space="preserve">
<value>Queues</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_RemoteServiceBindings" xml:space="preserve">
<value>Remote Service Bindings</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ReturnedColumns" xml:space="preserve">
<value>Returned Columns</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Roles" xml:space="preserve">
<value>Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Routes" xml:space="preserve">
<value>Routes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Rules" xml:space="preserve">
<value>Rules</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Schemas" xml:space="preserve">
<value>Schemas</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Security" xml:space="preserve">
<value>Security</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerObjects" xml:space="preserve">
<value>Server Objects</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Management" xml:space="preserve">
<value>Management</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerTriggers" xml:space="preserve">
<value>Triggers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServiceBroker" xml:space="preserve">
<value>Service Broker</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Services" xml:space="preserve">
<value>Services</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Signatures" xml:space="preserve">
<value>Signatures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_LogFiles" xml:space="preserve">
<value>Log Files</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Statistics" xml:space="preserve">
<value>Statistics</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Storage" xml:space="preserve">
<value>Storage</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_StoredProcedures" xml:space="preserve">
<value>Stored Procedures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SymmetricKeys" xml:space="preserve">
<value>Symmetric Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Synonyms" xml:space="preserve">
<value>Synonyms</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Tables" xml:space="preserve">
<value>Tables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Triggers" xml:space="preserve">
<value>Triggers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Types" xml:space="preserve">
<value>Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UniqueKeys" xml:space="preserve">
<value>Unique Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UserDefinedDataTypes" xml:space="preserve">
<value>User-Defined Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UserDefinedTypes" xml:space="preserve">
<value>User-Defined Types (CLR)</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Users" xml:space="preserve">
<value>Users</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Views" xml:space="preserve">
<value>Views</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_XmlIndexes" xml:space="preserve">
<value>XML Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_XMLSchemaCollections" xml:space="preserve">
<value>XML Schema Collections</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UserDefinedTableTypes" xml:space="preserve">
<value>User-Defined Table Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FilegroupFiles" xml:space="preserve">
<value>Files</value>
<comment></comment>
</data>
<data name="MissingCaption" xml:space="preserve">
<value>Missing Caption</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_BrokerPriorities" xml:space="preserve">
<value>Broker Priorities</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_CryptographicProviders" xml:space="preserve">
<value>Cryptographic Providers</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseAuditSpecifications" xml:space="preserve">
<value>Database Audit Specifications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseEncryptionKeys" xml:space="preserve">
<value>Database Encryption Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_EventSessions" xml:space="preserve">
<value>Event Sessions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_FullTextStopLists" xml:space="preserve">
<value>Full Text Stoplists</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ResourcePools" xml:space="preserve">
<value>Resource Pools</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerAudits" xml:space="preserve">
<value>Audits</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerAuditSpecifications" xml:space="preserve">
<value>Server Audit Specifications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SpatialIndexes" xml:space="preserve">
<value>Spatial Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_WorkloadGroups" xml:space="preserve">
<value>Workload Groups</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SqlFiles" xml:space="preserve">
<value>SQL Files</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerFunctions" xml:space="preserve">
<value>Server Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SqlType" xml:space="preserve">
<value>SQL Type</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerOptions" xml:space="preserve">
<value>Server Options</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseDiagrams" xml:space="preserve">
<value>Database Diagrams</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemTables" xml:space="preserve">
<value>System Tables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_Databases" xml:space="preserve">
<value>Databases</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemContracts" xml:space="preserve">
<value>System Contracts</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemDatabases" xml:space="preserve">
<value>System Databases</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemMessageTypes" xml:space="preserve">
<value>System Message Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemQueues" xml:space="preserve">
<value>System Queues</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemServices" xml:space="preserve">
<value>System Services</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemStoredProcedures" xml:space="preserve">
<value>System Stored Procedures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemViews" xml:space="preserve">
<value>System Views</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DataTierApplications" xml:space="preserve">
<value>Data-tier Applications</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExtendedStoredProcedures" xml:space="preserve">
<value>Extended Stored Procedures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemAggregateFunctions" xml:space="preserve">
<value>Aggregate Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemApproximateNumerics" xml:space="preserve">
<value>Approximate Numerics</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemBinaryStrings" xml:space="preserve">
<value>Binary Strings</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemCharacterStrings" xml:space="preserve">
<value>Character Strings</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemCLRDataTypes" xml:space="preserve">
<value>CLR Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemConfigurationFunctions" xml:space="preserve">
<value>Configuration Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemCursorFunctions" xml:space="preserve">
<value>Cursor Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemDataTypes" xml:space="preserve">
<value>System Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemDateAndTime" xml:space="preserve">
<value>Date and Time</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemDateAndTimeFunctions" xml:space="preserve">
<value>Date and Time Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemExactNumerics" xml:space="preserve">
<value>Exact Numerics</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemFunctions" xml:space="preserve">
<value>System Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemHierarchyIdFunctions" xml:space="preserve">
<value>Hierarchy Id Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemMathematicalFunctions" xml:space="preserve">
<value>Mathematical Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemMetadataFunctions" xml:space="preserve">
<value>Metadata Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemOtherDataTypes" xml:space="preserve">
<value>Other Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemOtherFunctions" xml:space="preserve">
<value>Other Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemRowsetFunctions" xml:space="preserve">
<value>Rowset Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemSecurityFunctions" xml:space="preserve">
<value>Security Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemSpatialDataTypes" xml:space="preserve">
<value>Spatial Data Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemStringFunctions" xml:space="preserve">
<value>String Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemSystemStatisticalFunctions" xml:space="preserve">
<value>System Statistical Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemTextAndImageFunctions" xml:space="preserve">
<value>Text and Image Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemUnicodeCharacterStrings" xml:space="preserve">
<value>Unicode Character Strings</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_AggregateFunctions" xml:space="preserve">
<value>Aggregate Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ScalarValuedFunctions" xml:space="preserve">
<value>Scalar-valued Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_TableValuedFunctions" xml:space="preserve">
<value>Table-valued Functions</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SystemExtendedStoredProcedures" xml:space="preserve">
<value>System Extended Stored Procedures</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_BuiltInType" xml:space="preserve">
<value>Built-in Types</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_BuiltInServerRole" xml:space="preserve">
<value>Built-in Server Roles</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_UserWithPassword" xml:space="preserve">
<value>User with Password</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SearchPropertyList" xml:space="preserve">
<value>Search Property List</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SecurityPolicies" xml:space="preserve">
<value>Security Policies</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SecurityPredicates" xml:space="preserve">
<value>Security Predicates</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerRole" xml:space="preserve">
<value>Server Role</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SearchPropertyLists" xml:space="preserve">
<value>Search Property Lists</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ColumnStoreIndexes" xml:space="preserve">
<value>Column Store Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_TableTypeIndexes" xml:space="preserve">
<value>Table Type Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ServerInstance" xml:space="preserve">
<value>ServerInstance</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SelectiveXmlIndexes" xml:space="preserve">
<value>Selective XML Indexes</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_XmlNamespaces" xml:space="preserve">
<value>XML Namespaces</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_XmlTypedPromotedPaths" xml:space="preserve">
<value>XML Typed Promoted Paths</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_SqlTypedPromotedPaths" xml:space="preserve">
<value>T-SQL Typed Promoted Paths</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_DatabaseScopedCredentials" xml:space="preserve">
<value>Database Scoped Credentials</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExternalDataSources" xml:space="preserve">
<value>External Data Sources</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExternalFileFormats" xml:space="preserve">
<value>External File Formats</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExternalResources" xml:space="preserve">
<value>External Resources</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ExternalTables" xml:space="preserve">
<value>External Tables</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_AlwaysEncryptedKeys" xml:space="preserve">
<value>Always Encrypted Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ColumnMasterKeys" xml:space="preserve">
<value>Column Master Keys</value>
<comment></comment>
</data>
<data name="SchemaHierarchy_ColumnEncryptionKeys" xml:space="preserve">
<value>Column Encryption Keys</value>
<comment></comment>
</data>
</root> </root>

View File

@@ -293,3 +293,333 @@ TestLocalizationConstant = test
# Utilities # Utilities
SqlScriptFormatterDecimalMissingPrecision = Decimal column is missing numeric precision or numeric scale 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

View File

@@ -601,6 +601,821 @@
<target state="new">Table or view requested for edit could not be found</target> <target state="new">Table or view requested for edit could not be found</target>
<note></note> <note></note>
</trans-unit> </trans-unit>
<trans-unit id="TreeNodeError">
<source>Error expanding: {0}</source>
<target state="new">Error expanding: {0}</target>
<note></note>
</trans-unit>
<trans-unit id="ServerNodeConnectionError">
<source>Error connecting to {0}</source>
<target state="new">Error connecting to {0}</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Aggregates">
<source>Aggregates</source>
<target state="new">Aggregates</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ServerRoles">
<source>Server Roles</source>
<target state="new">Server Roles</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ApplicationRoles">
<source>Application Roles</source>
<target state="new">Application Roles</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Assemblies">
<source>Assemblies</source>
<target state="new">Assemblies</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_AssemblyFiles">
<source>Assembly Files</source>
<target state="new">Assembly Files</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_AsymmetricKeys">
<source>Asymmetric Keys</source>
<target state="new">Asymmetric Keys</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_DatabaseAsymmetricKeys">
<source>Asymmetric Keys</source>
<target state="new">Asymmetric Keys</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_DataCompressionOptions">
<source>Data Compression Options</source>
<target state="new">Data Compression Options</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Certificates">
<source>Certificates</source>
<target state="new">Certificates</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_FileTables">
<source>FileTables</source>
<target state="new">FileTables</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_DatabaseCertificates">
<source>Certificates</source>
<target state="new">Certificates</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_CheckConstraints">
<source>Check Constraints</source>
<target state="new">Check Constraints</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Columns">
<source>Columns</source>
<target state="new">Columns</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Constraints">
<source>Constraints</source>
<target state="new">Constraints</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Contracts">
<source>Contracts</source>
<target state="new">Contracts</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Credentials">
<source>Credentials</source>
<target state="new">Credentials</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ErrorMessages">
<source>Error Messages</source>
<target state="new">Error Messages</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ServerRoleMembership">
<source>Server Role Membership</source>
<target state="new">Server Role Membership</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_DatabaseOptions">
<source>Database Options</source>
<target state="new">Database Options</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_DatabaseRoles">
<source>Database Roles</source>
<target state="new">Database Roles</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_RoleMemberships">
<source>Role Memberships</source>
<target state="new">Role Memberships</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_DatabaseTriggers">
<source>Database Triggers</source>
<target state="new">Database Triggers</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_DefaultConstraints">
<source>Default Constraints</source>
<target state="new">Default Constraints</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Defaults">
<source>Defaults</source>
<target state="new">Defaults</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Sequences">
<source>Sequences</source>
<target state="new">Sequences</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Endpoints">
<source>Endpoints</source>
<target state="new">Endpoints</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_EventNotifications">
<source>Event Notifications</source>
<target state="new">Event Notifications</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ServerEventNotifications">
<source>Server Event Notifications</source>
<target state="new">Server Event Notifications</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ExtendedProperties">
<source>Extended Properties</source>
<target state="new">Extended Properties</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_FileGroups">
<source>Filegroups</source>
<target state="new">Filegroups</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ForeignKeys">
<source>Foreign Keys</source>
<target state="new">Foreign Keys</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_FullTextCatalogs">
<source>Full-Text Catalogs</source>
<target state="new">Full-Text Catalogs</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_FullTextIndexes">
<source>Full-Text Indexes</source>
<target state="new">Full-Text Indexes</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Functions">
<source>Functions</source>
<target state="new">Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Indexes">
<source>Indexes</source>
<target state="new">Indexes</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_InlineFunctions">
<source>Inline Functions</source>
<target state="new">Inline Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Keys">
<source>Keys</source>
<target state="new">Keys</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_LinkedServers">
<source>Linked Servers</source>
<target state="new">Linked Servers</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_LinkedServerLogins">
<source>Linked Server Logins</source>
<target state="new">Linked Server Logins</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Logins">
<source>Logins</source>
<target state="new">Logins</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_MasterKey">
<source>Master Key</source>
<target state="new">Master Key</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_MasterKeys">
<source>Master Keys</source>
<target state="new">Master Keys</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_MessageTypes">
<source>Message Types</source>
<target state="new">Message Types</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_MultiSelectFunctions">
<source>Table-Valued Functions</source>
<target state="new">Table-Valued Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Parameters">
<source>Parameters</source>
<target state="new">Parameters</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_PartitionFunctions">
<source>Partition Functions</source>
<target state="new">Partition Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_PartitionSchemes">
<source>Partition Schemes</source>
<target state="new">Partition Schemes</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Permissions">
<source>Permissions</source>
<target state="new">Permissions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_PrimaryKeys">
<source>Primary Keys</source>
<target state="new">Primary Keys</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Programmability">
<source>Programmability</source>
<target state="new">Programmability</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Queues">
<source>Queues</source>
<target state="new">Queues</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_RemoteServiceBindings">
<source>Remote Service Bindings</source>
<target state="new">Remote Service Bindings</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ReturnedColumns">
<source>Returned Columns</source>
<target state="new">Returned Columns</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Roles">
<source>Roles</source>
<target state="new">Roles</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Routes">
<source>Routes</source>
<target state="new">Routes</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Rules">
<source>Rules</source>
<target state="new">Rules</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Schemas">
<source>Schemas</source>
<target state="new">Schemas</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Security">
<source>Security</source>
<target state="new">Security</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ServerObjects">
<source>Server Objects</source>
<target state="new">Server Objects</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Management">
<source>Management</source>
<target state="new">Management</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ServerTriggers">
<source>Triggers</source>
<target state="new">Triggers</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ServiceBroker">
<source>Service Broker</source>
<target state="new">Service Broker</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Services">
<source>Services</source>
<target state="new">Services</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Signatures">
<source>Signatures</source>
<target state="new">Signatures</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_LogFiles">
<source>Log Files</source>
<target state="new">Log Files</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Statistics">
<source>Statistics</source>
<target state="new">Statistics</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Storage">
<source>Storage</source>
<target state="new">Storage</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_StoredProcedures">
<source>Stored Procedures</source>
<target state="new">Stored Procedures</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SymmetricKeys">
<source>Symmetric Keys</source>
<target state="new">Symmetric Keys</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Synonyms">
<source>Synonyms</source>
<target state="new">Synonyms</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Tables">
<source>Tables</source>
<target state="new">Tables</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Triggers">
<source>Triggers</source>
<target state="new">Triggers</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Types">
<source>Types</source>
<target state="new">Types</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_UniqueKeys">
<source>Unique Keys</source>
<target state="new">Unique Keys</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_UserDefinedDataTypes">
<source>User-Defined Data Types</source>
<target state="new">User-Defined Data Types</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_UserDefinedTypes">
<source>User-Defined Types (CLR)</source>
<target state="new">User-Defined Types (CLR)</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Users">
<source>Users</source>
<target state="new">Users</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Views">
<source>Views</source>
<target state="new">Views</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_XmlIndexes">
<source>XML Indexes</source>
<target state="new">XML Indexes</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_XMLSchemaCollections">
<source>XML Schema Collections</source>
<target state="new">XML Schema Collections</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_UserDefinedTableTypes">
<source>User-Defined Table Types</source>
<target state="new">User-Defined Table Types</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_FilegroupFiles">
<source>Files</source>
<target state="new">Files</target>
<note></note>
</trans-unit>
<trans-unit id="MissingCaption">
<source>Missing Caption</source>
<target state="new">Missing Caption</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_BrokerPriorities">
<source>Broker Priorities</source>
<target state="new">Broker Priorities</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_CryptographicProviders">
<source>Cryptographic Providers</source>
<target state="new">Cryptographic Providers</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_DatabaseAuditSpecifications">
<source>Database Audit Specifications</source>
<target state="new">Database Audit Specifications</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_DatabaseEncryptionKeys">
<source>Database Encryption Keys</source>
<target state="new">Database Encryption Keys</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_EventSessions">
<source>Event Sessions</source>
<target state="new">Event Sessions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_FullTextStopLists">
<source>Full Text Stoplists</source>
<target state="new">Full Text Stoplists</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ResourcePools">
<source>Resource Pools</source>
<target state="new">Resource Pools</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ServerAudits">
<source>Audits</source>
<target state="new">Audits</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ServerAuditSpecifications">
<source>Server Audit Specifications</source>
<target state="new">Server Audit Specifications</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SpatialIndexes">
<source>Spatial Indexes</source>
<target state="new">Spatial Indexes</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_WorkloadGroups">
<source>Workload Groups</source>
<target state="new">Workload Groups</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SqlFiles">
<source>SQL Files</source>
<target state="new">SQL Files</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ServerFunctions">
<source>Server Functions</source>
<target state="new">Server Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SqlType">
<source>SQL Type</source>
<target state="new">SQL Type</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ServerOptions">
<source>Server Options</source>
<target state="new">Server Options</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_DatabaseDiagrams">
<source>Database Diagrams</source>
<target state="new">Database Diagrams</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemTables">
<source>System Tables</source>
<target state="new">System Tables</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_Databases">
<source>Databases</source>
<target state="new">Databases</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemContracts">
<source>System Contracts</source>
<target state="new">System Contracts</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemDatabases">
<source>System Databases</source>
<target state="new">System Databases</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemMessageTypes">
<source>System Message Types</source>
<target state="new">System Message Types</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemQueues">
<source>System Queues</source>
<target state="new">System Queues</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemServices">
<source>System Services</source>
<target state="new">System Services</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemStoredProcedures">
<source>System Stored Procedures</source>
<target state="new">System Stored Procedures</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemViews">
<source>System Views</source>
<target state="new">System Views</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_DataTierApplications">
<source>Data-tier Applications</source>
<target state="new">Data-tier Applications</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ExtendedStoredProcedures">
<source>Extended Stored Procedures</source>
<target state="new">Extended Stored Procedures</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemAggregateFunctions">
<source>Aggregate Functions</source>
<target state="new">Aggregate Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemApproximateNumerics">
<source>Approximate Numerics</source>
<target state="new">Approximate Numerics</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemBinaryStrings">
<source>Binary Strings</source>
<target state="new">Binary Strings</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemCharacterStrings">
<source>Character Strings</source>
<target state="new">Character Strings</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemCLRDataTypes">
<source>CLR Data Types</source>
<target state="new">CLR Data Types</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemConfigurationFunctions">
<source>Configuration Functions</source>
<target state="new">Configuration Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemCursorFunctions">
<source>Cursor Functions</source>
<target state="new">Cursor Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemDataTypes">
<source>System Data Types</source>
<target state="new">System Data Types</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemDateAndTime">
<source>Date and Time</source>
<target state="new">Date and Time</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemDateAndTimeFunctions">
<source>Date and Time Functions</source>
<target state="new">Date and Time Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemExactNumerics">
<source>Exact Numerics</source>
<target state="new">Exact Numerics</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemFunctions">
<source>System Functions</source>
<target state="new">System Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemHierarchyIdFunctions">
<source>Hierarchy Id Functions</source>
<target state="new">Hierarchy Id Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemMathematicalFunctions">
<source>Mathematical Functions</source>
<target state="new">Mathematical Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemMetadataFunctions">
<source>Metadata Functions</source>
<target state="new">Metadata Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemOtherDataTypes">
<source>Other Data Types</source>
<target state="new">Other Data Types</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemOtherFunctions">
<source>Other Functions</source>
<target state="new">Other Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemRowsetFunctions">
<source>Rowset Functions</source>
<target state="new">Rowset Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemSecurityFunctions">
<source>Security Functions</source>
<target state="new">Security Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemSpatialDataTypes">
<source>Spatial Data Types</source>
<target state="new">Spatial Data Types</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemStringFunctions">
<source>String Functions</source>
<target state="new">String Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemSystemStatisticalFunctions">
<source>System Statistical Functions</source>
<target state="new">System Statistical Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemTextAndImageFunctions">
<source>Text and Image Functions</source>
<target state="new">Text and Image Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemUnicodeCharacterStrings">
<source>Unicode Character Strings</source>
<target state="new">Unicode Character Strings</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_AggregateFunctions">
<source>Aggregate Functions</source>
<target state="new">Aggregate Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ScalarValuedFunctions">
<source>Scalar-valued Functions</source>
<target state="new">Scalar-valued Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_TableValuedFunctions">
<source>Table-valued Functions</source>
<target state="new">Table-valued Functions</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SystemExtendedStoredProcedures">
<source>System Extended Stored Procedures</source>
<target state="new">System Extended Stored Procedures</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_BuiltInType">
<source>Built-in Types</source>
<target state="new">Built-in Types</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_BuiltInServerRole">
<source>Built-in Server Roles</source>
<target state="new">Built-in Server Roles</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_UserWithPassword">
<source>User with Password</source>
<target state="new">User with Password</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SearchPropertyList">
<source>Search Property List</source>
<target state="new">Search Property List</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SecurityPolicies">
<source>Security Policies</source>
<target state="new">Security Policies</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SecurityPredicates">
<source>Security Predicates</source>
<target state="new">Security Predicates</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ServerRole">
<source>Server Role</source>
<target state="new">Server Role</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SearchPropertyLists">
<source>Search Property Lists</source>
<target state="new">Search Property Lists</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ColumnStoreIndexes">
<source>Column Store Indexes</source>
<target state="new">Column Store Indexes</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_TableTypeIndexes">
<source>Table Type Indexes</source>
<target state="new">Table Type Indexes</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ServerInstance">
<source>ServerInstance</source>
<target state="new">ServerInstance</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SelectiveXmlIndexes">
<source>Selective XML Indexes</source>
<target state="new">Selective XML Indexes</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_XmlNamespaces">
<source>XML Namespaces</source>
<target state="new">XML Namespaces</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_XmlTypedPromotedPaths">
<source>XML Typed Promoted Paths</source>
<target state="new">XML Typed Promoted Paths</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_SqlTypedPromotedPaths">
<source>T-SQL Typed Promoted Paths</source>
<target state="new">T-SQL Typed Promoted Paths</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_DatabaseScopedCredentials">
<source>Database Scoped Credentials</source>
<target state="new">Database Scoped Credentials</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ExternalDataSources">
<source>External Data Sources</source>
<target state="new">External Data Sources</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ExternalFileFormats">
<source>External File Formats</source>
<target state="new">External File Formats</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ExternalResources">
<source>External Resources</source>
<target state="new">External Resources</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ExternalTables">
<source>External Tables</source>
<target state="new">External Tables</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_AlwaysEncryptedKeys">
<source>Always Encrypted Keys</source>
<target state="new">Always Encrypted Keys</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ColumnMasterKeys">
<source>Column Master Keys</source>
<target state="new">Column Master Keys</target>
<note></note>
</trans-unit>
<trans-unit id="SchemaHierarchy_ColumnEncryptionKeys">
<source>Column Encryption Keys</source>
<target state="new">Column Encryption Keys</target>
<note></note>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View File

@@ -15,5 +15,8 @@
<PropertyGroup> <PropertyGroup>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project> </Project>

View File

@@ -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
{
/// <summary>
/// Information returned from a <see cref="CreateSessionRequest"/>.
/// Contains success information, a <see cref="SessionId"/> to be used when
/// requesting expansion of nodes, and a root node to display for this area.
/// </summary>
public class CreateSessionResponse
{
/// <summary>
/// Boolean indicating if the connection was successful
/// </summary>
public bool Success { get; set; }
/// <summary>
/// Unique ID to use when sending any requests for objects in the
/// tree under the node
/// </summary>
public string SessionId { get; set; }
/// <summary>
/// Information describing the base node in the tree
/// </summary>
public NodeInfo RootNode { get; set; }
}
/// <summary>
/// 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
/// </summary>
public class CreateSessionRequest
{
public static readonly
RequestType<ConnectionDetails, CreateSessionResponse> Type =
RequestType<ConnectionDetails, CreateSessionResponse>.Create("objectexplorer/createsession");
}
}

View File

@@ -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
{
/// <summary>
/// Information returned from a <see cref="ExpandRequest"/>.
/// </summary>
public class ExpandResponse
{
/// <summary>
/// Unique ID to use when sending any requests for objects in the
/// tree under the node
/// </summary>
public string SessionId { get; set; }
/// <summary>
/// Information describing the expanded nodes in the tree
/// </summary>
public NodeInfo[] Nodes { get; set; }
}
/// <summary>
/// Parameters to the <see cref="ExpandRequest"/>.
/// </summary>
public class ExpandParams
{
/// <summary>
/// The Id returned from a <see cref="CreateSessionRequest"/>. This
/// is used to disambiguate between different trees.
/// </summary>
public string SessionId { get; set; }
/// <summary>
/// Path identifying the node to expand. See <see cref="NodeInfo.NodePath"/> for details
/// </summary>
public string NodePath { get; set; }
}
/// <summary>
/// A request to expand a
/// </summary>
public class ExpandRequest
{
/// <summary>
/// Returns children of a given node as a <see cref="NodeInfo"/> array.
/// </summary>
public static readonly
RequestType<ExpandParams, ExpandResponse> Type =
RequestType<ExpandParams, ExpandResponse>.Create("objectexplorer/expand");
}
}

View File

@@ -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
{
/// <summary>
/// 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
/// </summary>
public class NodeInfo
{
/// <summary>
/// Path identifying this node: for example a table will be at ["server", "database", "tables", "tableName"].
/// This enables rapid navigation of the tree without the need for a global registry of elements.
/// The path functions as a unique ID and is used to disambiguate the node when sending requests for expansion.
/// A common ID is needed since processes do not share address space and need a unique identifier
/// </summary>
public string NodePath { get; set; }
/// <summary>
/// The type of the node - for example Server, Database, Folder, Table
/// </summary>
public string NodeType { get; set; }
/// <summary>
/// Label to display to the user, describing this node.
/// </summary>
public string Label { get; set; }
/// <summary>
/// Is this a leaf node (in which case no children can be generated) or
/// is it expandable?
/// </summary>
public bool IsLeaf { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// Parameters to the <see cref="ExpandRequest"/>.
/// </summary>
public class RefreshParams
{
/// <summary>
/// The Id returned from a <see cref="CreateSessionRequest"/>. This
/// is used to disambiguate between different trees.
/// </summary>
public string SessionId { get; set; }
/// <summary>
/// Path identifying the node to expand. See <see cref="NodeInfo.NodePath"/> for details
/// </summary>
public string[] NodePath { get; set; }
}
/// <summary>
/// A request to expand a
/// </summary>
public class RefreshRequest
{
/// <summary>
/// Returns children of a given node as a <see cref="NodeInfo"/> array.
/// </summary>
public static readonly
RequestType<ExpandParams, NodeInfo[]> Type =
RequestType<ExpandParams, NodeInfo[]>.Create("objectexplorer/refresh");
}
}

View File

@@ -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
{
/// <summary>
/// A <see cref="ChildFactory"/> supports creation of <see cref="TreeNode"/> children
/// for a class of objects in the tree. The
/// </summary>
public abstract class ChildFactory
{
/// <summary>
/// The set of applicable parents for which the factory can create children.
/// </summary>
/// <returns>
/// the string names for each <see cref="TreeNode.NodeType"/> that
/// this factory can create children for
/// </returns>
public abstract IEnumerable<string> ApplicableParents();
/// <summary>
/// Expands an element in the
/// </summary>
/// <param name="parent"></param>
/// <returns></returns>
public abstract IEnumerable<TreeNode> 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);
}
}

View File

@@ -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
{
/// <summary>
/// A collection class for <see cref="TreeNode"/>
/// </summary>
public sealed class NodeObservableCollection : ObservableCollection<TreeNode>
{
public event EventHandler Initialized;
private int? numInits;
private static int cleanupBlocker;
public bool IsInitialized
{
get { return numInits.HasValue && numInits == 0; }
}
public bool IsPopulating
{
get { return numInits.HasValue && numInits != 0; }
}
public void BeginInit()
{
if (!numInits.HasValue)
{
numInits = 1;
}
else
{
numInits = numInits + 1;
}
}
public void EndInit()
{
IList<TreeNode> empty = null;
EndInit(null, ref empty);
}
public void EndInit(TreeNode parent, ref IList<TreeNode> deferredChildren)
{
if (numInits.HasValue &&
numInits.Value == 1)
{
try
{
DoSort();
if (deferredChildren != null)
{
// Set the parents so the children know how to sort themselves
foreach (var item in deferredChildren)
{
item.Parent = parent;
}
deferredChildren = deferredChildren.OrderBy(x => x).ToList();
// Add the deferredChildren
foreach (var item in deferredChildren)
{
this.Add(item);
}
}
}
finally
{
if (deferredChildren != null)
{
deferredChildren.Clear();
}
numInits = numInits - 1;
}
Initialized?.Invoke(this, EventArgs.Empty);
}
else
{
numInits = numInits - 1;
}
}
/// <summary>
/// Repositions this child in the list
/// </summary>
public void ReSortChild(TreeNode child)
{
if (child == null)
return;
List<TreeNode> sorted = this.OrderBy(x => x).ToList();
// Remove without cleanup
try
{
cleanupBlocker++;
Remove(child);
}
finally
{
cleanupBlocker--;
}
// Then insert
for (int i = 0; i < sorted.Count; i++)
{
if (sorted[i] == child)
{
Insert(i, child);
return;
}
}
}
protected override void RemoveItem(int index)
{
// Cleanup all the children
Cleanup(this[index]);
base.RemoveItem(index);
}
protected override void ClearItems()
{
// Cleanup all the children
foreach (var child in this)
{
Cleanup(child);
}
base.ClearItems();
}
private static void Cleanup(TreeNode parent)
{
if (cleanupBlocker > 0 ||
parent.Parent == null)
return;
// TODO implement cleanup policy / pattern
//ICleanupPattern parentAsCleanup = parent as ICleanupPattern;
//if (parentAsCleanup != null)
// parentAsCleanup.DoCleanup();
//foreach (var child in parent.Children)
//{
// Cleanup(child);
//}
parent.Parent = null;
}
private void DoSort()
{
List<TreeNode> sorted = this.OrderBy(x => x).ToList();
for (int i = 0; i < sorted.Count(); i++)
{
int index = IndexOf(sorted[i]);
if (index != i)
{
Move(IndexOf(sorted[i]), i);
}
}
}
}
}

View File

@@ -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
{
/// <summary>
/// Enum listing possible node types in the object explorer tree
/// </summary>
// 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
}
}

View File

@@ -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
{
/// <summary>
/// Base class for elements in the object explorer tree. Provides common methods for tree navigation
/// and other core functionality
/// </summary>
public class TreeNode : IComparable<TreeNode>
{
private NodeObservableCollection children = new NodeObservableCollection();
private TreeNode parent;
private string nodePath;
private string label;
private ObjectExplorerService objectExplorerService;
public const char PathPartSeperator = '/';
/// <summary>
/// Constructor with no required inputs
/// </summary>
public TreeNode()
{
}
/// <summary>
/// Constructor that accepts a label to identify the node
/// </summary>
/// <param name="value">Label identifying the node</param>
public TreeNode(string value)
{
// We intentionally do not valid this being null or empty since
// some nodes may need to set it
NodeValue = value;
}
/// <summary>
/// Value describing this node
/// </summary>
public string NodeValue { get; set; }
/// <summary>
/// The type of the node - for example Server, Database, Folder, Table
/// </summary>
public string NodeType { get; set; }
/// <summary>
/// Enum defining the type of the node - for example Server, Database, Folder, Table
/// </summary>
public NodeTypes NodeTypeId { get; set; }
/// <summary>
/// Label to display to the user, describing this node.
/// If not explicitly set this will fall back to the <see cref="NodeValue"/> but
/// for many nodes such as the server, the display label will be different
/// to the value.
/// </summary>
public string Label {
get
{
if(label == null)
{
return NodeValue;
}
return label;
}
set
{
label = value;
}
}
/// <summary>
/// Is this a leaf node (in which case no children can be generated) or
/// is it expandable?
/// </summary>
public bool IsAlwaysLeaf { get; set; }
/// <summary>
/// Message to show if this Node is in an error state. This indicates
/// that children could be retrieved
/// </summary>
public string ErrorStateMessage { get; set; }
/// <summary>
/// Parent of this node
/// </summary>
public TreeNode Parent
{
get
{
return parent;
}
set
{
parent = value;
// Reset the node path since it's no longer valid
nodePath = null;
}
}
/// <summary>
/// Path identifying this node: for example a table will be at ["server", "database", "tables", "tableName"].
/// This enables rapid navigation of the tree without the need for a global registry of elements.
/// The path functions as a unique ID and is used to disambiguate the node when sending requests for expansion.
/// A common ID is needed since processes do not share address space and need a unique identifier
/// </summary>
public string GetNodePath()
{
if (nodePath == null)
{
GenerateNodePath();
}
return nodePath;
}
private void GenerateNodePath()
{
string path = "";
ObjectExplorerUtils.VisitChildAndParents(this, node =>
{
if (string.IsNullOrEmpty(node.NodeValue))
{
// Hit a node with no NodeValue. This indicates we need to stop traversing
return false;
}
// Otherwise add this value to the beginning of the path and keep iterating up
path = string.Format(CultureInfo.InvariantCulture,
"{0}{1}{2}", node.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;
}
/// <summary>
/// Converts to a <see cref="NodeInfo"/> object for serialization with just the relevant properties
/// needed to identify the node
/// </summary>
/// <returns></returns>
public NodeInfo ToNodeInfo()
{
return new NodeInfo()
{
IsLeaf = this.IsAlwaysLeaf,
Label = this.Label,
NodePath = this.GetNodePath(),
NodeType = this.NodeType
};
}
/// <summary>
/// Expands this node and returns its children
/// </summary>
/// <returns>Children as an IList. This is the raw children collection, not a copy</returns>
public IList<TreeNode> Expand()
{
// TODO consider why solution explorer has separate Children and Items options
if (children.IsInitialized)
{
return children;
}
PopulateChildren();
return children;
}
/// <summary>
/// Gets a readonly view of the currently defined children for this node.
/// This does not expand the node at all
/// Since the tree needs to keep track of parent relationships, directly
/// adding to the list is not supported.
/// </summary>
/// <returns><see cref="IList{TreeNode}"/> containing all children for this node</returns>
public IList<TreeNode> GetChildren()
{
return new ReadOnlyCollection<TreeNode>(children);
}
/// <summary>
/// Adds a child to the list of children under this node
/// </summary>
/// <param name="newChild"><see cref="TreeNode"/></param>
public void AddChild(TreeNode newChild)
{
Validate.IsNotNull(nameof(newChild), newChild);
children.Add(newChild);
newChild.Parent = this;
}
/// <summary>
/// Optional context to help with lookup of children
/// </summary>
public virtual object GetContext()
{
return null;
}
/// <summary>
/// Helper method to convert context to expected format
/// </summary>
/// <typeparam name="T">Type to convert to</typeparam>
/// <returns>context as expected type of null if it doesn't match</returns>
public T GetContextAs<T>()
where T : class
{
return GetContext() as T;
}
public T ParentAs<T>()
where T : TreeNode
{
return Parent as T;
}
protected void PopulateChildren()
{
Debug.Assert(IsAlwaysLeaf == false);
SmoQueryContext context = this.GetContextAs<SmoQueryContext>();
if (children.IsPopulating || context == null)
return;
children.Clear();
BeginChildrenInit();
try
{
IEnumerable<ChildFactory> childFactories = context.GetObjectExplorerService().GetApplicableChildFactories(this);
if (childFactories != null)
{
foreach (var factory in childFactories)
{
IEnumerable<TreeNode> 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);
}
/// <summary>
/// Sort Priority to help when ordering elements in the tree
/// </summary>
public int? SortPriority { get; set; }
protected virtual int CompareSamePriorities(TreeNode thisItem, TreeNode otherItem)
{
return string.Compare(thisItem.NodeValue, otherItem.NodeValue, StringComparison.OrdinalIgnoreCase);
}
public int CompareTo(TreeNode other)
{
if (!this.SortPriority.HasValue &&
!other.SortPriority.HasValue)
{
return CompareSamePriorities(this, other);
}
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;
}
}
}

View File

@@ -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
{
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes
{
/// <summary>
/// Indicates which type of server a given node type is valid for
/// </summary>
[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
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public class ObjectExplorerService : HostedService<ObjectExplorerService>, 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<string, ObjectExplorerSession> sessionMap;
private readonly Lazy<Dictionary<string, HashSet<ChildFactory>>> applicableNodeChildFactories;
private IMultiServiceProvider serviceProvider;
/// <summary>
/// Singleton constructor
/// </summary>
public ObjectExplorerService()
{
sessionMap = new Dictionary<string, ObjectExplorerSession>();
applicableNodeChildFactories = new Lazy<Dictionary<string, HashSet<ChildFactory>>>(() => PopulateFactories());
}
/// <summary>
/// Internal for testing only
/// </summary>
internal ObjectExplorerService(ExtensionServiceProvider serviceProvider)
: this()
{
SetServiceProvider(serviceProvider);
}
private Dictionary<string, HashSet<ChildFactory>> ApplicableNodeChildFactories
{
get
{
return applicableNodeChildFactories.Value;
}
}
/// <summary>
/// As an <see cref="IComposableService"/>, this will be set whenever the service is initialized
/// via an <see cref="IMultiServiceProvider"/>
/// </summary>
/// <param name="provider"></param>
public override void SetServiceProvider(IMultiServiceProvider provider)
{
Validate.IsNotNull(nameof(provider), provider);
serviceProvider = provider;
connectionService = provider.GetService<ConnectionService>();
}
/// <summary>
/// Initializes the service with the service host and registers request handlers.
/// </summary>
/// <param name="serviceHost">The service host instance to register with</param>
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<CreateSessionResponse> context)
{
Logger.Write(LogLevel.Verbose, "HandleCreateSessionRequest");
Func<Task<CreateSessionResponse>> 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<NodeInfo[]> 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;
});
}
/// <summary>
/// Establishes a new session and stores its information
/// </summary>
/// <returns><see cref="ObjectExplorerSession"/> object if successful, null if unsuccessful</returns>
internal async Task<ObjectExplorerSession> 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<ConnectionCompleteParams> 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<ExpandResponse> context)
{
Logger.Write(LogLevel.Verbose, "HandleExpandRequest");
Func<Task<ExpandResponse>> 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<T>(Func<Task<T>> handler, RequestContext<T> 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());
}
}
/// <summary>
/// Generates a URI for object explorer using a similar pattern to Mongo DB (which has URI-based database definition)
/// as this should ensure uniqueness
/// </summary>
/// <param name="details"></param>
/// <returns>string representing a URI</returns>
/// <remarks>Internal for testing purposes only</remarks>
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<ChildFactory> GetApplicableChildFactories(TreeNode item)
{
if (ApplicableNodeChildFactories != null)
{
HashSet<ChildFactory> applicableFactories;
if (ApplicableNodeChildFactories.TryGetValue(item.NodeTypeId.ToString(), out applicableFactories))
{
return applicableFactories;
}
}
return null;
}
internal Dictionary<string, HashSet<ChildFactory>> PopulateFactories()
{
VerifyServicesInitialized();
var childFactories = new Dictionary<string, HashSet<ChildFactory>>();
// Create our list of all NodeType to ChildFactory objects so we can expand appropriately
foreach (var factory in serviceProvider.GetServices<ChildFactory>())
{
var parents = factory.ApplicableParents();
if (parents != null)
{
foreach (var parent in parents)
{
AddToApplicableChildFactories(childFactories, factory, parent);
}
}
}
return childFactories;
}
private void VerifyServicesInitialized()
{
if (serviceProvider == null)
{
throw new InvalidOperationException(SqlTools.Hosting.Localization.sr.ServiceProviderNotSet);
}
if (connectionService == null)
{
throw new InvalidOperationException(SqlTools.Hosting.Localization.sr.ServiceProviderNotSet);
}
}
private static void AddToApplicableChildFactories(Dictionary<string, HashSet<ChildFactory>> childFactories, ChildFactory factory, string parent)
{
HashSet<ChildFactory> applicableFactories;
if (!childFactories.TryGetValue(parent, out applicableFactories))
{
applicableFactories = new HashSet<ChildFactory>();
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<string, NodeMapping> 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<ConnectionService>());
}
}
}
}

View File

@@ -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
{
/// <summary>
/// Utility class for Object Explorer related operations
/// </summary>
public static class ObjectExplorerUtils
{
/// <summary>
/// Visitor that walks all nodes from the child to the root node, unless the
/// <paramref name="visitor"/> function indicates that this should stop traversing
/// </summary>
/// <param name="child">node to start traversing at</param>
/// <param name="visitor">Predicate function that accesses the tree and
/// determines whether to stop going further up the tree</param>
/// <returns>
/// boolean - true to continue navigating up the tree, false to end the loop
/// and return early
/// </returns>
public static bool VisitChildAndParents(TreeNode child, Predicate<TreeNode> 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);
}
/// <summary>
/// Finds a node by traversing the tree starting from the given node through all the children
/// </summary>
/// <param name="node">node to start traversing at</param>
/// <param name="condition">Predicate function that accesses the tree and
/// determines whether to stop going further up the tree</param>
/// <param name="filter">Predicate function to filter the children when traversing</param>
/// <returns>A Tree Node that matches the condition</returns>
public static TreeNode FindNode(TreeNode node, Predicate<TreeNode> condition, Predicate<TreeNode> 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;
}
}
}

View File

@@ -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
{
/// <summary>
/// Initializes the context and ensures that
/// </summary>
protected override void EnsureContextInitialized()
{
if (context == null)
{
base.EnsureContextInitialized();
Database db = SmoObject as Database;
if (context != null && db != null)
{
context.Database = db;
}
}
}
}
}

View File

@@ -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
{
/// <summary>
/// Represents a folder node in the tree
/// </summary>
public class FolderNode : SmoTreeNode
{
/// <summary>
/// For folders, this copies the context of its parent if available
/// </summary>
/// <returns></returns>
public override object GetContext()
{
return Parent?.GetContext();
}
/// <summary>
/// For folders, searches for its parent's SMO object rather than copying for itself
/// </summary>
/// <returns><see cref="NamedSmoObject"/> from this parent's parent, or null if not found</returns>
public override NamedSmoObject GetParentSmoObject()
{
return ParentAs<SmoTreeNode>()?.GetParentSmoObject();
}
}
}

View File

@@ -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
{
/// <summary>
/// Server node implementation
/// </summary>
public class ServerNode : TreeNode
{
private ConnectionSummary connectionSummary;
private ServerInfo serverInfo;
private string connectionUri;
private Lazy<SmoQueryContext> 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<ConnectionService>();
this.context = new Lazy<SmoQueryContext>(() => 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;
}
}
/// <summary>
/// Returns the label to display to the user.
/// </summary>
internal string GetConnectionLabel()
{
string userName = connectionSummary.UserName;
// TODO Domain and username is not yet supported on .Net Core.
// Consider passing as an input from the extension where this can be queried
//if (string.IsNullOrWhiteSpace(userName))
//{
// userName = Environment.UserDomainName + @"\" + Environment.UserName;
//}
// TODO Consider adding IsAuthenticatingDatabaseMaster check in the code and
// referencing result here
if (!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;
}
}
/// <summary>
/// Internal for testing purposes only
/// </summary>
internal class SmoServerCreator
{
public virtual Server Create(SqlConnection connection)
{
ServerConnection serverConn = new ServerConnection(connection);
return new Server(serverConn);
}
}
}

View File

@@ -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<string> ApplicableParents()
{
return null;
}
public override IEnumerable<TreeNode> Expand(TreeNode parent)
{
//parent.BeginChildrenInit();
try
{
List<TreeNode> allChildren = new List<TreeNode>();
OnExpandPopulateFolders(allChildren, parent);
RemoveFoldersFromInvalidSqlServerVersions(allChildren, parent);
OnExpandPopulateNonFolders(allChildren, parent);
OnBeginAsyncOperations(parent);
return allChildren;
}
finally
{
//parent.EndChildrenInit();
}
}
/// <summary>
/// Populates any folders for a given parent node
/// </summary>
/// <param name="allChildren">List to which nodes should be added</param>
/// <param name="parent">Parent the nodes are being added to</param>
protected virtual void OnExpandPopulateFolders(IList<TreeNode> allChildren, TreeNode parent)
{
}
/// <summary>
/// Populates any non-folder nodes such as specific items in the tree.
/// </summary>
/// <param name="allChildren">List to which nodes should be added</param>
/// <param name="parent">Parent the nodes are being added to</param>
protected virtual void OnExpandPopulateNonFolders(IList<TreeNode> allChildren, TreeNode parent)
{
if (ChildQuerierTypes == null)
{
// This node does not support non-folder children
return;
}
SmoQueryContext context = parent.GetContextAs<SmoQueryContext>();
Validate.IsNotNull(nameof(context), context);
IEnumerable<SmoQuerier> queriers = context.ServiceProvider.GetServices<SmoQuerier>(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;
}
/// <summary>
/// Filters out invalid folders if they cannot be displayed for the current server version
/// </summary>
/// <param name="allChildren">List to which nodes should be added</param>
/// <param name="parent">Parent the nodes are being added to</param>
protected virtual void RemoveFoldersFromInvalidSqlServerVersions(IList<TreeNode> allChildren, TreeNode parent)
{
}
// TODO Assess whether async operations node is required
protected virtual void OnBeginAsyncOperations(TreeNode parent)
{
}
public override bool CanCreateChild(TreeNode parent, object context)
{
return false;
}
public override TreeNode CreateChild(TreeNode parent, object context)
{
throw new NotImplementedException();
}
protected virtual void InitializeChild(TreeNode 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;
}
}
/// <summary>
/// Returns true if any final validation of the object to be added passes, and false
/// if validation fails. This provides a chance to filter specific items out of a list
/// </summary>
/// <param name="parent"></param>
/// <param name="contextObject"></param>
/// <returns>boolean</returns>
public virtual bool PassesFinalFilters(TreeNode parent, object context)
{
return true;
}
}
}

View File

@@ -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
{
/// <summary>
/// Wrapper to convert non-generic Smo enumerables to generic enumerable types for easier use in
/// </summary>
/// <typeparam name="T"></typeparam>
public class SmoCollectionWrapper<T> : IEnumerable<T>
where T : SqlSmoObject
{
private SmoCollectionBase collection;
/// <summary>
/// Constructor which accepts a <see cref="SmoCollectionBase"/> containing the objects
/// to wrap
/// </summary>
/// <param name="collection"><see cref="SmoCollectionBase"/> or null if none were set</param>
public SmoCollectionWrapper(SmoCollectionBase collection)
{
this.collection = collection;
}
/// <summary>
/// <see cref="IEnumerable{T}.GetEnumerator"/>
/// </summary>
/// <returns></returns>
public IEnumerator<T> GetEnumerator()
{
if (collection == null)
{
yield break;
}
foreach(Object obj in collection)
{
yield return (T)obj;
}
}
/// <summary>
/// <see cref="IEnumerable.GetEnumerator"/>
/// </summary>
/// <returns></returns>
IEnumerator IEnumerable.GetEnumerator()
{
return collection?.GetEnumerator();
}
}
}

View File

@@ -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
{
/// <summary>
/// A <see cref="SmoQuerier"/> handles SMO queries for one or more SMO object types.
/// The <see cref="SupportedObjectTypes"/> property defines which types can be queried.
///
/// To query multiple
/// </summary>
public abstract class SmoQuerier : IComposableService
{
public abstract Type[] SupportedObjectTypes { get; }
/// <summary>
/// Queries SMO for a collection of objects using the <see cref="SmoQueryContext"/>
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public abstract IEnumerable<SqlSmoObject> Query(SmoQueryContext context);
internal IMultiServiceProvider ServiceProvider
{
get;
private set;
}
public void SetServiceProvider(IMultiServiceProvider provider)
{
ServiceProvider = provider;
}
}
}

View File

@@ -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
{
/// <summary>
/// Context object containing key properties needed to query for SMO objects
/// </summary>
public class SmoQueryContext
{
/// <summary>
/// Creates a context object with a server to use as the basis for any queries
/// </summary>
/// <param name="server"></param>
public SmoQueryContext(Server server, IMultiServiceProvider serviceProvider)
{
Server = server;
ServiceProvider = serviceProvider;
}
/// <summary>
/// The server SMO will query against
/// </summary>
public Server Server { get; private set; }
/// <summary>
/// Optional Database context object to query against
/// </summary>
public Database Database { get; set; }
/// <summary>
/// Parent of a give node to use for queries
/// </summary>
public SmoObjectBase Parent { get; set; }
/// <summary>
/// A query loader that can be used to find <see cref="SmoQuerier"/> objects
/// for specific SMO types
/// </summary>
public IMultiServiceProvider ServiceProvider { get; private set; }
/// <summary>
/// Helper method to cast a parent to a specific type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T ParentAs<T>()
where T : TreeNode
{
return Parent as T;
}
/// <summary>
/// Gets the <see cref="ObjectExplorerService"/> if available, by looking it up
/// from the <see cref="ServiceProvider"/>
/// </summary>
/// <returns></returns>
/// <exception cref="InvalidOperationException">
/// Thrown if the <see cref="ServiceProvider"/> is not set or the <see cref="ObjectExplorerService"/>
/// isn't available from that provider
/// </exception>
public ObjectExplorerService GetObjectExplorerService()
{
if (ServiceProvider == null)
{
throw new InvalidOperationException(SqlTools.Hosting.Localization.sr.ServiceProviderNotSet);
}
ObjectExplorerService service = ServiceProvider.GetService<ObjectExplorerService>();
if (service == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
SqlTools.Hosting.Localization.sr.ServiceNotFound, nameof(ObjectExplorerService)));
}
return service;
}
/// <summary>
/// Copies the context for use by another node
/// </summary>
/// <param name="parent">New Parent to set</param>
/// <returns>new <see cref="SmoQueryContext"/> with all fields except <see cref="Parent"/> the same</returns>
public SmoQueryContext CopyWithParent(SmoObjectBase parent)
{
SmoQueryContext context = new SmoQueryContext(this.Server, this.ServiceProvider)
{
Database = this.Database,
Parent = parent
};
return context;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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<string> 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<SqlSmoObject> 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<SqlSmoObject>();");
PopIndent();
WriteLine("}"); // close Query method
PopIndent();
WriteLine("}"); // close Class
PopIndent();
}
#>
}
<#+
public static string[] GetNodes(string xmlFile)
{
List<string> typesList = new List<string>();
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList treeTypes = doc.SelectNodes("/SmoQueryModel/Node");
if (treeTypes != null)
{
foreach (var type in treeTypes)
{
XmlElement element = type as XmlElement;
if (element != null)
{
typesList.Add(element.GetAttribute("Name"));
}
}
}
return typesList.ToArray();
}
public static XmlElement GetNodeElement(string xmlFile, string nodeName)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
return (XmlElement)doc.SelectSingleNode(string.Format("/SmoQueryModel/Node[@Name='{0}']", nodeName));
}
public static 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<string> GetParents(XmlElement nodeElement, string xmlFile, string parentName)
{
var parentAttr = nodeElement.GetAttribute("Parent");
if (!string.IsNullOrEmpty(parentAttr))
{
return new string[] { parentAttr };
}
var parentNodes = GetChildren(xmlFile, parentName, "Parent");
if (parentNodes != null && parentNodes.Count > 0)
{
List<string> parents = new List<string>();
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<XmlElement> GetChildren(string xmlFile, string parentName, string childNode)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/SmoQueryModel/Node[@Name='{0}']/{1}", parentName, childNode));
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
#>

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
This XML file defines how to query for a given SMO type based on a parent/child or
XPath relationship. From this file, the paths to query each type should be buildable
into code using a T4 template.
Key properties:
Name: This maps
Type: Optional SMO type. If not specified, the Name without the Sql prefix is used
Parent: Expected parent type. Needed to codegen the response. if there are multiple parents
then each one
NavigationPath: For types whose access path differs based on parent or needs custom navigation
this can be used.
-->
<SmoQueryModel>
<!--<Node Name="SqlServer"/> -->
<Node Name="SqlDatabase" Type="Database" Parent="Server" />
<Node Name="SqlLinkedServerLogin" Type="LinkedServer" Parent="Server"/>
<Node Name="SqlLogin" Type="Login" Parent="Server" />
<Node Name="SqlServerRole" Type="" Parent="Server" >
<NavigationPath Parent="Server" Field="Roles" />
</Node>
<Node Name="SqlCredential" Parent="Server" />
<Node Name="SqlCryptographicProvider" Parent="Server" />
<Node Name="SqlServerAudit" Type="Audit" Parent="Server" />
<Node Name="SqlServerAuditSpecification" Type="ServerAuditSpecification" Parent="Server"/>
<Node Name="SqlEndpoint" Parent="Server"/>
<Node Name="SqlLinkedServer" Parent="Server" />
<Node Name="SqlServerDdlTrigger" Parent="Server" >
<NavigationPath Parent="Server" Field="Triggers" />
</Node>
<Node Name="SqlErrorMessage" Type="UserDefinedMessage" Parent="Server" />
<Node Name="SqlTable" Parent="Database" />
<Node Name="SqlView" Parent="Database" />
<Node Name="SqlSynonym" Parent="Database" />
<Node Name="SqlColumn" Parent="TableViewTableTypeBase"/>
<Node Name="SqlIndex" Parent="TableViewTableTypeBase">
<NavigationPath Parent="TableViewTableTypeBase" Field="Indexes" />
</Node>
<Node Name="SqlCheck" Parent="Table"/>
<Node Name="SqlForeignKeyConstraint" Type="ForeignKey" Parent="Table" />
<Node Name="SqlDefaultConstraint" Parent="Column" Collection="False" />
<Node Name="SqlDmlTrigger" Type="Trigger" Parent="Table" />
<Node Name="SqlFullTextIndex" Parent="Table" Collection="False" />
<Node Name="SqlStatistic" Parent="TableViewBase"/>
<Node Name="SqlDatabaseDdlTrigger" Type="Trigger" Parent="Database"/>
<Node Name="SqlAssembly" Type="SqlAssembly" Parent="Database" >
<NavigationPath Parent="Database" Field="Assemblies" />
</Node>
<Node Name="SqlRule" Parent="Database" />
<Node Name="SqlDefault" Parent="Database" />
<Node Name="SqlSequence" Parent="Database" />
<Node Name="SqlSystemDataType" Parent="Server" />
<Node Name="SqlUserDefinedDataType" Parent="Database" />
<Node Name="SqlUserDefinedTableType" Parent="Database" />
<Node Name="SqlXmlSchemaCollection" />
<Node Name="SqlUserDefinedType" />
<Node Name="SqlUserDefinedFunction" />
<Node Name="SqlUserDefinedAggregate" />
<Node Name="SqlFileGroup" />
<Node Name="SqlFile" Type="DataFile" Parent="FileGroup" >
<NavigationPath Parent="FileGroup" Field="Files" />
</Node>
<Node Name="SqlFullTextCatalog"/>
<Node Name="SqlFullTextStopList" />
<Node Name="SqlPartitionFunction"/>
<Node Name="SqlPartitionScheme"/>
<Node Name="SqlSearchPropertyList" />
<Node Name="SqlUser"/>
<Node Name="SqlSchema"/>
<Node Name="SqlAsymmetricKey" />
<Node Name="SqlCertificate" />
<Node Name="SqlSymmetricKey" />
<Node Name="SqlDatabaseEncryptionKey" Collection="False" />
<Node Name="SqlMasterKey" Collection="False" />
<Node Name="SqlDatabaseAuditSpecification" />
<Node Name="SqlSecurityPolicy" >
<NavigationPath Parent="Database" Field="SecurityPolicies" />
</Node>
<Node Name="SqlDatabaseCredential" Type="DatabaseScopedCredential"/>
<Node Name="SqlRole" Type="DatabaseRole" >
<NavigationPath Parent="Database" Field="Roles" />
</Node>
<Node Name="SqlApplicationRole" />
<Node Name="SqlColumnMasterKey" />
<Node Name="SqlColumnEncryptionKey" />
<Node Name="SqlServiceBroker" Type="ServiceBroker" Collection="False" />
<Node Name="SqlService" Type="BrokerService" Parent="ServiceBroker" >
<NavigationPath Parent="ServiceBroker" Field="Services" />
</Node>
<Node Name="SqlContract" Type="ServiceContract" Parent="ServiceBroker" />
<Node Name="SqlQueue" Type="ServiceQueue" Parent="ServiceBroker" >
<NavigationPath Parent="ServiceBroker" Field="Queues" />
</Node>
<Node Name="SqlRemoteServiceBinding" Parent="ServiceBroker" />
<Node Name="SqlBrokerPriority" Parent="ServiceBroker" >
<NavigationPath Parent="ServiceBroker" Field="Priorities" />
</Node>
<Node Name="SqlMessageType" Parent="ServiceBroker"/>
<Node Name="SqlExternalDataSource" />
<Node Name="SqlExternalFileFormat" />
<Node Name="SqlProcedure" Type="StoredProcedure"/>
<Node Name="SqlExtendedStoredProcedure" />
<Node Name="SqlSubroutineParameter" Type="Parameter" >
<Parent>StoredProcedure</Parent>
<Parent>UserDefinedAggregate</Parent>
<Parent>UserDefinedFunction</Parent>
</Node>
<Node Name="SqlPartitionFunctionParameter" Parent="PartitionFunction" />
<Node Name="SqlBuiltInType" Type="SystemDataType" Parent="Server"/>
<!-- TODO Enable all types
<Node Name="SqlRoute"/>
-->
<!-- Signatures appear to be missing entirely from SMO and SSMS object explorer...
<Node Name="SqlSignature" />
-->
<!-- TODO find mapping - exists in SSDT but not SSMS / SMO?
<Node Name="SqlEventNotification" Parent="ServiceBroker" />
-->
<!-- TODO Requires XEvents SMO DLL in .Net Core
<Node Name="SqlEventSession" Type="Session" />
<Node Name="SqlServerEventNotification" Type="Event" Parent="Server" />
-->
</SmoQueryModel>

View File

@@ -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
{
/// <summary>
/// A Node in the tree representing a SMO-based object
/// </summary>
public class SmoTreeNode : TreeNode
{
public static int FolderSortPriority = 0;
private static int _nextSortPriority = FolderSortPriority + 1; // 0 is reserved for folders
protected SmoQueryContext context;
public SmoTreeNode() : base()
{
}
protected virtual void OnInitialize()
{
// TODO setup initialization
}
/// <summary>
/// Is this a system (MSShipped) object?
/// </summary>
public bool IsMsShippedOwned { get; set; }
/// <summary>
/// Indicates which platforms a node is valid for
/// </summary>
public ValidForFlag ValidFor { get; set; }
/// <summary>
/// Gets an incrementing sort priority value to assist in automatically sorting
/// elements in a tree
/// </summary>
public static int NextSortPriority
{
get
{
return System.Threading.Interlocked.Increment(ref _nextSortPriority);
}
}
public NamedSmoObject SmoObject { get; private set; }
public virtual void CacheInfoFromModel(NamedSmoObject smoObject)
{
SmoObject = smoObject;
NodeValue = smoObject.Name;
}
public virtual NamedSmoObject GetParentSmoObject()
{
if (SmoObject != null)
{
return SmoObject;
}
// Return the parent's object, or null if it's not set / not a SmoTreeNode
return ParentAs<SmoTreeNode>()?.GetParentSmoObject();
}
public override object GetContext()
{
EnsureContextInitialized();
return context;
}
protected virtual void EnsureContextInitialized()
{
if (context == null)
{
SmoObjectBase smoParent = GetParentSmoObject();
SmoQueryContext parentContext = Parent?.GetContextAs<SmoQueryContext>();
if (smoParent != null && parentContext != null)
{
context = parentContext.CopyWithParent(smoParent);
}
}
}
}
}

View File

@@ -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<string> _exactNumerics = new HashSet<string>{
"bit",
"tinyint",
"smallint",
"int",
"bigint",
"numeric",
"decimal",
"smallmoney",
"money"
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _exactNumerics.Contains(name);
}
}
return false;
}
}
internal partial class SystemApproximateNumericsChildFactory
{
private static readonly HashSet<string> _approxNumerics = new HashSet<string>{
"float",
"real"
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _approxNumerics.Contains(name);
}
}
return false;
}
}
internal partial class SystemDateAndTimesChildFactory
{
private static readonly HashSet<string> _dateAndTime = new HashSet<string>{
"datetime",
"smalldatetime",
"date",
"time",
"datetimeoffset",
"datetime2",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _dateAndTime.Contains(name);
}
}
return false;
}
}
internal partial class SystemCharacterStringsChildFactory
{
private static readonly HashSet<string> _characterStrings = new HashSet<string>{
"char",
"varchar",
"text",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _characterStrings.Contains(name);
}
}
return false;
}
}
internal partial class SystemUnicodeCharacterStringsChildFactory
{
private static readonly HashSet<string> _unicodeCharacterStrings = new HashSet<string>
{
"nchar",
"nvarchar",
"ntext",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _unicodeCharacterStrings.Contains(name);
}
}
return false;
}
}
internal partial class SystemBinaryStringsChildFactory
{
private static readonly HashSet<string> _binaryStrings = new HashSet<string>{
"binary",
"varbinary",
"image",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _binaryStrings.Contains(name);
}
}
return false;
}
}
internal partial class SystemOtherDataTypesChildFactory
{
private static readonly HashSet<string> _otherDataTypes = new HashSet<string>{
"sql_variant",
"timestamp",
"uniqueidentifier",
"xml",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _otherDataTypes.Contains(name);
}
}
return false;
}
}
internal partial class SystemClrDataTypesChildFactory
{
private static readonly HashSet<string> _clrDataTypes = new HashSet<string>{
"hierarchyid",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _clrDataTypes.Contains(name);
}
}
return false;
}
}
internal partial class SystemSpatialDataTypesChildFactory
{
private static readonly HashSet<string> _spatialDataTypes = new HashSet<string>{
"geometry",
"geography",
};
public override bool PassesFinalFilters(TreeNode parent, object contextObject)
{
NamedSmoObject smoObject = contextObject as NamedSmoObject;
if (smoObject != null)
{
string name = smoObject.Name;
if (!string.IsNullOrWhiteSpace(name))
{
return _spatialDataTypes.Contains(name);
}
}
return false;
}
}
}

View File

@@ -0,0 +1,396 @@
<?xml version="1.0" encoding="utf-8" ?>
<ServerExplorerTree>
<Node Name="ServerInstance" LocLabel="SR.SchemaHierarchy_ServerInstance" Image="Server">
<Child Name="Databases"/>
<Child Name="ServerLevelSecurity"/>
<Child Name="ServerLevelServerObjects"/>
</Node>
<Node Name="Databases" LocLabel="SR.SchemaHierarchy_Databases" IsAsyncLoad="" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabase" TreeNode="DatabaseInstanceTreeNode">
<Child Name="SystemDatabases"/>
</Node>
<Node Name="ServerLevelSecurity" LocLabel="SR.SchemaHierarchy_Security" BaseClass="ModelBased" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12|NotContainedUser|CanViewSecurity">
<Child Name="ServerLevelLinkedServerLogins"/>
<Child Name="ServerLevelLogins"/>
<Child Name="ServerLevelServerRoles"/>
<Child Name="ServerLevelCredentials"/>
<Child Name="ServerLevelCryptographicProviders"/>
<Child Name="ServerLevelServerAudits"/>
<Child Name="ServerLevelServerAuditSpecifications"/>
<!-- TODO Support XEvents in .Net Core SMO
<Child Name="ServerLevelEventSessions"/>
-->
</Node>
<Node Name="ServerLevelServerObjects" LocLabel="SR.SchemaHierarchy_ServerObjects" BaseClass="ModelBased" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|NotContainedUser">
<Child Name="ServerLevelEndpoints"/>
<Child Name="ServerLevelLinkedServers"/>
<Child Name="ServerLevelServerTriggers"/>
<Child Name="ServerLevelErrorMessages"/>
<!-- TODO Support XEvents in .Net Core SMO
<Child Name="ServerLevelEventNotifications"/>
-->
</Node>
<Node Name="SystemDatabases" LocLabel="SR.SchemaHierarchy_SystemDatabases" BaseClass="Databases" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12|NotContainedUser|CanConnectToMaster"/>
<!-- TODO Support XEvents in .Net Core SMO
<Node Name="ServerLevelEventSessions" LocLabel="SR.SchemaHierarchy_EventSessions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlEventSession" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelEventNotifications" LocLabel="SR.SchemaHierarchy_ServerEventNotifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerEventNotification"/>
-->
<Node Name="ServerLevelLinkedServerLogins" LocLabel="SR.SchemaHierarchy_LinkedServerLogins" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlLinkedServerLogin" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelLogins" LocLabel="SR.SchemaHierarchy_Logins" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlLogin"/>
<Node Name="ServerLevelServerRoles" LocLabel="SR.SchemaHierarchy_ServerRoles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerRole" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelCredentials" LocLabel="SR.SchemaHierarchy_Credentials" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlCredential" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelCryptographicProviders" LocLabel="SR.SchemaHierarchy_CryptographicProviders" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlCryptographicProvider" ValidFor="Sql2008|Sql2012|Sql2014|NotDebugInstance|Sql2016|SqlvNext"/>
<Node Name="ServerLevelServerAudits" LocLabel="SR.SchemaHierarchy_ServerAudits" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerAudit" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelServerAuditSpecifications" LocLabel="SR.SchemaHierarchy_ServerAuditSpecifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerAuditSpecification" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelEndpoints" LocLabel="SR.SchemaHierarchy_Endpoints" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlEndpoint" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="ServerLevelLinkedServers" LocLabel="SR.SchemaHierarchy_LinkedServers" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlLinkedServer"/>
<Node Name="ServerLevelServerTriggers" LocLabel="SR.SchemaHierarchy_ServerTriggers" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlServerDdlTrigger"/>
<Node Name="ServerLevelErrorMessages" LocLabel="SR.SchemaHierarchy_ErrorMessages" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlErrorMessage"/>
<Node Name="DatabaseInstance" LocLabel="string.Empty" Image="Database" BaseClass="ModelBased" IsAsyncLoad="" Strategy="CreateModel">
<Child Name="Tables"/>
<Child Name="Views"/>
<Child Name="Synonyms"/>
<Child Name="Programmability"/>
<Child Name="ExternalResources"/>
<Child Name="ServiceBroker"/>
<Child Name="Storage"/>
<Child Name="Security"/>
</Node>
<Node Name="Tables" LocLabel="SR.SchemaHierarchy_Tables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableInstanceTreeNode">
<Filters>
<Filter Property="IsFileTable" Value="0" Type="bool" />
<Filter Property="IsExternal" Value="0" Type="bool" ValidFor="Sql2016|SqlvNext|AzureV12"/>
<Filter Property="TemporalType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>TemporalTableType.None</Value>
<Value>TemporalTableType.SystemVersioned</Value>
</Filter>
</Filters>
<Child Name="SystemTables"/>
<Child Name="FileTables"/>
<Child Name="ExternalTables"/>
</Node>
<Node Name="Views" LocLabel="SR.SchemaHierarchy_Views" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlView" TreeNode="ViewInstanceTreeNode">
<Child Name="SystemViews"/>
</Node>
<Node Name="Synonyms" LocLabel="SR.SchemaHierarchy_Synonyms" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSynonym"/>
<Node Name="Programmability" LocLabel="SR.SchemaHierarchy_Programmability" BaseClass="ModelBased">
<Child Name="StoredProcedures"/>
<Child Name="Functions"/>
<Child Name="DatabaseTriggers"/>
<Child Name="Assemblies"/>
<Child Name="Types"/>
<Child Name="Rules"/>
<Child Name="Defaults"/>
<Child Name="Sequences"/>
</Node>
<Node Name="ExternalResources" LocLabel="SR.SchemaHierarchy_ExternalResources" BaseClass="ModelBased" TreeNode="ExternalResourceInstanceTreeNode" ValidFor="Sql2016|SqlvNext|AzureV12">
<Child Name="ExternalDataSources"/>
<Child Name="ExternalFileFormats"/>
</Node>
<Node Name="ServiceBroker" LocLabel="SR.SchemaHierarchy_ServiceBroker" BaseClass="ModelBased" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext">
<Child Name="MessageTypes"/>
<Child Name="Contracts"/>
<Child Name="Queues"/>
<Child Name="Services"/>
<!-- <Child Name="Routes"/> -->
<Child Name="DatabaseAndQueueEventNotifications"/>
<Child Name="RemoteServiceBindings"/>
<Child Name="BrokerPriorities"/>
</Node>
<Node Name="Storage" LocLabel="SR.SchemaHierarchy_Storage" BaseClass="ModelBased" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12">
<Child Name="FileGroups"/>
<Child Name="FullTextCatalogs"/>
<Child Name="FullTextStopLists"/>
<Child Name="SqlLogFiles"/>
<Child Name="PartitionFunctions"/>
<Child Name="PartitionSchemes"/>
<Child Name="SearchPropertyLists"/>
</Node>
<Node Name="Security" LocLabel="SR.SchemaHierarchy_Security" BaseClass="ModelBased" >
<Child Name="Users"/>
<Child Name="Roles"/>
<Child Name="Schemas"/>
<Child Name="AsymmetricKeys"/>
<Child Name="Certificates"/>
<Child Name="SymmetricKeys"/>
<Child Name="DatabaseScopedCredentials"/>
<Child Name="DatabaseEncryptionKeys"/>
<Child Name="MasterKeys"/>
<Child Name="Signatures"/>
<Child Name="DatabaseAuditSpecifications"/>
<Child Name="SecurityPolicies"/>
<Child Name="AlwaysEncryptedKeys"/>
</Node>
<!-- Childs of Tables -->
<Node Name="SystemTables" LocLabel="SR.SchemaHierarchy_SystemTables" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableInstanceTreeNode"/>
<Node Name="FileTables" LocLabel="SR.SchemaHierarchy_FileTables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="TableInstanceTreeNode" ValidFor="Sql2012|Sql2014|Sql2016|SqlvNext|NotDebugInstance">
<Filters>
<Filter Property="IsFileTable" Value="1" Type="boolean" />
</Filters>
</Node>
<Node Name="ExternalTables" LocLabel="SR.SchemaHierarchy_ExternalTables" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="ExternalTableInstanceTreeNode" ValidFor="Sql2016|SqlvNext|AzureV12">
<Filters>
<Filter Property="IsExternalTable" Value="1" Type="boolean" />
</Filters>
</Node>
<Node Name="TableInstance" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlTable" TreeNode="HistoryTableInstanceTreeNode">
<!-- TODO Add special history table handling to only return related history table instead of all! Under Table, we directly show any related history tables.-->
<Filters>
<Filter Property="TemporalType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>TemporalTableType.History</Value>
</Filter>
</Filters>
<Child Name="Columns"/>
<Child Name="Keys"/>
<Child Name="Constraints"/>
<Child Name="Triggers"/>
<Child Name="Indexes"/>
<Child Name="Statistics"/>
</Node>
<!-- TODO This should use display item not ChildQuerierTypes -->
<Node Name="HistoryTableInstance" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="PopulateDetails" ChildQuerierTypes="SqlTable" ValidFor="Sql2016|SqlvNext|AzureV12">
<Child Name="Columns"/>
<Child Name="Indexes"/>
<Child Name="Statistics"/>
</Node>
<!-- TODO This should use display item not ChildQuerierTypes -->
<Node Name="ExternalTableInstance" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="PopulateDetails" ChildQuerierTypes="SqlTable" ValidFor="Sql2016|SqlvNext|AzureV12">
<Child Name="Columns"/>
<Child Name="Statistics"/>
</Node>
<Node Name="Columns" LocLabel="SR.SchemaHierarchy_Columns" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlColumn" DisableSort=""/>
<Node Name="Keys" LocLabel="SR.SchemaHierarchy_Keys" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlIndex;SqlForeignKeyConstraint" >
<Filters>
<Filter TypeToReverse="SqlIndex" Property="IndexKeyType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>IndexKeyType.DriPrimaryKey</Value>
<Value>IndexKeyType.DriUniqueKey</Value>
</Filter>
</Filters>
</Node>
<Node Name="Constraints" LocLabel="SR.SchemaHierarchy_Constraints" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlDefaultConstraint;SqlCheck"/>
<Node Name="Triggers" LocLabel="SR.SchemaHierarchy_Triggers" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlDmlTrigger"/>
<Node Name="Indexes" LocLabel="SR.SchemaHierarchy_Indexes" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlIndex;SqlFullTextIndex">
<Filters>
<Filter TypeToReverse="SqlIndex" Property="IndexKeyType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>IndexKeyType.None</Value>
</Filter>
</Filters>
</Node>
<Node Name="Statistics" LocLabel="SR.SchemaHierarchy_Statistics" BaseClass="ModelBased" Strategy="ElementsInRelationship" ChildQuerierTypes="SqlStatistic"/>
<Node Name="SystemViews" LocLabel="SR.SchemaHierarchy_SystemViews" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlView" TreeNode="ViewInstanceTreeNode"/>
<Node Name="ViewInstance" LocLabel="string.Empty" BaseClass="ModelBased" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="Columns"/>
<Child Name="Triggers"/>
<Child Name="Indexes"/>
<Child Name="Statistics"/>
</Node>
<Node Name="Functions" LocLabel="SR.SchemaHierarchy_Functions" BaseClass="ModelBased" >
<Child Name="TableValuedFunctions"/>
<Child Name="ScalarValuedFunctions"/>
<Child Name="AggregateFunctions"/>
</Node>
<Node Name="DatabaseTriggers" LocLabel="SR.SchemaHierarchy_DatabaseTriggers" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseDdlTrigger"/>
<Node Name="Assemblies" LocLabel="SR.SchemaHierarchy_Assemblies" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlAssembly" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="Types" LocLabel="SR.SchemaHierarchy_Types" BaseClass="ModelBased" >
<Child Name="SystemDataTypes"/>
<Child Name="UserDefinedDataTypes"/>
<Child Name="UserDefinedTableTypes"/>
<Child Name="UserDefinedTypes"/>
<Child Name="XmlSchemaCollections"/>
</Node>
<Node Name="Rules" LocLabel="SR.SchemaHierarchy_Rules" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRule" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="Defaults" LocLabel="SR.SchemaHierarchy_Defaults" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDefault" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="Sequences" LocLabel="SR.SchemaHierarchy_Sequences" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSequence" ValidFor="Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="SystemDataTypes" LocLabel="SR.SchemaHierarchy_SystemDataTypes" BaseClass="ModelBased" >
<Child Name="SystemExactNumerics"/>
<Child Name="SystemApproximateNumerics"/>
<Child Name="SystemDateAndTimes"/>
<Child Name="SystemCharacterStrings"/>
<Child Name="SystemUnicodeCharacterStrings"/>
<Child Name="SystemBinaryStrings"/>
<Child Name="SystemOtherDataTypes"/>
<Child Name="SystemClrDataTypes"/>
<Child Name="SystemSpatialDataTypes"/>
</Node>
<Node Name="UserDefinedDataTypes" LocLabel="SR.SchemaHierarchy_UserDefinedDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedDataType"/>
<Node Name="UserDefinedTableTypes" LocLabel="SR.SchemaHierarchy_UserDefinedTableTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedTableType" TreeNode="UserDefinedTableTypeInstanceTreeNode" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12"/>
<Node Name="UserDefinedTypes" LocLabel="SR.SchemaHierarchy_UserDefinedTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedType" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="XmlSchemaCollections" LocLabel="SR.SchemaHierarchy_XMLSchemaCollections" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlXmlSchemaCollection" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="UserDefinedTableTypeInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="UserDefinedTableTypeColumns"/>
<Child Name="UserDefinedTableTypeKeys"/>
<Child Name="UserDefinedTableTypeConstraints"/>
</Node>
<Node Name="UserDefinedTableTypeColumns" LocLabel="SR.SchemaHierarchy_Columns" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlColumn" DisableSort=""/>
<Node Name="UserDefinedTableTypeKeys" LocLabel="SR.SchemaHierarchy_Keys" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlIndex">
<Filters>
<Filter TypeToReverse="SqlIndex" Property="IndexKeyType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>IndexKeyType.DriPrimaryKey</Value>
<Value>IndexKeyType.DriUniqueKey</Value>
</Filter>
</Filters>
</Node>
<Node Name="UserDefinedTableTypeConstraints" LocLabel="SR.SchemaHierarchy_Constraints" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlDefaultConstraint;SqlCheck"/>/>
<Node Name="SystemExactNumerics" LocLabel="SR.SchemaHierarchy_SystemExactNumerics" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemApproximateNumerics" LocLabel="SR.SchemaHierarchy_SystemApproximateNumerics" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemDateAndTimes" LocLabel="SR.SchemaHierarchy_SystemDateAndTime" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemCharacterStrings" LocLabel="SR.SchemaHierarchy_SystemCharacterStrings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemUnicodeCharacterStrings" LocLabel="SR.SchemaHierarchy_SystemUnicodeCharacterStrings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemBinaryStrings" LocLabel="SR.SchemaHierarchy_SystemBinaryStrings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemOtherDataTypes" LocLabel="SR.SchemaHierarchy_SystemOtherDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBuiltInType"/>
<Node Name="SystemClrDataTypes" LocLabel="SR.SchemaHierarchy_SystemCLRDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedType" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12"/>
<Node Name="SystemSpatialDataTypes" LocLabel="SR.SchemaHierarchy_SystemSpatialDataTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedType" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV11|AzureV12"/>
<!-- Childs of ExternalResources -->
<Node Name="ExternalDataSources" LocLabel="SR.SchemaHierarchy_ExternalDataSources" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlExternalDataSource" ValidFor="Sql2016|SqlvNext|AzureV12"/>
<Node Name="ExternalFileFormats" LocLabel="SR.SchemaHierarchy_ExternalFileFormats" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlExternalFileFormat" ValidFor="Sql2016|SqlvNext"/>
<Node Name="StoredProcedures" LocLabel="SR.SchemaHierarchy_StoredProcedures" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlProcedure" TreeNode="StoredProcedureInstanceTreeNode">
<Child Name="SystemStoredProcedures"/>
</Node>
<Node Name="SystemStoredProcedures" LocLabel="SR.SchemaHierarchy_SystemStoredProcedures" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlProcedure" TreeNode="StoredProcedureInstanceTreeNode"/>
<Node Name="StoredProcedureInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="StoredProcedureParameters"/>
</Node>
<Node Name="StoredProcedureParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" Strategy="StoredProcedureParameters" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
<Node Name="TableValuedFunctions" LocLabel="SR.SchemaHierarchy_TableValuedFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedFunction" TreeNode="TableValuedFunctionInstanceTreeNode">
<Filters>
<Filter Property="UserDefinedFunctionType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>UserDefinedFunctionType.Table</Value>
</Filter>
</Filters>
</Node>
<Node Name="TableValuedFunctionInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="TableValuedFunctionParameters"/>
</Node>
<Node Name="TableValuedFunctionParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" Strategy="FunctionParameters" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
<Node Name="ScalarValuedFunctions" LocLabel="SR.SchemaHierarchy_ScalarValuedFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedFunction" TreeNode="ScalarValuedFunctionInstanceTreeNode" >
<Filters>
<Filter Property="UserDefinedFunctionType" Type="Enum" ValidFor="Sql2016|SqlvNext|AzureV12">
<Value>UserDefinedFunctionType.Table</Value>
</Filter>
</Filters>
</Node>
<Node Name="ScalarValuedFunctionInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="ScalarValuedFunctionParameters"/>
</Node>
<Node Name="ScalarValuedFunctionParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" Strategy="FunctionParameters" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
<Node Name="AggregateFunctions" LocLabel="SR.SchemaHierarchy_AggregateFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUserDefinedAggregate" TreeNode="AggregateFunctionInstanceTreeNode" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="AggregateFunctionInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="" IsAsyncLoad="" Strategy="PopulateDetails">
<Child Name="AggregateFunctionParameters"/>
</Node>
<Node Name="AggregateFunctionParameters" LocLabel="SR.SchemaHierarchy_Parameters" BaseClass="ModelBased" Strategy="PopulateParentDetails" ChildQuerierTypes="SqlSubroutineParameter" DisableSort=""/>
<!-- TODO Support Route in SMO
<Node Name="Routes" LocLabel="SR.SchemaHierarchy_Routes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRoute"/>
-->
<!-- TODO support events
<Node Name="DatabaseAndQueueEventNotifications" LocLabel="SR.SchemaHierarchy_EventNotifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlEventNotification"/>
-->
<Node Name="RemoteServiceBindings" LocLabel="SR.SchemaHierarchy_RemoteServiceBindings" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRemoteServiceBinding"/>
<Node Name="BrokerPriorities" LocLabel="SR.SchemaHierarchy_BrokerPriorities" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlBrokerPriority" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="FileGroups" LocLabel="SR.SchemaHierarchy_FileGroups" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFileGroup" TreeNode="FileGroupInstanceTreeNode"/>
<Node Name="FullTextCatalogs" LocLabel="SR.SchemaHierarchy_FullTextCatalogs" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFullTextCatalog"/>
<Node Name="FullTextStopLists" LocLabel="SR.SchemaHierarchy_FullTextStopLists" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFullTextStopList" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="SqlLogFiles" LocLabel="SR.SchemaHierarchy_LogFiles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFile"/>
<Node Name="PartitionFunctions" LocLabel="SR.SchemaHierarchy_PartitionFunctions" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlPartitionFunction"/>
<Node Name="PartitionSchemes" LocLabel="SR.SchemaHierarchy_PartitionSchemes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlPartitionScheme"/>
<Node Name="SearchPropertyLists" LocLabel="SR.SchemaHierarchy_SearchPropertyLists" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSearchPropertyList" ValidFor="Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="FileGroupInstance" LocLabel="string.Empty" BaseClass="ModelBased" ChildQuerierTypes="">
<Child Name="FileGroupFiles"/>
</Node>
<Node Name="FileGroupFiles" LocLabel="SR.SchemaHierarchy_FilegroupFiles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlFile" >
</Node>
<Node Name="Users" LocLabel="SR.SchemaHierarchy_Users" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlUser"/>
<Node Name="Roles" LocLabel="SR.SchemaHierarchy_Roles" BaseClass="ModelBased" >
<Child Name="DatabaseRoles"/>
<Child Name="ApplicationRoles"/>
</Node>
<Node Name="Schemas" LocLabel="SR.SchemaHierarchy_Schemas" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSchema"/>
<Node Name="AsymmetricKeys" LocLabel="SR.SchemaHierarchy_AsymmetricKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlAsymmetricKey" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="Certificates" LocLabel="SR.SchemaHierarchy_Certificates" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlCertificate" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="SymmetricKeys" LocLabel="SR.SchemaHierarchy_SymmetricKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSymmetricKey" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="DatabaseEncryptionKeys" LocLabel="SR.SchemaHierarchy_DatabaseEncryptionKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseEncryptionKey" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="MasterKeys" LocLabel="SR.SchemaHierarchy_MasterKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlMasterKey" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<!-- TODO Support signatures
<Node Name="Signatures" LocLabel="SR.SchemaHierarchy_Signatures" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSignature" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
-->
<Node Name="DatabaseAuditSpecifications" LocLabel="SR.SchemaHierarchy_DatabaseAuditSpecifications" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseAuditSpecification" ValidFor="Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext"/>
<Node Name="SecurityPolicies" LocLabel="SR.SchemaHierarchy_SecurityPolicies" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlSecurityPolicy" ValidFor="Sql2016|SqlvNext|AzureV12"/>
<Node Name="DatabaseScopedCredentials" LocLabel="SR.SchemaHierarchy_DatabaseScopedCredentials" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlDatabaseCredential" ValidFor="Sql2016|SqlvNext|AzureV12"/>
<Node Name="AlwaysEncryptedKeys" LocLabel="SR.SchemaHierarchy_AlwaysEncryptedKeys" BaseClass="ModelBased" ValidFor="Sql2016|SqlvNext|AzureV12">
<Child Name="ColumnMasterKeys"/>
<Child Name="ColumnEncryptionKeys"/>
</Node>
<Node Name="DatabaseRoles" LocLabel="SR.SchemaHierarchy_DatabaseRoles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlRole"/>
<Node Name="ApplicationRoles" LocLabel="SR.SchemaHierarchy_ApplicationRoles" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlApplicationRole" ValidFor="Sql2005|Sql2008|Sql2012|Sql2014|Sql2016|SqlvNext|AzureV12"/>
<Node Name="ColumnMasterKeys" LocLabel="SR.SchemaHierarchy_ColumnMasterKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlColumnMasterKey" ValidFor="Sql2016|SqlvNext|AzureV12"/>
<Node Name="ColumnEncryptionKeys" LocLabel="SR.SchemaHierarchy_ColumnEncryptionKeys" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlColumnEncryptionKey" ValidFor="Sql2016|SqlvNext|AzureV12"/>
<Node Name="MessageTypes" LocLabel="SR.SchemaHierarchy_MessageTypes" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlMessageType">
<Child Name="SystemMessageTypes"/>
</Node>
<Node Name="SystemMessageTypes" LocLabel="SR.SchemaHierarchy_SystemMessageTypes" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlMessageType"/>
<Node Name="Contracts" LocLabel="SR.SchemaHierarchy_Contracts" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlContract">
<Child Name="SystemContracts"/>
</Node>
<Node Name="SystemContracts" LocLabel="SR.SchemaHierarchy_SystemContracts" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlContract"/>
<Node Name="Queues" LocLabel="SR.SchemaHierarchy_Queues" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlQueue">
<Child Name="SystemQueues"/>
</Node>
<Node Name="SystemQueues" LocLabel="SR.SchemaHierarchy_SystemQueues" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlQueue"/>
<Node Name="Services" LocLabel="SR.SchemaHierarchy_Services" BaseClass="ModelBased" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlService">
<Child Name="SystemServices"/>
</Node>
<Node Name="SystemServices" LocLabel="SR.SchemaHierarchy_SystemServices" BaseClass="ModelBased" IsMsShippedOwned="true" Strategy="MultipleElementsOfType" ChildQuerierTypes="SqlService"/>
<CodeGenOptions>
<UniqueTreeNode Name="DatabaseInstanceTreeNode"/>
<UniqueTreeNode Name="TableInstanceTreeNode"/>
<UniqueTreeNode Name="ViewInstanceTreeNode"/>
<UniqueTreeNode Name="UserDefinedTableTypeInstanceTreeNode"/>
<UniqueTreeNode Name="StoredProcedureInstanceTreeNode"/>
<UniqueTreeNode Name="TableValuedFunctionInstanceTreeNode"/>
<UniqueTreeNode Name="ScalarValuedFunctionInstanceTreeNode"/>
<UniqueTreeNode Name="AggregateFunctionInstanceTreeNode"/>
<UniqueTreeNode Name="FileGroupInstanceTreeNode"/>
<UniqueTreeNode Name="ExternalTableInstanceTreeNode"/>
<UniqueTreeNode Name="ExternalResourceInstanceTreeNode"/>
<UniqueTreeNode Name="HistoryTableInstanceTreeNode" />
</CodeGenOptions>
<!-- WARNING: Specifying reverse dependencies that could load large numbers of objects will be detrimental to performance. -->
<ReverseDependencyList>
<ReverseDependency Type="SqlUser" DependsOn="SqlRole;SqlRoleMembership"/>
</ReverseDependencyList>
</ServerExplorerTree>

File diff suppressed because it is too large Load Diff

View File

@@ -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<Type, IList<Type>> TypeReverseDependencyMap = new Dictionary<Type, IList<Type>>()");
// WriteLine(" {");
// foreach (var reverseDependencyKey in allReverseDependencies.Keys)
// {
// bool isFirstDependentType = true;
// StringBuilder dependentListBuilder = new StringBuilder("{");
// foreach (var dependentType in allReverseDependencies[reverseDependencyKey])
// {
// if (isFirstDependentType)
// {
// isFirstDependentType = false;
// }
// else
// {
// dependentListBuilder.Append(",");
// }
//
// dependentListBuilder.Append(string.Format(CultureInfo.InvariantCulture, " typeof({0})", dependentType));
// }
// dependentListBuilder.Append(" }");
//
// WriteLine(string.Format(CultureInfo.InvariantCulture, " {{ typeof({0}), new List<Type> {1} }}", reverseDependencyKey, dependentListBuilder.ToString()));
// }
// WriteLine(" };");
// WriteLine(" }");
// WriteLine("");
/////////
// First generate all the TreeNodes
/////////
var allTreeNodes = GetUniqueTreeNodes(xmlFile);
foreach (var TreeNode in allTreeNodes)
{
var name = TreeNode.GetAttribute("Name");
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<string> ApplicableParents() {{ return new[] {{ \"{0}\" }}; }}", type));
List<XmlElement> children = GetChildren(xmlFile, type);
if (children.Count > 0)
{
WriteLine("");
WriteLine(" protected override void OnExpandPopulateFolders(IList<TreeNode> 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<string> flags = new List<string>();
if (validForStr.Contains("Sql2005"))
{
flags.Add("ValidForFlag.Sql2005");
}
if (validForStr.Contains("Sql2008"))
{
flags.Add("ValidForFlag.Sql2008");
}
if (validForStr.Contains("Sql2012"))
{
flags.Add("ValidForFlag.Sql2012");
}
if (validForStr.Contains("Sql2014"))
{
flags.Add("ValidForFlag.Sql2014");
}
if (validForStr.Contains("Sql2016"))
{
flags.Add("ValidForFlag.Sql2016");
}
if (validForStr.Contains("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<string> typesList = new List<string>();
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList treeTypes = doc.SelectNodes("/ServerExplorerTree/Node");
if (treeTypes != null)
{
foreach (var type in treeTypes)
{
XmlElement element = type as XmlElement;
if (element != null)
{
typesList.Add(element.GetAttribute("Name"));
}
}
}
return typesList.ToArray();
}
public static Dictionary<string, List<string>> GetReverseDependencies(string xmlFile)
{
Dictionary<string, List<string>> dependencyMap = new Dictionary<string, List<string>>();
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList treeTypes = doc.SelectNodes("/ServerExplorerTree/ReverseDependencyList/ReverseDependency");
if (treeTypes != null)
{
foreach (var type in treeTypes)
{
XmlElement element = type as XmlElement;
if (element != null)
{
string typeName = element.GetAttribute("Type");
string dependency = element.GetAttribute("DependsOn");
List<string> dependenciesForType;
if (dependencyMap.TryGetValue(typeName, out dependenciesForType))
{
dependenciesForType.Add(dependency);
}
else
{
string[] allDepedencies = dependency.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
dependenciesForType = new List<string>();
dependenciesForType.AddRange(allDepedencies);
dependencyMap.Add(typeName, dependenciesForType);
}
}
}
}
return dependencyMap;
}
public static XmlElement GetNodeElement(string xmlFile, string nodeName)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
return (XmlElement)doc.SelectSingleNode(string.Format("/ServerExplorerTree/Node[@Name='{0}']", nodeName));
}
public static bool TreeNodeExists(string xmlFile, string TreeNode)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
var found = (XmlElement)doc.SelectSingleNode(string.Format("/ServerExplorerTree/CodeGenOptions/UniqueTreeNode[@Name='{0}']", TreeNode));
return (found != null);
}
public static List<XmlElement> GetUniqueTreeNodes(string xmlFile)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes("/ServerExplorerTree/CodeGenOptions/UniqueTreeNode");
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
public static List<XmlElement> GetChildren(string xmlFile, string parentName)
{
XmlElement nodeElement = GetNodeElement(xmlFile, parentName);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
List<XmlElement> retElements = new List<XmlElement>();
XmlNodeList nodeList = doc.SelectNodes(string.Format("/ServerExplorerTree/Node[@Name='{0}']/Child", parentName));
foreach (var item in nodeList)
{
XmlElement itemAsElement = item as XmlElement;
if (itemAsElement != null)
{
retElements.Add(itemAsElement);
}
}
return retElements;
}
#>

View File

@@ -44,3 +44,6 @@ using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.UnitTests")] [assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.UnitTests")]
[assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.IntegrationTests")] [assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.IntegrationTests")]
[assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.Test.Common")] [assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.Test.Common")]
// Allowing internals visible access to Moq library to help testing
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

View File

@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.Hosting; using Microsoft.SqlTools.Hosting;
using Microsoft.SqlTools.Hosting.Contracts; using Microsoft.SqlTools.Hosting.Contracts;
using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.Hosting.Protocol;
@@ -29,6 +30,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting
/// </summary> /// </summary>
private const int ShutdownTimeoutInSeconds = 120; private const int ShutdownTimeoutInSeconds = 120;
public static readonly string[] CompletionTriggerCharacters = new string[] { ".", "-", ":", "\\", "[", "\"" }; public static readonly string[] CompletionTriggerCharacters = new string[] { ".", "-", ":", "\\", "[", "\"" };
private IMultiServiceProvider serviceProvider;
#region Singleton Instance Code #region Singleton Instance Code
@@ -56,6 +58,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting
initializeCallbacks = new List<InitializeCallback>(); initializeCallbacks = new List<InitializeCallback>();
} }
public IMultiServiceProvider ServiceProvider
{
get
{
return serviceProvider;
}
internal set
{
serviceProvider = value;
}
}
/// <summary> /// <summary>
/// Provide initialization that must occur after the service host is started /// Provide initialization that must occur after the service host is started
/// </summary> /// </summary>

View File

@@ -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
{
/// <summary>
/// Common Constant values used across multiple services
/// </summary>
public static class CommonConstants
{
public const string MasterDatabaseName = "master";
public const string MsdbDatabaseName = "msdb";
public const string ModelDatabaseName = "model";
public const string TempDbDatabaseName = "tempdb";
}
}

View File

@@ -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<ObjectExplorerSession> 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<NodeInfo> 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);
}
}
}

View File

@@ -1,7 +1,10 @@
using System.Data.SqlClient; using System;
using System.Data.SqlClient;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; 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(); string sqlFilePath = GetTestSqlFile();
ScriptFile scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(sqlFilePath); 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; string ownerUri = scriptFile.ClientFilePath;
var connectionService = GetLiveTestConnectionService(); var connectionService = GetLiveTestConnectionService();
@@ -50,6 +53,35 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility
return new TestConnectionResult() { ConnectionInfo = connInfo, ScriptFile = scriptFile }; return new TestConnectionResult() { ConnectionInfo = connInfo, ScriptFile = scriptFile };
} }
public static async Task<TestConnectionResult> 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) public static ConnectionInfo InitLiveConnectionInfoForDefinition(string databaseName = null)
{ {
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName); ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);

File diff suppressed because one or more lines are too long

View File

@@ -45,6 +45,8 @@ END
public static string TestDbComplexSelectQueries { get { return TestDbSelectQueriesInstance.Value; } } public static string TestDbComplexSelectQueries { get { return TestDbSelectQueriesInstance.Value; } }
public static string AdventureWorksScript { get { return AdventureWorksScriptInstance.Value; } }
private static readonly Lazy<string> CreateDatabaseObjectsQueryInstance = new Lazy<string>(() => private static readonly Lazy<string> CreateDatabaseObjectsQueryInstance = new Lazy<string>(() =>
{ {
return GetScriptFileContent(ResourceNameRefix + "CreateTestDatabaseObjects.sql"); return GetScriptFileContent(ResourceNameRefix + "CreateTestDatabaseObjects.sql");
@@ -60,6 +62,11 @@ END
return GetScriptFileContent(ResourceNameRefix + "TestDbTableQueries.sql"); return GetScriptFileContent(ResourceNameRefix + "TestDbTableQueries.sql");
}); });
private static readonly Lazy<string> AdventureWorksScriptInstance = new Lazy<string>(() =>
{
return GetScriptFileContent(ResourceNameRefix + "AdventureWorks.sql");
});
private static string GetScriptFileContent(string fileName) private static string GetScriptFileContent(string fileName)
{ {
string fileContent = string.Empty; string fileContent = string.Empty;

View File

@@ -27,13 +27,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
/// <summary> /// <summary>
/// Create the test db if not already exists /// Create the test db if not already exists
/// </summary> /// </summary>
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(); SqlTestDb testDb = new SqlTestDb();
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{ {
databaseName = databaseName ?? GetUniqueDBName(""); databaseName = databaseName ?? GetUniqueDBName(dbNamePrefix);
string createDatabaseQuery = Scripts.CreateDatabaseQuery.Replace("#DatabaseName#", databaseName); string createDatabaseQuery = Scripts.CreateDatabaseQuery.Replace("#DatabaseName#", databaseName);
TestServiceProvider.Instance.RunQuery(serverType, MasterDatabaseName, createDatabaseQuery); TestServiceProvider.Instance.RunQuery(serverType, MasterDatabaseName, createDatabaseQuery);
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Test database '{0}' is created", databaseName)); Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Test database '{0}' is created", databaseName));

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
);

View File

@@ -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

View File

@@ -8,6 +8,7 @@ using Microsoft.SqlTools.Credentials;
using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.QueryExecution; using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.SqlContext; using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.Workspace; using Microsoft.SqlTools.ServiceLayer.Workspace;
@@ -45,6 +46,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
} }
} }
public ObjectExplorerService ObjectExplorerService
{
get
{
var serviceProvider = ServiceHost.Instance.ServiceProvider;
return serviceProvider.GetService<ObjectExplorerService>();
}
}
public TestConnectionProfileService ConnectionProfileService public TestConnectionProfileService ConnectionProfileService
{ {
get get

View File

@@ -6,7 +6,8 @@
"includeFiles": [ "includeFiles": [
"Scripts/CreateTestDatabaseObjects.sql", "Scripts/CreateTestDatabaseObjects.sql",
"Scripts/CreateTestDatabase.sql", "Scripts/CreateTestDatabase.sql",
"Scripts/TestDbTableQueries.sql" "Scripts/TestDbTableQueries.sql",
"Scripts/AdventureWorks.sql"
] ]
} }
}, },

View File

@@ -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
{
/// <summary>
/// Tests covering basic operation of Node based classes
/// </summary>
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<ArgumentNullException>(() => new ServerNode(null, ServiceProvider));
Assert.Throws<ArgumentNullException>(() => 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<TreeNode> children = node.GetChildren();
Assert.Throws<NotSupportedException>(() => 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<TreeNode> 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<SmoQueryContext>();
// 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<SmoQueryContext>();
// 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<SmoQueryContext>();
// 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<SmoQueryContext>();
// 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<SmoServerCreator> creator = new Mock<SmoServerCreator>();
creator.Setup(c => c.Create(It.IsAny<SqlConnection>()))
.Returns(() => smoServer);
ServerNode node = SetupServerNodeWithCreator(creator.Object);
return node;
}
private ServerNode SetupServerNodeWithExceptionCreator(Exception ex)
{
Mock<SmoServerCreator> creator = new Mock<SmoServerCreator>();
creator.Setup(c => c.Create(It.IsAny<SqlConnection>()))
.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<NamedSmoObject> smoObjectMock = new Mock<NamedSmoObject>();
smoObjectMock.SetupGet(s => s.Name).Returns(dbName);
Mock<SqlDatabaseQuerier> querierMock = new Mock<SqlDatabaseQuerier>();
querierMock.Setup(q => q.Query(It.IsAny<SmoQueryContext>()))
.Returns(smoObjectMock.Object.SingleItemAsEnumerable());
ServiceProvider.Register<SmoQuerier>(() => new[] { querierMock.Object });
Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString)));
ServerNode node = SetupServerNodeWithServer(smoServer);
// When I populate its children
IList<TreeNode> children = node.Expand();
// Then I expect it to contain server-level folders
Assert.Equal(3, children.Count);
VerifyTreeNode<FolderNode>(children[0], "Folder", SR.SchemaHierarchy_Databases);
VerifyTreeNode<FolderNode>(children[1], "Folder", SR.SchemaHierarchy_Security);
VerifyTreeNode<FolderNode>(children[2], "Folder", SR.SchemaHierarchy_ServerObjects);
// And the database is contained under it
TreeNode databases = children[0];
IList<TreeNode> 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<T>(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);
}
}
}

View File

@@ -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<ConnectionService> connectionServiceMock;
private Mock<IProtocolEndpoint> serviceHostMock;
public ObjectExplorerServiceTests()
{
connectionServiceMock = new Mock<ConnectionService>();
serviceHostMock = new Mock<IProtocolEndpoint>();
service = CreateOEService(connectionServiceMock.Object);
service.InitializeService(serviceHostMock.Object);
}
[Fact]
public async Task CreateSessionRequestErrorsIfConnectionDetailsIsNull()
{
object errorResponse = null;
var contextMock = RequestContextMocks.Create<CreateSessionResponse>(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<ConnectParams>()))
.Throws(new Exception(expectedExceptionText));
// when creating a new session
// then expect the create session request to return false
await RunAndVerify<CreateSessionResponse>(
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<ConnectionCompleteParams>()), 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<ConnectParams>()))
.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<CreateSessionResponse>(
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<ConnectionCompleteParams>()), 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<T>(Func<RequestContext<T>, Task> test, Action<T> verify)
{
T result = default(T);
var contextMock = RequestContextMocks.Create<T>(r => result = r).AddErrorHandling(null);
await test(contextMock.Object);
VerifyResult(contextMock, verify, result);
}
private void VerifyResult<T>(Mock<RequestContext<T>> contextMock, Action<T> verify, T actual)
{
contextMock.Verify(c => c.SendResult(It.IsAny<T>()), Times.Once);
contextMock.Verify(c => c.SendError(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<object>()), Times.Never);
verify(actual);
}
private void VerifyErrorSent<T>(Mock<RequestContext<T>> contextMock)
{
contextMock.Verify(c => c.SendResult(It.IsAny<T>()), Times.Never);
contextMock.Verify(c => c.SendError(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<object>()), Times.Once);
}
}
}

View File

@@ -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<ObjectExplorerService>();
}
}
}

View File

@@ -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<SmoQuerier>(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<SmoQuerier>(q => q.SupportedObjectTypes.Contains(smoType));
if (expectExists)
{
Assert.NotNull(querier);
Assert.Equal(querierType, querier.GetType());
Assert.NotNull(querier.ServiceProvider);
}
else
{
Assert.Null(querier);
}
}
}
}

View File

@@ -43,6 +43,169 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ServiceHost
var queryServiceErrorFormat = SR.QueryServiceErrorFormat(1, 1, 1, 1, "\n", ".."); var queryServiceErrorFormat = SR.QueryServiceErrorFormat(1, 1, 1, 1, "\n", "..");
var queryServiceQueryFailed = SR.QueryServiceQueryFailed(".."); var queryServiceQueryFailed = SR.QueryServiceQueryFailed("..");
var workspaceServiceBufferPositionOutOfOrder = SR.WorkspaceServiceBufferPositionOutOfOrder(1, 2, 3, 4); 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] [Fact]

View File

@@ -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<IProtocolEndpoint> AddEventHandling<TParams>(
this Mock<IProtocolEndpoint> mock,
EventType<TParams> expectedEvent,
Action<EventType<TParams>, TParams> eventCallback)
{
var flow = mock.Setup(h => h.SendEvent(
It.Is<EventType<TParams>>(m => m == expectedEvent),
It.IsAny<TParams>()))
.Returns(Task.FromResult(0));
if (eventCallback != null)
{
flow.Callback(eventCallback);
}
return mock;
}
}
}

View File

@@ -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 = ""
};
}
/// <summary>
/// Creates a test sql connection factory instance
/// </summary>
public static ISqlConnectionFactory GetTestSqlConnectionFactory()
{
// use mock database connection
return new TestSqlConnectionFactory();
}
/// <summary> /// <summary>
/// Creates a test connection details object /// Creates a test connection details object
/// </summary> /// </summary>