diff --git a/build.json b/build.json index 3b61480c..d91fd6e3 100644 --- a/build.json +++ b/build.json @@ -7,7 +7,7 @@ "BuildToolsFolder": ".tools", "ArtifactsFolder": "artifacts", "TestProjects": { - "Microsoft.SqlTools.ServiceLayer.Test": [ + "Microsoft.SqlTools.ServiceLayer.UnitTests": [ "netcoreapp1.0" ] }, diff --git a/src/Microsoft.SqlTools.Credentials/Localization/sr.es.resx b/src/Microsoft.SqlTools.Credentials/Localization/sr.es.resx index d65a6f96..00b8aacd 100644 --- a/src/Microsoft.SqlTools.Credentials/Localization/sr.es.resx +++ b/src/Microsoft.SqlTools.Credentials/Localization/sr.es.resx @@ -1,123 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ES_LOCALIZATION - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ES_LOCALIZATION + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Credentials/Localization/sr.xlf b/src/Microsoft.SqlTools.Credentials/Localization/sr.xlf index b340af8b..577660b5 100644 --- a/src/Microsoft.SqlTools.Credentials/Localization/sr.xlf +++ b/src/Microsoft.SqlTools.Credentials/Localization/sr.xlf @@ -1,32 +1,32 @@ - - - - - - Invalid CriticalHandle! - Invalid CriticalHandle! - - - - The password has exceeded 512 bytes - The password has exceeded 512 bytes - - - - Target must be specified to delete a credential - Target must be specified to delete a credential - - - - Target must be specified to check existance of a credential - Target must be specified to check existance of a credential - - - - Win32Credential object is already disposed - Win32Credential object is already disposed - - - - + + + + + + Invalid CriticalHandle! + Invalid CriticalHandle! + + + + The password has exceeded 512 bytes + The password has exceeded 512 bytes + + + + Target must be specified to delete a credential + Target must be specified to delete a credential + + + + Target must be specified to check existance of a credential + Target must be specified to check existance of a credential + + + + Win32Credential object is already disposed + Win32Credential object is already disposed + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting/Localization/sr.es.resx b/src/Microsoft.SqlTools.Hosting/Localization/sr.es.resx index d65a6f96..00b8aacd 100644 --- a/src/Microsoft.SqlTools.Hosting/Localization/sr.es.resx +++ b/src/Microsoft.SqlTools.Hosting/Localization/sr.es.resx @@ -1,123 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ES_LOCALIZATION - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ES_LOCALIZATION + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting/Localization/sr.xlf b/src/Microsoft.SqlTools.Hosting/Localization/sr.xlf index eb98421f..0d624148 100644 --- a/src/Microsoft.SqlTools.Hosting/Localization/sr.xlf +++ b/src/Microsoft.SqlTools.Hosting/Localization/sr.xlf @@ -1,82 +1,82 @@ - - - - - - Invalid CriticalHandle! - Invalid CriticalHandle! - - - - The password has exceeded 512 bytes - The password has exceeded 512 bytes - - - - Target must be specified to delete a credential - Target must be specified to delete a credential - - - - Target must be specified to check existance of a credential - Target must be specified to check existance of a credential - - - - Win32Credential object is already disposed - Win32Credential object is already disposed - - - - MessageReader's input stream ended unexpectedly, terminating - MessageReader's input stream ended unexpectedly, terminating - - - - Message header must separate key and value using ':' - Message header must separate key and value using ':' - - - - Fatal error: Content-Length header must be provided - Fatal error: Content-Length header must be provided - - - - Fatal error: Content-Length value is not an integer - Fatal error: Content-Length value is not an integer - - - - Cannot register service for type {0}, one or more services already registered - Cannot register service for type {0}, one or more services already registered - - - - Multiple services found for type {0}, expected only 1 - Multiple services found for type {0}, expected only 1 - - - - Service of type {0} cannot be created by ExtensionLoader<{1}> - Service of type {0} cannot be created by ExtensionLoader<{1}> - - - - SetServiceProvider() was not called to establish the required service provider - SetServiceProvider() was not called to establish the required service provider - - - - Service {0} was not found in the service provider - Service {0} was not found in the service provider - - - - Service of Type {0} is not compatible with registered Type {1} - Service of Type {0} is not compatible with registered Type {1} - - - - + + + + + + Invalid CriticalHandle! + Invalid CriticalHandle! + + + + The password has exceeded 512 bytes + The password has exceeded 512 bytes + + + + Target must be specified to delete a credential + Target must be specified to delete a credential + + + + Target must be specified to check existance of a credential + Target must be specified to check existance of a credential + + + + Win32Credential object is already disposed + Win32Credential object is already disposed + + + + MessageReader's input stream ended unexpectedly, terminating + MessageReader's input stream ended unexpectedly, terminating + + + + Message header must separate key and value using ':' + Message header must separate key and value using ':' + + + + Fatal error: Content-Length header must be provided + Fatal error: Content-Length header must be provided + + + + Fatal error: Content-Length value is not an integer + Fatal error: Content-Length value is not an integer + + + + Cannot register service for type {0}, one or more services already registered + Cannot register service for type {0}, one or more services already registered + + + + Multiple services found for type {0}, expected only 1 + Multiple services found for type {0}, expected only 1 + + + + Service of type {0} cannot be created by ExtensionLoader<{1}> + Service of type {0} cannot be created by ExtensionLoader<{1}> + + + + SetServiceProvider() was not called to establish the required service provider + SetServiceProvider() was not called to establish the required service provider + + + + Service {0} was not found in the service provider + Service {0} was not found in the service provider + + + + Service of Type {0} is not compatible with registered Type {1} + Service of Type {0} is not compatible with registered Type {1} + + + + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/CachedServerInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/CachedServerInfo.cs index 3c22d368..71f3f505 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/CachedServerInfo.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/CachedServerInfo.cs @@ -12,16 +12,89 @@ using Microsoft.SqlTools.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { + /// /// This class caches server information for subsequent use /// - internal static class CachedServerInfo + internal class CachedServerInfo { + /// + /// Singleton service instance + /// + private static readonly Lazy instance + = new Lazy(() => new CachedServerInfo()); + + /// + /// Gets the singleton instance + /// + public static CachedServerInfo Instance + { + get + { + return instance.Value; + } + } + public enum CacheVariable { IsSqlDw, IsAzure } + #region CacheKey implementation + internal class CacheKey : IEquatable + { + private string dataSource; + private string dbName; + + public CacheKey(SqlConnectionStringBuilder builder) + { + Validate.IsNotNull(nameof(builder), builder); + dataSource = builder.DataSource; + dbName = GetDatabaseName(builder); + } + + internal static string GetDatabaseName(SqlConnectionStringBuilder builder) + { + string dbName = string.Empty; + if (!string.IsNullOrEmpty((builder.InitialCatalog))) + { + dbName = builder.InitialCatalog; + } + else if (!string.IsNullOrEmpty((builder.AttachDBFilename))) + { + dbName = builder.AttachDBFilename; + } + return dbName; + } + + public override bool Equals(object obj) + { + if (obj == null) { return false; } + + CacheKey keyObj = obj as CacheKey; + if (keyObj == null) { return false; } + else { return Equals(keyObj); } + } + + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hash = 17; + hash = (hash * 23) + (dataSource != null ? dataSource.GetHashCode() : 0); + hash = (hash * 23) + (dbName != null ? dbName.GetHashCode() : 0); + return hash; + } + } + + public bool Equals(CacheKey other) + { + return string.Equals(dataSource, other.dataSource, StringComparison.OrdinalIgnoreCase) + && string.Equals(dbName, other.dbName, StringComparison.OrdinalIgnoreCase); + } + } + #endregion + private struct CachedInfo { public bool IsAzure; @@ -29,38 +102,43 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection public bool IsSqlDw; } - private static ConcurrentDictionary _cache; - private static object _cacheLock; private const int _maxCacheSize = 1024; private const int _deleteBatchSize = 512; private const int MinimalQueryTimeoutSecondsForAzure = 300; - static CachedServerInfo() + private ConcurrentDictionary _cache; + private object _cacheLock; + + /// + /// Internal constructor for testing purposes. For all code use, please use the + /// default instance. + /// + internal CachedServerInfo() { - _cache = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + _cache = new ConcurrentDictionary(); _cacheLock = new object(); } - public static int GetQueryTimeoutSeconds(IDbConnection connection) + public int GetQueryTimeoutSeconds(IDbConnection connection) { - string dataSource = SafeGetDataSourceFromConnection(connection); - return GetQueryTimeoutSeconds(dataSource); + SqlConnectionStringBuilder connStringBuilder = SafeGetConnectionStringFromConnection(connection); + return GetQueryTimeoutSeconds(connStringBuilder); } - public static int GetQueryTimeoutSeconds(string dataSource) + public int GetQueryTimeoutSeconds(SqlConnectionStringBuilder builder) { //keep existing behavior and return the default ambient settings //if the provided data source is null or whitespace, or the original //setting is already 0 which means no limit. int originalValue = AmbientSettings.QueryTimeoutSeconds; - if (string.IsNullOrWhiteSpace(dataSource) + if (builder == null || string.IsNullOrWhiteSpace(builder.DataSource) || (originalValue == 0)) { return originalValue; } CachedInfo info; - bool hasFound = _cache.TryGetValue(dataSource, out info); + bool hasFound = TryGetCacheValue(builder, out info); if (hasFound && info.IsAzure && originalValue < MinimalQueryTimeoutSecondsForAzure) @@ -73,55 +151,43 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection } } - public static void AddOrUpdateIsAzure(IDbConnection connection, bool isAzure) + public void AddOrUpdateIsAzure(IDbConnection connection, bool isAzure) { AddOrUpdateCache(connection, isAzure, CacheVariable.IsAzure); } - public static void AddOrUpdateIsSqlDw(IDbConnection connection, bool isSqlDw) + public void AddOrUpdateIsSqlDw(IDbConnection connection, bool isSqlDw) { AddOrUpdateCache(connection, isSqlDw, CacheVariable.IsSqlDw); } - private static void AddOrUpdateCache(IDbConnection connection, bool newState, CacheVariable cacheVar) + private void AddOrUpdateCache(IDbConnection connection, bool newState, CacheVariable cacheVar) { Validate.IsNotNull(nameof(connection), connection); SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connection.ConnectionString); - AddOrUpdateCache(builder.DataSource, newState, cacheVar); + AddOrUpdateCache(builder, newState, cacheVar); } - internal static void AddOrUpdateCache(string dataSource, bool newState, CacheVariable cacheVar) + internal void AddOrUpdateCache(SqlConnectionStringBuilder builder, bool newState, CacheVariable cacheVar) { - Validate.IsNotNullOrWhitespaceString(nameof(dataSource), dataSource); + Validate.IsNotNull(nameof(builder), builder); + Validate.IsNotNullOrWhitespaceString(nameof(builder) + ".DataSource", builder.DataSource); CachedInfo info; - bool hasFound = _cache.TryGetValue(dataSource, out info); + bool hasFound = TryGetCacheValue(builder, out info); if ((cacheVar == CacheVariable.IsSqlDw && hasFound && info.IsSqlDw == newState) || (cacheVar == CacheVariable.IsAzure && hasFound && info.IsAzure == newState)) { + // No change needed return; } else { lock (_cacheLock) { - if (! _cache.ContainsKey(dataSource)) - { - //delete a batch of old elements when we try to add a new one and - //the capacity limitation is hit - if (_cache.Keys.Count > _maxCacheSize - 1) - { - var keysToDelete = _cache - .OrderBy(x => x.Value.LastUpdate) - .Take(_deleteBatchSize) - .Select(pair => pair.Key); - - foreach (string key in keysToDelete) - { - _cache.TryRemove(key, out info); - } - } - } + // Clean older keys, update info, and add this back into the cache + CacheKey key = new CacheKey(builder); + CleanupCache(key); if (cacheVar == CacheVariable.IsSqlDw) { @@ -132,24 +198,47 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection info.IsAzure = newState; } info.LastUpdate = DateTime.UtcNow; - _cache.AddOrUpdate(dataSource, info, (key, oldValue) => info); + _cache.AddOrUpdate(key, info, (k, oldValue) => info); } } } - public static bool TryGetIsSqlDw(IDbConnection connection, out bool isSqlDw) + private void CleanupCache(CacheKey newKey) + { + if (!_cache.ContainsKey(newKey)) + { + //delete a batch of old elements when we try to add a new one and + //the capacity limitation is hit + if (_cache.Keys.Count > _maxCacheSize - 1) + { + var keysToDelete = _cache + .OrderBy(x => x.Value.LastUpdate) + .Take(_deleteBatchSize) + .Select(pair => pair.Key); + + foreach (CacheKey key in keysToDelete) + { + CachedInfo info; + _cache.TryRemove(key, out info); + } + } + } + } + + public bool TryGetIsSqlDw(IDbConnection connection, out bool isSqlDw) { Validate.IsNotNull(nameof(connection), connection); SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connection.ConnectionString); - return TryGetIsSqlDw(builder.DataSource, out isSqlDw); + return TryGetIsSqlDw(builder, out isSqlDw); } - public static bool TryGetIsSqlDw(string dataSource, out bool isSqlDw) + public bool TryGetIsSqlDw(SqlConnectionStringBuilder builder, out bool isSqlDw) { - Validate.IsNotNullOrWhitespaceString(nameof(dataSource), dataSource); + Validate.IsNotNull(nameof(builder), builder); + Validate.IsNotNullOrWhitespaceString(nameof(builder) + ".DataSource", builder.DataSource); CachedInfo info; - bool hasFound = _cache.TryGetValue(dataSource, out info); + bool hasFound = TryGetCacheValue(builder, out info); if(hasFound) { @@ -161,7 +250,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection return false; } - private static string SafeGetDataSourceFromConnection(IDbConnection connection) + private static SqlConnectionStringBuilder SafeGetConnectionStringFromConnection(IDbConnection connection) { if (connection == null) { @@ -171,7 +260,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection try { SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connection.ConnectionString); - return builder.DataSource; + return builder; } catch { @@ -179,5 +268,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection return null; } } + + private bool TryGetCacheValue(SqlConnectionStringBuilder builder, out CachedInfo value) + { + CacheKey key = new CacheKey(builder); + return _cache.TryGetValue(key, out value); + } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs index 8256c3dc..2c190b15 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs @@ -407,7 +407,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection public static void SetCommandTimeout(IDbCommand cmd) { Validate.IsNotNull(nameof(cmd), cmd); - cmd.CommandTimeout = CachedServerInfo.GetQueryTimeoutSeconds(cmd.Connection); + cmd.CommandTimeout = CachedServerInfo.Instance.GetQueryTimeoutSeconds(cmd.Connection); } @@ -773,7 +773,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection try { - CachedServerInfo.AddOrUpdateIsAzure(connection, serverInfo.IsCloud); + CachedServerInfo.Instance.AddOrUpdateIsAzure(connection, serverInfo.IsCloud); } catch (Exception ex) { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs index 73f50b15..5696d2be 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs @@ -109,10 +109,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection //This is assuming that it is highly unlikely for a connection to change between instances. //Hence any subsequent calls to this method will just return the cached value and not //verify again if this is a SQL DW database connection or not. - if (!CachedServerInfo.TryGetIsSqlDw(conn, out _isSqlDwDatabase)) + if (!CachedServerInfo.Instance.TryGetIsSqlDw(conn, out _isSqlDwDatabase)) { _isSqlDwDatabase = ReliableConnectionHelper.IsSqlDwDatabase(conn); - CachedServerInfo.AddOrUpdateIsSqlDw(conn, _isSqlDwDatabase);; + CachedServerInfo.Instance.AddOrUpdateIsSqlDw(conn, _isSqlDwDatabase);; } return _isSqlDwDatabase; @@ -137,7 +137,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { cmd.CommandText = string.Format(CultureInfo.InvariantCulture, setLockTimeout, AmbientSettings.LockTimeoutMilliSeconds); cmd.CommandType = CommandType.Text; - cmd.CommandTimeout = CachedServerInfo.GetQueryTimeoutSeconds(conn); + cmd.CommandTimeout = CachedServerInfo.Instance.GetQueryTimeoutSeconds(conn); cmd.ExecuteNonQuery(); } } @@ -157,7 +157,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection // Configure the connection with proper ANSI settings and lock timeout using (IDbCommand cmd = conn.CreateCommand()) { - cmd.CommandTimeout = CachedServerInfo.GetQueryTimeoutSeconds(conn); + cmd.CommandTimeout = CachedServerInfo.Instance.GetQueryTimeoutSeconds(conn); if (!isSqlDw) { cmd.CommandText = @"SET ANSI_NULLS, ANSI_PADDING, ANSI_WARNINGS, ARITHABORT, CONCAT_NULL_YIELDS_NULL, QUOTED_IDENTIFIER ON; diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.cs index 82c27138..93e2f07a 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.cs @@ -1,199 +1,199 @@ -// -// 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.IO; -using System.Collections.Generic; -using System.Collections.Specialized; -using Microsoft.SqlServer.Management.Smo; -using Microsoft.SqlServer.Management.SqlParser.Intellisense; -using Microsoft.SqlTools.Utility; -namespace Microsoft.SqlTools.ServiceLayer.LanguageServices -{ - internal partial class PeekDefinition - { - - private void Initialize() - { - AddSupportedType(DeclarationType.Table, GetTableScripts, "Table", "table"); - AddSupportedType(DeclarationType.View, GetViewScripts, "View", "view"); - AddSupportedType(DeclarationType.StoredProcedure, GetStoredProcedureScripts, "Procedure", "stored procedure"); - AddSupportedType(DeclarationType.UserDefinedDataType, GetUserDefinedDataTypeScripts, "Type", "user-defined data type"); - AddSupportedType(DeclarationType.UserDefinedTableType, GetUserDefinedTableTypeScripts, "Type", "user-defined table type"); - AddSupportedType(DeclarationType.Synonym, GetSynonymScripts, "Synonym", ""); - AddSupportedType(DeclarationType.ScalarValuedFunction, GetScalarValuedFunctionScripts, "Function", "scalar-valued function"); - AddSupportedType(DeclarationType.TableValuedFunction, GetTableValuedFunctionScripts, "Function", "table-valued function"); +// +// 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.IO; +using System.Collections.Generic; +using System.Collections.Specialized; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlServer.Management.SqlParser.Intellisense; +using Microsoft.SqlTools.Utility; +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices +{ + internal partial class PeekDefinition + { + + private void Initialize() + { + AddSupportedType(DeclarationType.Table, GetTableScripts, "Table", "table"); + AddSupportedType(DeclarationType.View, GetViewScripts, "View", "view"); + AddSupportedType(DeclarationType.StoredProcedure, GetStoredProcedureScripts, "Procedure", "stored procedure"); + AddSupportedType(DeclarationType.UserDefinedDataType, GetUserDefinedDataTypeScripts, "Type", "user-defined data type"); + AddSupportedType(DeclarationType.UserDefinedTableType, GetUserDefinedTableTypeScripts, "Type", "user-defined table type"); + AddSupportedType(DeclarationType.Synonym, GetSynonymScripts, "Synonym", ""); + AddSupportedType(DeclarationType.ScalarValuedFunction, GetScalarValuedFunctionScripts, "Function", "scalar-valued function"); + AddSupportedType(DeclarationType.TableValuedFunction, GetTableValuedFunctionScripts, "Function", "table-valued function"); } - - /// - /// Script a Table using SMO - /// - /// Table name - /// Schema name - /// String collection of scripts - internal StringCollection GetTableScripts(string objectName, string schemaName) - { - try - { - Table smoObject = string.IsNullOrEmpty(schemaName) ? new Table(this.Database, objectName) : new Table(this.Database, objectName, schemaName); - smoObject.Refresh(); - return smoObject.Script(); - } - catch (Exception ex) - { - Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableScripts : " + ex.Message); - return null; - } + + /// + /// Script a Table using SMO + /// + /// Table name + /// Schema name + /// String collection of scripts + internal StringCollection GetTableScripts(string objectName, string schemaName) + { + try + { + Table smoObject = string.IsNullOrEmpty(schemaName) ? new Table(this.Database, objectName) : new Table(this.Database, objectName, schemaName); + smoObject.Refresh(); + return smoObject.Script(); + } + catch (Exception ex) + { + Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableScripts : " + ex.Message); + return null; + } } - - /// - /// Script a View using SMO - /// - /// View name - /// Schema name - /// String collection of scripts - internal StringCollection GetViewScripts(string objectName, string schemaName) - { - try - { - View smoObject = string.IsNullOrEmpty(schemaName) ? new View(this.Database, objectName) : new View(this.Database, objectName, schemaName); - smoObject.Refresh(); - return smoObject.Script(); - } - catch (Exception ex) - { - Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetViewScripts : " + ex.Message); - return null; - } + + /// + /// Script a View using SMO + /// + /// View name + /// Schema name + /// String collection of scripts + internal StringCollection GetViewScripts(string objectName, string schemaName) + { + try + { + View smoObject = string.IsNullOrEmpty(schemaName) ? new View(this.Database, objectName) : new View(this.Database, objectName, schemaName); + smoObject.Refresh(); + return smoObject.Script(); + } + catch (Exception ex) + { + Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetViewScripts : " + ex.Message); + return null; + } } - - /// - /// Script a StoredProcedure using SMO - /// - /// StoredProcedure name - /// Schema name - /// String collection of scripts - internal StringCollection GetStoredProcedureScripts(string objectName, string schemaName) - { - try - { - StoredProcedure smoObject = string.IsNullOrEmpty(schemaName) ? new StoredProcedure(this.Database, objectName) : new StoredProcedure(this.Database, objectName, schemaName); - smoObject.Refresh(); - return smoObject.Script(); - } - catch (Exception ex) - { - Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetStoredProcedureScripts : " + ex.Message); - return null; - } + + /// + /// Script a StoredProcedure using SMO + /// + /// StoredProcedure name + /// Schema name + /// String collection of scripts + internal StringCollection GetStoredProcedureScripts(string objectName, string schemaName) + { + try + { + StoredProcedure smoObject = string.IsNullOrEmpty(schemaName) ? new StoredProcedure(this.Database, objectName) : new StoredProcedure(this.Database, objectName, schemaName); + smoObject.Refresh(); + return smoObject.Script(); + } + catch (Exception ex) + { + Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetStoredProcedureScripts : " + ex.Message); + return null; + } } - - /// - /// Script a UserDefinedDataType using SMO - /// - /// UserDefinedDataType name - /// Schema name - /// String collection of scripts - internal StringCollection GetUserDefinedDataTypeScripts(string objectName, string schemaName) - { - try - { - UserDefinedDataType smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedDataType(this.Database, objectName) : new UserDefinedDataType(this.Database, objectName, schemaName); - smoObject.Refresh(); - return smoObject.Script(); - } - catch (Exception ex) - { - Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedDataTypeScripts : " + ex.Message); - return null; - } + + /// + /// Script a UserDefinedDataType using SMO + /// + /// UserDefinedDataType name + /// Schema name + /// String collection of scripts + internal StringCollection GetUserDefinedDataTypeScripts(string objectName, string schemaName) + { + try + { + UserDefinedDataType smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedDataType(this.Database, objectName) : new UserDefinedDataType(this.Database, objectName, schemaName); + smoObject.Refresh(); + return smoObject.Script(); + } + catch (Exception ex) + { + Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedDataTypeScripts : " + ex.Message); + return null; + } } - - /// - /// Script a UserDefinedTableType using SMO - /// - /// UserDefinedTableType name - /// Schema name - /// String collection of scripts - internal StringCollection GetUserDefinedTableTypeScripts(string objectName, string schemaName) - { - try - { - UserDefinedTableType smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedTableType(this.Database, objectName) : new UserDefinedTableType(this.Database, objectName, schemaName); - smoObject.Refresh(); - return smoObject.Script(); - } - catch (Exception ex) - { - Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedTableTypeScripts : " + ex.Message); - return null; - } + + /// + /// Script a UserDefinedTableType using SMO + /// + /// UserDefinedTableType name + /// Schema name + /// String collection of scripts + internal StringCollection GetUserDefinedTableTypeScripts(string objectName, string schemaName) + { + try + { + UserDefinedTableType smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedTableType(this.Database, objectName) : new UserDefinedTableType(this.Database, objectName, schemaName); + smoObject.Refresh(); + return smoObject.Script(); + } + catch (Exception ex) + { + Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedTableTypeScripts : " + ex.Message); + return null; + } } - - /// - /// Script a Synonym using SMO - /// - /// Synonym name - /// Schema name - /// String collection of scripts - internal StringCollection GetSynonymScripts(string objectName, string schemaName) - { - try - { - Synonym smoObject = string.IsNullOrEmpty(schemaName) ? new Synonym(this.Database, objectName) : new Synonym(this.Database, objectName, schemaName); - smoObject.Refresh(); - return smoObject.Script(); - } - catch (Exception ex) - { - Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetSynonymScripts : " + ex.Message); - return null; - } + + /// + /// Script a Synonym using SMO + /// + /// Synonym name + /// Schema name + /// String collection of scripts + internal StringCollection GetSynonymScripts(string objectName, string schemaName) + { + try + { + Synonym smoObject = string.IsNullOrEmpty(schemaName) ? new Synonym(this.Database, objectName) : new Synonym(this.Database, objectName, schemaName); + smoObject.Refresh(); + return smoObject.Script(); + } + catch (Exception ex) + { + Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetSynonymScripts : " + ex.Message); + return null; + } } - - /// - /// Script a ScalarValuedFunction using SMO - /// - /// ScalarValuedFunction name - /// Schema name - /// String collection of scripts - internal StringCollection GetScalarValuedFunctionScripts(string objectName, string schemaName) - { - try - { - UserDefinedFunction smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedFunction(this.Database, objectName) : new UserDefinedFunction(this.Database, objectName, schemaName); - smoObject.Refresh(); - return smoObject.Script(); - } - catch (Exception ex) - { - Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetScalarValuedFunctionScripts : " + ex.Message); - return null; - } + + /// + /// Script a ScalarValuedFunction using SMO + /// + /// ScalarValuedFunction name + /// Schema name + /// String collection of scripts + internal StringCollection GetScalarValuedFunctionScripts(string objectName, string schemaName) + { + try + { + UserDefinedFunction smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedFunction(this.Database, objectName) : new UserDefinedFunction(this.Database, objectName, schemaName); + smoObject.Refresh(); + return smoObject.Script(); + } + catch (Exception ex) + { + Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetScalarValuedFunctionScripts : " + ex.Message); + return null; + } } - - /// - /// Script a TableValuedFunction using SMO - /// - /// TableValuedFunction name - /// Schema name - /// String collection of scripts - internal StringCollection GetTableValuedFunctionScripts(string objectName, string schemaName) - { - try - { - UserDefinedFunction smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedFunction(this.Database, objectName) : new UserDefinedFunction(this.Database, objectName, schemaName); - smoObject.Refresh(); - return smoObject.Script(); - } - catch (Exception ex) - { - Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableValuedFunctionScripts : " + ex.Message); - return null; - } + + /// + /// Script a TableValuedFunction using SMO + /// + /// TableValuedFunction name + /// Schema name + /// String collection of scripts + internal StringCollection GetTableValuedFunctionScripts(string objectName, string schemaName) + { + try + { + UserDefinedFunction smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedFunction(this.Database, objectName) : new UserDefinedFunction(this.Database, objectName, schemaName); + smoObject.Refresh(); + return smoObject.Script(); + } + catch (Exception ex) + { + Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableValuedFunctionScripts : " + ex.Message); + return null; + } } - - } -} + + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.tt b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.tt index ac72a0b5..aedf33c1 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.tt +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.tt @@ -1,144 +1,144 @@ -<#@ template debug="false" hostspecific="true" language="C#" #> -<#@ output extension=".cs" #> -<#@ assembly name="System.Xml.dll" #> -<#@ import namespace="System" #> -<#@ import namespace="System.Globalization" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Xml" #> -<#@ import namespace="System.Collections.Generic" #> -<#@ import namespace="System.IO" #> -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// -using System; -using System.IO; -using System.Collections.Generic; -using System.Collections.Specialized; -using Microsoft.SqlServer.Management.Smo; -using Microsoft.SqlServer.Management.SqlParser.Intellisense; -using Microsoft.SqlTools.ServiceLayer.Utility; -namespace Microsoft.SqlTools.ServiceLayer.LanguageServices -{ - internal partial class PeekDefinition - { - - <# - /// - /// Generate Initialize method - /// - var indent = " "; - var directory = Path.GetDirectoryName(Host.TemplateFile); - string xmlFile = Path.Combine(directory, "PeekDefinitionSupportedTypes.xml"); - var supportedTypes = GetSupportedTypes(xmlFile); - if (supportedTypes != null && supportedTypes.Count > 0) - { - WriteLine("private void Initialize()"); - PushIndent(indent); - PushIndent(indent); - WriteLine("{"); - PushIndent(indent); - foreach(var typeProperty in supportedTypes) - { - string functionCall = string.Format("AddSupportedType(DeclarationType.{0}, Get{0}Scripts, \"{1}\", \"{2}\");", typeProperty["Name"], typeProperty["CreateSyntax"], typeProperty["QuickInfoType"]); - WriteLine(functionCall); - } - PopIndent(); - WriteLine("}\n"); - - /// - /// Generate scriptGetters for each type - /// - - foreach(var typeProperty in supportedTypes) - { - string statement; - // Write comments - WriteLine("/// "); - WriteLine(string.Format("/// Script a {0} using SMO", typeProperty["Name"])); - WriteLine("/// "); - WriteLine(string.Format("/// {0} name", typeProperty["Name"])); - WriteLine(string.Format("/// Schema name")); - WriteLine("/// String collection of scripts"); - - WriteLine(string.Format("internal StringCollection Get{0}Scripts(string objectName, string schemaName)", typeProperty["Name"])); - WriteLine("{"); - PushIndent(indent); - - // Write try block to retrieve object and return script - WriteLine("try"); - WriteLine("{"); - if(typeProperty["SupportsSchemaQuery"].IndexOf("true", StringComparison.OrdinalIgnoreCase) >= 0) - { - statement = string.Format("{0} smoObject = string.IsNullOrEmpty(schemaName) ? new {0}(this.Database, objectName) : new {0}(this.Database, objectName, schemaName);", typeProperty["AccessClass"]); - } - else - { - statement = string.Format("{0} smoObject = new {0}(this.Database, objectName);", typeProperty["Name"]); - } - PushIndent(indent); - WriteLine(statement); - WriteLine("smoObject.Refresh();"); - WriteLine("return smoObject.Script();"); - PopIndent(); - WriteLine("}"); - - // Write catch block to catch and log exceptions - WriteLine("catch (Exception ex)"); - WriteLine("{"); - PushIndent(indent); - statement = string.Format("LogLevel.Error,\"Exception at PeekDefinition Get{0}Scripts : \" + ex.Message", typeProperty["Name"]); - WriteLine("Logger.Write(" + statement + ");"); - WriteLine("return null;"); - PopIndent(); - WriteLine("}"); - PopIndent(); - WriteLine("}\n"); - } - } - PopIndent(); - PopIndent(); - #> - } -} - <#+ - /// - /// Get the supported types from the xml file - /// - public static List> GetSupportedTypes(string xmlFile) - { - List> typeList = null; - XmlDocument doc = new XmlDocument(); - doc.Load(xmlFile); - XmlNodeList supportedTypes = doc.SelectNodes("/SupportedTypes/Type"); - if (supportedTypes != null) - { - typeList = new List>(); - foreach (var type in supportedTypes) - { - XmlElement node = type as XmlElement; - if (node != null) - { - string typeName = (node["Name"] != null) ? node["Name"].InnerText : null; - string createSyntax = (node["CreateSyntax"] != null) ? node["CreateSyntax"].InnerText : null; - string accessClass = (node["AccessClass"] != null) ? node["AccessClass"].InnerText : null; - string supportsSchemaQuery = (node["SupportsSchemaQuery"] != null) ? node["SupportsSchemaQuery"].InnerText : null; - string quickInfoType = (node["QuickInfoType"] != null) ? node["QuickInfoType"].InnerText : null; - if (typeName != null && createSyntax != null && accessClass != null && supportsSchemaQuery!= null) - { - Dictionary typeProperties = new Dictionary(); - typeProperties.Add("Name", typeName); - typeProperties.Add("CreateSyntax", createSyntax); - typeProperties.Add("AccessClass", accessClass); - typeProperties.Add("SupportsSchemaQuery", supportsSchemaQuery); - typeProperties.Add("QuickInfoType", quickInfoType); - typeList.Add(typeProperties); - } - - } - } - } - return typeList; - } - +<#@ template debug="false" hostspecific="true" language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Xml.dll" #> +<#@ import namespace="System" #> +<#@ import namespace="System.Globalization" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Xml" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="System.IO" #> +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +using System; +using System.IO; +using System.Collections.Generic; +using System.Collections.Specialized; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlServer.Management.SqlParser.Intellisense; +using Microsoft.SqlTools.Utility; +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices +{ + internal partial class PeekDefinition + { + + <# + /// + /// Generate Initialize method + /// + var indent = " "; + var directory = Path.GetDirectoryName(Host.TemplateFile); + string xmlFile = Path.Combine(directory, "PeekDefinitionSupportedTypes.xml"); + var supportedTypes = GetSupportedTypes(xmlFile); + if (supportedTypes != null && supportedTypes.Count > 0) + { + WriteLine("private void Initialize()"); + PushIndent(indent); + PushIndent(indent); + WriteLine("{"); + PushIndent(indent); + foreach(var typeProperty in supportedTypes) + { + string functionCall = string.Format("AddSupportedType(DeclarationType.{0}, Get{0}Scripts, \"{1}\", \"{2}\");", typeProperty["Name"], typeProperty["CreateSyntax"], typeProperty["QuickInfoType"]); + WriteLine(functionCall); + } + PopIndent(); + WriteLine("}\n"); + + /// + /// Generate scriptGetters for each type + /// + + foreach(var typeProperty in supportedTypes) + { + string statement; + // Write comments + WriteLine("/// "); + WriteLine(string.Format("/// Script a {0} using SMO", typeProperty["Name"])); + WriteLine("/// "); + WriteLine(string.Format("/// {0} name", typeProperty["Name"])); + WriteLine(string.Format("/// Schema name")); + WriteLine("/// String collection of scripts"); + + WriteLine(string.Format("internal StringCollection Get{0}Scripts(string objectName, string schemaName)", typeProperty["Name"])); + WriteLine("{"); + PushIndent(indent); + + // Write try block to retrieve object and return script + WriteLine("try"); + WriteLine("{"); + if(typeProperty["SupportsSchemaQuery"].IndexOf("true", StringComparison.OrdinalIgnoreCase) >= 0) + { + statement = string.Format("{0} smoObject = string.IsNullOrEmpty(schemaName) ? new {0}(this.Database, objectName) : new {0}(this.Database, objectName, schemaName);", typeProperty["AccessClass"]); + } + else + { + statement = string.Format("{0} smoObject = new {0}(this.Database, objectName);", typeProperty["Name"]); + } + PushIndent(indent); + WriteLine(statement); + WriteLine("smoObject.Refresh();"); + WriteLine("return smoObject.Script();"); + PopIndent(); + WriteLine("}"); + + // Write catch block to catch and log exceptions + WriteLine("catch (Exception ex)"); + WriteLine("{"); + PushIndent(indent); + statement = string.Format("LogLevel.Error,\"Exception at PeekDefinition Get{0}Scripts : \" + ex.Message", typeProperty["Name"]); + WriteLine("Logger.Write(" + statement + ");"); + WriteLine("return null;"); + PopIndent(); + WriteLine("}"); + PopIndent(); + WriteLine("}\n"); + } + } + PopIndent(); + PopIndent(); + #> + } +} + <#+ + /// + /// Get the supported types from the xml file + /// + public static List> GetSupportedTypes(string xmlFile) + { + List> typeList = null; + XmlDocument doc = new XmlDocument(); + doc.Load(xmlFile); + XmlNodeList supportedTypes = doc.SelectNodes("/SupportedTypes/Type"); + if (supportedTypes != null) + { + typeList = new List>(); + foreach (var type in supportedTypes) + { + XmlElement node = type as XmlElement; + if (node != null) + { + string typeName = (node["Name"] != null) ? node["Name"].InnerText : null; + string createSyntax = (node["CreateSyntax"] != null) ? node["CreateSyntax"].InnerText : null; + string accessClass = (node["AccessClass"] != null) ? node["AccessClass"].InnerText : null; + string supportsSchemaQuery = (node["SupportsSchemaQuery"] != null) ? node["SupportsSchemaQuery"].InnerText : null; + string quickInfoType = (node["QuickInfoType"] != null) ? node["QuickInfoType"].InnerText : null; + if (typeName != null && createSyntax != null && accessClass != null && supportsSchemaQuery!= null) + { + Dictionary typeProperties = new Dictionary(); + typeProperties.Add("Name", typeName); + typeProperties.Add("CreateSyntax", createSyntax); + typeProperties.Add("AccessClass", accessClass); + typeProperties.Add("SupportsSchemaQuery", supportsSchemaQuery); + typeProperties.Add("QuickInfoType", quickInfoType); + typeList.Add(typeProperties); + } + + } + } + } + return typeList; + } + #> \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx index d65a6f96..00b8aacd 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.es.resx @@ -1,123 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ES_LOCALIZATION - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ES_LOCALIZATION + \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf index 810e675b..88a6570c 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf @@ -1,541 +1,541 @@ - - - - - - Connection parameters cannot be null - Connection parameters cannot be null - - - - OwnerUri cannot be null or empty - OwnerUri cannot be null or empty - - - - SpecifiedUri '{0}' does not have existing connection - SpecifiedUri '{0}' does not have existing connection - . - Parameters: 0 - uri (string) - - - Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. - Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. - . - Parameters: 0 - authType (string) - - - Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. - Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. - . - Parameters: 0 - intent (string) - - - Connection canceled - Connection canceled - - - - OwnerUri cannot be null or empty - OwnerUri cannot be null or empty - - - - Connection details object cannot be null - Connection details object cannot be null - - - - ServerName cannot be null or empty - ServerName cannot be null or empty - - - - {0} cannot be null or empty when using SqlLogin authentication - {0} cannot be null or empty when using SqlLogin authentication - . - Parameters: 0 - component (string) - - - The query has already completed, it cannot be cancelled - The query has already completed, it cannot be cancelled - - - - Query successfully cancelled, failed to dispose query. Owner URI not found. - Query successfully cancelled, failed to dispose query. Owner URI not found. - - - - Query was canceled by user - Query was canceled by user - - - - The batch has not completed, yet - The batch has not completed, yet - - - - Batch index cannot be less than 0 or greater than the number of batches - Batch index cannot be less than 0 or greater than the number of batches - - - - Result set index cannot be less than 0 or greater than the number of result sets - Result set index cannot be less than 0 or greater than the number of result sets - - - - Maximum number of bytes to return must be greater than zero - Maximum number of bytes to return must be greater than zero - - - - Maximum number of chars to return must be greater than zero - Maximum number of chars to return must be greater than zero - - - - Maximum number of XML bytes to return must be greater than zero - Maximum number of XML bytes to return must be greater than zero - - - - Access method cannot be write-only - Access method cannot be write-only - - - - FileStreamWrapper must be initialized before performing operations - FileStreamWrapper must be initialized before performing operations - - - - This FileStreamWrapper cannot be used for writing - This FileStreamWrapper cannot be used for writing - - - - (1 row affected) - (1 row affected) - - - - ({0} rows affected) - ({0} rows affected) - . - Parameters: 0 - rows (long) - - - Commands completed successfully. - Commands completed successfully. - - - - Msg {0}, Level {1}, State {2}, Line {3}{4}{5} - Msg {0}, Level {1}, State {2}, Line {3}{4}{5} - . - Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) - - - Query failed: {0} - Query failed: {0} - . - Parameters: 0 - message (string) - - - (No column name) - (No column name) - - - - The requested query does not exist - The requested query does not exist - - - - This editor is not connected to a database - This editor is not connected to a database - - - - A query is already in progress for this editor session. Please cancel this query or wait for its completion. - A query is already in progress for this editor session. Please cancel this query or wait for its completion. - - - - Sender for OnInfoMessage event must be a SqlConnection - Sender for OnInfoMessage event must be a SqlConnection - - - - Result cannot be saved until query execution has completed - Result cannot be saved until query execution has completed - - - - Internal error occurred while starting save task - Internal error occurred while starting save task - - - - A save request to the same path is in progress - A save request to the same path is in progress - - - - Failed to save {0}: {1} - Failed to save {0}: {1} - . - Parameters: 0 - fileName (string), 1 - message (string) - - - Cannot read subset unless the results have been read from the server - Cannot read subset unless the results have been read from the server - - - - Start row cannot be less than 0 or greater than the number of rows in the result set - Start row cannot be less than 0 or greater than the number of rows in the result set - - - - Row count must be a positive integer - Row count must be a positive integer - - - - Could not retrieve column schema for result set - Could not retrieve column schema for result set - - - - Could not retrieve an execution plan from the result set - Could not retrieve an execution plan from the result set - - - - This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} - This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} - . - Parameters: 0 - errorMessage (string) - - - An unexpected error occurred during Peek Definition execution: {0} - An unexpected error occurred during Peek Definition execution: {0} - . - Parameters: 0 - errorMessage (string) - - - No results were found. - No results were found. - - - - No database object was retrieved. - No database object was retrieved. - - - - Please connect to a server. - Please connect to a server. - - - - Operation timed out. - Operation timed out. - - - - This object type is currently not supported by this feature. - This object type is currently not supported by this feature. - - - - Position is outside of file line range - Position is outside of file line range - - - - Position is outside of column range for line {0} - Position is outside of column range for line {0} - . - Parameters: 0 - line (int) - - - Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) - Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) - . - Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) - - - Msg {0}, Level {1}, State {2}, Line {3} - Msg {0}, Level {1}, State {2}, Line {3} - - - - Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} - Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} - - - - Msg {0}, Level {1}, State {2} - Msg {0}, Level {1}, State {2} - - - - An error occurred while the batch was being processed. The error message is: {0} - An error occurred while the batch was being processed. The error message is: {0} - - - - ({0} row(s) affected) - ({0} row(s) affected) - - - - The previous execution is not yet complete. - The previous execution is not yet complete. - - - - A scripting error occurred. - A scripting error occurred. - - - - Incorrect syntax was encountered while {0} was being parsed. - Incorrect syntax was encountered while {0} was being parsed. - - - - A fatal error occurred. - A fatal error occurred. - - - - Execution completed {0} times... - Execution completed {0} times... - - - - You cancelled the query. - You cancelled the query. - - - - An error occurred while the batch was being executed. - An error occurred while the batch was being executed. - - - - An error occurred while the batch was being executed, but the error has been ignored. - An error occurred while the batch was being executed, but the error has been ignored. - - - - Starting execution loop of {0} times... - Starting execution loop of {0} times... - - - - Command {0} is not supported. - Command {0} is not supported. - - - - The variable {0} could not be found. - The variable {0} could not be found. - - - - SQL Execution error: {0} - SQL Execution error: {0} - - - - Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} - Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} - - - - Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} - Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} - - - - Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} - Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} - - - - Batch parser wrapper execution engine batch ResultSet finished. - Batch parser wrapper execution engine batch ResultSet finished. - - - - Canceling batch parser wrapper batch execution. - Canceling batch parser wrapper batch execution. - - - - Scripting warning. - Scripting warning. - - - - For more information about this error, see the troubleshooting topics in the product documentation. - For more information about this error, see the troubleshooting topics in the product documentation. - - - - File '{0}' recursively included. - File '{0}' recursively included. - - - - Missing end comment mark '*/'. - Missing end comment mark '*/'. - - - - Unclosed quotation mark after the character string. - Unclosed quotation mark after the character string. - - - - Incorrect syntax was encountered while parsing '{0}'. - Incorrect syntax was encountered while parsing '{0}'. - - - - Variable {0} is not defined. - Variable {0} is not defined. - - - - EN_LOCALIZATION - EN_LOCALIZATION - - - - Cannot convert SqlCodeObject Type {0} to Type {1} - Cannot convert SqlCodeObject Type {0} to Type {1} - - - - Replacement of an empty string by an empty string. - Replacement of an empty string by an empty string. - - - - Edit session does not exist. - Edit session does not exist. - - - - Query has not completed execution - Query has not completed execution - - - - Query did not generate exactly one result set - Query did not generate exactly one result set - - - - Failed to add new row to update cache - Failed to add new row to update cache - - - - Given row ID is outside the range of rows in the edit cache - Given row ID is outside the range of rows in the edit cache - - - - An update is already pending for this row and must be reverted first - An update is already pending for this row and must be reverted first - - - - Given row ID does not have pending updated - Given row ID does not have pending updated - - - - Table or view metadata could not be found - Table or view metadata could not be found - - - - Invalid format for binary column - Invalid format for binary column - - - - Allowed values for boolean columns are 0, 1, "true", or "false" - Boolean columns must be numeric 1 or 0, or string true or false - - - - A required cell value is missing - A required cell value is missing - - - - A delete is pending for this row, a cell update cannot be applied. - A delete is pending for this row, a cell update cannot be applied. - - - - Column ID must be in the range of columns for the query - Column ID must be in the range of columns for the query - - - - Column cannot be edited - Column cannot be edited - - - - No key columns were found - No key columns were found - - - - An output filename must be provided - An output filename must be provided - - - - Database object {0} cannot be used for editing. - Database object {0} cannot be used for editing. - . - Parameters: 0 - typeName (string) - - - Specified URI '{0}' does not have a default connection - Specified URI '{0}' does not have a default connection - . - Parameters: 0 - uri (string) - - - A commit task is in progress. Please wait for completion. - A commit task is in progress. Please wait for completion. - - - - Decimal column is missing numeric precision or numeric scale - Decimal column is missing numeric precision or numeric scale - - - - Cannot add row to result buffer, data reader does not contain rows - Cannot add row to result buffer, data reader does not contain rows - - - - + + + + + + Connection parameters cannot be null + Connection parameters cannot be null + + + + OwnerUri cannot be null or empty + OwnerUri cannot be null or empty + + + + SpecifiedUri '{0}' does not have existing connection + SpecifiedUri '{0}' does not have existing connection + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + . + Parameters: 0 - intent (string) + + + Connection canceled + Connection canceled + + + + OwnerUri cannot be null or empty + OwnerUri cannot be null or empty + + + + Connection details object cannot be null + Connection details object cannot be null + + + + ServerName cannot be null or empty + ServerName cannot be null or empty + + + + {0} cannot be null or empty when using SqlLogin authentication + {0} cannot be null or empty when using SqlLogin authentication + . + Parameters: 0 - component (string) + + + The query has already completed, it cannot be cancelled + The query has already completed, it cannot be cancelled + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + Query successfully cancelled, failed to dispose query. Owner URI not found. + + + + Query was canceled by user + Query was canceled by user + + + + The batch has not completed, yet + The batch has not completed, yet + + + + Batch index cannot be less than 0 or greater than the number of batches + Batch index cannot be less than 0 or greater than the number of batches + + + + Result set index cannot be less than 0 or greater than the number of result sets + Result set index cannot be less than 0 or greater than the number of result sets + + + + Maximum number of bytes to return must be greater than zero + Maximum number of bytes to return must be greater than zero + + + + Maximum number of chars to return must be greater than zero + Maximum number of chars to return must be greater than zero + + + + Maximum number of XML bytes to return must be greater than zero + Maximum number of XML bytes to return must be greater than zero + + + + Access method cannot be write-only + Access method cannot be write-only + + + + FileStreamWrapper must be initialized before performing operations + FileStreamWrapper must be initialized before performing operations + + + + This FileStreamWrapper cannot be used for writing + This FileStreamWrapper cannot be used for writing + + + + (1 row affected) + (1 row affected) + + + + ({0} rows affected) + ({0} rows affected) + . + Parameters: 0 - rows (long) + + + Commands completed successfully. + Commands completed successfully. + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + Query failed: {0} + Query failed: {0} + . + Parameters: 0 - message (string) + + + (No column name) + (No column name) + + + + The requested query does not exist + The requested query does not exist + + + + This editor is not connected to a database + This editor is not connected to a database + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + + + + Sender for OnInfoMessage event must be a SqlConnection + Sender for OnInfoMessage event must be a SqlConnection + + + + Result cannot be saved until query execution has completed + Result cannot be saved until query execution has completed + + + + Internal error occurred while starting save task + Internal error occurred while starting save task + + + + A save request to the same path is in progress + A save request to the same path is in progress + + + + Failed to save {0}: {1} + Failed to save {0}: {1} + . + Parameters: 0 - fileName (string), 1 - message (string) + + + Cannot read subset unless the results have been read from the server + Cannot read subset unless the results have been read from the server + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + Start row cannot be less than 0 or greater than the number of rows in the result set + + + + Row count must be a positive integer + Row count must be a positive integer + + + + Could not retrieve column schema for result set + Could not retrieve column schema for result set + + + + Could not retrieve an execution plan from the result set + Could not retrieve an execution plan from the result set + + + + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + This feature is currently not supported on Azure SQL DB and Data Warehouse: {0} + . + Parameters: 0 - errorMessage (string) + + + An unexpected error occurred during Peek Definition execution: {0} + An unexpected error occurred during Peek Definition execution: {0} + . + Parameters: 0 - errorMessage (string) + + + No results were found. + No results were found. + + + + No database object was retrieved. + No database object was retrieved. + + + + Please connect to a server. + Please connect to a server. + + + + Operation timed out. + Operation timed out. + + + + This object type is currently not supported by this feature. + This object type is currently not supported by this feature. + + + + Position is outside of file line range + Position is outside of file line range + + + + Position is outside of column range for line {0} + Position is outside of column range for line {0} + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + + Msg {0}, Level {1}, State {2}, Line {3} + Msg {0}, Level {1}, State {2}, Line {3} + + + + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + Msg {0}, Level {1}, State {2}, Procedure {3}, Line {4} + + + + Msg {0}, Level {1}, State {2} + Msg {0}, Level {1}, State {2} + + + + An error occurred while the batch was being processed. The error message is: {0} + An error occurred while the batch was being processed. The error message is: {0} + + + + ({0} row(s) affected) + ({0} row(s) affected) + + + + The previous execution is not yet complete. + The previous execution is not yet complete. + + + + A scripting error occurred. + A scripting error occurred. + + + + Incorrect syntax was encountered while {0} was being parsed. + Incorrect syntax was encountered while {0} was being parsed. + + + + A fatal error occurred. + A fatal error occurred. + + + + Execution completed {0} times... + Execution completed {0} times... + + + + You cancelled the query. + You cancelled the query. + + + + An error occurred while the batch was being executed. + An error occurred while the batch was being executed. + + + + An error occurred while the batch was being executed, but the error has been ignored. + An error occurred while the batch was being executed, but the error has been ignored. + + + + Starting execution loop of {0} times... + Starting execution loop of {0} times... + + + + Command {0} is not supported. + Command {0} is not supported. + + + + The variable {0} could not be found. + The variable {0} could not be found. + + + + SQL Execution error: {0} + SQL Execution error: {0} + + + + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + Batch parser wrapper execution: {0} found... at line {1}: {2} Description: {3} + + + + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + Batch parser wrapper execution engine batch message received: Message: {0} Detailed message: {1} + + + + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + Batch parser wrapper execution engine batch ResultSet processing: DataReader.FieldCount: {0} DataReader.RecordsAffected: {1} + + + + Batch parser wrapper execution engine batch ResultSet finished. + Batch parser wrapper execution engine batch ResultSet finished. + + + + Canceling batch parser wrapper batch execution. + Canceling batch parser wrapper batch execution. + + + + Scripting warning. + Scripting warning. + + + + For more information about this error, see the troubleshooting topics in the product documentation. + For more information about this error, see the troubleshooting topics in the product documentation. + + + + File '{0}' recursively included. + File '{0}' recursively included. + + + + Missing end comment mark '*/'. + Missing end comment mark '*/'. + + + + Unclosed quotation mark after the character string. + Unclosed quotation mark after the character string. + + + + Incorrect syntax was encountered while parsing '{0}'. + Incorrect syntax was encountered while parsing '{0}'. + + + + Variable {0} is not defined. + Variable {0} is not defined. + + + + EN_LOCALIZATION + EN_LOCALIZATION + + + + Cannot convert SqlCodeObject Type {0} to Type {1} + Cannot convert SqlCodeObject Type {0} to Type {1} + + + + Replacement of an empty string by an empty string. + Replacement of an empty string by an empty string. + + + + Edit session does not exist. + Edit session does not exist. + + + + Query has not completed execution + Query has not completed execution + + + + Query did not generate exactly one result set + Query did not generate exactly one result set + + + + Failed to add new row to update cache + Failed to add new row to update cache + + + + Given row ID is outside the range of rows in the edit cache + Given row ID is outside the range of rows in the edit cache + + + + An update is already pending for this row and must be reverted first + An update is already pending for this row and must be reverted first + + + + Given row ID does not have pending updated + Given row ID does not have pending updated + + + + Table or view metadata could not be found + Table or view metadata could not be found + + + + Invalid format for binary column + Invalid format for binary column + + + + Allowed values for boolean columns are 0, 1, "true", or "false" + Boolean columns must be numeric 1 or 0, or string true or false + + + + A required cell value is missing + A required cell value is missing + + + + A delete is pending for this row, a cell update cannot be applied. + A delete is pending for this row, a cell update cannot be applied. + + + + Column ID must be in the range of columns for the query + Column ID must be in the range of columns for the query + + + + Column cannot be edited + Column cannot be edited + + + + No key columns were found + No key columns were found + + + + An output filename must be provided + An output filename must be provided + + + + Database object {0} cannot be used for editing. + Database object {0} cannot be used for editing. + . + Parameters: 0 - typeName (string) + + + Specified URI '{0}' does not have a default connection + Specified URI '{0}' does not have a default connection + . + Parameters: 0 - uri (string) + + + A commit task is in progress. Please wait for completion. + A commit task is in progress. Please wait for completion. + + + + Decimal column is missing numeric precision or numeric scale + Decimal column is missing numeric precision or numeric scale + + + + Cannot add row to result buffer, data reader does not contain rows + Cannot add row to result buffer, data reader does not contain rows + + + + \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Connection/ReliableConnectionTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Connection/ReliableConnectionTests.cs index de5d8ec7..6396bfbb 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Connection/ReliableConnectionTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Connection/ReliableConnectionTests.cs @@ -15,7 +15,6 @@ using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection; using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility; using Microsoft.SqlTools.ServiceLayer.Test.Common; using Xunit; -using static Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection.ReliableConnectionHelper; using static Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection.RetryPolicy; using static Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection.RetryPolicy.TimeBasedRetryPolicy; using static Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection.SqlSchemaModelErrorCodes; diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/CachedServerInfoTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/CachedServerInfoTests.cs index a19a5c92..09c377af 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/CachedServerInfoTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/CachedServerInfoTests.cs @@ -5,6 +5,7 @@ using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection; using Xunit; +using System.Data.SqlClient; namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection { @@ -13,18 +14,70 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection /// public class CachedServerInfoTests { + private CachedServerInfo cache; + + public CachedServerInfoTests() + { + cache = new CachedServerInfo(); + } + + [Fact] + public void CacheMatchesNullDbNameToEmptyString() + { + // Set sqlDw result into cache + string dataSource = "testDataSource"; + bool isSqlDwResult; + SqlConnectionStringBuilder testSource = new SqlConnectionStringBuilder + { + DataSource = dataSource, + InitialCatalog = string.Empty + }; + cache.AddOrUpdateCache(testSource, true, CachedServerInfo.CacheVariable.IsSqlDw); + + // Expect the same returned result + Assert.True(cache.TryGetIsSqlDw(testSource, out isSqlDwResult)); + Assert.True(isSqlDwResult); + + // And expect the same for the null string + Assert.True(cache.TryGetIsSqlDw(new SqlConnectionStringBuilder + { + DataSource = dataSource + // Initial Catalog is null. Can't set explicitly as this throws + }, out isSqlDwResult)); + Assert.True(isSqlDwResult); + + // But expect false for a different DB + Assert.False(cache.TryGetIsSqlDw(new SqlConnectionStringBuilder + { + DataSource = dataSource, + InitialCatalog = "OtherDb" + }, out isSqlDwResult)); + } [Theory] - [InlineData(true)] // is SqlDW instance - [InlineData(false)] // is not a SqlDw Instance - public void AddOrUpdateIsSqlDw(bool state) + [InlineData(null, true)] // is SqlDW instance + [InlineData("", true)] // is SqlDW instance + [InlineData("myDb", true)] // is SqlDW instance + [InlineData(null, false)] // is not a SqlDw Instance + [InlineData("", false)] // is not a SqlDw Instance + [InlineData("myDb", false)] // is not SqlDW instance + public void AddOrUpdateIsSqlDw(string dbName, bool state) { // Set sqlDw result into cache bool isSqlDwResult; - CachedServerInfo.AddOrUpdateCache("testDataSource", state, CachedServerInfo.CacheVariable.IsSqlDw); + SqlConnectionStringBuilder testSource = new SqlConnectionStringBuilder + { + DataSource = "testDataSource" + }; + if (dbName != null) + { + testSource.InitialCatalog = dbName; + } + + cache.AddOrUpdateCache(testSource, state, CachedServerInfo.CacheVariable.IsSqlDw); // Expect the same returned result - Assert.True(CachedServerInfo.TryGetIsSqlDw("testDataSource", out isSqlDwResult)); + Assert.True(cache.TryGetIsSqlDw(testSource, out isSqlDwResult)); Assert.Equal(isSqlDwResult, state); } @@ -35,18 +88,22 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection { // Set sqlDw result into cache bool isSqlDwResult; - CachedServerInfo.AddOrUpdateCache("testDataSource", state, CachedServerInfo.CacheVariable.IsSqlDw); + SqlConnectionStringBuilder testSource = new SqlConnectionStringBuilder + { + DataSource = "testDataSource" + }; + cache.AddOrUpdateCache(testSource, state, CachedServerInfo.CacheVariable.IsSqlDw); // Expect the same returned result - Assert.True(CachedServerInfo.TryGetIsSqlDw("testDataSource", out isSqlDwResult)); + Assert.True(cache.TryGetIsSqlDw(testSource, out isSqlDwResult)); Assert.Equal(isSqlDwResult, state); // Toggle isSqlDw cache state bool isSqlDwResultToggle; - CachedServerInfo.AddOrUpdateCache("testDataSource", !state, CachedServerInfo.CacheVariable.IsSqlDw); + cache.AddOrUpdateCache(testSource, !state, CachedServerInfo.CacheVariable.IsSqlDw); // Expect the oppisite returned result - Assert.True(CachedServerInfo.TryGetIsSqlDw("testDataSource", out isSqlDwResultToggle)); + Assert.True(cache.TryGetIsSqlDw(testSource, out isSqlDwResultToggle)); Assert.Equal(isSqlDwResultToggle, !state); } @@ -55,19 +112,40 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection public void AddOrUpdateIsSqlDwFalseToggle() { bool state = true; + + SqlConnectionStringBuilder testSource = new SqlConnectionStringBuilder + { + DataSource = "testDataSource" + }; + + SqlConnectionStringBuilder sameServerDifferentDb = new SqlConnectionStringBuilder + { + DataSource = "testDataSource", + InitialCatalog = "myDb" + }; + SqlConnectionStringBuilder differentServerSameDb = new SqlConnectionStringBuilder + { + DataSource = "testDataSource2", + InitialCatalog = "" + }; + + cache.AddOrUpdateCache(testSource, state, CachedServerInfo.CacheVariable.IsSqlDw); + cache.AddOrUpdateCache(sameServerDifferentDb, !state, CachedServerInfo.CacheVariable.IsSqlDw); + cache.AddOrUpdateCache(differentServerSameDb, !state, CachedServerInfo.CacheVariable.IsSqlDw); + + // Expect the same returned result // Set sqlDw result into cache bool isSqlDwResult; bool isSqlDwResult2; - CachedServerInfo.AddOrUpdateCache("testDataSource", state, CachedServerInfo.CacheVariable.IsSqlDw); - CachedServerInfo.AddOrUpdateCache("testDataSource2", !state, CachedServerInfo.CacheVariable.IsSqlDw); - - // Expect the same returned result - Assert.True(CachedServerInfo.TryGetIsSqlDw("testDataSource", out isSqlDwResult)); - Assert.True(CachedServerInfo.TryGetIsSqlDw("testDataSource2", out isSqlDwResult2)); + bool isSqlDwResult3; + Assert.True(cache.TryGetIsSqlDw(testSource, out isSqlDwResult)); + Assert.True(cache.TryGetIsSqlDw(sameServerDifferentDb, out isSqlDwResult2)); + Assert.True(cache.TryGetIsSqlDw(differentServerSameDb, out isSqlDwResult3)); // Assert cache is set on a per connection basis Assert.Equal(isSqlDwResult, state); Assert.Equal(isSqlDwResult2, !state); + Assert.Equal(isSqlDwResult3, !state); } @@ -75,7 +153,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection public void AskforSqlDwBeforeCached() { bool isSqlDwResult; - Assert.False(CachedServerInfo.TryGetIsSqlDw("testDataSourceWithNoCache", out isSqlDwResult)); + Assert.False(cache.TryGetIsSqlDw(new SqlConnectionStringBuilder + { + DataSource = "testDataSourceUnCached" + }, + out isSqlDwResult)); } } } \ No newline at end of file