diff --git a/src/Microsoft.SqlTools.ServiceLayer/Admin/Database/DatabasePrototype.cs b/src/Microsoft.SqlTools.ServiceLayer/Admin/Database/DatabasePrototype.cs index c726f9f3..fe7fa776 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Admin/Database/DatabasePrototype.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Admin/Database/DatabasePrototype.cs @@ -299,7 +299,16 @@ WHERE do.database_id = @DbID ResourceManager manager = new ResourceManager("Microsoft.SqlTools.ServiceLayer.Localization.SR", typeof(DatabasePrototype).GetAssembly()); - this.owner = db.Owner; + try + { + this.owner = db.Owner; + } + catch (Exception) + { + // TODO: fix the exception in SMO + this.owner = string.Empty; + } + // Databases that are restored from other servers might not have valid owners. // If the logged in user is an administrator and the owner is not valid, show diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs index 8120b2e8..b427f5b7 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs @@ -404,7 +404,7 @@ SET NUMERIC_ROUNDABORT OFF;"; switch (e.CurrentState) { case ConnectionState.Open: - RetreiveSessionId(); + RetrieveSessionId(); break; case ConnectionState.Broken: case ConnectionState.Closed: @@ -418,20 +418,24 @@ SET NUMERIC_ROUNDABORT OFF;"; } } - private void RetreiveSessionId() + private void RetrieveSessionId() { try { using (IDbCommand command = CreateReliableCommand()) { - command.CommandText = QueryAzureSessionId; - object result = command.ExecuteScalar(); - - // Only returns a session id for SQL Azure - if (DBNull.Value != result) + IDbConnection connection = command.Connection; + if (!IsSqlDwConnection(connection)) { - string sessionId = (string)command.ExecuteScalar(); - _azureSessionId = new Guid(sessionId); + command.CommandText = QueryAzureSessionId; + object result = command.ExecuteScalar(); + + // Only returns a session id for SQL Azure + if (DBNull.Value != result) + { + string sessionId = (string)command.ExecuteScalar(); + _azureSessionId = new Guid(sessionId); + } } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyUtils.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyUtils.cs index 6a3c103e..a22549a7 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyUtils.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyUtils.cs @@ -342,15 +342,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection /// internal static void RaiseSchemaAmbientRetryMessage(RetryState retryState, int errorCode, Guid azureSessionId) { - Logger.Write(LogLevel.Warning, string.Format( - "Retry occurred: session: {0}; attempt - {1}; delay - {2}; exception - \"{3}\"", - azureSessionId, - retryState.RetryCount, - retryState.Delay, - retryState.LastError - )); + if (azureSessionId != Guid.Empty) + { + Logger.Write(LogLevel.Warning, string.Format( + "Retry occurred: session: {0}; attempt - {1}; delay - {2}; exception - \"{3}\"", + azureSessionId, + retryState.RetryCount, + retryState.Delay, + retryState.LastError + )); - RaiseAmbientRetryMessage(retryState, errorCode); + RaiseAmbientRetryMessage(retryState, errorCode); + } } #region ProcessNetLibErrorCode enumeration diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/CommonUtilities.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/CommonUtilities.cs index 7f05d899..0c036dbb 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/CommonUtilities.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/CommonUtilities.cs @@ -291,30 +291,30 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery return szRecoveryModel; } - - - public string GetDefaultBackupFolder() + + + public string GetDefaultBackupFolder() { string BackupFolder = ""; - - Enumerator en = null; - DataSet ds = new DataSet(); + + Enumerator en = null; + DataSet ds = new DataSet(); ds.Locale = System.Globalization.CultureInfo.InvariantCulture; - Request req = new Request(); - + Request req = new Request(); + en = new Enumerator(); - req.Urn = "Server/Setting"; + req.Urn = "Server/Setting"; ds = en.Process(SqlConnection, req); - int iCount = ds.Tables[0].Rows.Count; + int iCount = ds.Tables[0].Rows.Count; - if(iCount > 0) + if (iCount > 0) { BackupFolder = Convert.ToString(ds.Tables[0].Rows[0]["BackupDirectory"], System.Globalization.CultureInfo.InvariantCulture); } - return BackupFolder; + return BackupFolder; } diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/DisasterRecoveryService.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/DisasterRecoveryService.cs index 555fcbba..2b7d58ae 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/DisasterRecoveryService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/DisasterRecoveryService.cs @@ -83,9 +83,12 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery if (sqlConn != null) { DisasterRecoveryService.Instance.InitializeBackup(helper.DataContainer, sqlConn); - BackupConfigInfo backupConfigInfo = DisasterRecoveryService.Instance.GetBackupConfigInfo(sqlConn.Database); - backupConfigInfo.DatabaseInfo = AdminService.GetDatabaseInfo(connInfo); - response.BackupConfigInfo = backupConfigInfo; + if (!connInfo.IsSqlDW) + { + BackupConfigInfo backupConfigInfo = DisasterRecoveryService.Instance.GetBackupConfigInfo(sqlConn.Database); + backupConfigInfo.DatabaseInfo = AdminService.GetDatabaseInfo(connInfo); + response.BackupConfigInfo = backupConfigInfo; + } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeSmoProperty.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeSmoProperty.cs index 5b7f100e..5ac08a6d 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeSmoProperty.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeSmoProperty.cs @@ -15,6 +15,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes /// Property name /// public string Name { get; set; } + /// /// Indicates which platforms a filter is valid for /// diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/DatabaseTreeNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/DatabaseTreeNode.cs index 777791a0..2463b7ea 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/DatabaseTreeNode.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/DatabaseTreeNode.cs @@ -7,6 +7,7 @@ using System; using System.Globalization; using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; using Microsoft.SqlTools.Utility; namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel @@ -35,6 +36,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { context.Database = db; } + context.ValidFor = ServerVersionHelper.GetValidForFlag(context.SqlServerType, db); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs index bab0afb8..045f0a76 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs @@ -28,11 +28,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel try { - OnExpandPopulateFolders(allChildren, parent); - if(!includeSystemObjects) - { - allChildren.RemoveAll(x => x.IsSystemObject); - } + OnExpandPopulateFoldersAndFilter(allChildren, parent, includeSystemObjects); RemoveFoldersFromInvalidSqlServerVersions(allChildren, parent); OnExpandPopulateNonFolders(allChildren, parent, refresh, name); OnBeginAsyncOperations(parent); @@ -50,6 +46,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel return allChildren; } + private void OnExpandPopulateFoldersAndFilter(List allChildren, TreeNode parent, bool includeSystemObjects) + { + SmoQueryContext context = parent.GetContextAs(); + OnExpandPopulateFolders(allChildren, parent); + if (!includeSystemObjects) + { + allChildren.RemoveAll(x => x.IsSystemObject); + } + if (context != null && context.ValidFor != 0 && context.ValidFor != ValidForFlag.All) + { + allChildren.RemoveAll(x => + { + FolderNode folderNode = x as FolderNode; + if (folderNode != null && !ServerVersionHelper.IsValidFor(context.ValidFor, folderNode.ValidFor)) + { + return true; + } + return false; + }); + } + } + /// /// Populates any folders for a given parent node /// @@ -76,15 +94,15 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel SmoQueryContext context = parent.GetContextAs(); Validate.IsNotNull(nameof(context), context); - var validForFlag = ServerVersionHelper.GetValidForFlag(context.SqlServerType); - if (ShouldFilterNode(parent, validForFlag)) + var serverValidFor = context.ValidFor; + if (ShouldFilterNode(parent, serverValidFor)) { return; } IEnumerable queriers = context.ServiceProvider.GetServices(q => IsCompatibleQuerier(q)); var filters = this.Filters.ToList(); - var smoProperties = this.SmoProperties.Where(p => (p.ValidFor == 0 || p.ValidFor.HasFlag(validForFlag))).Select(x => x.Name); + var smoProperties = this.SmoProperties.Where(p => ServerVersionHelper.IsValidFor(serverValidFor, p.ValidFor)).Select(x => x.Name); if (!string.IsNullOrEmpty(name)) { filters.Add(new NodeFilter @@ -96,7 +114,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel } foreach (var querier in queriers) { - string propertyFilter = GetProperyFilter(filters, querier.GetType(), validForFlag); + if (!querier.IsValidFor(serverValidFor)) + { + continue; + } + string propertyFilter = GetProperyFilter(filters, querier.GetType(), serverValidFor); try { var smoObjectList = querier.Query(context, propertyFilter, refresh, smoProperties).ToList(); @@ -107,7 +129,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Logger.Write(LogLevel.Error, "smoObject should not be null"); } TreeNode childNode = CreateChild(parent, smoObject); - if (childNode != null && PassesFinalFilters(childNode, smoObject) && !ShouldFilterNode(childNode, validForFlag)) + if (childNode != null && PassesFinalFilters(childNode, smoObject) && !ShouldFilterNode(childNode, serverValidFor)) { allChildren.Add(childNode); } @@ -128,9 +150,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { bool filterTheNode = false; SmoTreeNode smoTreeNode = childNode as SmoTreeNode; - if (smoTreeNode != null && smoTreeNode.ValidFor != 0) + if (smoTreeNode != null) { - if (!(smoTreeNode.ValidFor.HasFlag(validForFlag))) + if (!ServerVersionHelper.IsValidFor(validForFlag, smoTreeNode.ValidFor)) { filterTheNode = true; } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQuerier.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQuerier.cs index 72516a54..2697703e 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQuerier.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQuerier.cs @@ -72,9 +72,26 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { return true; } - - + /// + /// Returns true if the querier is valid for the given server version + /// + /// + /// + public bool IsValidFor(ValidForFlag serverValidFor) + { + return ServerVersionHelper.IsValidFor(serverValidFor, ValidFor); + } + + /// + /// Indicates which platforms the querier is valid for + /// + public virtual ValidForFlag ValidFor + { + get + { + return ValidForFlag.All; + } + } } - } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryContext.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryContext.cs index 3da36c6c..5b3e5fb2 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryContext.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryContext.cs @@ -24,6 +24,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel private Database database; private SmoObjectBase parent; private SmoWrapper smoWrapper; + private ValidForFlag validFor = 0; /// /// Creates a context object with a server to use as the basis for any queries @@ -137,11 +138,31 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { database = this.Database, Parent = parent, - SqlServerType = this.SqlServerType + SqlServerType = this.SqlServerType, + ValidFor = ValidFor }; return context; } + /// + /// Indicates which platforms the server and database is valid for + /// + public ValidForFlag ValidFor + { + get + { + if(validFor == 0) + { + validFor = ServerVersionHelper.GetValidForFlag(SqlServerType, Database); + } + return validFor; + } + set + { + validFor = value; + } + } + private T GetObjectWithOpenedConnection(T smoObj) where T : SmoObjectBase { diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs index 425d57ff..8fe4033b 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs @@ -247,6 +247,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { Type[] supportedTypes = new Type[] { typeof(ServerDdlTrigger) }; + public override ValidForFlag ValidFor { get { return ValidForFlag.NotSqlDw; } } + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } public override IEnumerable Query(SmoQueryContext context, string filter, bool refresh, IEnumerable extraProperties) @@ -362,6 +365,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { Type[] supportedTypes = new Type[] { typeof(Synonym) }; + public override ValidForFlag ValidFor { get { return ValidForFlag.NotSqlDw; } } + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } public override IEnumerable Query(SmoQueryContext context, string filter, bool refresh, IEnumerable extraProperties) @@ -503,6 +509,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { Type[] supportedTypes = new Type[] { typeof(Trigger) }; + public override ValidForFlag ValidFor { get { return ValidForFlag.NotSqlDw; } } + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } public override IEnumerable Query(SmoQueryContext context, string filter, bool refresh, IEnumerable extraProperties) @@ -526,6 +535,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { Type[] supportedTypes = new Type[] { typeof(FullTextIndex) }; + public override ValidForFlag ValidFor { get { return ValidForFlag.NotSqlDw; } } + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } public override IEnumerable Query(SmoQueryContext context, string filter, bool refresh, IEnumerable extraProperties) @@ -575,6 +587,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { Type[] supportedTypes = new Type[] { typeof(DatabaseDdlTrigger) }; + public override ValidForFlag ValidFor { get { return ValidForFlag.NotSqlDw; } } + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } public override IEnumerable Query(SmoQueryContext context, string filter, bool refresh, IEnumerable extraProperties) @@ -644,6 +659,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { Type[] supportedTypes = new Type[] { typeof(UserDefinedDataType) }; + public override ValidForFlag ValidFor { get { return ValidForFlag.NotSqlDw; } } + + public override Type[] SupportedObjectTypes { get { return supportedTypes; } } public override IEnumerable Query(SmoQueryContext context, string filter, bool refresh, IEnumerable extraProperties) diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.tt b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.tt index 0117a71b..0c9fb75c 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.tt +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.tt @@ -34,6 +34,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel XmlElement nodeElement = GetNodeElement(xmlFile, nodeName); IList parents = GetParents(nodeElement, xmlFile, nodeName); string nodeType = GetNodeType(nodeElement, nodeName); + var validFor = nodeElement.GetAttribute("ValidFor"); string queryBaseClass = "SmoQuerier"; PushIndent(indent); @@ -45,6 +46,13 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel // Supported Types WriteLine("Type[] supportedTypes = new Type[] { typeof("+ nodeType + ") };"); + if (!string.IsNullOrWhiteSpace(validFor)) + { + WriteLine(""); + WriteLine(string.Format("public override ValidForFlag ValidFor {{ get {{ return {0}; }} }}", GetValidForFlags(validFor))); + WriteLine(""); + } + WriteLine(""); WriteLine("public override Type[] SupportedObjectTypes { get { return supportedTypes; } }"); WriteLine(""); @@ -232,4 +240,57 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel return retElements; } + public static string GetValidForFlags(string validForStr) + { + List flags = new List(); + if (validForStr.Contains("Sql2005")) + { + flags.Add("ValidForFlag.Sql2005"); + } + + if (validForStr.Contains("Sql2008")) + { + flags.Add("ValidForFlag.Sql2008"); + } + + if (validForStr.Contains("Sql2012")) + { + flags.Add("ValidForFlag.Sql2012"); + } + + if (validForStr.Contains("Sql2014")) + { + flags.Add("ValidForFlag.Sql2014"); + } + + if (validForStr.Contains("Sql2016")) + { + flags.Add("ValidForFlag.Sql2016"); + } + + if (validForStr.Contains("AzureV12")) + { + flags.Add("ValidForFlag.AzureV12"); + } + + if (validForStr.Contains("AllOnPrem")) + { + flags.Add("ValidForFlag.AllOnPrem"); + } + if (validForStr.Contains("AllAzure")) + { + flags.Add("ValidForFlag.AllAzure"); + } + if (validForStr.Contains("NotSqlDw")) + { + flags.Add("ValidForFlag.NotSqlDw"); + } + if (validForStr == "All") + { + flags.Add("ValidForFlag.All"); + } + + return string.Join("|", flags); + } + #> \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModelDefinition.xml b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModelDefinition.xml index 034067d7..c0367964 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModelDefinition.xml +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModelDefinition.xml @@ -29,7 +29,7 @@ - + @@ -42,7 +42,7 @@ - + @@ -52,11 +52,11 @@ - - + + - + @@ -69,7 +69,7 @@ --> - + diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeDefinition.xml b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeDefinition.xml index 8f62c523..d307a9b5 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeDefinition.xml +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeDefinition.xml @@ -92,7 +92,7 @@ - + @@ -203,7 +203,7 @@ - + @@ -238,7 +238,7 @@ - + @@ -264,8 +264,8 @@ - - + + @@ -293,7 +293,7 @@ - + diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.cs index 103df035..a54614f2 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.cs @@ -673,6 +673,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel NodeType = "Folder", NodeTypeId = NodeTypes.Synonyms, IsSystemObject = false, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, SortPriority = SmoTreeNode.NextSortPriority, }); currentChildren.Add(new FolderNode { @@ -906,6 +907,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel NodeType = "Folder", NodeTypeId = NodeTypes.DatabaseTriggers, IsSystemObject = false, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, SortPriority = SmoTreeNode.NextSortPriority, }); currentChildren.Add(new FolderNode { @@ -1312,6 +1314,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel NodeType = "Folder", NodeTypeId = NodeTypes.Triggers, IsSystemObject = false, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, SortPriority = SmoTreeNode.NextSortPriority, }); currentChildren.Add(new FolderNode { @@ -1686,6 +1689,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel NodeType = "Folder", NodeTypeId = NodeTypes.Triggers, IsSystemObject = false, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, SortPriority = SmoTreeNode.NextSortPriority, }); currentChildren.Add(new FolderNode { @@ -1877,6 +1881,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel NodeType = "Folder", NodeTypeId = NodeTypes.UserDefinedDataTypes, IsSystemObject = false, + ValidFor = ValidForFlag.Sql2005|ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, SortPriority = SmoTreeNode.NextSortPriority, }); currentChildren.Add(new FolderNode { @@ -1884,7 +1889,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel NodeType = "Folder", NodeTypeId = NodeTypes.UserDefinedTableTypes, IsSystemObject = false, - ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.Azure|ValidForFlag.AzureV12, + ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, SortPriority = SmoTreeNode.NextSortPriority, }); currentChildren.Add(new FolderNode { @@ -2008,7 +2013,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel NodeType = "Folder", NodeTypeId = NodeTypes.SystemSpatialDataTypes, IsSystemObject = false, - ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.Azure|ValidForFlag.AzureV12, + ValidFor = ValidForFlag.Sql2008|ValidForFlag.Sql2012|ValidForFlag.Sql2014|ValidForFlag.Sql2016|ValidForFlag.AzureV12, SortPriority = SmoTreeNode.NextSortPriority, }); } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.tt b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.tt index 3bea3edd..5d626c38 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.tt +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.tt @@ -369,11 +369,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel flags.Add("ValidForFlag.Sql2016"); } - if (validForStr.Contains("AzureV11")) - { - flags.Add("ValidForFlag.Azure"); - } - if (validForStr.Contains("AzureV12")) { flags.Add("ValidForFlag.AzureV12"); @@ -383,11 +378,15 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { flags.Add("ValidForFlag.AllOnPrem"); } - if (validForStr.Contains("AllAzure")) + if (validForStr.Contains("AllAzure")) { flags.Add("ValidForFlag.AllAzure"); } - if (validForStr == "All") + if (validForStr.Contains("NotSqlDw")) + { + flags.Add("ValidForFlag.NotSqlDw"); + } + if (validForStr == "All") { flags.Add("ValidForFlag.All"); } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/SqlServerType.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SqlServerType.cs similarity index 70% rename from src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/SqlServerType.cs rename to src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SqlServerType.cs index d15dc4ec..5b4fc395 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/SqlServerType.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SqlServerType.cs @@ -4,9 +4,10 @@ // using System; +using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; -namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer { /// /// Server Types @@ -20,7 +21,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes Sql2014, Sql2016, Sql2017, - Azure, AzureV12 } @@ -32,11 +32,38 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes /// /// Converts a server type to ValidForFlag /// - public static ValidForFlag GetValidForFlag(SqlServerType serverType) + public static ValidForFlag GetValidForFlag(SqlServerType serverType, Database database = null) + { + return GetValidForFlag(serverType, database != null && database.IsSqlDw); + } + + /// + /// Returns true if the given valid for flag is not set or it includes the server version + /// + /// Server version + /// Valid for flag + /// + public static bool IsValidFor(ValidForFlag serverVersion, ValidForFlag validFor) + { + return validFor == ValidForFlag.None || validFor.HasFlag(serverVersion); + } + + /// + /// Converts a server type to ValidForFlag + /// + public static ValidForFlag GetValidForFlag(SqlServerType serverType, bool isSqlDw) { ValidForFlag validforFlag = ValidForFlag.All; if (Enum.TryParse(serverType.ToString(), out validforFlag)) { + if (isSqlDw && serverType == SqlServerType.AzureV12) + { + validforFlag = ValidForFlag.SqlDw; + } + else + { + //TODO: not supporting SQL DW for on prem + } return validforFlag; } return ValidForFlag.All; @@ -52,14 +79,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes if (serverInfo.IsCloud) { - if (serverVersion.StartsWith("11", StringComparison.Ordinal)) - { - serverType = SqlServerType.Azure; - } - else - { - serverType = SqlServerType.AzureV12; - } + serverType = SqlServerType.AzureV12; } else if (!string.IsNullOrWhiteSpace(serverVersion)) { diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ValidForFlag.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ValidForFlag.cs similarity index 61% rename from src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ValidForFlag.cs rename to src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ValidForFlag.cs index 32e5648a..663dafa4 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/ValidForFlag.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ValidForFlag.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer { /// /// Indicates which type of server a given node type is valid for @@ -11,16 +11,18 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes [Flags] public enum ValidForFlag { + None = 0x00, Sql2005 = 0x01, Sql2008 = 0x02, Sql2012 = 0x04, Sql2014 = 0x08, - Azure = 0x10, - AzureV12 = 0x20, - Sql2016 = 0x40, - Sql2017 = 0x80, + AzureV12 = 0x10, + Sql2016 = 0x20, + Sql2017 = 0x40, + SqlDw = 0x80, AllOnPrem = Sql2005 | Sql2008 | Sql2012 | Sql2014 | Sql2016 | Sql2017, - AllAzure = Azure | AzureV12, - All = Sql2005 | Sql2008 | Sql2012 | Sql2014 | Sql2016 | Sql2017 | Azure | AzureV12 + AllAzure = AzureV12, + All = Sql2005 | Sql2008 | Sql2012 | Sql2014 | Sql2016 | Sql2017 | AzureV12 | SqlDw, + NotSqlDw = Sql2005 | Sql2008 | Sql2012 | Sql2014 | Sql2016 | Sql2017 | AzureV12 } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ServerVersionHelperTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ServerVersionHelperTests.cs new file mode 100644 index 00000000..1dc1541f --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ServerVersionHelperTests.cs @@ -0,0 +1,162 @@ +// +// 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.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer +{ + public class ServerVersionHelperTests + { + [Fact] + public void GetValidForFlagShouldReturnAllGivenUnKnownVersion() + { + ValidForFlag validforFlag = ServerVersionHelper.GetValidForFlag(SqlServerType.Unknown); + ValidForFlag expected = ValidForFlag.All; + + Assert.Equal(validforFlag, expected); + } + + [Fact] + public void GetValidForFlagShouldReturnTheFlagCorrectlyGivenValidVersion() + { + VerifyGetValidForFlag(SqlServerType.AzureV12, ValidForFlag.AzureV12); + VerifyGetValidForFlag(SqlServerType.Sql2005, ValidForFlag.Sql2005); + VerifyGetValidForFlag(SqlServerType.Sql2008, ValidForFlag.Sql2008); + VerifyGetValidForFlag(SqlServerType.Sql2012, ValidForFlag.Sql2012); + VerifyGetValidForFlag(SqlServerType.Sql2014, ValidForFlag.Sql2014); + VerifyGetValidForFlag(SqlServerType.Sql2016, ValidForFlag.Sql2016); + VerifyGetValidForFlag(SqlServerType.Sql2017, ValidForFlag.Sql2017); + } + + [Fact] + public void GetValidForFlagShouldReturnTheFlagIncludingSqlDwGivenSqlDwdatabase() + { + ValidForFlag validforFlag = ServerVersionHelper.GetValidForFlag(SqlServerType.AzureV12, true); + ValidForFlag expected = ValidForFlag.SqlDw; + + Assert.Equal(validforFlag, expected); + } + + [Fact] + public void CalculateServerTypeShouldReturnSql2005Given2005Version() + { + string serverVersion = "9.1.2.3"; + SqlServerType expected = SqlServerType.Sql2005; + VerifyCalculateServerType(serverVersion, expected); + + } + + [Fact] + public void CalculateServerTypeShouldReturnSql2008Given2008Version() + { + string serverVersion = "10.1.2.3"; + SqlServerType expected = SqlServerType.Sql2008; + VerifyCalculateServerType(serverVersion, expected); + } + + [Fact] + public void CalculateServerTypeShouldReturnSql2012Given2012Version() + { + string serverVersion = "11.1.2.3"; + SqlServerType expected = SqlServerType.Sql2012; + VerifyCalculateServerType(serverVersion, expected); + } + + [Fact] + public void CalculateServerTypeShouldReturnSql2014Given2014Version() + { + string serverVersion = "12.1.2.3"; + SqlServerType expected = SqlServerType.Sql2014; + VerifyCalculateServerType(serverVersion, expected); + } + + [Fact] + public void CalculateServerTypeShouldReturnSql2016Given2016Version() + { + string serverVersion = "13.1.2.3"; + SqlServerType expected = SqlServerType.Sql2016; + VerifyCalculateServerType(serverVersion, expected); + } + + [Fact] + public void CalculateServerTypeShouldReturnSql2017Given2017Version() + { + string serverVersion = "14.1.2.3"; + SqlServerType expected = SqlServerType.Sql2017; + VerifyCalculateServerType(serverVersion, expected); + } + + [Fact] + public void IsValidForShouldReturnTrueGivenSqlDwAndAll() + { + ValidForFlag serverValidFor = ValidForFlag.SqlDw; + ValidForFlag validFor = ValidForFlag.All; + bool expected = true; + VerifyIsValidFor(serverValidFor, validFor, expected); + } + + [Fact] + public void IsValidForShouldReturnTrueGivenSqlDwAndNone() + { + ValidForFlag serverValidFor = ValidForFlag.SqlDw; + ValidForFlag validFor = ValidForFlag.None; + bool expected = true; + VerifyIsValidFor(serverValidFor, validFor, expected); + } + + [Fact] + public void IsValidForShouldReturnTrueGivenSqlDwAndSqlDw() + { + ValidForFlag serverValidFor = ValidForFlag.SqlDw; + ValidForFlag validFor = ValidForFlag.SqlDw; + bool expected = true; + VerifyIsValidFor(serverValidFor, validFor, expected); + } + + [Fact] + public void IsValidForShouldReturnTrueGivenSqlDwAndNotSqlDw() + { + ValidForFlag serverValidFor = ValidForFlag.SqlDw; + ValidForFlag validFor = ValidForFlag.NotSqlDw; + bool expected = false; + VerifyIsValidFor(serverValidFor, validFor, expected); + } + + [Fact] + public void IsValidForShouldReturnTrueGivenSqlDwAndAllOnPrem() + { + ValidForFlag serverValidFor = ValidForFlag.SqlDw; + ValidForFlag validFor = ValidForFlag.AllOnPrem; + bool expected = false; + VerifyIsValidFor(serverValidFor, validFor, expected); + } + + private void VerifyIsValidFor(ValidForFlag serverValidFor, ValidForFlag validFor, bool expected) + { + bool actual = ServerVersionHelper.IsValidFor(serverValidFor, validFor); + Assert.Equal(expected, actual); + } + + private void VerifyCalculateServerType(string serverVersion, SqlServerType expected) + { + ServerInfo serverInfo = new ServerInfo + { + ServerVersion = serverVersion + }; + SqlServerType actual = ServerVersionHelper.CalculateServerType(serverInfo); + Assert.Equal(expected, actual); + } + + private void VerifyGetValidForFlag(SqlServerType serverType, ValidForFlag validForFlag) + { + ValidForFlag validforFlag = ServerVersionHelper.GetValidForFlag(serverType); + ValidForFlag expected = validForFlag; + + Assert.Equal(validforFlag, expected); + } + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/SmoQueryModelTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/SmoQueryModelTests.cs index c6f46554..eb0e76c3 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/SmoQueryModelTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/SmoQueryModelTests.cs @@ -1,65 +1,108 @@ -// -// 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; +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Linq; +using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlTools.Extensibility; -using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel; -using Xunit; - -namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer -{ - public class SmoQueryModelTests - { - - [Fact] - public void ShouldFindDatabaseQuerierFromRealPath() - { - // Given the extension type loader is set to find SmoCollectionQuerier objects - IMultiServiceProvider serviceProvider = ExtensionServiceProvider.CreateDefaultServiceProvider(); - // When I request a database compatible querier - SmoQuerier querier = serviceProvider.GetService(q => q.SupportedObjectTypes.Contains(typeof(Database))); - // Then I expect to get back the SqlDatabaseQuerier - Assert.NotNull(querier); - Assert.Equal(typeof(SqlDatabaseQuerier), querier.GetType()); - - // And I expect the service provider to have been set by the extension code - Assert.NotNull(querier.ServiceProvider); - } - - [Fact] - public void ShouldFindQuerierIfInExtensionList() - { - VerifyQuerierLookup(typeof(Table), typeof(SqlTableQuerier), expectExists: true); - } - - [Fact] - public void ShouldNotFindQuerierIfNotInExtensionList() - { - VerifyQuerierLookup(typeof(Database), null, expectExists: false); - } - - private static void VerifyQuerierLookup(Type smoType, Type querierType, bool expectExists) - { - ExtensionServiceProvider serviceProvider = ExtensionServiceProvider.Create(new Type[] { - typeof(SqlTableQuerier), - typeof(SqlLinkedServerQuerier) - }); - SmoQuerier querier = serviceProvider.GetService(q => q.SupportedObjectTypes.Contains(smoType)); - if (expectExists) - { - Assert.NotNull(querier); - Assert.Equal(querierType, querier.GetType()); - Assert.NotNull(querier.ServiceProvider); - } - else - { - Assert.Null(querier); - } - } - - } -} +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer +{ + public class SmoQueryModelTests + { + + [Fact] + public void ShouldFindDatabaseQuerierFromRealPath() + { + // Given the extension type loader is set to find SmoCollectionQuerier objects + IMultiServiceProvider serviceProvider = ExtensionServiceProvider.CreateDefaultServiceProvider(); + // When I request a database compatible querier + SmoQuerier querier = serviceProvider.GetService(q => q.SupportedObjectTypes.Contains(typeof(Database))); + // Then I expect to get back the SqlDatabaseQuerier + Assert.NotNull(querier); + Assert.Equal(typeof(SqlDatabaseQuerier), querier.GetType()); + + // And I expect the service provider to have been set by the extension code + Assert.NotNull(querier.ServiceProvider); + } + + [Fact] + public void ShouldFindQuerierIfInExtensionList() + { + VerifyQuerierLookup(typeof(Table), typeof(SqlTableQuerier), expectExists: true); + } + + [Fact] + public void ShouldNotFindQuerierIfNotInExtensionList() + { + VerifyQuerierLookup(typeof(Database), null, expectExists: false); + } + + [Fact] + public void SqlServerDdlTriggerQuerierShouldNotBeAvailableForSqlDw() + { + SmoQuerier querier = GetSmoQuerier(typeof(ServerDdlTrigger)); + Assert.False(querier.ValidFor.HasFlag(ValidForFlag.SqlDw)); + } + + [Fact] + public void SqlSynonymQuerierShouldNotBeAvailableForSqlDw() + { + SmoQuerier querier = GetSmoQuerier(typeof(Synonym)); + Assert.False(querier.ValidFor.HasFlag(ValidForFlag.SqlDw)); + } + + [Fact] + public void SqlTriggerQuerierShouldNotBeAvailableForSqlDw() + { + SmoQuerier querier = GetSmoQuerier(typeof(Trigger)); + Assert.False(querier.ValidFor.HasFlag(ValidForFlag.SqlDw)); + } + + [Fact] + public void SqlFullTextIndexQuerierShouldNotBeAvailableForSqlDw() + { + SmoQuerier querier = GetSmoQuerier(typeof(FullTextIndex)); + Assert.False(querier.ValidFor.HasFlag(ValidForFlag.SqlDw)); + } + + private SmoQuerier GetSmoQuerier(Type querierType) + { + // Given the extension type loader is set to find SmoCollectionQuerier objects + IMultiServiceProvider serviceProvider = ExtensionServiceProvider.CreateDefaultServiceProvider(); + // When I request a compatible querier + SmoQuerier querier = serviceProvider.GetService(q => q.SupportedObjectTypes.Contains(querierType)); + // Then I expect to get back the Querier + Assert.NotNull(querier); + + // And I expect the service provider to have been set by the extension code + Assert.NotNull(querier.ServiceProvider); + + return querier; + } + + private static void VerifyQuerierLookup(Type smoType, Type querierType, bool expectExists) + { + ExtensionServiceProvider serviceProvider = ExtensionServiceProvider.Create(new Type[] { + typeof(SqlTableQuerier), + typeof(SqlLinkedServerQuerier) + }); + SmoQuerier querier = serviceProvider.GetService(q => q.SupportedObjectTypes.Contains(smoType)); + if (expectExists) + { + Assert.NotNull(querier); + Assert.Equal(querierType, querier.GetType()); + Assert.NotNull(querier.ServiceProvider); + } + else + { + Assert.Null(querier); + } + } + } +}