diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 05b3aa21..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-sudo: required
-dist: xenial
-
-os:
- - linux
-# TODO https://github.com/Microsoft/vscode-mssql/issues/1004 reenable OSX once travis issue is fixed
-# - osx
-
-mono: none
-dotnet: 5.0
-
-# safelist
-branches:
- only:
- - master
- - dev
-
-language: csharp
-solution: sqltoolsservice.sln
-
-env:
- # Since we are building from root, current directory is the project path
- - ProjectPath=$TRAVIS_BUILD_DIR
- - HOMEBREW_NO_AUTO_UPDATE=1
-before_install:
- - if [ $TRAVIS_OS_NAME == "linux" ]; then
- sudo apt-get update;
- sudo apt-get install dotnet-sdk-5.0;
- else
- brew update;
- fi
-
-install:
- - dotnet restore
-
-script:
- - dotnet build src/Microsoft.SqlTools.ServiceLayer
- - dotnet test test/Microsoft.SqlTools.ServiceLayer.UnitTests
- - dotnet build src/Microsoft.Kusto.ServiceLayer
- - dotnet test test/Microsoft.Kusto.ServiceLayer.UnitTests
- - dotnet build src/Microsoft.SqlTools.CoreServices
- - dotnet test test/Microsoft.SqlTools.Hosting.UnitTests
\ No newline at end of file
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/CancelTokenKey.cs b/external/Microsoft.SqlTools.CoreServices/Connection/CancelTokenKey.cs
deleted file mode 100644
index 63f2032a..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/CancelTokenKey.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.SqlTools.DataProtocol.Contracts.Connection;
-
-namespace Microsoft.SqlTools.CoreServices.Connection
-{
- ///
- /// Used to uniquely identify a CancellationTokenSource associated with both
- /// a string URI and a string connection type.
- ///
- public class CancelTokenKey : CancelConnectParams, IEquatable
- {
- public override bool Equals(object obj)
- {
- CancelTokenKey other = obj as CancelTokenKey;
- if (other == null)
- {
- return false;
- }
-
- return other.OwnerUri == OwnerUri && other.Type == Type;
- }
-
- public bool Equals(CancelTokenKey obj)
- {
- return obj.OwnerUri == OwnerUri && obj.Type == Type;
- }
-
- public override int GetHashCode()
- {
- return OwnerUri.GetHashCode() ^ Type.GetHashCode();
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ConnectParamsExtensions.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ConnectParamsExtensions.cs
deleted file mode 100644
index e2824e2d..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ConnectParamsExtensions.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using Microsoft.SqlTools.DataProtocol.Contracts.Connection;
-
-namespace Microsoft.SqlTools.CoreServices.Connection
-{
- ///
- /// Extension methods to ConnectParams
- ///
- public static class ConnectParamsExtensions
- {
- ///
- /// Check that the fields in ConnectParams are all valid
- ///
- public static bool IsValid(this ConnectParams parameters, out string errorMessage)
- {
- errorMessage = string.Empty;
- if (string.IsNullOrEmpty(parameters.OwnerUri))
- {
- errorMessage = SR.ConnectionParamsValidateNullOwnerUri;
- }
- else if (parameters.Connection == null)
- {
- errorMessage = SR.ConnectionParamsValidateNullConnection;
- }
- else if (!string.IsNullOrEmpty(parameters.Connection.ConnectionString))
- {
- // Do not check other connection parameters if a connection string is present
- return string.IsNullOrEmpty(errorMessage);
- }
- else if (string.IsNullOrEmpty(parameters.Connection.ServerName))
- {
- errorMessage = SR.ConnectionParamsValidateNullServerName;
- }
- else if (string.IsNullOrEmpty(parameters.Connection.AuthenticationType) || parameters.Connection.AuthenticationType == "SqlLogin")
- {
- // For SqlLogin, username cannot be empty
- if (string.IsNullOrEmpty(parameters.Connection.UserName))
- {
- errorMessage = SR.ConnectionParamsValidateNullSqlAuth("UserName");
- }
- }
-
- return string.IsNullOrEmpty(errorMessage);
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ConnectionInfo.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ConnectionInfo.cs
deleted file mode 100644
index 96aeeee3..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ConnectionInfo.cs
+++ /dev/null
@@ -1,171 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Data.Common;
-using Microsoft.SqlTools.DataProtocol.Contracts.Connection;
-using Microsoft.SqlTools.Hosting.Utility;
-
-namespace Microsoft.SqlTools.CoreServices.Connection
-{
- ///
- /// Information pertaining to a unique connection instance.
- ///
- public class ConnectionInfo
- {
- ///
- /// Constructor
- ///
- public ConnectionInfo(ISqlConnectionFactory factory, string ownerUri, ConnectionDetails details)
- {
- Factory = factory;
- OwnerUri = ownerUri;
- ConnectionDetails = details;
- ConnectionId = Guid.NewGuid();
- IntellisenseMetrics = new InteractionMetrics(new int[] {50, 100, 200, 500, 1000, 2000});
- }
-
- ///
- /// Unique Id, helpful to identify a connection info object
- ///
- public Guid ConnectionId { get; private set; }
-
- ///
- /// URI identifying the owner/user of the connection. Could be a file, service, resource, etc.
- ///
- public string OwnerUri { get; private set; }
-
- ///
- /// Factory used for creating the SQL connection associated with the connection info.
- ///
- public ISqlConnectionFactory Factory { get; private set; }
-
- ///
- /// Properties used for creating/opening the SQL connection.
- ///
- public ConnectionDetails ConnectionDetails { get; private set; }
-
- ///
- /// A map containing all connections to the database that are associated with
- /// this ConnectionInfo's OwnerUri.
- /// This is internal for testing access only
- ///
- internal readonly ConcurrentDictionary ConnectionTypeToConnectionMap =
- new ConcurrentDictionary();
-
- ///
- /// Intellisense Metrics
- ///
- public InteractionMetrics IntellisenseMetrics { get; private set; }
-
- ///
- /// Returns true if the db connection is to any cloud instance
- ///
- public bool IsCloud { get; set; }
-
- ///
- /// Returns true if the db connection is to a SQL db instance
- ///
- public bool IsSqlDb { get; set; }
-
- /// Returns true if the sql connection is to a DW instance
- ///
- public bool IsSqlDW { get; set; }
-
- ///
- /// Returns the major version number of the db we are connected to
- ///
- public int MajorVersion { get; set; }
-
- ///
- /// All DbConnection instances held by this ConnectionInfo
- ///
- public ICollection AllConnections
- {
- get
- {
- return ConnectionTypeToConnectionMap.Values;
- }
- }
-
- ///
- /// All connection type strings held by this ConnectionInfo
- ///
- ///
- public ICollection AllConnectionTypes
- {
- get
- {
- return ConnectionTypeToConnectionMap.Keys;
- }
- }
-
- public bool HasConnectionType(string connectionType)
- {
- connectionType = connectionType ?? ConnectionType.Default;
- return ConnectionTypeToConnectionMap.ContainsKey(connectionType);
- }
-
- ///
- /// The count of DbConnectioninstances held by this ConnectionInfo
- ///
- public int CountConnections
- {
- get
- {
- return ConnectionTypeToConnectionMap.Count;
- }
- }
-
- ///
- /// Try to get the DbConnection associated with the given connection type string.
- ///
- /// true if a connection with type connectionType was located and out connection was set,
- /// false otherwise
- /// Thrown when connectionType is null or empty
- public bool TryGetConnection(string connectionType, out DbConnection connection)
- {
- Validate.IsNotNullOrEmptyString("Connection Type", connectionType);
- return ConnectionTypeToConnectionMap.TryGetValue(connectionType, out connection);
- }
-
- ///
- /// Adds a DbConnection to this object and associates it with the given
- /// connection type string. If a connection already exists with an identical
- /// connection type string, it is not overwritten. Ignores calls where connectionType = null
- ///
- /// Thrown when connectionType is null or empty
- public void AddConnection(string connectionType, DbConnection connection)
- {
- Validate.IsNotNullOrEmptyString("Connection Type", connectionType);
- ConnectionTypeToConnectionMap.TryAdd(connectionType, connection);
- }
-
- ///
- /// Removes the single DbConnection instance associated with string connectionType
- ///
- /// Thrown when connectionType is null or empty
- public void RemoveConnection(string connectionType)
- {
- Validate.IsNotNullOrEmptyString("Connection Type", connectionType);
- DbConnection connection;
- ConnectionTypeToConnectionMap.TryRemove(connectionType, out connection);
- }
-
- ///
- /// Removes all DbConnection instances held by this object
- ///
- public void RemoveAllConnections()
- {
- foreach (var type in AllConnectionTypes)
- {
- DbConnection connection;
- ConnectionTypeToConnectionMap.TryRemove(type, out connection);
- }
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ConnectionServiceCore.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ConnectionServiceCore.cs
deleted file mode 100644
index 96a5ca6d..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ConnectionServiceCore.cs
+++ /dev/null
@@ -1,1317 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Data;
-using System.Data.Common;
-using Microsoft.Data.SqlClient;
-using System.Globalization;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.SqlTools.DataProtocol.Contracts.Connection;
-using Microsoft.SqlTools.CoreServices.Connection.ReliableConnection;
-using Microsoft.SqlTools.CoreServices.LanguageServices;
-using Microsoft.SqlServer.Management.Common;
-using Microsoft.SqlTools.Hosting.Utility;
-using Microsoft.SqlTools.Hosting;
-using Microsoft.SqlTools.Hosting.Protocol;
-using Microsoft.SqlTools.CoreServices.LanguageServices.Contracts;
-using ConnectionType = Microsoft.SqlTools.DataProtocol.Contracts.Connection.ConnectionType;
-using Microsoft.SqlTools.Hosting.Extensibility;
-using System.Composition;
-using System.Diagnostics;
-
-namespace Microsoft.SqlTools.CoreServices.Connection
-{
- ///
- /// Core Connection Management services, not including hosted service implementation
- ///
- [Export(typeof(ConnectionServiceCore))]
- public class ConnectionServiceCore : IComposableService
- {
- public const string AdminConnectionPrefix = "ADMIN:";
- private const string SqlAzureEdition = "SQL Azure";
-
-
- ///
- /// The SQL connection factory object
- ///
- private ISqlConnectionFactory connectionFactory;
-
- private DatabaseLocksManager lockedDatabaseManager;
-
- private readonly Dictionary ownerToConnectionMap = new Dictionary();
-
- ///
- /// A map containing all CancellationTokenSource objects that are associated with a given URI/ConnectionType pair.
- /// Entries in this map correspond to DbConnection instances that are in the process of connecting.
- ///
- private readonly ConcurrentDictionary cancelTupleToCancellationTokenSourceMap =
- new ConcurrentDictionary();
-
- private readonly object cancellationTokenSourceLock = new object();
-
- private ConcurrentDictionary connectedQueues = new ConcurrentDictionary();
-
- private IMultiServiceProvider serviceProvider;
-
- ///
- /// Default constructor should be private since it's a singleton class, but we need a constructor
- /// for use in unit test mocking.
- ///
- public ConnectionServiceCore()
- {
- var defaultQueue = new ConnectedBindingQueue(needsMetadata: false);
- connectedQueues.AddOrUpdate(ConnectionType.Default, defaultQueue, (key, old) => defaultQueue);
- this.LockedDatabaseManager.ConnectionService = this;
- }
-
- ///
- /// Test constructor that injects dependency interfaces
- ///
- ///
- public ConnectionServiceCore(ISqlConnectionFactory testFactory)
- {
- this.connectionFactory = testFactory;
- }
-
- public void SetServiceProvider(IMultiServiceProvider provider)
- {
- this.serviceProvider = provider;
- }
-
-
- ///
- /// Map from script URIs to ConnectionInfo objects
- /// This is internal for testing access only
- ///
- internal Dictionary OwnerToConnectionMap
- {
- get
- {
- return this.ownerToConnectionMap;
- }
- }
-
- ///
- /// Database Lock manager instance
- ///
- internal DatabaseLocksManager LockedDatabaseManager
- {
- get
- {
- if (lockedDatabaseManager == null)
- {
- lockedDatabaseManager = DatabaseLocksManager.Instance;
- }
- return lockedDatabaseManager;
- }
- set
- {
- this.lockedDatabaseManager = value;
- }
- }
-
- ///
- /// Gets the connection queue
- ///
- internal IConnectedBindingQueue ConnectionQueue
- {
- get
- {
- return this.GetConnectedQueue("Default");
- }
- }
-
- ///
- /// Returns a connection queue for given type
- ///
- ///
- ///
- public IConnectedBindingQueue GetConnectedQueue(string type)
- {
- IConnectedBindingQueue connectedBindingQueue;
- if (connectedQueues.TryGetValue(type, out connectedBindingQueue))
- {
- return connectedBindingQueue;
- }
- return null;
- }
-
- ///
- /// Returns all the connection queues
- ///
- public IEnumerable ConnectedQueues
- {
- get
- {
- return this.connectedQueues.Values;
- }
- }
-
- ///
- /// Register a new connection queue if not already registered
- ///
- ///
- ///
- public virtual void RegisterConnectedQueue(string type, IConnectedBindingQueue connectedQueue)
- {
- if (!connectedQueues.ContainsKey(type))
- {
- connectedQueues.AddOrUpdate(type, connectedQueue, (key, old) => connectedQueue);
- }
- }
-
- ///
- /// Callback for onconnection handler
- ///
- ///
- public delegate Task OnConnectionHandler(ConnectionInfo info);
-
- ///
- /// Callback for ondisconnect handler
- ///
- public delegate Task OnDisconnectHandler(IConnectionSummary summary, string ownerUri);
-
- ///
- /// List of onconnection handlers
- ///
- private readonly List onConnectionActivities = new List();
-
- ///
- /// List of ondisconnect handlers
- ///
- private readonly List onDisconnectActivities = new List();
-
- ///
- /// Gets the SQL connection factory instance
- ///
- public ISqlConnectionFactory ConnectionFactory
- {
- get
- {
- if (this.connectionFactory == null)
- {
- this.connectionFactory = new SqlConnectionFactory();
- }
- return this.connectionFactory;
- }
-
- internal set { this.connectionFactory = value; }
- }
-
- // Attempts to link a URI to an actively used connection for this URI
- public virtual bool TryFindConnection(string ownerUri, out ConnectionInfo connectionInfo)
- {
- return this.ownerToConnectionMap.TryGetValue(ownerUri, out connectionInfo);
- }
-
- ///
- /// Validates the given ConnectParams object.
- ///
- /// The params to validate
- /// A ConnectionCompleteParams object upon validation error,
- /// null upon validation success
- public ConnectionCompleteParams ValidateConnectParams(ConnectParams connectionParams)
- {
- string paramValidationErrorMessage;
- if (connectionParams == null)
- {
- return new ConnectionCompleteParams
- {
- Messages = SR.ConnectionServiceConnectErrorNullParams
- };
- }
- if (!connectionParams.IsValid(out paramValidationErrorMessage))
- {
- return new ConnectionCompleteParams
- {
- OwnerUri = connectionParams.OwnerUri,
- Messages = paramValidationErrorMessage
- };
- }
-
- // return null upon success
- return null;
- }
-
- ///
- /// Open a connection with the specified ConnectParams
- ///
- public virtual async Task Connect(ConnectParams connectionParams)
- {
- // Validate parameters
- ConnectionCompleteParams validationResults = ValidateConnectParams(connectionParams);
- if (validationResults != null)
- {
- return validationResults;
- }
-
- TrySetConnectionType(connectionParams);
-
- connectionParams.Connection.ApplicationName = GetApplicationNameWithFeature(connectionParams.Connection.ApplicationName, connectionParams.Purpose);
- // If there is no ConnectionInfo in the map, create a new ConnectionInfo,
- // but wait until later when we are connected to add it to the map.
- ConnectionInfo connectionInfo;
- bool connectionChanged = false;
- if (!ownerToConnectionMap.TryGetValue(connectionParams.OwnerUri, out connectionInfo))
- {
- connectionInfo = new ConnectionInfo(ConnectionFactory, connectionParams.OwnerUri, connectionParams.Connection);
- }
- else if (IsConnectionChanged(connectionParams, connectionInfo))
- {
- // We are actively changing the connection information for this connection. We must disconnect
- // all active connections, since it represents a full context change
- connectionChanged = true;
- }
-
- DisconnectExistingConnectionIfNeeded(connectionParams, connectionInfo, disconnectAll: connectionChanged);
-
- if (connectionChanged)
- {
- connectionInfo = new ConnectionInfo(ConnectionFactory, connectionParams.OwnerUri, connectionParams.Connection);
- }
-
- // Try to open a connection with the given ConnectParams
- ConnectionCompleteParams response = await TryOpenConnection(connectionInfo, connectionParams);
- if (response != null)
- {
- return response;
- }
-
- // If this is the first connection for this URI, add the ConnectionInfo to the map
- bool addToMap = connectionChanged || !ownerToConnectionMap.ContainsKey(connectionParams.OwnerUri);
- if (addToMap)
- {
- ownerToConnectionMap[connectionParams.OwnerUri] = connectionInfo;
- }
-
- // Return information about the connected SQL Server instance
- ConnectionCompleteParams completeParams = GetConnectionCompleteParams(connectionParams.Type, connectionInfo);
- // Invoke callback notifications
- InvokeOnConnectionActivities(connectionInfo, connectionParams);
-
- TryCloseConnectionTemporaryConnection(connectionParams, connectionInfo);
-
- return completeParams;
- }
-
- private void TryCloseConnectionTemporaryConnection(ConnectParams connectionParams, ConnectionInfo connectionInfo)
- {
- try
- {
- if (connectionParams.Purpose == ConnectionType.ObjectExplorer || connectionParams.Purpose == ConnectionType.Dashboard || connectionParams.Purpose == ConnectionType.GeneralConnection)
- {
- DbConnection connection;
- string type = connectionParams.Type;
- if (connectionInfo.TryGetConnection(type, out connection))
- {
- // OE doesn't need to keep the connection open
- connection.Close();
- }
- }
- }
- catch (Exception ex)
- {
- Logger.Write(TraceEventType.Information, "Failed to close temporary connections. error: " + ex.Message);
- }
- }
-
- private static string GetApplicationNameWithFeature(string applicationName, string featureName)
- {
- string appNameWithFeature = applicationName;
-
- if (!string.IsNullOrWhiteSpace(applicationName) && !string.IsNullOrWhiteSpace(featureName))
- {
- int index = applicationName.IndexOf('-');
- string appName = applicationName;
- if (index > 0)
- {
- appName = applicationName.Substring(0, index);
- }
- appNameWithFeature = $"{appName}-{featureName}";
- }
-
- return appNameWithFeature;
- }
-
- private void TrySetConnectionType(ConnectParams connectionParams)
- {
- if (connectionParams != null && connectionParams.Type == ConnectionType.Default && !string.IsNullOrWhiteSpace(connectionParams.OwnerUri))
- {
- if (connectionParams.OwnerUri.ToLowerInvariant().StartsWith("dashboard://"))
- {
- connectionParams.Purpose = ConnectionType.Dashboard;
- }
- else if (connectionParams.OwnerUri.ToLowerInvariant().StartsWith("connection://"))
- {
- connectionParams.Purpose = ConnectionType.GeneralConnection;
- }
- }
- else if (connectionParams != null)
- {
- connectionParams.Purpose = connectionParams.Type;
- }
- }
-
- private bool IsConnectionChanged(ConnectParams connectionParams, ConnectionInfo connectionInfo)
- {
- if (connectionInfo.HasConnectionType(connectionParams.Type)
- && !connectionInfo.ConnectionDetails.IsComparableTo(connectionParams.Connection))
- {
- return true;
- }
- return false;
- }
-
- private bool IsDefaultConnectionType(string connectionType)
- {
- return string.IsNullOrEmpty(connectionType) || ConnectionType.Default.Equals(connectionType, StringComparison.CurrentCultureIgnoreCase);
- }
-
- private void DisconnectExistingConnectionIfNeeded(ConnectParams connectionParams, ConnectionInfo connectionInfo, bool disconnectAll)
- {
- // Resolve if it is an existing connection
- // Disconnect active connection if the URI is already connected for this connection type
- DbConnection existingConnection;
- if (connectionInfo.TryGetConnection(connectionParams.Type, out existingConnection))
- {
- var disconnectParams = new DisconnectParams()
- {
- OwnerUri = connectionParams.OwnerUri,
- Type = disconnectAll ? null : connectionParams.Type
- };
- Disconnect(disconnectParams);
- }
- }
-
- ///
- /// Creates a ConnectionCompleteParams as a response to a successful connection.
- /// Also sets the DatabaseName and IsAzure properties of ConnectionInfo.
- ///
- /// A ConnectionCompleteParams in response to the successful connection
- private ConnectionCompleteParams GetConnectionCompleteParams(string connectionType, ConnectionInfo connectionInfo)
- {
- ConnectionCompleteParams response = new ConnectionCompleteParams { OwnerUri = connectionInfo.OwnerUri, Type = connectionType };
-
- try
- {
- DbConnection connection;
- connectionInfo.TryGetConnection(connectionType, out connection);
-
- // Update with the actual database name in connectionInfo and result
- // Doing this here as we know the connection is open - expect to do this only on connecting
- connectionInfo.ConnectionDetails.DatabaseName = connection.Database;
- if (!string.IsNullOrEmpty(connectionInfo.ConnectionDetails.ConnectionString))
- {
- // If the connection was set up with a connection string, use the connection string to get the details
- var connectionString = new SqlConnectionStringBuilder(connection.ConnectionString);
- response.ConnectionSummary = new ConnectionSummary
- {
- ServerName = connectionString.DataSource,
- DatabaseName = connectionString.InitialCatalog,
- UserName = connectionString.UserID
- };
- }
- else
- {
- response.ConnectionSummary = new ConnectionSummary
- {
- ServerName = connectionInfo.ConnectionDetails.ServerName,
- DatabaseName = connectionInfo.ConnectionDetails.DatabaseName,
- UserName = connectionInfo.ConnectionDetails.UserName
- };
- }
-
- response.ConnectionId = connectionInfo.ConnectionId.ToString();
-
- var reliableConnection = connection as ReliableSqlConnection;
- DbConnection underlyingConnection = reliableConnection != null
- ? reliableConnection.GetUnderlyingConnection()
- : connection;
-
- ReliableConnectionHelper.ServerInfo serverInfo = ReliableConnectionHelper.GetServerVersion(underlyingConnection);
- response.ServerInfo = new ServerInfo
- {
- ServerMajorVersion = serverInfo.ServerMajorVersion,
- ServerMinorVersion = serverInfo.ServerMinorVersion,
- ServerReleaseVersion = serverInfo.ServerReleaseVersion,
- EngineEditionId = serverInfo.EngineEditionId,
- ServerVersion = serverInfo.ServerVersion,
- ServerLevel = serverInfo.ServerLevel,
- ServerEdition = MapServerEdition(serverInfo),
- IsCloud = serverInfo.IsCloud,
- AzureVersion = serverInfo.AzureVersion,
- OsVersion = serverInfo.OsVersion,
- MachineName = serverInfo.MachineName
- };
- connectionInfo.IsCloud = serverInfo.IsCloud;
- connectionInfo.MajorVersion = serverInfo.ServerMajorVersion;
- connectionInfo.IsSqlDb = serverInfo.EngineEditionId == (int)DatabaseEngineEdition.SqlDatabase;
- connectionInfo.IsSqlDW = (serverInfo.EngineEditionId == (int)DatabaseEngineEdition.SqlDataWarehouse);
- }
- catch (Exception ex)
- {
- response.Messages = ex.ToString();
- }
-
- return response;
- }
-
- private string MapServerEdition(ReliableConnectionHelper.ServerInfo serverInfo)
- {
- string serverEdition = serverInfo.ServerEdition;
- if (string.IsNullOrWhiteSpace(serverEdition))
- {
- return string.Empty;
- }
- if (SqlAzureEdition.Equals(serverEdition, StringComparison.OrdinalIgnoreCase))
- {
- switch(serverInfo.EngineEditionId)
- {
- case (int) DatabaseEngineEdition.SqlDataWarehouse:
- serverEdition = SR.AzureSqlDwEdition;
- break;
- case (int)DatabaseEngineEdition.SqlStretchDatabase:
- serverEdition = SR.AzureSqlStretchEdition;
- break;
- case (int)DatabaseEngineEdition.SqlOnDemand:
- serverEdition = SR.AzureSqlAnalyticsOnDemandEdition;
- break;
- default:
- serverEdition = SR.AzureSqlDbEdition;
- break;
- }
- }
- return serverEdition;
- }
-
- ///
- /// Tries to create and open a connection with the given ConnectParams.
- ///
- /// null upon success, a ConnectionCompleteParams detailing the error upon failure
- private async Task TryOpenConnection(ConnectionInfo connectionInfo, ConnectParams connectionParams)
- {
- CancellationTokenSource source = null;
- DbConnection connection = null;
- CancelTokenKey cancelKey = new CancelTokenKey { OwnerUri = connectionParams.OwnerUri, Type = connectionParams.Type };
- ConnectionCompleteParams response = new ConnectionCompleteParams { OwnerUri = connectionInfo.OwnerUri, Type = connectionParams.Type };
- bool? currentPooling = connectionInfo.ConnectionDetails.Pooling;
-
- try
- {
- connectionInfo.ConnectionDetails.Pooling = false;
- // build the connection string from the input parameters
- string connectionString = BuildConnectionString(connectionInfo.ConnectionDetails);
-
- // create a sql connection instance
- connection = connectionInfo.Factory.CreateSqlConnection(connectionString);
- connectionInfo.AddConnection(connectionParams.Type, connection);
-
- // Add a cancellation token source so that the connection OpenAsync() can be cancelled
- source = new CancellationTokenSource();
- // Locking here to perform two operations as one atomic operation
- lock (cancellationTokenSourceLock)
- {
- // If the URI is currently connecting from a different request, cancel it before we try to connect
- CancellationTokenSource currentSource;
- if (cancelTupleToCancellationTokenSourceMap.TryGetValue(cancelKey, out currentSource))
- {
- currentSource.Cancel();
- }
- cancelTupleToCancellationTokenSourceMap[cancelKey] = source;
- }
-
- // Open the connection
- await connection.OpenAsync(source.Token);
- }
- catch (SqlException ex)
- {
- response.ErrorNumber = ex.Number;
- response.ErrorMessage = ex.Message;
- response.Messages = ex.ToString();
- return response;
- }
- catch (OperationCanceledException)
- {
- // OpenAsync was cancelled
- response.Messages = SR.ConnectionServiceConnectionCanceled;
- return response;
- }
- catch (Exception ex)
- {
- response.ErrorMessage = ex.Message;
- response.Messages = ex.ToString();
- return response;
- }
- finally
- {
- // Remove our cancellation token from the map since we're no longer connecting
- // Using a lock here to perform two operations as one atomic operation
- lock (cancellationTokenSourceLock)
- {
- // Only remove the token from the map if it is the same one created by this request
- CancellationTokenSource sourceValue;
- if (cancelTupleToCancellationTokenSourceMap.TryGetValue(cancelKey, out sourceValue) && sourceValue == source)
- {
- cancelTupleToCancellationTokenSourceMap.TryRemove(cancelKey, out sourceValue);
- }
- source?.Dispose();
- }
- if (connectionInfo != null && connectionInfo.ConnectionDetails != null)
- {
- connectionInfo.ConnectionDetails.Pooling = currentPooling;
- }
- }
-
- // Return null upon success
- return null;
- }
-
- ///
- /// Gets the existing connection with the given URI and connection type string. If none exists,
- /// creates a new connection. This cannot be used to create a default connection or to create a
- /// connection if a default connection does not exist.
- ///
- /// URI identifying the resource mapped to this connection
- ///
- /// What the purpose for this connection is. A single resource
- /// such as a SQL file may have multiple connections - one for Intellisense, another for query execution
- ///
- ///
- /// Workaround for .Net Core clone connection issues: should persist security be used so that
- /// when SMO clones connections it can do so without breaking on SQL Password connections.
- /// This should be removed once the core issue is resolved and clone works as expected
- ///
- /// A DB connection for the connection type requested
- public virtual async Task GetOrOpenConnection(string ownerUri, string connectionType, bool alwaysPersistSecurity = false)
- {
- Validate.IsNotNullOrEmptyString(nameof(ownerUri), ownerUri);
- Validate.IsNotNullOrEmptyString(nameof(connectionType), connectionType);
-
- // Try to get the ConnectionInfo, if it exists
- ConnectionInfo connectionInfo;
- if (!ownerToConnectionMap.TryGetValue(ownerUri, out connectionInfo))
- {
- throw new ArgumentOutOfRangeException(SR.ConnectionServiceListDbErrorNotConnected(ownerUri));
- }
-
- // Make sure a default connection exists
- DbConnection connection;
- DbConnection defaultConnection;
- if (!connectionInfo.TryGetConnection(ConnectionType.Default, out defaultConnection))
- {
- throw new InvalidOperationException(SR.ConnectionServiceDbErrorDefaultNotConnected(ownerUri));
- }
-
- if(IsDedicatedAdminConnection(connectionInfo.ConnectionDetails))
- {
- // Since this is a dedicated connection only 1 is allowed at any time. Return the default connection for use in the requested action
- connection = defaultConnection;
- }
- else
- {
- // Try to get the DbConnection and create if it doesn't already exist
- if (!connectionInfo.TryGetConnection(connectionType, out connection) && ConnectionType.Default != connectionType)
- {
- connection = await TryOpenConnectionForConnectionType(ownerUri, connectionType, alwaysPersistSecurity, connectionInfo);
- }
- }
-
- VerifyConnectionOpen(connection);
-
- return connection;
- }
-
- private async Task TryOpenConnectionForConnectionType(string ownerUri, string connectionType,
- bool alwaysPersistSecurity, ConnectionInfo connectionInfo)
- {
- // If the DbConnection does not exist and is not the default connection, create one.
- // We can't create the default (initial) connection here because we won't have a ConnectionDetails
- // if Connect() has not yet been called.
- bool? originalPersistSecurityInfo = connectionInfo.ConnectionDetails.PersistSecurityInfo;
- if (alwaysPersistSecurity)
- {
- connectionInfo.ConnectionDetails.PersistSecurityInfo = true;
- }
- ConnectParams connectParams = new ConnectParams
- {
- OwnerUri = ownerUri,
- Connection = connectionInfo.ConnectionDetails,
- Type = connectionType
- };
- try
- {
- await Connect(connectParams);
- }
- finally
- {
- connectionInfo.ConnectionDetails.PersistSecurityInfo = originalPersistSecurityInfo;
- }
-
- DbConnection connection;
- connectionInfo.TryGetConnection(connectionType, out connection);
- return connection;
- }
-
- private void VerifyConnectionOpen(DbConnection connection)
- {
- if (connection == null)
- {
- // Ignore this connection
- return;
- }
-
- if (connection.State != ConnectionState.Open)
- {
- // Note: this will fail and throw to the caller if something goes wrong.
- // This seems the right thing to do but if this causes serviceability issues where stack trace
- // is unexpected, might consider catching and allowing later code to fail. But given we want to get
- // an opened connection for any action using this, it seems OK to handle in this manner
- ClearPool(connection);
- connection.Open();
- }
- }
-
- ///
- /// Clears the connection pool if this is a SqlConnection of some kind.
- ///
- private void ClearPool(DbConnection connection)
- {
- SqlConnection sqlConn;
- if (TryGetAsSqlConnection(connection, out sqlConn))
- {
- SqlConnection.ClearPool(sqlConn);
- }
- }
-
- private bool TryGetAsSqlConnection(DbConnection dbConn, out SqlConnection sqlConn)
- {
- ReliableSqlConnection reliableConn = dbConn as ReliableSqlConnection;
- if (reliableConn != null)
- {
- sqlConn = reliableConn.GetUnderlyingConnection();
- }
- else
- {
- sqlConn = dbConn as SqlConnection;
- }
-
- return sqlConn != null;
- }
-
- ///
- /// Cancel a connection that is in the process of opening.
- ///
- public bool CancelConnect(CancelConnectParams cancelParams)
- {
- // Validate parameters
- if (cancelParams == null || string.IsNullOrEmpty(cancelParams.OwnerUri))
- {
- return false;
- }
-
- CancelTokenKey cancelKey = new CancelTokenKey
- {
- OwnerUri = cancelParams.OwnerUri,
- Type = cancelParams.Type
- };
-
- // Cancel any current connection attempts for this URI
- CancellationTokenSource source;
- if (cancelTupleToCancellationTokenSourceMap.TryGetValue(cancelKey, out source))
- {
- try
- {
- source.Cancel();
- return true;
- }
- catch
- {
- return false;
- }
- }
-
- return false;
- }
-
- ///
- /// Close a connection with the specified connection details.
- ///
- public virtual bool Disconnect(DisconnectParams disconnectParams)
- {
- // Validate parameters
- if (disconnectParams == null || string.IsNullOrEmpty(disconnectParams.OwnerUri))
- {
- return false;
- }
-
- // Cancel if we are in the middle of connecting
- if (CancelConnections(disconnectParams.OwnerUri, disconnectParams.Type))
- {
- return false;
- }
-
- // Lookup the ConnectionInfo owned by the URI
- ConnectionInfo info;
- if (!ownerToConnectionMap.TryGetValue(disconnectParams.OwnerUri, out info))
- {
- return false;
- }
-
- // Call Close() on the connections we want to disconnect
- // If no connections were located, return false
- if (!CloseConnections(info, disconnectParams.Type))
- {
- return false;
- }
-
- // Remove the disconnected connections from the ConnectionInfo map
- if (disconnectParams.Type == null)
- {
- info.RemoveAllConnections();
- }
- else
- {
- info.RemoveConnection(disconnectParams.Type);
- }
-
- // If the ConnectionInfo has no more connections, remove the ConnectionInfo
- if (info.CountConnections == 0)
- {
- ownerToConnectionMap.Remove(disconnectParams.OwnerUri);
- }
-
- // Handle Telemetry disconnect events if we are disconnecting the default connection
- if (disconnectParams.Type == null || disconnectParams.Type == ConnectionType.Default)
- {
- HandleDisconnectTelemetry(info);
- InvokeOnDisconnectionActivities(info);
- }
-
- // Return true upon success
- return true;
- }
-
- ///
- /// Cancel connections associated with the given ownerUri.
- /// If connectionType is not null, cancel the connection with the given connectionType
- /// If connectionType is null, cancel all pending connections associated with ownerUri.
- ///
- /// true if a single pending connection associated with the non-null connectionType was
- /// found and cancelled, false otherwise
- private bool CancelConnections(string ownerUri, string connectionType)
- {
- // Cancel the connection of the given type
- if (connectionType != null)
- {
- // If we are trying to disconnect a specific connection and it was just cancelled,
- // this will return true
- return CancelConnect(new CancelConnectParams() { OwnerUri = ownerUri, Type = connectionType });
- }
-
- // Cancel all pending connections
- foreach (var entry in cancelTupleToCancellationTokenSourceMap)
- {
- string entryConnectionUri = entry.Key.OwnerUri;
- string entryConnectionType = entry.Key.Type;
- if (ownerUri.Equals(entryConnectionUri))
- {
- CancelConnect(new CancelConnectParams() { OwnerUri = ownerUri, Type = entryConnectionType });
- }
- }
-
- return false;
- }
-
- ///
- /// Closes DbConnections associated with the given ConnectionInfo.
- /// If connectionType is not null, closes the DbConnection with the type given by connectionType.
- /// If connectionType is null, closes all DbConnections.
- ///
- /// true if connections were found and attempted to be closed,
- /// false if no connections were found
- private bool CloseConnections(ConnectionInfo connectionInfo, string connectionType)
- {
- ICollection connectionsToDisconnect = new List();
- if (connectionType == null)
- {
- connectionsToDisconnect = connectionInfo.AllConnections;
- }
- else
- {
- // Make sure there is an existing connection of this type
- DbConnection connection;
- if (!connectionInfo.TryGetConnection(connectionType, out connection))
- {
- return false;
- }
- connectionsToDisconnect.Add(connection);
- }
-
- if (connectionsToDisconnect.Count == 0)
- {
- return false;
- }
-
- foreach (DbConnection connection in connectionsToDisconnect)
- {
- try
- {
- connection.Close();
- }
- catch (Exception)
- {
- // Ignore
- }
- }
-
- return true;
- }
-
- ///
- /// List all databases on the server specified
- ///
- public ListDatabasesResponse ListDatabases(ListDatabasesParams listDatabasesParams)
- {
- // Verify parameters
- var owner = listDatabasesParams.OwnerUri;
- if (string.IsNullOrEmpty(owner))
- {
- throw new ArgumentException(SR.ConnectionServiceListDbErrorNullOwnerUri);
- }
-
- // Use the existing connection as a base for the search
- ConnectionInfo info;
- if (!TryFindConnection(owner, out info))
- {
- throw new Exception(SR.ConnectionServiceListDbErrorNotConnected(owner));
- }
-
- ListDatabasesResponse response = new ListDatabasesResponse();
- response.DatabaseNames = ListDatabasesFromConnInfo(info);
-
- return response;
- }
-
- public string[] ListDatabasesFromConnInfo(ConnectionInfo info, bool includeSystemDBs = true)
- {
- ConnectionDetails connectionDetails = info.ConnectionDetails.Clone();
-
- // Connect to master and query sys.databases
- connectionDetails.DatabaseName = "master";
- List dbNames = new List();
-
- using (DbConnection connection = this.ConnectionFactory.CreateSqlConnection(BuildConnectionString(connectionDetails)))
- using (DbCommand command = connection.CreateCommand())
- {
- connection.Open();
- command.CommandText = @"SELECT name FROM sys.databases WHERE state_desc='ONLINE' ORDER BY name ASC";
- command.CommandTimeout = 15;
- command.CommandType = CommandType.Text;
-
- using (DbDataReader reader = command.ExecuteReader())
- {
- while (reader.Read())
- {
- dbNames.Add(reader[0].ToString());
- }
- }
- }
-
- string[] results;
- var systemDBSet = new HashSet(new[] {"master", "model", "msdb", "tempdb", "DWConfiguration", "DWDiagnostics", "DWQueue"});
- if (includeSystemDBs)
- {
- // Put system databases at the top of the list
- results =
- dbNames.Where(s => systemDBSet.Contains(s))
- .Concat(dbNames.Where(s => !systemDBSet.Contains(s)))
- .ToArray();
- }
- else
- {
- results = dbNames.Where(s => !systemDBSet.Contains(s)).ToArray();
- }
-
- return results;
- }
-
- ///
- /// Add a new method to be called when the onconnection request is submitted
- ///
- ///
- public void RegisterOnConnectionTask(OnConnectionHandler activity)
- {
- onConnectionActivities.Add(activity);
- }
-
- ///
- /// Add a new method to be called when the ondisconnect request is submitted
- ///
- public void RegisterOnDisconnectTask(OnDisconnectHandler activity)
- {
- onDisconnectActivities.Add(activity);
- }
-
- ///
- /// Checks if a ConnectionDetails object represents a DAC connection
- ///
- ///
- public static bool IsDedicatedAdminConnection(ConnectionDetails connectionDetails)
- {
- Validate.IsNotNull(nameof(connectionDetails), connectionDetails);
- SqlConnectionStringBuilder builder = CreateConnectionStringBuilder(connectionDetails);
- string serverName = builder.DataSource;
- return serverName != null && serverName.StartsWith(AdminConnectionPrefix, StringComparison.OrdinalIgnoreCase);
- }
-
- ///
- /// Build a connection string from a connection details instance
- ///
- ///
- public static string BuildConnectionString(ConnectionDetails connectionDetails)
- {
- return CreateConnectionStringBuilder(connectionDetails).ToString();
- }
-
- ///
- /// Build a connection string builder a connection details instance
- ///
- ///
- public static SqlConnectionStringBuilder CreateConnectionStringBuilder(ConnectionDetails connectionDetails)
- {
- SqlConnectionStringBuilder connectionBuilder;
-
- // If connectionDetails has a connection string already, use it to initialize the connection builder, then override any provided options.
- // Otherwise use the server name, username, and password from the connection details.
- if (!string.IsNullOrEmpty(connectionDetails.ConnectionString))
- {
- connectionBuilder = new SqlConnectionStringBuilder(connectionDetails.ConnectionString);
- }
- else
- {
- // add alternate port to data source property if provided
- string dataSource = !connectionDetails.Port.HasValue
- ? connectionDetails.ServerName
- : string.Format("{0},{1}", connectionDetails.ServerName, connectionDetails.Port.Value);
-
- connectionBuilder = new SqlConnectionStringBuilder
- {
- ["Data Source"] = dataSource,
- ["User Id"] = connectionDetails.UserName,
- ["Password"] = connectionDetails.Password
- };
- }
-
- // Check for any optional parameters
- if (!string.IsNullOrEmpty(connectionDetails.DatabaseName))
- {
- connectionBuilder["Initial Catalog"] = connectionDetails.DatabaseName;
- }
- if (!string.IsNullOrEmpty(connectionDetails.AuthenticationType))
- {
- switch(connectionDetails.AuthenticationType)
- {
- case "Integrated":
- connectionBuilder.IntegratedSecurity = true;
- break;
- case "SqlLogin":
- break;
- case "ActiveDirectoryPassword":
- connectionBuilder.Authentication = SqlAuthenticationMethod.ActiveDirectoryPassword;
- break;
- default:
- throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAuthType(connectionDetails.AuthenticationType));
- }
- }
- if (connectionDetails.Encrypt.HasValue)
- {
- connectionBuilder.Encrypt = connectionDetails.Encrypt.Value;
- }
- if (connectionDetails.TrustServerCertificate.HasValue)
- {
- connectionBuilder.TrustServerCertificate = connectionDetails.TrustServerCertificate.Value;
- }
- if (connectionDetails.PersistSecurityInfo.HasValue)
- {
- connectionBuilder.PersistSecurityInfo = connectionDetails.PersistSecurityInfo.Value;
- }
- if (connectionDetails.ConnectTimeout.HasValue)
- {
- connectionBuilder.ConnectTimeout = connectionDetails.ConnectTimeout.Value;
- }
- if (connectionDetails.ConnectRetryCount.HasValue)
- {
- connectionBuilder.ConnectRetryCount = connectionDetails.ConnectRetryCount.Value;
- }
- if (connectionDetails.ConnectRetryInterval.HasValue)
- {
- connectionBuilder.ConnectRetryInterval = connectionDetails.ConnectRetryInterval.Value;
- }
- if (!string.IsNullOrEmpty(connectionDetails.ApplicationName))
- {
- connectionBuilder.ApplicationName = connectionDetails.ApplicationName;
- }
- if (!string.IsNullOrEmpty(connectionDetails.WorkstationId))
- {
- connectionBuilder.WorkstationID = connectionDetails.WorkstationId;
- }
- if (!string.IsNullOrEmpty(connectionDetails.ApplicationIntent))
- {
- ApplicationIntent intent;
- switch (connectionDetails.ApplicationIntent)
- {
- case "ReadOnly":
- intent = ApplicationIntent.ReadOnly;
- break;
- case "ReadWrite":
- intent = ApplicationIntent.ReadWrite;
- break;
- default:
- throw new ArgumentException(SR.ConnectionServiceConnStringInvalidIntent(connectionDetails.ApplicationIntent));
- }
- connectionBuilder.ApplicationIntent = intent;
- }
- if (!string.IsNullOrEmpty(connectionDetails.CurrentLanguage))
- {
- connectionBuilder.CurrentLanguage = connectionDetails.CurrentLanguage;
- }
- if (connectionDetails.Pooling.HasValue)
- {
- connectionBuilder.Pooling = connectionDetails.Pooling.Value;
- }
- if (connectionDetails.MaxPoolSize.HasValue)
- {
- connectionBuilder.MaxPoolSize = connectionDetails.MaxPoolSize.Value;
- }
- if (connectionDetails.MinPoolSize.HasValue)
- {
- connectionBuilder.MinPoolSize = connectionDetails.MinPoolSize.Value;
- }
- if (connectionDetails.LoadBalanceTimeout.HasValue)
- {
- connectionBuilder.LoadBalanceTimeout = connectionDetails.LoadBalanceTimeout.Value;
- }
- if (connectionDetails.Replication.HasValue)
- {
- connectionBuilder.Replication = connectionDetails.Replication.Value;
- }
- if (!string.IsNullOrEmpty(connectionDetails.AttachDbFilename))
- {
- connectionBuilder.AttachDBFilename = connectionDetails.AttachDbFilename;
- }
- if (!string.IsNullOrEmpty(connectionDetails.FailoverPartner))
- {
- connectionBuilder.FailoverPartner = connectionDetails.FailoverPartner;
- }
- if (connectionDetails.MultiSubnetFailover.HasValue)
- {
- connectionBuilder.MultiSubnetFailover = connectionDetails.MultiSubnetFailover.Value;
- }
- if (connectionDetails.MultipleActiveResultSets.HasValue)
- {
- connectionBuilder.MultipleActiveResultSets = connectionDetails.MultipleActiveResultSets.Value;
- }
- if (connectionDetails.PacketSize.HasValue)
- {
- connectionBuilder.PacketSize = connectionDetails.PacketSize.Value;
- }
- if (!string.IsNullOrEmpty(connectionDetails.TypeSystemVersion))
- {
- connectionBuilder.TypeSystemVersion = connectionDetails.TypeSystemVersion;
- }
- connectionBuilder.Pooling = false;
-
- return connectionBuilder;
- }
-
- ///
- /// Change the database context of a connection.
- ///
- /// URI of the owner of the connection
- /// Name of the database to change the connection to
- public bool ChangeConnectionDatabaseContext(string ownerUri, string newDatabaseName, bool force = false)
- {
- ConnectionInfo info;
- if (TryFindConnection(ownerUri, out info))
- {
- try
- {
- info.ConnectionDetails.DatabaseName = newDatabaseName;
-
- foreach (string key in info.AllConnectionTypes)
- {
- DbConnection conn;
- info.TryGetConnection(key, out conn);
- if (conn != null && conn.Database != newDatabaseName && conn.State == ConnectionState.Open)
- {
- if (info.IsCloud && force)
- {
- conn.Close();
- conn.Dispose();
- info.RemoveConnection(key);
-
- string connectionString = BuildConnectionString(info.ConnectionDetails);
-
- // create a sql connection instance
- DbConnection connection = info.Factory.CreateSqlConnection(connectionString);
- connection.Open();
- info.AddConnection(key, connection);
- }
- else
- {
- conn.ChangeDatabase(newDatabaseName);
- }
- }
-
- }
-
- // Fire a connection changed event
- ConnectionChangedParams parameters = new ConnectionChangedParams();
- IConnectionSummary summary = info.ConnectionDetails;
- parameters.Connection = summary.Clone();
- parameters.OwnerUri = ownerUri;
- SendUsingServiceHost((host) => host.SendEvent(ConnectionChangedNotification.Type, parameters));
- return true;
- }
- catch (Exception e)
- {
- Logger.Write(
- TraceEventType.Error,
- string.Format(
- "Exception caught while trying to change database context to [{0}] for OwnerUri [{1}]. Exception:{2}",
- newDatabaseName,
- ownerUri,
- e.ToString())
- );
- }
- }
- return false;
- }
-
- ///
- /// Invokes an action on the service host, if the host exists
- ///
- private void SendUsingServiceHost(Action send)
- {
- var serviceHost = serviceProvider.GetService();
- if (serviceHost != null)
- {
- send(serviceHost);
- }
- }
-
- ///
- /// Invokes the initial on-connect activities if the provided ConnectParams represents the default
- /// connection.
- ///
- private void InvokeOnConnectionActivities(ConnectionInfo connectionInfo, ConnectParams connectParams)
- {
- if (connectParams.Type != ConnectionType.Default && connectParams.Type != ConnectionType.GeneralConnection)
- {
- return;
- }
-
- foreach (var activity in this.onConnectionActivities)
- {
- // not awaiting here to allow handlers to run in the background
- activity(connectionInfo);
- }
- }
-
- ///
- /// Invokes the final on-disconnect activities if the provided DisconnectParams represents the default
- /// connection or is null - representing that all connections are being disconnected.
- ///
- private void InvokeOnDisconnectionActivities(ConnectionInfo connectionInfo)
- {
- foreach (var activity in this.onDisconnectActivities)
- {
- activity(connectionInfo.ConnectionDetails, connectionInfo.OwnerUri);
- }
- }
-
- ///
- /// Handles the Telemetry events that occur upon disconnect.
- ///
- ///
- private void HandleDisconnectTelemetry(ConnectionInfo connectionInfo)
- {
- SendUsingServiceHost(host => {
- try
- {
- // Send a telemetry notification for intellisense performance metrics
- host.SendEvent(TelemetryNotification.Type, new TelemetryParams()
- {
- Params = new TelemetryProperties
- {
- Properties = new Dictionary
- {
- { TelemetryPropertyNames.IsAzure, connectionInfo.IsCloud.ToOneOrZeroString() }
- },
- EventName = TelemetryEventNames.IntellisenseQuantile,
- Measures = connectionInfo.IntellisenseMetrics.Quantile
- }
- });
- }
- catch (Exception ex)
- {
- Logger.Write(TraceEventType.Verbose, "Could not send Connection telemetry event " + ex.ToString());
- }
-
- });
- }
-
- ///
- /// Create and open a new SqlConnection from a ConnectionInfo object
- /// Note: we need to audit all uses of this method to determine why we're
- /// bypassing normal ConnectionService connection management
- ///
- internal static SqlConnection OpenSqlConnection(ConnectionInfo connInfo, string featureName = null)
- {
- try
- {
- // capture original values
- int? originalTimeout = connInfo.ConnectionDetails.ConnectTimeout;
- bool? originalPersistSecurityInfo = connInfo.ConnectionDetails.PersistSecurityInfo;
- bool? originalPooling = connInfo.ConnectionDetails.Pooling;
-
- // increase the connection timeout to at least 30 seconds and and build connection string
- connInfo.ConnectionDetails.ConnectTimeout = Math.Max(30, originalTimeout ?? 0);
- // enable PersistSecurityInfo to handle issues in SMO where the connection context is lost in reconnections
- connInfo.ConnectionDetails.PersistSecurityInfo = true;
- // turn off connection pool to avoid hold locks on server resources after calling SqlConnection Close method
- connInfo.ConnectionDetails.Pooling = false;
- connInfo.ConnectionDetails.ApplicationName = GetApplicationNameWithFeature(connInfo.ConnectionDetails.ApplicationName, featureName);
-
- // generate connection string
- string connectionString = ConnectionServiceCore.BuildConnectionString(connInfo.ConnectionDetails);
-
- // restore original values
- connInfo.ConnectionDetails.ConnectTimeout = originalTimeout;
- connInfo.ConnectionDetails.PersistSecurityInfo = originalPersistSecurityInfo;
- connInfo.ConnectionDetails.Pooling = originalPooling;
-
- // open a dedicated binding server connection
- SqlConnection sqlConn = new SqlConnection(connectionString);
- sqlConn.Open();
- return sqlConn;
- }
- catch (Exception ex)
- {
- string error = string.Format(CultureInfo.InvariantCulture,
- "Failed opening a SqlConnection: error:{0} inner:{1} stacktrace:{2}",
- ex.Message, ex.InnerException != null ? ex.InnerException.Message : string.Empty, ex.StackTrace);
- Logger.Write(TraceEventType.Error, error);
- }
-
- return null;
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ConnectionUtils.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ConnectionUtils.cs
deleted file mode 100644
index 534b2b4e..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ConnectionUtils.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-
-using System.Data.Common;
-using Microsoft.Data.SqlClient;
-using Microsoft.SqlTools.CoreServices.Connection.ReliableConnection;
-
-public static class ConnectionUtils
-{
- public static SqlConnection GetAsSqlConnection(DbConnection connection)
- {
- SqlConnection sqlConn = connection as SqlConnection;
- if (sqlConn == null)
- {
- // It's not actually a SqlConnection, so let's try a reliable SQL connection
- ReliableSqlConnection reliableConn = connection as ReliableSqlConnection;
- if (reliableConn == null)
- {
- // If we don't have connection we can use with SMO, just give up on using SMO
- return null;
- }
-
- // We have a reliable connection, use the underlying connection
- sqlConn = reliableConn.GetUnderlyingConnection();
- }
- return sqlConn;
- }
-}
\ No newline at end of file
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/DatabaseFullAccessException.cs b/external/Microsoft.SqlTools.CoreServices/Connection/DatabaseFullAccessException.cs
deleted file mode 100644
index 0286e024..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/DatabaseFullAccessException.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-
-namespace Microsoft.SqlTools.CoreServices.Connection
-{
- public class DatabaseFullAccessException: Exception
- {
- public DatabaseFullAccessException()
- : base()
- {
- }
-
- public DatabaseFullAccessException(string message, Exception exception)
- : base(message, exception)
- {
- }
-
-
- public DatabaseFullAccessException(string message)
- : base(message)
- {
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/DatabaseLocksManager.cs b/external/Microsoft.SqlTools.CoreServices/Connection/DatabaseLocksManager.cs
deleted file mode 100644
index 872a2949..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/DatabaseLocksManager.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using Microsoft.SqlTools.CoreServices.LanguageServices;
-using System;
-using System.Collections.Generic;
-using System.Threading;
-
-namespace Microsoft.SqlTools.CoreServices.Connection
-{
- public class DatabaseLocksManager: IDisposable
- {
- internal DatabaseLocksManager(int waitToGetFullAccess)
- {
- this.waitToGetFullAccess = waitToGetFullAccess;
- }
-
- private static DatabaseLocksManager instance = new DatabaseLocksManager(DefaultWaitToGetFullAccess);
-
- public static DatabaseLocksManager Instance
- {
- get
- {
- return instance;
- }
- }
-
- public ConnectionServiceCore ConnectionService { get; set; }
-
- private Dictionary databaseAccessEvents = new Dictionary();
- private object databaseAccessLock = new object();
- public const int DefaultWaitToGetFullAccess = 10000;
- public int waitToGetFullAccess = DefaultWaitToGetFullAccess;
-
- private ManualResetEvent GetResetEvent(string serverName, string databaseName)
- {
- string key = GenerateKey(serverName, databaseName);
- ManualResetEvent resetEvent = null;
- lock (databaseAccessLock)
- {
- if (!databaseAccessEvents.TryGetValue(key, out resetEvent))
- {
- resetEvent = new ManualResetEvent(true);
- databaseAccessEvents.Add(key, resetEvent);
- }
- }
-
- return resetEvent;
- }
-
- public bool GainFullAccessToDatabase(string serverName, string databaseName)
- {
- /*
- * TODO: add the lock so not two process can get full access at the same time
- ManualResetEvent resetEvent = GetResetEvent(serverName, databaseName);
- if (resetEvent.WaitOne(this.waitToGetFullAccess))
- {
- resetEvent.Reset();
-
- foreach (IConnectedBindingQueue item in ConnectionService.ConnectedQueues)
- {
- item.CloseConnections(serverName, databaseName);
- }
- return true;
- }
- else
- {
- throw new DatabaseFullAccessException($"Waited more than {waitToGetFullAccess} milli seconds for others to release the lock");
- }
- */
- foreach (IConnectedBindingQueue item in ConnectionService.ConnectedQueues)
- {
- item.CloseConnections(serverName, databaseName, DefaultWaitToGetFullAccess);
- }
- return true;
-
- }
-
- public bool ReleaseAccess(string serverName, string databaseName)
- {
- /*
- ManualResetEvent resetEvent = GetResetEvent(serverName, databaseName);
-
- foreach (IConnectedBindingQueue item in ConnectionService.ConnectedQueues)
- {
- item.OpenConnections(serverName, databaseName);
- }
-
- resetEvent.Set();
- */
- foreach (IConnectedBindingQueue item in ConnectionService.ConnectedQueues)
- {
- item.OpenConnections(serverName, databaseName, DefaultWaitToGetFullAccess);
- }
- return true;
-
- }
-
- private string GenerateKey(string serverName, string databaseName)
- {
- return $"{serverName.ToLowerInvariant()}-{databaseName.ToLowerInvariant()}";
- }
-
- public void Dispose()
- {
- foreach (var resetEvent in databaseAccessEvents)
- {
- resetEvent.Value.Dispose();
- }
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/FeatureWithFullDbAccess.cs b/external/Microsoft.SqlTools.CoreServices/Connection/FeatureWithFullDbAccess.cs
deleted file mode 100644
index 155386e1..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/FeatureWithFullDbAccess.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-namespace Microsoft.SqlTools.CoreServices.Connection
-{
- ///
- /// Any operation that needs full access to databas should implement this interface.
- /// Make sure to call GainAccessToDatabase before the operation and ReleaseAccessToDatabase after
- ///
- public interface IFeatureWithFullDbAccess
- {
- ///
- /// Database Lock Manager
- ///
- DatabaseLocksManager LockedDatabaseManager { get; set; }
-
- ///
- /// Makes sure the feature has fill access to the database
- ///
- bool GainAccessToDatabase();
-
- ///
- /// Release the access to db
- ///
- bool ReleaseAccessToDatabase();
-
- ///
- /// Server name
- ///
- string ServerName { get; }
-
- ///
- /// Database name
- ///
- string DatabaseName { get; }
- }
-
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ISqlConnectionFactory.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ISqlConnectionFactory.cs
deleted file mode 100644
index 36af7375..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ISqlConnectionFactory.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System.Data.Common;
-
-namespace Microsoft.SqlTools.CoreServices.Connection
-{
- ///
- /// Interface for the SQL Connection factory
- ///
- public interface ISqlConnectionFactory
- {
- ///
- /// Create a new SQL Connection object
- ///
- DbConnection CreateSqlConnection(string connectionString);
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs
deleted file mode 100644
index 7a7c8841..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs
+++ /dev/null
@@ -1,453 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Reflection;
-using Microsoft.SqlTools.Hosting.Utility;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- ///
- /// This class represents connection (and other) settings specified by called of the DacFx API. DacFx
- /// cannot rely on the registry to supply override values therefore setting overrides must be made
- /// by the top-of-the-stack
- ///
- internal sealed class AmbientSettings
- {
- private const string LogicalContextName = "__LocalContextConfigurationName";
-
- internal enum StreamBackingStore
- {
- // MemoryStream
- Memory = 0,
-
- // FileStream
- File = 1
- }
-
- // Internal for test purposes
- internal const string MasterReferenceFilePathIndex = "MasterReferenceFilePath";
- internal const string DatabaseLockTimeoutIndex = "DatabaseLockTimeout";
- internal const string QueryTimeoutIndex = "QueryTimeout";
- internal const string LongRunningQueryTimeoutIndex = "LongRunningQueryTimeout";
- internal const string AlwaysRetryOnTransientFailureIndex = "AlwaysRetryOnTransientFailure";
- internal const string MaxDataReaderDegreeOfParallelismIndex = "MaxDataReaderDegreeOfParallelism";
- internal const string ConnectionRetryHandlerIndex = "ConnectionRetryHandler";
- internal const string TraceRowCountFailureIndex = "TraceRowCountFailure";
- internal const string TableProgressUpdateIntervalIndex = "TableProgressUpdateInterval";
- internal const string UseOfflineDataReaderIndex = "UseOfflineDataReader";
- internal const string StreamBackingStoreForOfflineDataReadingIndex = "StreamBackingStoreForOfflineDataReading";
- internal const string DisableIndexesForDataPhaseIndex = "DisableIndexesForDataPhase";
- internal const string ReliableDdlEnabledIndex = "ReliableDdlEnabled";
- internal const string ImportModelDatabaseIndex = "ImportModelDatabase";
- internal const string SupportAlwaysEncryptedIndex = "SupportAlwaysEncrypted";
- internal const string SkipObjectTypeBlockingIndex = "SkipObjectTypeBlocking";
- internal const string DoNotSerializeQueryStoreSettingsIndex = "DoNotSerializeQueryStoreSettings";
- internal const string AlwaysEncryptedWizardMigrationIndex = "AlwaysEncryptedWizardMigration";
-
- internal static AmbientData _defaultSettings;
-
- static AmbientSettings()
- {
- _defaultSettings = new AmbientData();
- }
-
- ///
- /// Access to the default ambient settings. Access to these settings is made available
- /// for SSDT scenarios where settings are read from the registry and not set explicitly through
- /// the API
- ///
- public static AmbientData DefaultSettings
- {
- get { return _defaultSettings; }
- }
-
- public static string MasterReferenceFilePath
- {
- get { return GetValue(MasterReferenceFilePathIndex); }
- }
-
- public static int LockTimeoutMilliSeconds
- {
- get { return GetValue(DatabaseLockTimeoutIndex); }
- }
-
- public static int QueryTimeoutSeconds
- {
- get { return GetValue(QueryTimeoutIndex); }
- }
-
- public static int LongRunningQueryTimeoutSeconds
- {
- get { return GetValue(LongRunningQueryTimeoutIndex); }
- }
-
- public static Action ConnectionRetryMessageHandler
- {
- get { return GetValue>(ConnectionRetryHandlerIndex); }
- }
-
- public static bool AlwaysRetryOnTransientFailure
- {
- get { return GetValue(AlwaysRetryOnTransientFailureIndex); }
- }
-
- public static int MaxDataReaderDegreeOfParallelism
- {
- get { return GetValue(MaxDataReaderDegreeOfParallelismIndex); }
- }
-
- public static int TableProgressUpdateInterval
- {
- // value of zero means do not fire 'heartbeat' progress events. Non-zero values will
- // fire a heartbeat progress event every n seconds.
- get { return GetValue(TableProgressUpdateIntervalIndex); }
- }
-
- public static bool TraceRowCountFailure
- {
- get { return GetValue(TraceRowCountFailureIndex); }
- }
-
- public static bool UseOfflineDataReader
- {
- get { return GetValue(UseOfflineDataReaderIndex); }
- }
-
- public static StreamBackingStore StreamBackingStoreForOfflineDataReading
- {
- get { return GetValue(StreamBackingStoreForOfflineDataReadingIndex); }
- }
-
- public static bool DisableIndexesForDataPhase
- {
- get { return GetValue(DisableIndexesForDataPhaseIndex); }
- }
-
- public static bool ReliableDdlEnabled
- {
- get { return GetValue(ReliableDdlEnabledIndex); }
- }
-
- public static bool ImportModelDatabase
- {
- get { return GetValue(ImportModelDatabaseIndex); }
- }
-
- ///
- /// Setting that shows whether Always Encrypted is supported.
- /// If false, then reverse engineering and script interpretation of a database with any Always Encrypted object will fail
- ///
- public static bool SupportAlwaysEncrypted
- {
- get { return GetValue(SupportAlwaysEncryptedIndex); }
- }
-
- public static bool AlwaysEncryptedWizardMigration
- {
- get { return GetValue(AlwaysEncryptedWizardMigrationIndex); }
- }
-
- ///
- /// Setting that determines whether checks for unsupported object types are performed.
- /// If false, unsupported object types will prevent extract from being performed.
- /// Default value is false.
- ///
- public static bool SkipObjectTypeBlocking
- {
- get { return GetValue(SkipObjectTypeBlockingIndex); }
- }
-
- ///
- /// Setting that determines whether the Database Options that store Query Store settings will be left out during package serialization.
- /// Default value is false.
- ///
- public static bool DoNotSerializeQueryStoreSettings
- {
- get { return GetValue(DoNotSerializeQueryStoreSettingsIndex); }
- }
-
- ///
- /// Called by top-of-stack API to setup/configure settings that should be used
- /// throughout the API (lower in the stack). The settings are reverted once the returned context
- /// has been disposed.
- ///
- public static IStackSettingsContext CreateSettingsContext()
- {
- return new StackConfiguration();
- }
-
- private static T1 GetValue(string configIndex)
- {
- IAmbientDataDirectAccess config = _defaultSettings;
-
- return (T1)config.Data[configIndex].Value;
- }
-
- ///
- /// Data-transfer object that represents a specific configuration
- ///
- public class AmbientData : IAmbientDataDirectAccess
- {
- private readonly Dictionary _configuration;
-
- public AmbientData()
- {
- _configuration = new Dictionary(StringComparer.OrdinalIgnoreCase);
- _configuration[DatabaseLockTimeoutIndex] = new AmbientValue(5000);
- _configuration[QueryTimeoutIndex] = new AmbientValue(60);
- _configuration[LongRunningQueryTimeoutIndex] = new AmbientValue(0);
- _configuration[AlwaysRetryOnTransientFailureIndex] = new AmbientValue(false);
- _configuration[ConnectionRetryHandlerIndex] = new AmbientValue(typeof(Action), null);
- _configuration[MaxDataReaderDegreeOfParallelismIndex] = new AmbientValue(8);
- _configuration[TraceRowCountFailureIndex] = new AmbientValue(false); // default: throw DacException on rowcount mismatch during import/export data validation
- _configuration[TableProgressUpdateIntervalIndex] = new AmbientValue(300); // default: fire heartbeat progress update events every 5 minutes
- _configuration[UseOfflineDataReaderIndex] = new AmbientValue(false);
- _configuration[StreamBackingStoreForOfflineDataReadingIndex] = new AmbientValue(StreamBackingStore.File); //applicable only when UseOfflineDataReader is set to true
- _configuration[MasterReferenceFilePathIndex] = new AmbientValue(typeof(string), null);
- // Defect 1210884: Enable an option to allow secondary index, check and fk constraints to stay enabled during data upload with import in DACFX for IES
- _configuration[DisableIndexesForDataPhaseIndex] = new AmbientValue(true);
- _configuration[ReliableDdlEnabledIndex] = new AmbientValue(false);
- _configuration[ImportModelDatabaseIndex] = new AmbientValue(true);
- _configuration[SupportAlwaysEncryptedIndex] = new AmbientValue(false);
- _configuration[AlwaysEncryptedWizardMigrationIndex] = new AmbientValue(false);
- _configuration[SkipObjectTypeBlockingIndex] = new AmbientValue(false);
- _configuration[DoNotSerializeQueryStoreSettingsIndex] = new AmbientValue(false);
- }
-
- public string MasterReferenceFilePath
- {
- get { return (string)_configuration[MasterReferenceFilePathIndex].Value; }
- set { _configuration[MasterReferenceFilePathIndex].Value = value; }
- }
-
- public int LockTimeoutMilliSeconds
- {
- get { return (int)_configuration[DatabaseLockTimeoutIndex].Value; }
- set { _configuration[DatabaseLockTimeoutIndex].Value = value; }
- }
- public int QueryTimeoutSeconds
- {
- get { return (int)_configuration[QueryTimeoutIndex].Value; }
- set { _configuration[QueryTimeoutIndex].Value = value; }
- }
- public int LongRunningQueryTimeoutSeconds
- {
- get { return (int)_configuration[LongRunningQueryTimeoutIndex].Value; }
- set { _configuration[LongRunningQueryTimeoutIndex].Value = value; }
- }
- public bool AlwaysRetryOnTransientFailure
- {
- get { return (bool)_configuration[AlwaysRetryOnTransientFailureIndex].Value; }
- set { _configuration[AlwaysRetryOnTransientFailureIndex].Value = value; }
- }
- public Action ConnectionRetryMessageHandler
- {
- get { return (Action)_configuration[ConnectionRetryHandlerIndex].Value; }
- set { _configuration[ConnectionRetryHandlerIndex].Value = value; }
- }
- public bool TraceRowCountFailure
- {
- get { return (bool)_configuration[TraceRowCountFailureIndex].Value; }
- set { _configuration[TraceRowCountFailureIndex].Value = value; }
- }
- public int TableProgressUpdateInterval
- {
- get { return (int)_configuration[TableProgressUpdateIntervalIndex].Value; }
- set { _configuration[TableProgressUpdateIntervalIndex].Value = value; }
- }
-
- public bool UseOfflineDataReader
- {
- get { return (bool)_configuration[UseOfflineDataReaderIndex].Value; }
- set { _configuration[UseOfflineDataReaderIndex].Value = value; }
- }
-
- public StreamBackingStore StreamBackingStoreForOfflineDataReading
- {
- get { return (StreamBackingStore)_configuration[StreamBackingStoreForOfflineDataReadingIndex].Value; }
- set { _configuration[StreamBackingStoreForOfflineDataReadingIndex].Value = value; }
- }
-
- public bool DisableIndexesForDataPhase
- {
- get { return (bool)_configuration[DisableIndexesForDataPhaseIndex].Value; }
- set { _configuration[DisableIndexesForDataPhaseIndex].Value = value; }
- }
-
- public bool ReliableDdlEnabled
- {
- get { return (bool)_configuration[ReliableDdlEnabledIndex].Value; }
- set { _configuration[ReliableDdlEnabledIndex].Value = value; }
- }
-
- public bool ImportModelDatabase
- {
- get { return (bool)_configuration[ImportModelDatabaseIndex].Value; }
- set { _configuration[ImportModelDatabaseIndex].Value = value; }
- }
-
- internal bool SupportAlwaysEncrypted
- {
- get { return (bool)_configuration[SupportAlwaysEncryptedIndex].Value; }
- set { _configuration[SupportAlwaysEncryptedIndex].Value = value; }
- }
-
- internal bool AlwaysEncryptedWizardMigration
- {
- get { return (bool)_configuration[AlwaysEncryptedWizardMigrationIndex].Value; }
- set { _configuration[AlwaysEncryptedWizardMigrationIndex].Value = value; }
- }
-
- internal bool SkipObjectTypeBlocking
- {
- get { return (bool)_configuration[SkipObjectTypeBlockingIndex].Value; }
- set { _configuration[SkipObjectTypeBlockingIndex].Value = value; }
- }
-
- internal bool DoNotSerializeQueryStoreSettings
- {
- get { return (bool)_configuration[DoNotSerializeQueryStoreSettingsIndex].Value; }
- set { _configuration[DoNotSerializeQueryStoreSettingsIndex].Value = value; }
- }
-
- ///
- /// Provides a way to bulk populate settings from a dictionary
- ///
- public void PopulateSettings(IDictionary settingsCollection)
- {
- if (settingsCollection != null)
- {
- Dictionary newSettings = new Dictionary();
-
- // We know all the values are set on the current configuration
- foreach (KeyValuePair potentialPair in settingsCollection)
- {
- AmbientValue currentValue;
- if (_configuration.TryGetValue(potentialPair.Key, out currentValue))
- {
- object newValue = potentialPair.Value;
- newSettings[potentialPair.Key] = newValue;
- }
- }
-
- if (newSettings.Count > 0)
- {
- foreach (KeyValuePair newSetting in newSettings)
- {
- _configuration[newSetting.Key].Value = newSetting.Value;
- }
- }
- }
- }
-
- ///
- /// Logs the Ambient Settings
- ///
- public void TraceSettings()
- {
- // NOTE: logging as warning so we can get this data in the IEService DacFx logs
- Logger.Write(TraceEventType.Warning, Resources.LoggingAmbientSettings);
-
- foreach (KeyValuePair setting in _configuration)
- {
- // Log Ambient Settings
- Logger.Write(
- TraceEventType.Warning,
- string.Format(
- Resources.AmbientSettingFormat,
- setting.Key,
- setting.Value == null ? setting.Value : setting.Value.Value));
- }
- }
-
- Dictionary IAmbientDataDirectAccess.Data
- {
- get { return _configuration; }
- }
- }
-
- ///
- /// This class is used as value in the dictionary to ensure that the type of value is correct.
- ///
- private class AmbientValue
- {
- private readonly Type _type;
- private readonly bool _isTypeNullable;
- private object _value;
-
- public AmbientValue(object value)
- : this(value == null ? null : value.GetType(), value)
- {
- }
-
- public AmbientValue(Type type, object value)
- {
- if (type == null)
- {
- throw new ArgumentNullException("type");
- }
- _type = type;
- _isTypeNullable = !type.GetTypeInfo().IsValueType || Nullable.GetUnderlyingType(type) != null;
- Value = value;
- }
-
- public object Value
- {
- get { return _value; }
- set
- {
- if ((_isTypeNullable && value == null) || _type.GetTypeInfo().IsInstanceOfType(value))
- {
- _value = value;
- }
- else
- {
- Logger.Write(TraceEventType.Error, string.Format(Resources.UnableToAssignValue, value.GetType().FullName, _type.FullName));
- }
- }
- }
- }
-
- ///
- /// This private interface allows pass-through access directly to member data
- ///
- private interface IAmbientDataDirectAccess
- {
- Dictionary Data { get; }
- }
-
- ///
- /// This class encapsulated the concept of configuration that is set on the stack and
- /// flows across multiple threads as part of the logical call context
- ///
- private sealed class StackConfiguration : IStackSettingsContext
- {
- private readonly AmbientData _data;
-
- public StackConfiguration()
- {
- _data = new AmbientData();
- //CallContext.LogicalSetData(LogicalContextName, _data);
- }
-
- public AmbientData Settings
- {
- get { return _data; }
- }
-
- public void Dispose()
- {
- Dispose(true);
- }
- private void Dispose(bool disposing)
- {
- //CallContext.LogicalSetData(LogicalContextName, null);
- }
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/CachedServerInfo.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/CachedServerInfo.cs
deleted file mode 100644
index cc45bb59..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/CachedServerInfo.cs
+++ /dev/null
@@ -1,285 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Concurrent;
-using System.Data;
-using Microsoft.Data.SqlClient;
-using System.Diagnostics;
-using System.Linq;
-using Microsoft.SqlTools.Hosting.Utility;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
-
- ///
- /// This class caches server information for subsequent use
- ///
- 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,
- IsCloud
- }
-
- #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;
- public DateTime LastUpdate;
- public bool IsSqlDw;
- }
-
- private const int _maxCacheSize = 1024;
- private const int _deleteBatchSize = 512;
- private const int MinimalQueryTimeoutSecondsForAzure = 300;
-
- 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();
- _cacheLock = new object();
- }
-
- public int GetQueryTimeoutSeconds(IDbConnection connection)
- {
- SqlConnectionStringBuilder connStringBuilder = SafeGetConnectionStringFromConnection(connection);
- return GetQueryTimeoutSeconds(connStringBuilder);
- }
-
- 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 (builder == null || string.IsNullOrWhiteSpace(builder.DataSource)
- || (originalValue == 0))
- {
- return originalValue;
- }
-
- CachedInfo info;
- bool hasFound = TryGetCacheValue(builder, out info);
-
- if (hasFound && info.IsAzure
- && originalValue < MinimalQueryTimeoutSecondsForAzure)
- {
- return MinimalQueryTimeoutSecondsForAzure;
- }
- else
- {
- return originalValue;
- }
- }
-
- public void AddOrUpdateIsCloud(IDbConnection connection, bool isCloud)
- {
- AddOrUpdateCache(connection, isCloud, CacheVariable.IsCloud);
- }
-
- public void AddOrUpdateIsAzure(IDbConnection connection, bool isAzure)
- {
- AddOrUpdateCache(connection, isAzure, CacheVariable.IsAzure);
- }
-
- public void AddOrUpdateIsSqlDw(IDbConnection connection, bool isSqlDw)
- {
- AddOrUpdateCache(connection, isSqlDw, CacheVariable.IsSqlDw);
- }
-
- private void AddOrUpdateCache(IDbConnection connection, bool newState, CacheVariable cacheVar)
- {
- Validate.IsNotNull(nameof(connection), connection);
- SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connection.ConnectionString);
- AddOrUpdateCache(builder, newState, cacheVar);
- }
-
- internal void AddOrUpdateCache(SqlConnectionStringBuilder builder, bool newState, CacheVariable cacheVar)
- {
- Validate.IsNotNull(nameof(builder), builder);
- Validate.IsNotNullOrWhitespaceString(nameof(builder) + ".DataSource", builder.DataSource);
- CachedInfo 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)
- {
- // Clean older keys, update info, and add this back into the cache
- CacheKey key = new CacheKey(builder);
- CleanupCache(key);
-
- if (cacheVar == CacheVariable.IsSqlDw)
- {
- info.IsSqlDw = newState;
- }
- else if (cacheVar == CacheVariable.IsAzure)
- {
- info.IsAzure = newState;
- }
- info.LastUpdate = DateTime.UtcNow;
- _cache.AddOrUpdate(key, info, (k, oldValue) => info);
- }
- }
- }
-
- 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, out isSqlDw);
- }
-
- public bool TryGetIsSqlDw(SqlConnectionStringBuilder builder, out bool isSqlDw)
- {
- Validate.IsNotNull(nameof(builder), builder);
- Validate.IsNotNullOrWhitespaceString(nameof(builder) + ".DataSource", builder.DataSource);
- CachedInfo info;
- bool hasFound = TryGetCacheValue(builder, out info);
-
- if(hasFound)
- {
- isSqlDw = info.IsSqlDw;
- return true;
- }
-
- isSqlDw = false;
- return false;
- }
-
- private static SqlConnectionStringBuilder SafeGetConnectionStringFromConnection(IDbConnection connection)
- {
- if (connection == null)
- {
- return null;
- }
-
- try
- {
- SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connection.ConnectionString);
- return builder;
- }
- catch
- {
- Logger.Write(TraceEventType.Error, String.Format(Resources.FailedToParseConnectionString, connection.ConnectionString));
- return null;
- }
- }
-
- private bool TryGetCacheValue(SqlConnectionStringBuilder builder, out CachedInfo value)
- {
- CacheKey key = new CacheKey(builder);
- return _cache.TryGetValue(key, out value);
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Constants.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Constants.cs
deleted file mode 100644
index 80e65098..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Constants.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- ///
- /// Contains common constants used throughout ReliableConnection code.
- ///
- internal static class Constants
- {
- internal const int UndefinedErrorCode = 0;
-
- internal const string Local = "(local)";
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DataSchemaError.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DataSchemaError.cs
deleted file mode 100644
index 51335141..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DataSchemaError.cs
+++ /dev/null
@@ -1,214 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Globalization;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- ///
- /// This class is used to encapsulate all the information needed by the DataSchemaErrorTaskService to create a corresponding entry in the Visual Studio Error List.
- /// A component should add this Error Object to the for such purpose.
- /// Errors and their children are expected to be thread-safe. Ideally, this means that
- /// the objects are just data-transfer-objects initialized during construction.
- ///
- [Serializable]
- internal class DataSchemaError
- {
- internal const string DefaultPrefix = "SQL";
- private const int MaxErrorCode = 99999;
- protected const int UndefinedErrorCode = 0;
-
- public DataSchemaError() : this(string.Empty, ErrorSeverity.Unknown)
- {
- }
-
- public DataSchemaError(string message, ErrorSeverity severity)
- : this(message, string.Empty, severity)
- {
- }
-
- public DataSchemaError(string message, Exception innerException, ErrorSeverity severity)
- : this(message, innerException, string.Empty, 0, severity)
- {
- }
-
- public DataSchemaError(string message, string document, ErrorSeverity severity)
- : this(message, document, 0, 0, DefaultPrefix, UndefinedErrorCode, severity)
- {
- }
-
- public DataSchemaError(string message, string document, int errorCode, ErrorSeverity severity)
- : this(message, document, 0, 0, DefaultPrefix, errorCode, severity)
- {
- }
-
- public DataSchemaError(string message, string document, int line, int column, ErrorSeverity severity)
- : this(message, document,line, column, DefaultPrefix, UndefinedErrorCode, severity)
- {
- }
-
- public DataSchemaError(DataSchemaError source, ErrorSeverity severity)
- : this(source.Message, source.Document, source.Line, source.Column, source.Prefix, source.ErrorCode, severity)
- {
- }
-
- public DataSchemaError(
- Exception exception,
- string prefix,
- int errorCode,
- ErrorSeverity severity)
- : this(exception, string.Empty, 0, 0, prefix, errorCode, severity)
- {
- }
-
- public DataSchemaError(
- string message,
- Exception exception,
- string prefix,
- int errorCode,
- ErrorSeverity severity)
- : this(message, exception, string.Empty, 0, 0, prefix, errorCode, severity)
- {
- }
-
- public DataSchemaError(
- Exception exception,
- string document,
- int line,
- int column,
- string prefix,
- int errorCode,
- ErrorSeverity severity)
- : this(exception.Message, exception, document, line, column, prefix, errorCode, severity)
- {
- }
-
- public DataSchemaError(
- string message,
- string document,
- int line,
- int column,
- string prefix,
- int errorCode,
- ErrorSeverity severity)
- : this(message, null, document, line, column, prefix, errorCode, severity)
- {
- }
-
- public DataSchemaError(
- string message,
- Exception exception,
- string document,
- int line,
- int column,
- string prefix,
- int errorCode,
- ErrorSeverity severity)
- {
- if (errorCode > MaxErrorCode || errorCode < 0)
- {
- throw new ArgumentOutOfRangeException("errorCode");
- }
-
- Document = document;
- Severity = severity;
- Line = line;
- Column = column;
- Message = message;
- Exception = exception;
-
- ErrorCode = errorCode;
- Prefix = prefix;
- IsPriorityEditable = true;
- }
-
- ///
- /// The filename of the error. It corresponds to the File column on the Visual Studio Error List window.
- ///
- public string Document { get; set; }
-
- ///
- /// The severity of the error
- ///
- public ErrorSeverity Severity { get; private set; }
-
- public int ErrorCode { get; private set; }
-
- ///
- /// Line Number of the error
- ///
- public int Line { get; set; }
-
- ///
- /// Column Number of the error
- ///
- public int Column { get; set; }
-
- ///
- /// Prefix of the error
- ///
- public string Prefix { get; private set; }
-
- ///
- /// If the error has any special help topic, this property may hold the ID to the same.
- ///
- public string HelpKeyword { get; set; }
-
- ///
- /// Exception associated with the error, or null
- ///
- public Exception Exception { get; set; }
-
- ///
- /// Message
- ///
- public string Message { get; set; }
-
- ///
- /// Should this message honor the "treat warnings as error" flag?
- ///
- public Boolean IsPriorityEditable { get; set; }
-
- ///
- /// Represents the error code used in MSBuild output. This is the prefix and the
- /// error code
- ///
- ///
- public string BuildErrorCode
- {
- get { return FormatErrorCode(Prefix, ErrorCode); }
- }
-
- internal Boolean IsBuildErrorCodeDefined
- {
- get { return (ErrorCode != UndefinedErrorCode); }
- }
-
- ///
- /// true if this error is being displayed in ErrorList. More of an Accounting Mechanism to be used internally.
- ///
- internal bool IsOnDisplay { get; set; }
-
- internal static string FormatErrorCode(string prefix, int code)
- {
- return string.Format(
- CultureInfo.InvariantCulture,
- "{0}{1:d5}",
- prefix,
- code);
- }
-
- ///
- /// String form of this error.
- /// NB: This is for debugging only.
- ///
- /// String form of the error.
- public override string ToString()
- {
- return string.Format(CultureInfo.CurrentCulture, "{0} - {1}({2},{3}): {4}", FormatErrorCode(Prefix, ErrorCode), Document, Line, Column, Message);
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbCommandWrapper.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbCommandWrapper.cs
deleted file mode 100644
index ffc03a9b..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbCommandWrapper.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Data;
-using Microsoft.Data.SqlClient;
-using Microsoft.SqlTools.Hosting.Utility;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
-
- ///
- /// Wraps objects that could be a or
- /// a , providing common methods across both.
- ///
- internal sealed class DbCommandWrapper
- {
- private readonly IDbCommand _command;
- private readonly bool _isReliableCommand;
-
- public DbCommandWrapper(IDbCommand command)
- {
- Validate.IsNotNull(nameof(command), command);
- if (command is ReliableSqlConnection.ReliableSqlCommand)
- {
- _isReliableCommand = true;
- }
- else if (!(command is SqlCommand))
- {
- throw new InvalidOperationException(Resources.InvalidCommandType);
- }
- _command = command;
- }
-
- public static bool IsSupportedCommand(IDbCommand command)
- {
- return command is ReliableSqlConnection.ReliableSqlCommand
- || command is SqlCommand;
- }
-
-
- public event StatementCompletedEventHandler StatementCompleted
- {
- add
- {
- SqlCommand sqlCommand = GetAsSqlCommand();
- sqlCommand.StatementCompleted += value;
- }
- remove
- {
- SqlCommand sqlCommand = GetAsSqlCommand();
- sqlCommand.StatementCompleted -= value;
- }
- }
-
- ///
- /// Gets this as a SqlCommand by casting (if we know it is actually a SqlCommand)
- /// or by getting the underlying command (if it's a ReliableSqlCommand)
- ///
- private SqlCommand GetAsSqlCommand()
- {
- if (_isReliableCommand)
- {
- return ((ReliableSqlConnection.ReliableSqlCommand) _command).GetUnderlyingCommand();
- }
- return (SqlCommand) _command;
- }
- }
-}
\ No newline at end of file
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbConnectionWrapper.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbConnectionWrapper.cs
deleted file mode 100644
index 9b6e2587..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/DbConnectionWrapper.cs
+++ /dev/null
@@ -1,113 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Data;
-using Microsoft.Data.SqlClient;
-using Microsoft.SqlTools.Hosting.Utility;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- ///
- /// Wraps objects that could be a or
- /// a , providing common methods across both.
- ///
- internal sealed class DbConnectionWrapper
- {
- private readonly IDbConnection _connection;
- private readonly bool _isReliableConnection;
-
- public DbConnectionWrapper(IDbConnection connection)
- {
- Validate.IsNotNull(nameof(connection), connection);
- if (connection is ReliableSqlConnection)
- {
- _isReliableConnection = true;
- }
- else if (!(connection is SqlConnection))
- {
- throw new InvalidOperationException(Resources.InvalidConnectionType);
- }
-
- _connection = connection;
- }
-
- public static bool IsSupportedConnection(IDbConnection connection)
- {
- return connection is ReliableSqlConnection
- || connection is SqlConnection;
- }
-
- public event SqlInfoMessageEventHandler InfoMessage
- {
- add
- {
- SqlConnection conn = GetAsSqlConnection();
- conn.InfoMessage += value;
- }
- remove
- {
- SqlConnection conn = GetAsSqlConnection();
- conn.InfoMessage -= value;
- }
- }
-
- public string DataSource
- {
- get
- {
- if (_isReliableConnection)
- {
- return ((ReliableSqlConnection) _connection).DataSource;
- }
- return ((SqlConnection)_connection).DataSource;
- }
- }
-
- public string ServerVersion
- {
- get
- {
- if (_isReliableConnection)
- {
- return ((ReliableSqlConnection)_connection).ServerVersion;
- }
- return ((SqlConnection)_connection).ServerVersion;
- }
- }
-
- ///
- /// Gets this as a SqlConnection by casting (if we know it is actually a SqlConnection)
- /// or by getting the underlying connection (if it's a ReliableSqlConnection)
- ///
- public SqlConnection GetAsSqlConnection()
- {
- if (_isReliableConnection)
- {
- return ((ReliableSqlConnection) _connection).GetUnderlyingConnection();
- }
- return (SqlConnection) _connection;
- }
-
- /*
- TODO - IClonable does not exist in .NET Core.
- ///
- /// Clones the connection and ensures it's opened.
- /// If it's a SqlConnection it will clone it,
- /// and for ReliableSqlConnection it will clone the underling connection.
- /// The reason the entire ReliableSqlConnection is not cloned is that it includes
- /// several callbacks and we don't want to try and handle deciding how to clone these
- /// yet.
- ///
- public SqlConnection CloneAndOpenConnection()
- {
- SqlConnection conn = GetAsSqlConnection();
- SqlConnection clonedConn = ((ICloneable) conn).Clone() as SqlConnection;
- clonedConn.Open();
- return clonedConn;
- }
- */
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ErrorSeverity.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ErrorSeverity.cs
deleted file mode 100644
index ce2c6163..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ErrorSeverity.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- internal enum ErrorSeverity
- {
- Unknown = 0,
- Error,
- Warning,
- Message
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/IStackSettingsContext.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/IStackSettingsContext.cs
deleted file mode 100644
index 2d0990db..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/IStackSettingsContext.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- ///
- /// This interface controls the lifetime of settings created as part of the
- /// top-of-stack API. Changes made to this context's AmbientData instance will
- /// flow to lower in the stack while this object is not disposed.
- ///
- internal interface IStackSettingsContext : IDisposable
- {
- AmbientSettings.AmbientData Settings { get; }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableConnectionHelper.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableConnectionHelper.cs
deleted file mode 100644
index 3c856e94..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableConnectionHelper.cs
+++ /dev/null
@@ -1,1321 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Data;
-using Microsoft.Data.SqlClient;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
-using System.Security;
-using Microsoft.SqlTools.Hosting.Utility;
-using Microsoft.SqlServer.Management.Common;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- internal static class ReliableConnectionHelper
- {
- private const int PCU1BuildNumber = 2816;
- public readonly static SqlConnectionStringBuilder BuilderWithDefaultApplicationName = new SqlConnectionStringBuilder("server=(local);");
-
- private const string ServerNameLocalhost = "localhost";
- private const string SqlProviderName = "System.Data.SqlClient";
-
- private const string ApplicationIntent = "ApplicationIntent";
- private const string MultiSubnetFailover = "MultiSubnetFailover";
- private const string DacFxApplicationName = "DacFx";
-
- private const int SqlDwEngineEditionId = (int)DatabaseEngineEdition.SqlDataWarehouse;
-
- // See MSDN documentation for "SERVERPROPERTY (SQL Azure Database)" for "EngineEdition" property:
- // http://msdn.microsoft.com/en-us/library/ee336261.aspx
- private const int SqlAzureEngineEditionId = 5;
-
- private static Lazy> cloudEditions = new Lazy>(() => new HashSet()
- {
- (int)DatabaseEngineEdition.SqlDatabase,
- (int)DatabaseEngineEdition.SqlDataWarehouse,
- (int)DatabaseEngineEdition.SqlStretchDatabase,
- (int)DatabaseEngineEdition.SqlOnDemand,
- // Note: for now, ignoring managed instance as it should be treated just like on prem.
- });
-
- ///
- /// Opens the connection and sets the lock/command timeout and pooling=false.
- ///
- /// The opened connection
- public static IDbConnection OpenConnection(SqlConnectionStringBuilder csb, bool useRetry)
- {
- csb.Pooling = false;
- return OpenConnection(csb.ToString(), useRetry);
- }
-
- ///
- /// Opens the connection and sets the lock/command timeout. This routine
- /// will assert if pooling!=false.
- ///
- /// The opened connection
- public static IDbConnection OpenConnection(string connectionString, bool useRetry)
- {
-#if DEBUG
- try
- {
- SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString);
- Debug.Assert(!builder.Pooling, "Pooling should be false");
- }
- catch (Exception ex)
- {
- Debug.Assert(false, "Invalid connectionstring: " + ex.Message);
- }
-#endif
-
- if (AmbientSettings.AlwaysRetryOnTransientFailure)
- {
- useRetry = true;
- }
-
- RetryPolicy commandRetryPolicy, connectionRetryPolicy;
- if (useRetry)
- {
- commandRetryPolicy = RetryPolicyFactory.CreateDefaultSchemaCommandRetryPolicy(useRetry: true);
- connectionRetryPolicy = RetryPolicyFactory.CreateDefaultSchemaConnectionRetryPolicy();
- }
- else
- {
- commandRetryPolicy = RetryPolicyFactory.CreateNoRetryPolicy();
- connectionRetryPolicy = RetryPolicyFactory.CreateNoRetryPolicy();
- }
-
- ReliableSqlConnection connection = new ReliableSqlConnection(connectionString, connectionRetryPolicy, commandRetryPolicy);
-
- try
- {
- connection.Open();
- }
- catch (Exception ex)
- {
-
- string debugMessage = String.Format(CultureInfo.CurrentCulture,
- "Opening connection using connection string '{0}' failed with exception: {1}", connectionString, ex.Message);
-#if DEBUG
- Debug.WriteLine(debugMessage);
-#endif
- connection.Dispose();
- throw;
- }
-
- return connection;
- }
-
- ///
- /// Opens the connection (if it is not already) and sets
- /// the lock/command timeout.
- ///
- /// The connection to open
- public static void OpenConnection(IDbConnection conn)
- {
- if (conn.State == ConnectionState.Closed)
- {
- conn.Open();
- }
- }
-
- ///
- /// Opens a connection using 'csb' as the connection string. Provide
- /// 'usingConnection' to execute T-SQL against the open connection and
- /// 'catchException' to handle errors.
- ///
- /// The connection string used when opening the IDbConnection
- /// delegate called when the IDbConnection has been successfully opened
- /// delegate called when an exception has occurred. Pass back 'true' to handle the
- /// exception, 'false' to throw. If Null is passed in then all exceptions are thrown.
- /// Should retry logic be used when opening the connection
- public static void OpenConnection(
- SqlConnectionStringBuilder csb,
- Action usingConnection,
- Predicate catchException,
- bool useRetry)
- {
- Validate.IsNotNull(nameof(csb), csb);
- Validate.IsNotNull(nameof(usingConnection), usingConnection);
-
- try
- {
- // Always disable pooling
- csb.Pooling = false;
- using (IDbConnection conn = OpenConnection(csb.ConnectionString, useRetry))
- {
- usingConnection(conn);
- }
- }
- catch (Exception ex)
- {
- if (catchException == null || !catchException(ex))
- {
- throw;
- }
- }
- }
-
- /*
- TODO - re-enable if we port ConnectionStringSecurer
- ///
- /// This method provides the provides a connection string configured with the specified database name.
- /// This is also an opportunity to decrypt the connection string based on the encryption/decryption strategy.
- /// InvalidConnectionStringException could be thrown since this routine attempts to restore the connection
- /// string if 'restoreConnectionString' is true.
- ///
- /// Will only set DatabaseName/ApplicationName if the value is not null.
- ///
- ///
- public static SqlConnectionStringBuilder ConfigureConnectionString(
- string connectionString,
- string databaseName,
- string applicationName,
- bool restoreConnectionString = true)
- {
- if (restoreConnectionString)
- {
- // Read the connection string through the persistence layer
- connectionString = ConnectionStringSecurer.RestoreConnectionString(
- connectionString,
- SqlProviderName);
- }
-
- SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString);
-
- builder.Pooling = false;
- builder.MultipleActiveResultSets = false;
-
- // Cannot set the applicationName/initialCatalog to null but empty string is valid
- if (databaseName != null)
- {
- builder.InitialCatalog = databaseName;
- }
-
- if (applicationName != null)
- {
- builder.ApplicationName = applicationName;
- }
-
- return builder;
- }
- */
-
- ///
- /// Optional 'initializeConnection' routine. This sets the lock and command timeout for the connection.
- ///
- public static void SetLockAndCommandTimeout(IDbConnection conn)
- {
- ReliableSqlConnection.SetLockAndCommandTimeout(conn);
- }
-
- ///
- /// Opens a IDbConnection, creates a IDbCommand and calls ExecuteNonQuery against the connection.
- ///
- /// The connection string.
- /// The scalar T-SQL command.
- /// Optional delegate to initialize the IDbCommand before execution.
- /// Default is SqlConnectionHelper.SetCommandTimeout
- /// delegate called when an exception has occurred. Pass back 'true' to handle the
- /// exception, 'false' to throw. If Null is passed in then all exceptions are thrown.
- /// Should a retry policy be used when calling ExecuteNonQuery
- /// The number of rows affected
- public static object ExecuteNonQuery(
- SqlConnectionStringBuilder csb,
- string commandText,
- Action initializeCommand,
- Predicate catchException,
- bool useRetry)
- {
- object retObject = null;
- OpenConnection(
- csb,
- (connection) =>
- {
- retObject = ExecuteNonQuery(connection, commandText, initializeCommand, catchException);
- },
- catchException,
- useRetry);
-
- return retObject;
- }
-
- ///
- /// Creates a IDbCommand and calls ExecuteNonQuery against the connection.
- ///
- /// The connection. This must be opened.
- /// The scalar T-SQL command.
- /// Optional delegate to initialize the IDbCommand before execution.
- /// Default is SqlConnectionHelper.SetCommandTimeout
- /// Optional exception handling. Pass back 'true' to handle the
- /// exception, 'false' to throw. If Null is passed in then all exceptions are thrown.
- /// The number of rows affected
- [SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")]
- public static object ExecuteNonQuery(
- IDbConnection conn,
- string commandText,
- Action initializeCommand,
- Predicate catchException)
- {
- Validate.IsNotNull(nameof(conn), conn);
- Validate.IsNotNullOrEmptyString(nameof(commandText), commandText);
-
- IDbCommand cmd = null;
- try
- {
-
- Debug.Assert(conn.State == ConnectionState.Open, "connection passed to ExecuteNonQuery should be open.");
-
- cmd = conn.CreateCommand();
- if (initializeCommand == null)
- {
- initializeCommand = SetCommandTimeout;
- }
- initializeCommand(cmd);
-
- cmd.CommandText = commandText;
- cmd.CommandType = CommandType.Text;
-
- return cmd.ExecuteNonQuery();
- }
- catch (Exception ex)
- {
- if (catchException == null || !catchException(ex))
- {
- throw;
- }
- }
- finally
- {
- if (cmd != null)
- {
- cmd.Dispose();
- }
- }
- return null;
- }
-
- ///
- /// Creates a IDbCommand and calls ExecuteScalar against the connection.
- ///
- /// The connection. This must be opened.
- /// The scalar T-SQL command.
- /// Optional delegate to initialize the IDbCommand before execution.
- /// Default is SqlConnectionHelper.SetCommandTimeout
- /// Optional exception handling. Pass back 'true' to handle the
- /// exception, 'false' to throw. If Null is passed in then all exceptions are thrown.
- /// The scalar result
- [SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")]
- public static object ExecuteScalar(
- IDbConnection conn,
- string commandText,
- Action initializeCommand = null,
- Predicate catchException = null)
- {
- Validate.IsNotNull(nameof(conn), conn);
- Validate.IsNotNullOrEmptyString(nameof(commandText), commandText);
-
- IDbCommand cmd = null;
-
- try
- {
- Debug.Assert(conn.State == ConnectionState.Open, "connection passed to ExecuteScalar should be open.");
-
- cmd = conn.CreateCommand();
- if (initializeCommand == null)
- {
- initializeCommand = SetCommandTimeout;
- }
- initializeCommand(cmd);
-
- cmd.CommandText = commandText;
- cmd.CommandType = CommandType.Text;
- return cmd.ExecuteScalar();
- }
- catch (Exception ex)
- {
- if (catchException == null || !catchException(ex))
- {
- throw;
- }
- }
- finally
- {
- if (cmd != null)
- {
- cmd.Dispose();
- }
- }
- return null;
- }
-
- ///
- /// Creates a IDbCommand and calls ExecuteReader against the connection.
- ///
- /// The connection to execute the reader on. This must be opened.
- /// The command text to execute
- /// A delegate used to read from the reader
- /// Optional delegate to initialize the IDbCommand object
- /// Optional exception handling. Pass back 'true' to handle the
- /// exception, 'false' to throw. If Null is passed in then all exceptions are thrown.
- [SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")]
- public static void ExecuteReader(
- IDbConnection conn,
- string commandText,
- Action readResult,
- Action initializeCommand = null,
- Predicate catchException = null)
- {
- Validate.IsNotNull(nameof(conn), conn);
- Validate.IsNotNullOrEmptyString(nameof(commandText), commandText);
- Validate.IsNotNull(nameof(readResult), readResult);
-
- IDbCommand cmd = null;
- try
- {
- cmd = conn.CreateCommand();
-
- if (initializeCommand == null)
- {
- initializeCommand = SetCommandTimeout;
- }
-
- initializeCommand(cmd);
-
- cmd.CommandText = commandText;
- cmd.CommandType = CommandType.Text;
- using (IDataReader reader = cmd.ExecuteReader())
- {
- readResult(reader);
- }
- }
- catch (Exception ex)
- {
- if (catchException == null || !catchException(ex))
- {
- throw;
- }
- }
- finally
- {
- if (cmd != null)
- {
- cmd.Dispose();
- }
- }
- }
-
- ///
- /// optional 'initializeCommand' routine. This initializes the IDbCommand
- ///
- ///
- public static void SetCommandTimeout(IDbCommand cmd)
- {
- Validate.IsNotNull(nameof(cmd), cmd);
- cmd.CommandTimeout = CachedServerInfo.Instance.GetQueryTimeoutSeconds(cmd.Connection);
- }
-
-
- ///
- /// Return true if the database is an Azure database
- ///
- ///
- ///
- public static bool IsCloud(IDbConnection connection)
- {
- Validate.IsNotNull(nameof(connection), connection);
- if (!(connection.State == ConnectionState.Open))
- {
- Logger.Write(TraceEventType.Warning, Resources.ConnectionPassedToIsCloudShouldBeOpen);
- }
-
- Func executeCommand = commandText =>
- {
- bool result = false;
- ExecuteReader(connection,
- commandText,
- readResult: (reader) =>
- {
- reader.Read();
- int engineEditionId = int.Parse(reader[0].ToString(), CultureInfo.InvariantCulture);
-
- result = IsCloudEngineId(engineEditionId);
- }
- );
- return result;
- };
-
- bool isSqlCloud = false;
- try
- {
- isSqlCloud = executeCommand(SqlConnectionHelperScripts.EngineEdition);
- }
- catch (SqlException)
- {
- // The default query contains a WITH (NOLOCK). This doesn't work for Azure DW, so when things don't work out,
- // we'll fall back to a version without NOLOCK and try again.
- isSqlCloud = executeCommand(SqlConnectionHelperScripts.EngineEditionWithLock);
- }
-
- return isSqlCloud;
- }
-
- private static bool IsCloudEngineId(int engineEditionId)
- {
- return cloudEditions.Value.Contains(engineEditionId);
- }
-
- ///
- /// Determines if the type of database that a connection is being made to is SQL data warehouse.
- ///
- ///
- /// True if the database is a SQL data warehouse
- public static bool IsSqlDwDatabase(IDbConnection connection)
- {
- Validate.IsNotNull(nameof(connection), connection);
-
- Func executeCommand = commandText =>
- {
- bool result = false;
- ExecuteReader(connection,
- commandText,
- readResult: (reader) =>
- {
- reader.Read();
- int engineEditionId = int.Parse(reader[0].ToString(), CultureInfo.InvariantCulture);
-
- result = IsSqlDwEngineId(engineEditionId);
- }
- );
- return result;
- };
-
- bool isSqlDw = false;
- try
- {
- isSqlDw = executeCommand(SqlConnectionHelperScripts.EngineEdition);
- }
- catch (SqlException)
- {
- // The default query contains a WITH (NOLOCK). This doesn't work for Azure DW, so when things don't work out,
- // we'll fall back to a version without NOLOCK and try again.
- isSqlDw = executeCommand(SqlConnectionHelperScripts.EngineEditionWithLock);
- }
-
- return isSqlDw;
- }
-
- ///
- /// Compares the engine edition id of a given database with that of SQL data warehouse.
- ///
- ///
- /// True if the engine edition id is that of SQL data warehouse
- private static bool IsSqlDwEngineId(int engineEditionId)
- {
- return engineEditionId == SqlDwEngineEditionId;
- }
-
- ///
- /// Handles the exceptions typically thrown when a SQLConnection is being opened
- ///
- /// True if the exception was handled
- public static bool StandardExceptionHandler(Exception ex)
- {
- Validate.IsNotNull(nameof(ex), ex);
-
- if (ex is SqlException ||
- ex is RetryLimitExceededException)
- {
- return true;
- }
- if (ex is InvalidCastException ||
- ex is ArgumentException || // Thrown when a particular connection string property is invalid (i.e. failover parner = "yes")
- ex is InvalidOperationException || // thrown when the connection pool is empty and SQL is down
- ex is TimeoutException ||
- ex is SecurityException)
- {
- return true;
- }
-
- Logger.Write(TraceEventType.Error, ex.ToString());
- return false;
- }
-
- ///
- /// Returns the default database path.
- ///
- /// The connection
- /// The delegate used to initialize the command
- /// The exception handler delegate. If Null is passed in then all exceptions are thrown
- public static string GetDefaultDatabaseFilePath(
- IDbConnection conn,
- Action initializeCommand = null,
- Predicate catchException = null)
- {
- Validate.IsNotNull(nameof(conn), conn);
-
- string filePath = null;
- ServerInfo info = GetServerVersion(conn);
-
- if (!info.IsCloud)
- {
- filePath = GetDefaultDatabasePath(conn, SqlConnectionHelperScripts.GetDatabaseFilePathAndName, initializeCommand, catchException);
- }
-
- return filePath;
- }
-
- ///
- /// Returns the log path or null
- ///
- /// The connection
- /// The delegate used to initialize the command
- /// The exception handler delegate. If Null is passed in then all exceptions are thrown
- public static string GetDefaultDatabaseLogPath(
- IDbConnection conn,
- Action initializeCommand = null,
- Predicate catchException = null)
- {
- Validate.IsNotNull(nameof(conn), conn);
-
- string logPath = null;
- ServerInfo info = GetServerVersion(conn);
-
- if (!info.IsCloud)
- {
- logPath = GetDefaultDatabasePath(conn, SqlConnectionHelperScripts.GetDatabaseLogPathAndName, initializeCommand, catchException);
- }
-
- return logPath;
- }
-
- ///
- /// Returns the database path or null
- ///
- /// The connection
- /// The command to issue
- /// The delegate used to initialize the command
- /// The exception handler delegate. If Null is passed in then all exceptions are thrown
- private static string GetDefaultDatabasePath(
- IDbConnection conn,
- string commandText,
- Action initializeCommand = null,
- Predicate catchException = null)
- {
- Validate.IsNotNull(nameof(conn), conn);
- Validate.IsNotNullOrEmptyString(nameof(commandText), commandText);
-
- string filePath = ExecuteScalar(conn, commandText, initializeCommand, catchException) as string;
- if (!string.IsNullOrWhiteSpace(filePath))
- {
- // Remove filename from the filePath
- Uri pathUri;
- if (!Uri.IsWellFormedUriString(filePath, UriKind.Absolute))
- {
- // In linux "file://" is required otehrwise the Uri cannot parse the path
- //this should be fixed in dotenet core 2.0
- filePath = $"file://{filePath}";
- }
- if (!Uri.TryCreate(filePath, UriKind.Absolute, out pathUri))
- {
- // Invalid Uri
- return null;
- }
-
- // Get a current directory path relative to the pathUri
- // This will remove filename from the uri.
- Uri filePathUri = new Uri(pathUri, ".");
- // For file uri we need to get LocalPath instead of file:// url
- filePath = filePathUri.IsFile ? filePathUri.LocalPath : filePathUri.OriginalString;
- }
- return filePath;
- }
-
- ///
- /// Returns true if the database is readonly. This routine will swallow the exceptions you might expect from SQL using StandardExceptionHandler.
- ///
- public static bool IsDatabaseReadonly(SqlConnectionStringBuilder builder)
- {
- Validate.IsNotNull(nameof(builder), builder);
-
- if (builder == null)
- {
- throw new ArgumentNullException("builder");
- }
- bool isDatabaseReadOnly = false;
-
- OpenConnection(
- builder,
- (connection) =>
- {
- string commandText = String.Format(CultureInfo.InvariantCulture, SqlConnectionHelperScripts.CheckDatabaseReadonly, builder.InitialCatalog);
- ExecuteReader(connection,
- commandText,
- readResult: (reader) =>
- {
- if (reader.Read())
- {
- string currentSetting = reader.GetString(1);
- if (String.Compare(currentSetting, "ON", StringComparison.OrdinalIgnoreCase) == 0)
- {
- isDatabaseReadOnly = true;
- }
- }
- });
- },
- (ex) =>
- {
- Logger.Write(TraceEventType.Error, ex.ToString());
- return StandardExceptionHandler(ex); // handled
- },
- useRetry: true);
-
- return isDatabaseReadOnly;
- }
-
- public class ServerInfo
- {
- public int ServerMajorVersion;
- public int ServerMinorVersion;
- public int ServerReleaseVersion;
- public int EngineEditionId;
- public string ServerVersion;
- public string ServerLevel;
- public string ServerEdition;
- public bool IsCloud;
- public int AzureVersion;
-
- // In SQL 2012 SP1 Selective XML indexes were added. There is bug where upgraded databases from previous versions
- // of SQL Server do not have their metadata upgraded to include the xml_index_type column in the sys.xml_indexes view. Because
- // of this, we must detect the presence of the column to determine if we can query for Selective Xml Indexes
- public bool IsSelectiveXmlIndexMetadataPresent;
-
- public string OsVersion;
-
- public string MachineName;
- }
-
- public static bool TryGetServerVersion(string connectionString, out ServerInfo serverInfo)
- {
- serverInfo = null;
- SqlConnectionStringBuilder builder;
- if (!TryGetConnectionStringBuilder(connectionString, out builder))
- {
- return false;
- }
-
- serverInfo = GetServerVersion(builder);
- return true;
- }
-
- ///
- /// Returns the version of the server. This routine will throw if an exception is encountered.
- ///
- public static ServerInfo GetServerVersion(SqlConnectionStringBuilder csb)
- {
- Validate.IsNotNull(nameof(csb), csb);
- ServerInfo serverInfo = null;
-
- OpenConnection(
- csb,
- (connection) =>
- {
- serverInfo = GetServerVersion(connection);
- },
- catchException: null, // Always throw
- useRetry: true);
-
- return serverInfo;
- }
-
- ///
- /// Returns the version of the server. This routine will throw if an exception is encountered.
- ///
- public static ServerInfo GetServerVersion(IDbConnection connection)
- {
- Validate.IsNotNull(nameof(connection), connection);
- if (!(connection.State == ConnectionState.Open))
- {
- Logger.Write(TraceEventType.Error, "connection passed to GetServerVersion should be open.");
- }
-
- Func getServerInfo = commandText =>
- {
- ServerInfo serverInfo = new ServerInfo();
- ExecuteReader(
- connection,
- commandText,
- delegate (IDataReader reader)
- {
- reader.Read();
- int engineEditionId = Int32.Parse(reader[0].ToString(), CultureInfo.InvariantCulture);
-
- serverInfo.EngineEditionId = engineEditionId;
- serverInfo.IsCloud = IsCloudEngineId(engineEditionId);
-
- serverInfo.ServerVersion = reader[1].ToString();
- serverInfo.ServerLevel = reader[2].ToString();
- serverInfo.ServerEdition = reader[3].ToString();
- serverInfo.MachineName = reader[4].ToString();
-
- if (reader.FieldCount > 5)
- {
- // Detect the presence of SXI
- serverInfo.IsSelectiveXmlIndexMetadataPresent = reader.GetInt32(5) == 1;
- }
-
- // The 'ProductVersion' server property is of the form ##.#[#].####.#,
- Version serverVersion = new Version(serverInfo.ServerVersion);
-
- // The server version is of the form ##.##.####,
- serverInfo.ServerMajorVersion = serverVersion.Major;
- serverInfo.ServerMinorVersion = serverVersion.Minor;
- serverInfo.ServerReleaseVersion = serverVersion.Build;
-
- if (serverInfo.IsCloud)
- {
- serverInfo.AzureVersion = serverVersion.Major > 11 ? 2 : 1;
- }
-
- try
- {
- CachedServerInfo.Instance.AddOrUpdateIsCloud(connection, serverInfo.IsCloud);
- }
- catch (Exception ex)
- {
- //we don't want to fail the normal flow if any unexpected thing happens
- //during caching although it's unlikely. So we just log the exception and ignore it
- Logger.Write(TraceEventType.Error, Resources.FailedToCacheIsCloud);
- Logger.Write(TraceEventType.Error, ex.ToString());
- }
- });
-
- // Also get the OS Version
- ExecuteReader(
- connection,
- SqlConnectionHelperScripts.GetOsVersion,
- delegate (IDataReader reader)
- {
- reader.Read();
- serverInfo.OsVersion = reader[0].ToString();
- });
-
- return serverInfo;
- };
-
- ServerInfo result = null;
- try
- {
- result = getServerInfo(SqlConnectionHelperScripts.EngineEdition);
- }
- catch (SqlException)
- {
- // The default query contains a WITH (NOLOCK). This doesn't work for Azure DW, so when things don't work out,
- // we'll fall back to a version without NOLOCK and try again.
- result = getServerInfo(SqlConnectionHelperScripts.EngineEditionWithLock);
- }
-
- return result;
- }
-
- public static string GetServerName(IDbConnection connection)
- {
- return new DbConnectionWrapper(connection).DataSource;
- }
-
- public static string ReadServerVersion(IDbConnection connection)
- {
- return new DbConnectionWrapper(connection).ServerVersion;
- }
-
- ///
- /// Converts to a SqlConnection by casting (if we know it is actually a SqlConnection)
- /// or by getting the underlying connection (if it's a ReliableSqlConnection)
- ///
- public static SqlConnection GetAsSqlConnection(IDbConnection connection)
- {
- return new DbConnectionWrapper(connection).GetAsSqlConnection();
- }
-
- /* TODO - CloneAndOpenConnection() requires IClonable, which doesn't exist in .NET Core
- ///
- /// Clones a connection and ensures it's opened.
- /// If it's a SqlConnection it will clone it,
- /// and for ReliableSqlConnection it will clone the underling connection.
- /// The reason the entire ReliableSqlConnection is not cloned is that it includes
- /// several callbacks and we don't want to try and handle deciding how to clone these
- /// yet.
- ///
- public static SqlConnection CloneAndOpenConnection(IDbConnection connection)
- {
- return new DbConnectionWrapper(connection).CloneAndOpenConnection();
- }
- */
-
- public class ServerAndDatabaseInfo : ServerInfo
- {
- public int DbCompatibilityLevel;
- public string DatabaseName;
- }
-
- internal static bool TryGetConnectionStringBuilder(string connectionString, out SqlConnectionStringBuilder builder)
- {
- builder = null;
-
- if (String.IsNullOrEmpty(connectionString))
- {
- // Connection string is not valid
- return false;
- }
-
- // Attempt to initialize the builder
- Exception handledEx = null;
- try
- {
- builder = new SqlConnectionStringBuilder(connectionString);
- }
- catch (KeyNotFoundException ex)
- {
- handledEx = ex;
- }
- catch (FormatException ex)
- {
- handledEx = ex;
- }
- catch (ArgumentException ex)
- {
- handledEx = ex;
- }
-
- if (handledEx != null)
- {
- Logger.Write(TraceEventType.Error, String.Format(Resources.ErrorParsingConnectionString, handledEx));
- return false;
- }
-
- return true;
- }
-
- /*
- ///
- /// Get the version of the server and database using
- /// the connection string provided. This routine will
- /// throw if an exception is encountered.
- ///
- /// The connection string used to connect to the database.
- /// Basic information about the server
- public static bool GetServerAndDatabaseVersion(string connectionString, out ServerAndDatabaseInfo info)
- {
- bool foundVersion = false;
- info = new ServerAndDatabaseInfo { IsCloud = false, ServerMajorVersion = -1, DbCompatibilityLevel = -1, DatabaseName = String.Empty };
-
- SqlConnectionStringBuilder builder;
- if (!TryGetConnectionStringBuilder(connectionString, out builder))
- {
- return false;
- }
-
- // The database name is either the InitialCatalog or the AttachDBFilename. The
- // AttachDBFilename is used if an mdf file is specified in the connections dialog.
- if (String.IsNullOrEmpty(builder.InitialCatalog) ||
- String.IsNullOrEmpty(builder.AttachDBFilename))
- {
- builder.Pooling = false;
-
- string tempDatabaseName = String.Empty;
- int tempDbCompatibilityLevel = 0;
- ServerInfo serverInfo = null;
-
- OpenConnection(
- builder,
- (connection) =>
- {
- // Set the lock timeout to 3 seconds
- SetLockAndCommandTimeout(connection);
-
- serverInfo = GetServerVersion(connection);
-
- tempDatabaseName = (!string.IsNullOrEmpty(builder.InitialCatalog)) ?
- builder.InitialCatalog : builder.AttachDBFilename;
-
- // If at this point the dbName remained an empty string then
- // we should get the database name from the open IDbConnection
- if (String.IsNullOrEmpty(tempDatabaseName))
- {
- tempDatabaseName = connection.Database;
- }
-
- // SQL Azure does not support custom DBCompat values.
- SqlParameter databaseNameParameter = new SqlParameter(
- "@dbname",
- SqlDbType.NChar,
- 128,
- ParameterDirection.Input,
- false,
- 0,
- 0,
- null,
- DataRowVersion.Default,
- tempDatabaseName);
-
- object compatibilityLevel;
-
- using (IDbCommand versionCommand = connection.CreateCommand())
- {
- versionCommand.CommandText = "SELECT compatibility_level FROM sys.databases WITH (NOLOCK) WHERE name = @dbname";
- versionCommand.CommandType = CommandType.Text;
- versionCommand.Parameters.Add(databaseNameParameter);
- compatibilityLevel = versionCommand.ExecuteScalar();
- }
-
- // value is null if db is not online
- foundVersion = compatibilityLevel != null && !(compatibilityLevel is DBNull);
- if(foundVersion)
- {
- tempDbCompatibilityLevel = (byte)compatibilityLevel;
- }
- else
- {
- string conString = connection.ConnectionString == null ? "null" : connection.ConnectionString;
- string dbName = tempDatabaseName == null ? "null" : tempDatabaseName;
- string message = string.Format(CultureInfo.CurrentCulture,
- "Querying database compatibility level failed. Connection string: '{0}'. dbname: '{1}'.",
- conString, dbName);
- Tracer.TraceEvent(TraceEventType.Error, TraceId.CoreServices, message);
- }
- },
- catchException: null, // Always throw
- useRetry: true);
-
- info.IsCloud = serverInfo.IsCloud;
- info.ServerMajorVersion = serverInfo.ServerMajorVersion;
- info.ServerMinorVersion = serverInfo.ServerMinorVersion;
- info.ServerReleaseVersion = serverInfo.ServerReleaseVersion;
- info.ServerVersion = serverInfo.ServerVersion;
- info.ServerLevel = serverInfo.ServerLevel;
- info.ServerEdition = serverInfo.ServerEdition;
- info.AzureVersion = serverInfo.AzureVersion;
- info.DatabaseName = tempDatabaseName;
- info.DbCompatibilityLevel = tempDbCompatibilityLevel;
- }
-
- return foundVersion;
- }
- */
-
- ///
- /// Returns true if the authenticating database is master, otherwise false. An example of
- /// false is when the user is a contained user connecting to a contained database.
- ///
- public static bool IsAuthenticatingDatabaseMaster(IDbConnection connection)
- {
- try
- {
- const string sqlCommand =
- @"use [{0}];
- if (db_id() = 1)
- begin
- -- contained auth is 0 when connected to master
- select 0
- end
- else
- begin
- -- need dynamic sql so that we compile this query only when we know resource db is available
- exec('select case when authenticating_database_id = 1 then 0 else 1 end from sys.dm_exec_sessions where session_id = @@SPID')
- end";
-
- string finalCmd = null;
- if (!String.IsNullOrWhiteSpace(connection.Database))
- {
- finalCmd = String.Format(CultureInfo.InvariantCulture, sqlCommand, connection.Database);
- }
- else
- {
- finalCmd = String.Format(CultureInfo.InvariantCulture, sqlCommand, "master");
- }
-
- object retValue = ExecuteScalar(connection, finalCmd);
- if (retValue != null && retValue.ToString() == "1")
- {
- // contained auth is 0 when connected to non-master
- return false;
- }
- return true;
- }
- catch (Exception ex)
- {
- if (StandardExceptionHandler(ex))
- {
- return true;
- }
- throw;
- }
- }
-
- ///
- /// Returns true if the authenticating database is master, otherwise false. An example of
- /// false is when the user is a contained user connecting to a contained database.
- ///
- public static bool IsAuthenticatingDatabaseMaster(SqlConnectionStringBuilder builder)
- {
- bool authIsMaster = true;
- OpenConnection(
- builder,
- usingConnection: (connection) =>
- {
- authIsMaster = IsAuthenticatingDatabaseMaster(connection);
- },
- catchException: StandardExceptionHandler, // Don't throw unless it's an unexpected exception
- useRetry: true);
- return authIsMaster;
- }
-
- ///
- /// Returns the form of the server as a it's name - replaces . and (localhost)
- ///
- public static string GetCompleteServerName(string server)
- {
- if (String.IsNullOrEmpty(server))
- {
- return server;
- }
-
- int nlen = 0;
- if (server[0] == '.')
- {
- nlen = 1;
- }
- else if (String.Compare(server, Constants.Local, StringComparison.OrdinalIgnoreCase) == 0)
- {
- nlen = Constants.Local.Length;
- }
- else if (String.Compare(server, 0, ServerNameLocalhost, 0, ServerNameLocalhost.Length, StringComparison.OrdinalIgnoreCase) == 0)
- {
- nlen = ServerNameLocalhost.Length;
- }
-
- if (nlen > 0)
- {
- string strMachine = Environment.MachineName;
- if (server.Length == nlen)
- return strMachine;
- if (server.Length > (nlen + 1) && server[nlen] == '\\') // instance
- {
- string strRet = strMachine + server.Substring(nlen);
- return strRet;
- }
- }
-
- return server;
- }
-
- /*
- ///
- /// Processes a user-supplied connection string and provides a trimmed connection string
- /// that eliminates everything except for DataSource, InitialCatalog, UserId, Password,
- /// ConnectTimeout, Encrypt, TrustServerCertificate and IntegratedSecurity.
- ///
- /// When connection string is invalid
- public static string TrimConnectionString(string connectionString)
- {
- Exception handledException;
-
- try
- {
- SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder(connectionString);
- return TrimConnectionStringBuilder(scsb).ConnectionString;
- }
- catch (ArgumentException exception)
- {
- handledException = exception;
- }
- catch (KeyNotFoundException exception)
- {
- handledException = exception;
- }
- catch (FormatException exception)
- {
- handledException = exception;
- }
-
- throw new InvalidConnectionStringException(handledException);
- }
- */
-
- ///
- /// Sql 2012 PCU1 introduces breaking changes to metadata queries and adds new Selective XML Index support.
- /// This method allows components to detect if the represents a build of SQL 2012 after RTM.
- ///
- public static bool IsVersionGreaterThan2012RTM(ServerInfo _serverInfo)
- {
- return _serverInfo.ServerMajorVersion > 11 ||
- // Use the presence of SXI metadata rather than build number as upgrade bugs leave out the SXI metadata for some upgraded databases.
- _serverInfo.ServerMajorVersion == 11 && _serverInfo.IsSelectiveXmlIndexMetadataPresent;
- }
-
-
- // SQL Server: Defect 1122301: ReliableConnectionHelper does not maintain ApplicationIntent
- // The ApplicationIntent and MultiSubnetFailover property is not introduced to .NET until .NET 4.0 update 2
- // However, DacFx is officially depends on .NET 4.0 RTM
- // So here we want to support both senarios, on machine with 4.0 RTM installed, it will ignore these 2 properties
- // On machine with higher .NET version which included those properties, it will pick them up.
- public static void TryAddAlwaysOnConnectionProperties(SqlConnectionStringBuilder userBuilder, SqlConnectionStringBuilder trimBuilder)
- {
- if (userBuilder.ContainsKey(ApplicationIntent))
- {
- trimBuilder[ApplicationIntent] = userBuilder[ApplicationIntent];
- }
-
- if (userBuilder.ContainsKey(MultiSubnetFailover))
- {
- trimBuilder[MultiSubnetFailover] = userBuilder[MultiSubnetFailover];
- }
- }
-
- /* TODO - this relies on porting SqlAuthenticationMethodUtils
- ///
- /// Processes a user-supplied connection string and provides a trimmed connection string
- /// that eliminates everything except for DataSource, InitialCatalog, UserId, Password,
- /// ConnectTimeout, Encrypt, TrustServerCertificate, IntegratedSecurity and Pooling.
- ///
- ///
- /// Pooling is always set to false to avoid connections remaining open.
- ///
- /// When connection string is invalid
- public static SqlConnectionStringBuilder TrimConnectionStringBuilder(SqlConnectionStringBuilder userBuilder, Action throwException = null)
- {
-
- Exception handledException;
-
- if (throwException == null)
- {
- throwException = (propertyName) =>
- {
- throw new InvalidConnectionStringException(String.Format(CultureInfo.CurrentCulture, Resources.UnsupportedConnectionStringArgument, propertyName));
- };
- }
- if (!String.IsNullOrEmpty(userBuilder.AttachDBFilename))
- {
- throwException("AttachDBFilename");
- }
- if (userBuilder.UserInstance)
- {
- throwException("User Instance");
- }
-
- try
- {
- SqlConnectionStringBuilder trimBuilder = new SqlConnectionStringBuilder();
-
- if (String.IsNullOrWhiteSpace(userBuilder.DataSource))
- {
- throw new InvalidConnectionStringException();
- }
-
- trimBuilder.ConnectTimeout = userBuilder.ConnectTimeout;
- trimBuilder.DataSource = userBuilder.DataSource;
-
- if (false == String.IsNullOrWhiteSpace(userBuilder.InitialCatalog))
- {
- trimBuilder.InitialCatalog = userBuilder.InitialCatalog;
- }
-
- trimBuilder.IntegratedSecurity = userBuilder.IntegratedSecurity;
-
- if (!String.IsNullOrWhiteSpace(userBuilder.UserID))
- {
- trimBuilder.UserID = userBuilder.UserID;
- }
-
- if (!String.IsNullOrWhiteSpace(userBuilder.Password))
- {
- trimBuilder.Password = userBuilder.Password;
- }
-
- trimBuilder.TrustServerCertificate = userBuilder.TrustServerCertificate;
- trimBuilder.Encrypt = userBuilder.Encrypt;
-
- if (String.IsNullOrWhiteSpace(userBuilder.ApplicationName) ||
- String.Equals(BuilderWithDefaultApplicationName.ApplicationName, userBuilder.ApplicationName, StringComparison.Ordinal))
- {
- trimBuilder.ApplicationName = DacFxApplicationName;
- }
- else
- {
- trimBuilder.ApplicationName = userBuilder.ApplicationName;
- }
-
- TryAddAlwaysOnConnectionProperties(userBuilder, trimBuilder);
-
- if (SqlAuthenticationMethodUtils.IsAuthenticationSupported())
- {
- SqlAuthenticationMethodUtils.SetAuthentication(userBuilder, trimBuilder);
- }
-
- if (SqlAuthenticationMethodUtils.IsCertificateSupported())
- {
- SqlAuthenticationMethodUtils.SetCertificate(userBuilder, trimBuilder);
- }
-
- trimBuilder.Pooling = false;
- return trimBuilder;
- }
- catch (ArgumentException exception)
- {
- handledException = exception;
- }
- catch (KeyNotFoundException exception)
- {
- handledException = exception;
- }
- catch (FormatException exception)
- {
- handledException = exception;
- }
-
- throw new InvalidConnectionStringException(handledException);
- }
-
- public static bool TryCreateConnectionStringBuilder(string connectionString, out SqlConnectionStringBuilder builder, out Exception handledException)
- {
- bool success = false;
- builder = null;
- handledException = null;
- try
- {
- builder = TrimConnectionStringBuilder(new SqlConnectionStringBuilder(connectionString));
-
- success = true;
- }
- catch (InvalidConnectionStringException e)
- {
- handledException = e;
- }
- catch (ArgumentException exception)
- {
- handledException = exception;
- }
- catch (KeyNotFoundException exception)
- {
- handledException = exception;
- }
- catch (FormatException exception)
- {
- handledException = exception;
- }
- finally
- {
- if (handledException != null)
- {
- success = false;
- }
- }
- return success;
- }
- */
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlCommand.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlCommand.cs
deleted file mode 100644
index 548a902b..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlCommand.cs
+++ /dev/null
@@ -1,247 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-// This code is copied from the source described in the comment below.
-
-// =======================================================================================
-// Microsoft Windows Server AppFabric Customer Advisory Team (CAT) Best Practices Series
-//
-// This sample is supplemental to the technical guidance published on the community
-// blog at http://blogs.msdn.com/appfabriccat/ and copied from
-// sqlmain ./sql/manageability/mfx/common/
-//
-// =======================================================================================
-// Copyright © 2012 Microsoft Corporation. All rights reserved.
-//
-// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE RISK OF USING IT.
-// =======================================================================================
-
-// namespace Microsoft.AppFabricCAT.Samples.Azure.TransientFaultHandling.SqlAzure
-// namespace Microsoft.SqlServer.Management.Common
-
-using System;
-using System.Data;
-using System.Data.Common;
-using Microsoft.Data.SqlClient;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- ///
- /// Provides a reliable way of opening connections to and executing commands
- /// taking into account potential network unreliability and a requirement for connection retry.
- ///
- internal sealed partial class ReliableSqlConnection
- {
- internal class ReliableSqlCommand : DbCommand
- {
- private const int Dummy = 0;
- private readonly SqlCommand _command;
-
- // connection is settable
- private ReliableSqlConnection _connection;
-
- public ReliableSqlCommand()
- : this(null, Dummy)
- {
- }
-
- public ReliableSqlCommand(ReliableSqlConnection connection)
- : this(connection, Dummy)
- {
- Contract.Requires(connection != null);
- }
-
- private ReliableSqlCommand(ReliableSqlConnection connection, int dummy)
- {
- if (connection != null)
- {
- _connection = connection;
- _command = connection.CreateSqlCommand();
- }
- else
- {
- _command = new SqlCommand();
- }
- }
-
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- _command.Dispose();
- }
- }
-
- ///
- /// Gets or sets the text command to run against the data source.
- ///
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")]
- public override string CommandText
- {
- get { return _command.CommandText; }
- set { _command.CommandText = value; }
- }
-
- ///
- /// Gets or sets the wait time before terminating the attempt to execute a command and generating an error.
- ///
- public override int CommandTimeout
- {
- get { return _command.CommandTimeout; }
- set { _command.CommandTimeout = value; }
- }
-
- ///
- /// Gets or sets a value that specifies how the property is interpreted.
- ///
- public override CommandType CommandType
- {
- get { return _command.CommandType; }
- set { _command.CommandType = value; }
- }
-
- ///
- /// Gets or sets the used by this .
- ///
- protected override DbConnection DbConnection
- {
- get
- {
- return _connection;
- }
-
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException("value");
- }
-
- ReliableSqlConnection newConnection = value as ReliableSqlConnection;
-
- if (newConnection == null)
- {
- throw new InvalidOperationException(Resources.OnlyReliableConnectionSupported);
- }
-
- _connection = newConnection;
- _command.Connection = _connection._underlyingConnection;
- }
- }
-
- ///
- /// Gets the .
- ///
- protected override DbParameterCollection DbParameterCollection
- {
- get { return _command.Parameters; }
- }
-
- ///
- /// Gets or sets the transaction within which the Command object of a .NET Framework data provider executes.
- ///
- protected override DbTransaction DbTransaction
- {
- get { return _command.Transaction; }
- set { _command.Transaction = value as SqlTransaction; }
- }
-
- ///
- /// Gets or sets a value indicating whether the command object should be visible in a customized interface control.
- ///
- public override bool DesignTimeVisible
- {
- get { return _command.DesignTimeVisible; }
- set { _command.DesignTimeVisible = value; }
- }
-
- ///
- /// Gets or sets how command results are applied to the System.Data.DataRow when
- /// used by the System.Data.IDataAdapter.Update(System.Data.DataSet) method of
- /// a .
- ///
- public override UpdateRowSource UpdatedRowSource
- {
- get { return _command.UpdatedRowSource; }
- set { _command.UpdatedRowSource = value; }
- }
-
- ///
- /// Attempts to cancels the execution of an .
- ///
- public override void Cancel()
- {
- _command.Cancel();
- }
-
- ///
- /// Creates a new instance of an object.
- ///
- /// An object.
- protected override DbParameter CreateDbParameter()
- {
- return _command.CreateParameter();
- }
-
- ///
- /// Executes an SQL statement against the Connection object of a .NET Framework
- /// data provider, and returns the number of rows affected.
- ///
- /// The number of rows affected.
- public override int ExecuteNonQuery()
- {
- ValidateConnectionIsSet();
- return _connection.ExecuteNonQuery(_command);
- }
-
- ///
- /// Executes the against the
- /// and builds an using one of the values.
- ///
- /// One of the values.
- /// An object.
- protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
- {
- ValidateConnectionIsSet();
- return (DbDataReader)_connection.ExecuteReader(_command, behavior);
- }
-
- ///
- /// Executes the query, and returns the first column of the first row in the
- /// resultset returned by the query. Extra columns or rows are ignored.
- ///
- /// The first column of the first row in the resultset.
- public override object ExecuteScalar()
- {
- ValidateConnectionIsSet();
- return _connection.ExecuteScalar(_command);
- }
-
- ///
- /// Creates a prepared (or compiled) version of the command on the data source.
- ///
- public override void Prepare()
- {
- _command.Prepare();
- }
-
- internal SqlCommand GetUnderlyingCommand()
- {
- return _command;
- }
-
- internal void ValidateConnectionIsSet()
- {
- if (_connection == null)
- {
- throw new InvalidOperationException(Resources.ConnectionPropertyNotSet);
- }
- }
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlConnection.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlConnection.cs
deleted file mode 100644
index c7b46a8f..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlConnection.cs
+++ /dev/null
@@ -1,610 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-// This code is copied from the source described in the comment below.
-
-// =======================================================================================
-// Microsoft Windows Server AppFabric Customer Advisory Team (CAT) Best Practices Series
-//
-// This sample is supplemental to the technical guidance published on the community
-// blog at http://blogs.msdn.com/appfabriccat/ and copied from
-// sqlmain ./sql/manageability/mfx/common/
-//
-// =======================================================================================
-// Copyright © 2012 Microsoft Corporation. All rights reserved.
-//
-// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE RISK OF USING IT.
-// =======================================================================================
-
-// namespace Microsoft.AppFabricCAT.Samples.Azure.TransientFaultHandling.SqlAzure
-// namespace Microsoft.SqlServer.Management.Common
-
-using System;
-using System.Collections.Generic;
-using System.Data;
-using System.Data.Common;
-using Microsoft.Data.SqlClient;
-using System.Diagnostics;
-using System.Globalization;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.SqlTools.Hosting.Utility;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- ///
- /// Provides a reliable way of opening connections to and executing commands
- /// taking into account potential network unreliability and a requirement for connection retry.
- ///
- internal sealed partial class ReliableSqlConnection : DbConnection, IDisposable
- {
- private const string QueryAzureSessionId = "SELECT CONVERT(NVARCHAR(36), CONTEXT_INFO())";
-
- private readonly SqlConnection _underlyingConnection;
- private readonly RetryPolicy _connectionRetryPolicy;
- private RetryPolicy _commandRetryPolicy;
- private Guid _azureSessionId;
- private bool _isSqlDwDatabase;
-
- ///
- /// Initializes a new instance of the ReliableSqlConnection class with a given connection string
- /// and a policy defining whether to retry a request if the connection fails to be opened or a command
- /// fails to be successfully executed.
- ///
- /// The connection string used to open the SQL Azure database.
- /// The retry policy defining whether to retry a request if a connection fails to be established.
- /// The retry policy defining whether to retry a request if a command fails to be executed.
- public ReliableSqlConnection(string connectionString, RetryPolicy connectionRetryPolicy, RetryPolicy commandRetryPolicy)
- {
- _underlyingConnection = new SqlConnection(connectionString);
- _connectionRetryPolicy = connectionRetryPolicy ?? RetryPolicyFactory.CreateNoRetryPolicy();
- _commandRetryPolicy = commandRetryPolicy ?? RetryPolicyFactory.CreateNoRetryPolicy();
-
- _underlyingConnection.StateChange += OnConnectionStateChange;
- _connectionRetryPolicy.RetryOccurred += RetryConnectionCallback;
- _commandRetryPolicy.RetryOccurred += RetryCommandCallback;
- }
-
- ///
- /// Performs application-defined tasks associated with freeing, releasing, or
- /// resetting managed and unmanaged resources.
- ///
- /// A flag indicating that managed resources must be released.
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (_connectionRetryPolicy != null)
- {
- _connectionRetryPolicy.RetryOccurred -= RetryConnectionCallback;
- }
-
- if (_commandRetryPolicy != null)
- {
- _commandRetryPolicy.RetryOccurred -= RetryCommandCallback;
- }
-
- _underlyingConnection.StateChange -= OnConnectionStateChange;
- if (_underlyingConnection.State == ConnectionState.Open)
- {
- _underlyingConnection.Close();
- }
-
- _underlyingConnection.Dispose();
- }
- }
-
- ///
- /// Determines if a connection is being made to a SQL DW database.
- ///
- /// A connection object.
- private bool IsSqlDwConnection(IDbConnection conn)
- {
- //Set the connection only if it has not been set earlier.
- //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.Instance.TryGetIsSqlDw(conn, out _isSqlDwDatabase))
- {
- _isSqlDwDatabase = ReliableConnectionHelper.IsSqlDwDatabase(conn);
- CachedServerInfo.Instance.AddOrUpdateIsSqlDw(conn, _isSqlDwDatabase);;
- }
-
- return _isSqlDwDatabase;
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")]
- internal static void SetLockAndCommandTimeout(IDbConnection conn)
- {
- Validate.IsNotNull(nameof(conn), conn);
-
- // Make sure we use the underlying connection as ReliableConnection.Open also calls
- // this method
- ReliableSqlConnection reliableConn = conn as ReliableSqlConnection;
- if (reliableConn != null)
- {
- conn = reliableConn._underlyingConnection;
- }
-
- const string setLockTimeout = @"set LOCK_TIMEOUT {0}";
-
- using (IDbCommand cmd = conn.CreateCommand())
- {
- cmd.CommandText = string.Format(CultureInfo.InvariantCulture, setLockTimeout, AmbientSettings.LockTimeoutMilliSeconds);
- cmd.CommandType = CommandType.Text;
- cmd.CommandTimeout = CachedServerInfo.Instance.GetQueryTimeoutSeconds(conn);
- cmd.ExecuteNonQuery();
- }
- }
-
- internal static void SetDefaultAnsiSettings(IDbConnection conn, bool isSqlDw)
- {
- Validate.IsNotNull(nameof(conn), conn);
-
- // Make sure we use the underlying connection as ReliableConnection.Open also calls
- // this method
- ReliableSqlConnection reliableConn = conn as ReliableSqlConnection;
- if (reliableConn != null)
- {
- conn = reliableConn._underlyingConnection;
- }
-
- // Configure the connection with proper ANSI settings and lock timeout
- using (IDbCommand cmd = conn.CreateCommand())
- {
- 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;
-SET NUMERIC_ROUNDABORT OFF;";
- }
- else
- {
- cmd.CommandText = @"SET ANSI_NULLS ON; SET ANSI_PADDING ON; SET ANSI_WARNINGS ON; SET ARITHABORT ON; SET CONCAT_NULL_YIELDS_NULL ON; SET QUOTED_IDENTIFIER ON;"; //SQL DW does not support NUMERIC_ROUNDABORT
- }
- cmd.ExecuteNonQuery();
- }
- }
-
- ///
- /// Gets or sets the connection string for opening a connection to the SQL Azure database.
- ///
- public override string ConnectionString
- {
- get { return _underlyingConnection.ConnectionString; }
- set { _underlyingConnection.ConnectionString = value; }
- }
-
- ///
- /// Gets the policy which decides whether to retry a connection request, based on how many
- /// times the request has been made and the reason for the last failure.
- ///
- public RetryPolicy ConnectionRetryPolicy
- {
- get { return _connectionRetryPolicy; }
- }
-
- ///
- /// Gets the policy which decides whether to retry a command, based on how many
- /// times the request has been made and the reason for the last failure.
- ///
- public RetryPolicy CommandRetryPolicy
- {
- get { return _commandRetryPolicy; }
- set
- {
- Validate.IsNotNull(nameof(value), value);
-
- if (_commandRetryPolicy != null)
- {
- _commandRetryPolicy.RetryOccurred -= RetryCommandCallback;
- }
-
- _commandRetryPolicy = value;
- _commandRetryPolicy.RetryOccurred += RetryCommandCallback;
- }
- }
-
- ///
- /// Gets the server name from the underlying connection.
- ///
- public override string DataSource
- {
- get { return _underlyingConnection.DataSource; }
- }
-
- ///
- /// Gets the server version from the underlying connection.
- ///
- public override string ServerVersion
- {
- get { return _underlyingConnection.ServerVersion; }
- }
-
- ///
- /// If the underlying SqlConnection absolutely has to be accessed, for instance
- /// to pass to external APIs that require this type of connection, then this
- /// can be used.
- ///
- ///
- public SqlConnection GetUnderlyingConnection()
- {
- return _underlyingConnection;
- }
-
- ///
- /// Begins a database transaction with the specified System.Data.IsolationLevel value.
- ///
- /// One of the System.Data.IsolationLevel values.
- /// An object representing the new transaction.
- protected override DbTransaction BeginDbTransaction(IsolationLevel level)
- {
- return _underlyingConnection.BeginTransaction(level);
- }
-
- ///
- /// Changes the current database for an open Connection object.
- ///
- /// The name of the database to use in place of the current database.
- public override void ChangeDatabase(string databaseName)
- {
- _underlyingConnection.ChangeDatabase(databaseName);
- }
-
- ///
- /// Opens a database connection with the settings specified by the ConnectionString
- /// property of the provider-specific Connection object.
- ///
- public override void Open()
- {
- // Check if retry policy was specified, if not, disable retries by executing the Open method using RetryPolicy.NoRetry.
- _connectionRetryPolicy.ExecuteAction(() =>
- {
- if (_underlyingConnection.State != ConnectionState.Open)
- {
- _underlyingConnection.Open();
- }
- SetLockAndCommandTimeout(_underlyingConnection);
- SetDefaultAnsiSettings(_underlyingConnection, IsSqlDwConnection(_underlyingConnection));
- });
- }
-
- ///
- /// Opens a database connection with the settings specified by the ConnectionString
- /// property of the provider-specific Connection object.
- ///
- public override Task OpenAsync(CancellationToken token)
- {
- // Make sure that the token isn't cancelled before we try
- if (token.IsCancellationRequested)
- {
- return Task.FromCanceled(token);
- }
-
- // Check if retry policy was specified, if not, disable retries by executing the Open method using RetryPolicy.NoRetry.
- try
- {
- return _connectionRetryPolicy.ExecuteAction(async () =>
- {
- if (_underlyingConnection.State != ConnectionState.Open)
- {
- await _underlyingConnection.OpenAsync(token);
- }
- SetLockAndCommandTimeout(_underlyingConnection);
- SetDefaultAnsiSettings(_underlyingConnection, IsSqlDwConnection(_underlyingConnection));
- });
- }
- catch (Exception e)
- {
- return Task.FromException(e);
- }
- }
-
- ///
- /// Closes the connection to the database.
- ///
- public override void Close()
- {
- _underlyingConnection.Close();
- }
-
- ///
- /// Gets the time to wait while trying to establish a connection before terminating
- /// the attempt and generating an error.
- ///
- public override int ConnectionTimeout
- {
- get { return _underlyingConnection.ConnectionTimeout; }
- }
-
- ///
- /// Creates and returns an object implementing the IDbCommand interface which is associated
- /// with the underlying SqlConnection.
- ///
- /// A object.
- protected override DbCommand CreateDbCommand()
- {
- return CreateReliableCommand();
- }
-
- ///
- /// Creates and returns an object implementing the IDbCommand interface which is associated
- /// with the underlying SqlConnection.
- ///
- /// A object.
- public SqlCommand CreateSqlCommand()
- {
- return _underlyingConnection.CreateCommand();
- }
-
- ///
- /// Gets the name of the current database or the database to be used after a
- /// connection is opened.
- ///
- public override string Database
- {
- get { return _underlyingConnection.Database; }
- }
-
- ///
- /// Gets the current state of the connection.
- ///
- public override ConnectionState State
- {
- get { return _underlyingConnection.State; }
- }
-
- ///
- /// Adds an info message event listener.
- ///
- /// An info message event listener.
- public void AddInfoMessageHandler(SqlInfoMessageEventHandler handler)
- {
- _underlyingConnection.InfoMessage += handler;
- }
-
- ///
- /// Removes an info message event listener.
- ///
- /// An info message event listener.
- public void RemoveInfoMessageHandler(SqlInfoMessageEventHandler handler)
- {
- _underlyingConnection.InfoMessage -= handler;
- }
-
- ///
- /// Clears underlying connection pool.
- ///
- public void ClearPool()
- {
- if (_underlyingConnection != null)
- {
- SqlConnection.ClearPool(_underlyingConnection);
- }
- }
-
- private void RetryCommandCallback(RetryState retryState)
- {
- RetryPolicyUtils.RaiseSchemaAmbientRetryMessage(retryState, SqlSchemaModelErrorCodes.ServiceActions.CommandRetry, _azureSessionId);
- }
-
- private void RetryConnectionCallback(RetryState retryState)
- {
- RetryPolicyUtils.RaiseSchemaAmbientRetryMessage(retryState, SqlSchemaModelErrorCodes.ServiceActions.ConnectionRetry, _azureSessionId);
- }
-
- public void OnConnectionStateChange(object sender, StateChangeEventArgs e)
- {
- SqlConnection conn = (SqlConnection)sender;
- switch (e.CurrentState)
- {
- case ConnectionState.Open:
- RetrieveSessionId();
- break;
- case ConnectionState.Broken:
- case ConnectionState.Closed:
- _azureSessionId = Guid.Empty;
- break;
- case ConnectionState.Connecting:
- case ConnectionState.Executing:
- case ConnectionState.Fetching:
- default:
- break;
- }
- }
-
- private void RetrieveSessionId()
- {
- try
- {
- using (IDbCommand command = CreateReliableCommand())
- {
- IDbConnection connection = command.Connection;
- if (!IsSqlDwConnection(connection))
- {
- 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);
- }
- }
- }
- }
- catch (SqlException exception)
- {
- Logger.Write(TraceEventType.Error, Resources.UnableToRetrieveAzureSessionId + exception.ToString());
- }
- }
-
- ///
- /// Creates and returns a ReliableSqlCommand object associated
- /// with the underlying SqlConnection.
- ///
- /// A object.
- private ReliableSqlCommand CreateReliableCommand()
- {
- return new ReliableSqlCommand(this);
- }
-
- private void VerifyConnectionOpen(IDbCommand command)
- {
- // Verify whether or not the connection is valid and is open. This code may be retried therefore
- // it is important to ensure that a connection is re-established should it have previously failed.
- if (command.Connection == null)
- {
- command.Connection = this;
- }
-
- if (command.Connection.State != ConnectionState.Open)
- {
- SqlConnection.ClearPool(_underlyingConnection);
-
- command.Connection.Open();
- }
- }
-
- private IDataReader ExecuteReader(IDbCommand command, CommandBehavior behavior)
- {
- Tuple[] sessionSettings = null;
- return _commandRetryPolicy.ExecuteAction(() =>
- {
- VerifyConnectionOpen(command);
- sessionSettings = CacheOrReplaySessionSettings(command, sessionSettings);
-
- return command.ExecuteReader(behavior);
- });
- }
-
- // Because retry loses session settings, cache session settings or reply if the settings are already cached.
- internal Tuple[] CacheOrReplaySessionSettings(IDbCommand originalCommand, Tuple[] sessionSettings)
- {
- if (sessionSettings == null)
- {
- sessionSettings = QuerySessionSettings(originalCommand);
- }
- else
- {
- SetSessionSettings(originalCommand.Connection, sessionSettings);
- }
-
- return sessionSettings;
- }
-
- private object ExecuteScalar(IDbCommand command)
- {
- Tuple[] sessionSettings = null;
- return _commandRetryPolicy.ExecuteAction(() =>
- {
- VerifyConnectionOpen(command);
- sessionSettings = CacheOrReplaySessionSettings(command, sessionSettings);
-
- return command.ExecuteScalar();
- });
- }
-
- private Tuple[] QuerySessionSettings(IDbCommand originalCommand)
- {
- Tuple[] sessionSettings = new Tuple[2];
-
- IDbConnection connection = originalCommand.Connection;
- if (IsSqlDwConnection(connection))
- {
- // SESSIONPROPERTY is not supported. Use default values for now
- sessionSettings[0] = Tuple.Create("ANSI_NULLS", true);
- sessionSettings[1] = Tuple.Create("QUOTED_IDENTIFIER", true);
- }
- else
- {
- using (IDbCommand localCommand = connection.CreateCommand())
- {
- // Executing a reader requires preservation of any pending transaction created by the calling command
- localCommand.Transaction = originalCommand.Transaction;
- localCommand.CommandText = "SELECT ISNULL(SESSIONPROPERTY ('ANSI_NULLS'), 0), ISNULL(SESSIONPROPERTY ('QUOTED_IDENTIFIER'), 1)";
- using (IDataReader reader = localCommand.ExecuteReader())
- {
- if (reader.Read())
- {
- sessionSettings[0] = Tuple.Create("ANSI_NULLS", ((int)reader[0] == 1));
- sessionSettings[1] = Tuple.Create("QUOTED_IDENTIFIER", ((int)reader[1] ==1));
- }
- else
- {
- Debug.Assert(false, "Reader cannot be empty");
- }
- }
- }
- }
- return sessionSettings;
- }
-
- private void SetSessionSettings(IDbConnection connection, params Tuple[] settings)
- {
- List setONOptions = new List();
- List setOFFOptions = new List();
- if(settings != null)
- {
- foreach (Tuple setting in settings)
- {
- if (setting.Item2)
- {
- setONOptions.Add(setting.Item1);
- }
- else
- {
- setOFFOptions.Add(setting.Item1);
- }
- }
- }
-
- SetSessionSettings(connection, setONOptions, "ON");
- SetSessionSettings(connection, setOFFOptions, "OFF");
-
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities")]
- private static void SetSessionSettings(IDbConnection connection, List sessionOptions, string onOff)
- {
- if (sessionOptions.Count > 0)
- {
- using (IDbCommand localCommand = connection.CreateCommand())
- {
- StringBuilder builder = new StringBuilder("SET ");
- for (int i = 0; i < sessionOptions.Count; i++)
- {
- if (i > 0)
- {
- builder.Append(',');
- }
- builder.Append(sessionOptions[i]);
- }
- builder.Append(" ");
- builder.Append(onOff);
- localCommand.CommandText = builder.ToString();
- localCommand.ExecuteNonQuery();
- }
- }
- }
-
- private int ExecuteNonQuery(IDbCommand command)
- {
- Tuple[] sessionSettings = null;
- return _commandRetryPolicy.ExecuteAction(() =>
- {
- VerifyConnectionOpen(command);
- sessionSettings = CacheOrReplaySessionSettings(command, sessionSettings);
-
- return command.ExecuteNonQuery();
- });
- }
- }
-}
-
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Resources.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Resources.cs
deleted file mode 100644
index 1885e53c..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/Resources.cs
+++ /dev/null
@@ -1,157 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- ///
- /// Contains string resources used throughout ReliableConnection code.
- ///
- internal static class Resources
- {
- internal static string AmbientSettingFormat
- {
- get
- {
- return "{0}: {1}";
- }
- }
-
- internal static string ConnectionPassedToIsCloudShouldBeOpen
- {
- get
- {
- return "connection passed to IsCloud should be open.";
- }
- }
-
- internal static string ConnectionPropertyNotSet
- {
- get
- {
- return "Connection property has not been initialized.";
- }
- }
-
- internal static string ExceptionCannotBeRetried
- {
- get
- {
- return "Exception cannot be retried because of err #{0}:{1}";
- }
- }
-
- internal static string ErrorParsingConnectionString
- {
- get
- {
- return "Error parsing connection string {0}";
- }
- }
-
- internal static string FailedToCacheIsCloud
- {
- get
- {
- return "failed to cache the server property of IsAzure";
- }
- }
-
- internal static string FailedToParseConnectionString
- {
- get
- {
- return "failed to parse the provided connection string: {0}";
- }
- }
-
- internal static string IgnoreOnException
- {
- get
- {
- return "Retry number {0}. Ignoring Exception: {1}";
- }
- }
-
- internal static string InvalidCommandType
- {
- get
- {
- return "Unsupported command object. Use SqlCommand or ReliableSqlCommand.";
- }
- }
-
- internal static string InvalidConnectionType
- {
- get
- {
- return "Unsupported connection object. Use SqlConnection or ReliableSqlConnection.";
- }
- }
-
- internal static string LoggingAmbientSettings
- {
- get
- {
- return "Logging Ambient Settings...";
- }
- }
-
- internal static string Mode
- {
- get
- {
- return "Mode";
- }
- }
-
- internal static string OnlyReliableConnectionSupported
- {
- get
- {
- return "Connection property can only be set to a value of type ReliableSqlConnection.";
- }
- }
-
- internal static string RetryOnException
- {
- get
- {
- return "Retry number {0}. Delaying {1} ms before next retry. Exception: {2}";
- }
- }
-
- internal static string ThrottlingTypeInfo
- {
- get
- {
- return "ThrottlingTypeInfo";
- }
- }
-
- internal static string UnableToAssignValue
- {
- get
- {
- return "Unable to assign the value of type {0} to {1}";
- }
- }
-
- internal static string UnableToRetrieveAzureSessionId
- {
- get
- {
- return "Unable to retrieve Azure session-id.";
- }
- }
-
- internal static string ServerInfoCacheMiss
- {
- get
- {
- return "Server Info does not have the requested property in the cache";
- }
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryCallbackEventArgs.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryCallbackEventArgs.cs
deleted file mode 100644
index f9b6a4a0..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryCallbackEventArgs.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-// This code is copied from the source described in the comment below.
-
-// =======================================================================================
-// Microsoft Windows Server AppFabric Customer Advisory Team (CAT) Best Practices Series
-//
-// This sample is supplemental to the technical guidance published on the community
-// blog at http://blogs.msdn.com/appfabriccat/ and copied from
-// sqlmain ./sql/manageability/mfx/common/
-//
-// =======================================================================================
-// Copyright © 2012 Microsoft Corporation. All rights reserved.
-//
-// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE RISK OF USING IT.
-// =======================================================================================
-
-// namespace Microsoft.SQL.CAT.BestPractices.SqlAzure.Framework
-// namespace Microsoft.SqlServer.Management.Common
-
-using System;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- ///
- /// Defines a arguments for event handler which will be invoked whenever a retry condition is encountered.
- ///
- internal sealed class RetryCallbackEventArgs : EventArgs
- {
- private readonly int _retryCount;
- private readonly Exception _exception;
- private readonly TimeSpan _delay;
-
- public RetryCallbackEventArgs(int retryCount, Exception exception, TimeSpan delay)
- {
- _retryCount = retryCount;
- _exception = exception;
- _delay = delay;
- }
-
- public TimeSpan Delay
- {
- get { return _delay; }
- }
-
- public Exception Exception
- {
- get { return _exception; }
- }
-
- public int RetryCount
- {
- get { return _retryCount; }
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryLimitExceededException.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryLimitExceededException.cs
deleted file mode 100644
index d08e91d0..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryLimitExceededException.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-// This code is copied from the source described in the comment below.
-
-// =======================================================================================
-// Microsoft Windows Server AppFabric Customer Advisory Team (CAT) Best Practices Series
-//
-// This sample is supplemental to the technical guidance published on the community
-// blog at http://blogs.msdn.com/appfabriccat/ and copied from
-// sqlmain ./sql/manageability/mfx/common/
-//
-// =======================================================================================
-// Copyright © 2012 Microsoft Corporation. All rights reserved.
-//
-// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE RISK OF USING IT.
-// =======================================================================================
-
-// namespace Microsoft.SQL.CAT.BestPractices.SqlAzure.Framework
-// namespace Microsoft.SqlServer.Management.Common
-
-using System;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- ///
- /// The special type of exception that provides managed exit from a retry loop. The user code can use this
- /// exception to notify the retry policy that no further retry attempts are required.
- ///
- [Serializable]
- internal sealed class RetryLimitExceededException : Exception
- {
- internal RetryLimitExceededException() : base()
- {
- }
-
- internal RetryLimitExceededException(string m, Exception e) : base(m, e)
- {
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs
deleted file mode 100644
index 68f9beb8..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using Microsoft.Data.SqlClient;
-using System.Diagnostics;
-using Microsoft.SqlTools.Hosting.Utility;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- internal abstract partial class RetryPolicy
- {
- ///
- /// Provides the error detection logic for temporary faults that are commonly found during data transfer.
- ///
- internal class DataTransferErrorDetectionStrategy : ErrorDetectionStrategyBase
- {
- private static readonly DataTransferErrorDetectionStrategy instance = new DataTransferErrorDetectionStrategy();
-
- public static DataTransferErrorDetectionStrategy Instance
- {
- get { return instance; }
- }
-
- protected override bool CanRetrySqlException(SqlException sqlException)
- {
- // Enumerate through all errors found in the exception.
- foreach (SqlError err in sqlException.Errors)
- {
- RetryPolicyUtils.AppendThrottlingDataIfIsThrottlingError(sqlException, err);
- if (RetryPolicyUtils.IsNonRetryableDataTransferError(err.Number))
- {
- Logger.Write(TraceEventType.Error, string.Format(Resources.ExceptionCannotBeRetried, err.Number, err.Message));
- return false;
- }
- }
-
- // Default is to treat all SqlException as retriable.
- return true;
- }
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.IErrorDetectionStrategy.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.IErrorDetectionStrategy.cs
deleted file mode 100644
index 018296c6..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.IErrorDetectionStrategy.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using Microsoft.Data.SqlClient;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- internal abstract partial class RetryPolicy
- {
- public interface IErrorDetectionStrategy
- {
- ///
- /// Determines whether the specified exception represents a temporary failure that can be compensated by a retry.
- ///
- /// The exception object to be verified.
- /// True if the specified exception is considered as temporary, otherwise false.
- bool CanRetry(Exception ex);
-
- ///
- /// Determines whether the specified exception can be ignored.
- ///
- /// The exception object to be verified.
- /// True if the specified exception is considered as non-harmful.
- bool ShouldIgnoreError(Exception ex);
- }
-
- ///
- /// Base class with common retry logic. The core behavior for retrying non SqlExceptions is the same
- /// across retry policies
- ///
- internal abstract class ErrorDetectionStrategyBase : IErrorDetectionStrategy
- {
- public bool CanRetry(Exception ex)
- {
- if (ex != null)
- {
- SqlException sqlException;
- if ((sqlException = ex as SqlException) != null)
- {
- return CanRetrySqlException(sqlException);
- }
- if (ex is InvalidOperationException)
- {
- // Operations can throw this exception if the connection is killed before the write starts to the server
- // However if there's an inner SqlException it may be a CLR load failure or other non-transient error
- if (ex.InnerException != null
- && ex.InnerException is SqlException)
- {
- return CanRetry(ex.InnerException);
- }
- return true;
- }
- if (ex is TimeoutException)
- {
- return true;
- }
- }
-
- return false;
- }
-
- public bool ShouldIgnoreError(Exception ex)
- {
- if (ex != null)
- {
- SqlException sqlException;
- if ((sqlException = ex as SqlException) != null)
- {
- return ShouldIgnoreSqlException(sqlException);
- }
- if (ex is InvalidOperationException)
- {
- // Operations can throw this exception if the connection is killed before the write starts to the server
- // However if there's an inner SqlException it may be a CLR load failure or other non-transient error
- if (ex.InnerException != null
- && ex.InnerException is SqlException)
- {
- return ShouldIgnoreError(ex.InnerException);
- }
- }
- }
-
- return false;
- }
-
- protected virtual bool ShouldIgnoreSqlException(SqlException sqlException)
- {
- return false;
- }
-
- protected abstract bool CanRetrySqlException(SqlException sqlException);
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.NetworkConnectivityErrorStrategy.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.NetworkConnectivityErrorStrategy.cs
deleted file mode 100644
index 0ab2bfa1..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.NetworkConnectivityErrorStrategy.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using Microsoft.Data.SqlClient;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- internal abstract partial class RetryPolicy
- {
- ///
- /// Provides the error detection logic for temporary faults that are commonly found in SQL Azure.
- /// The same errors CAN occur on premise also, but they are not seen as often.
- ///
- internal sealed class NetworkConnectivityErrorDetectionStrategy : ErrorDetectionStrategyBase
- {
- private static NetworkConnectivityErrorDetectionStrategy instance = new NetworkConnectivityErrorDetectionStrategy();
-
- public static NetworkConnectivityErrorDetectionStrategy Instance
- {
- get { return instance; }
- }
-
- protected override bool CanRetrySqlException(SqlException sqlException)
- {
- // Enumerate through all errors found in the exception.
- bool foundRetryableError = false;
- foreach (SqlError err in sqlException.Errors)
- {
- RetryPolicyUtils.AppendThrottlingDataIfIsThrottlingError(sqlException, err);
- if (!RetryPolicyUtils.IsRetryableNetworkConnectivityError(err.Number))
- {
- // If any error is not retryable then cannot retry
- return false;
- }
- foundRetryableError = true;
- }
- return foundRetryableError;
- }
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy.cs
deleted file mode 100644
index 8914a34e..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryAndIgnorableErrorDetectionStrategy.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System.Collections.Generic;
-using Microsoft.Data.SqlClient;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- internal abstract partial class RetryPolicy
- {
- ///
- /// Provides the error detection logic for temporary faults that are commonly found in SQL Azure.
- /// This strategy is similar to SqlAzureTemporaryErrorDetectionStrategy, but it exposes ways
- /// to accept a certain exception and treat it as passing.
- /// For example, if we are retrying, and we get a failure that an object already exists, we might
- /// want to consider this as passing since the first execution that has timed out (or failed for some other temporary error)
- /// might have managed to create the object.
- ///
- internal class SqlAzureTemporaryAndIgnorableErrorDetectionStrategy : ErrorDetectionStrategyBase
- {
- ///
- /// Azure error that can be ignored
- ///
- private readonly IList ignorableAzureErrors = null;
-
- public SqlAzureTemporaryAndIgnorableErrorDetectionStrategy(params int[] ignorableErrors)
- {
- this.ignorableAzureErrors = ignorableErrors;
- }
-
- protected override bool CanRetrySqlException(SqlException sqlException)
- {
- // Enumerate through all errors found in the exception.
- bool foundRetryableError = false;
- foreach (SqlError err in sqlException.Errors)
- {
- RetryPolicyUtils.AppendThrottlingDataIfIsThrottlingError(sqlException, err);
- if (!RetryPolicyUtils.IsRetryableAzureError(err.Number))
- {
- return false;
- }
-
- foundRetryableError = true;
- }
- return foundRetryableError;
- }
-
- protected override bool ShouldIgnoreSqlException(SqlException sqlException)
- {
- int errorNumber = sqlException.Number;
-
- if (ignorableAzureErrors == null)
- {
- return false;
- }
-
- return ignorableAzureErrors.Contains(errorNumber);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryErrorDetectionStrategy.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryErrorDetectionStrategy.cs
deleted file mode 100644
index 4e364391..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.SqlAzureTemporaryErrorDetectionStrategy.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using Microsoft.Data.SqlClient;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- internal abstract partial class RetryPolicy
- {
- ///
- /// Provides the error detection logic for temporary faults that are commonly found in SQL Azure.
- /// The same errors CAN occur on premise also, but they are not seen as often.
- ///
- internal sealed class SqlAzureTemporaryErrorDetectionStrategy : ErrorDetectionStrategyBase
- {
- private static SqlAzureTemporaryErrorDetectionStrategy instance = new SqlAzureTemporaryErrorDetectionStrategy();
-
- public static SqlAzureTemporaryErrorDetectionStrategy Instance
- {
- get { return instance; }
- }
-
- protected override bool CanRetrySqlException(SqlException sqlException)
- {
- // Enumerate through all errors found in the exception.
- bool foundRetryableError = false;
- foreach (SqlError err in sqlException.Errors)
- {
- RetryPolicyUtils.AppendThrottlingDataIfIsThrottlingError(sqlException, err);
- if (!RetryPolicyUtils.IsRetryableAzureError(err.Number))
- {
- // If any error is not retryable then cannot retry
- return false;
- }
- foundRetryableError = true;
- }
- return foundRetryableError;
- }
- }
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.ThrottleReason.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.ThrottleReason.cs
deleted file mode 100644
index de96ac14..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.ThrottleReason.cs
+++ /dev/null
@@ -1,357 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-using System;
-using System.Collections.Generic;
-using Microsoft.Data.SqlClient;
-using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- internal abstract partial class RetryPolicy
- {
- ///
- /// Implements an object holding the decoded reason code returned from SQL Azure when encountering throttling conditions.
- ///
- [Serializable]
- public class ThrottlingReason
- {
- ///
- /// Returns the error number that corresponds to throttling conditions reported by SQL Azure.
- ///
- public const int ThrottlingErrorNumber = 40501;
-
- ///
- /// Gets an unknown throttling condition in the event the actual throttling condition cannot be determined.
- ///
- public static ThrottlingReason Unknown
- {
- get
- {
- var unknownCondition = new ThrottlingReason() { ThrottlingMode = ThrottlingMode.Unknown };
- unknownCondition.throttledResources.Add(Tuple.Create(ThrottledResourceType.Unknown, ThrottlingType.Unknown));
-
- return unknownCondition;
- }
- }
-
- ///
- /// Maintains a collection of key-value pairs where a key is resource type and a value is the type of throttling applied to the given resource type.
- ///
- private readonly IList> throttledResources = new List>(9);
-
- ///
- /// Provides a compiled regular expression used for extracting the reason code from the error message.
- ///
- private static readonly Regex sqlErrorCodeRegEx = new Regex(@"Code:\s*(\d+)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
-
- ///
- /// Gets the value that reflects the throttling mode in SQL Azure.
- ///
- public ThrottlingMode ThrottlingMode
- {
- get;
- private set;
- }
-
- ///
- /// Gets the list of resources in SQL Azure that were subject to throttling conditions.
- ///
- public IEnumerable> ThrottledResources
- {
- get
- {
- return this.throttledResources;
- }
- }
-
- ///
- /// Determines throttling conditions from the specified SQL exception.
- ///
- /// The object containing information relevant to an error returned by SQL Server when encountering throttling conditions.
- /// An instance of the object holding the decoded reason codes returned from SQL Azure upon encountering throttling conditions.
- public static ThrottlingReason FromException(SqlException ex)
- {
- if (ex != null)
- {
- foreach (SqlError error in ex.Errors)
- {
- if (error.Number == ThrottlingErrorNumber)
- {
- return FromError(error);
- }
- }
- }
-
- return Unknown;
- }
-
- ///
- /// Determines the throttling conditions from the specified SQL error.
- ///
- /// The object containing information relevant to a warning or error returned by SQL Server.
- /// An instance of the object holding the decoded reason codes returned from SQL Azure when encountering throttling conditions.
- public static ThrottlingReason FromError(SqlError error)
- {
- if (error != null)
- {
- var match = sqlErrorCodeRegEx.Match(error.Message);
- int reasonCode = 0;
-
- if (match.Success && Int32.TryParse(match.Groups[1].Value, out reasonCode))
- {
- return FromReasonCode(reasonCode);
- }
- }
-
- return Unknown;
- }
-
- ///
- /// Determines the throttling conditions from the specified reason code.
- ///
- /// The reason code returned by SQL Azure which contains the throttling mode and the exceeded resource types.
- /// An instance of the object holding the decoded reason codes returned from SQL Azure when encountering throttling conditions.
- public static ThrottlingReason FromReasonCode(int reasonCode)
- {
- if (reasonCode > 0)
- {
- // Decode throttling mode from the last 2 bits.
- ThrottlingMode throttlingMode = (ThrottlingMode)(reasonCode & 3);
-
- var condition = new ThrottlingReason() { ThrottlingMode = throttlingMode };
-
- // Shift 8 bits to truncate throttling mode.
- int groupCode = reasonCode >> 8;
-
- // Determine throttling type for all well-known resources that may be subject to throttling conditions.
- condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.PhysicalDatabaseSpace, (ThrottlingType)(groupCode & 3)));
- condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.PhysicalLogSpace, (ThrottlingType)((groupCode = groupCode >> 2) & 3)));
- condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.LogWriteIODelay, (ThrottlingType)((groupCode = groupCode >> 2) & 3)));
- condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.DataReadIODelay, (ThrottlingType)((groupCode = groupCode >> 2) & 3)));
- condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.CPU, (ThrottlingType)((groupCode = groupCode >> 2) & 3)));
- condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.DatabaseSize, (ThrottlingType)((groupCode = groupCode >> 2) & 3)));
- condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.Internal, (ThrottlingType)((groupCode = groupCode >> 2) & 3)));
- condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.WorkerThreads, (ThrottlingType)((groupCode = groupCode >> 2) & 3)));
- condition.throttledResources.Add(Tuple.Create(ThrottledResourceType.Internal, (ThrottlingType)((groupCode = groupCode >> 2) & 3)));
-
- return condition;
- }
- else
- {
- return Unknown;
- }
- }
-
- ///
- /// Gets a value indicating whether physical data file space throttling was reported by SQL Azure.
- ///
- public bool IsThrottledOnDataSpace
- {
- get
- {
- return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.PhysicalDatabaseSpace).Count() > 0;
- }
- }
-
- ///
- /// Gets a value indicating whether physical log space throttling was reported by SQL Azure.
- ///
- public bool IsThrottledOnLogSpace
- {
- get
- {
- return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.PhysicalLogSpace).Count() > 0;
- }
- }
-
- ///
- /// Gets a value indicating whether transaction activity throttling was reported by SQL Azure.
- ///
- public bool IsThrottledOnLogWrite
- {
- get { return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.LogWriteIODelay).Count() > 0; }
- }
-
- ///
- /// Gets a value indicating whether data read activity throttling was reported by SQL Azure.
- ///
- public bool IsThrottledOnDataRead
- {
- get { return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.DataReadIODelay).Count() > 0; }
- }
-
- ///
- /// Gets a value indicating whether CPU throttling was reported by SQL Azure.
- ///
- public bool IsThrottledOnCPU
- {
- get { return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.CPU).Count() > 0; }
- }
-
- ///
- /// Gets a value indicating whether database size throttling was reported by SQL Azure.
- ///
- public bool IsThrottledOnDatabaseSize
- {
- get { return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.DatabaseSize).Count() > 0; }
- }
-
- ///
- /// Gets a value indicating whether concurrent requests throttling was reported by SQL Azure.
- ///
- public bool IsThrottledOnWorkerThreads
- {
- get { return this.throttledResources.Where(x => x.Item1 == ThrottledResourceType.WorkerThreads).Count() > 0; }
- }
-
- ///
- /// Gets a value indicating whether throttling conditions were not determined with certainty.
- ///
- public bool IsUnknown
- {
- get { return ThrottlingMode == ThrottlingMode.Unknown; }
- }
-
- ///
- /// Returns a textual representation the current ThrottlingReason object including the information held with respect to throttled resources.
- ///
- /// A string that represents the current ThrottlingReason object.
- public override string ToString()
- {
- StringBuilder result = new StringBuilder();
-
- result.AppendFormat(Resources.Mode, ThrottlingMode);
-
- var resources = this.throttledResources.Where(x => x.Item1 != ThrottledResourceType.Internal).
- Select, string>(x => String.Format(CultureInfo.CurrentCulture, Resources.ThrottlingTypeInfo, x.Item1, x.Item2)).
- OrderBy(x => x).ToArray();
-
- result.Append(String.Join(", ", resources));
-
- return result.ToString();
- }
- }
-
- #region ThrottlingMode enumeration
- ///
- /// Defines the possible throttling modes in SQL Azure.
- ///
- public enum ThrottlingMode
- {
- ///
- /// Corresponds to "No Throttling" throttling mode whereby all SQL statements can be processed.
- ///
- NoThrottling = 0,
-
- ///
- /// Corresponds to "Reject Update / Insert" throttling mode whereby SQL statements such as INSERT, UPDATE, CREATE TABLE and CREATE INDEX are rejected.
- ///
- RejectUpdateInsert = 1,
-
- ///
- /// Corresponds to "Reject All Writes" throttling mode whereby SQL statements such as INSERT, UPDATE, DELETE, CREATE, DROP are rejected.
- ///
- RejectAllWrites = 2,
-
- ///
- /// Corresponds to "Reject All" throttling mode whereby all SQL statements are rejected.
- ///
- RejectAll = 3,
-
- ///
- /// Corresponds to an unknown throttling mode whereby throttling mode cannot be determined with certainty.
- ///
- Unknown = -1
- }
- #endregion
-
- #region ThrottlingType enumeration
- ///
- /// Defines the possible throttling types in SQL Azure.
- ///
- public enum ThrottlingType
- {
- ///
- /// Indicates that no throttling was applied to a given resource.
- ///
- None = 0,
-
- ///
- /// Corresponds to a Soft throttling type. Soft throttling is applied when machine resources such as, CPU, IO, storage, and worker threads exceed
- /// predefined safety thresholds despite the load balancer’s best efforts.
- ///
- Soft = 1,
-
- ///
- /// Corresponds to a Hard throttling type. Hard throttling is applied when the machine is out of resources, for example storage space.
- /// With hard throttling, no new connections are allowed to the databases hosted on the machine until resources are freed up.
- ///
- Hard = 2,
-
- ///
- /// Corresponds to an unknown throttling type in the event when the throttling type cannot be determined with certainty.
- ///
- Unknown = 3
- }
- #endregion
-
- #region ThrottledResourceType enumeration
- ///
- /// Defines the types of resources in SQL Azure which may be subject to throttling conditions.
- ///
- public enum ThrottledResourceType
- {
- ///
- /// Corresponds to "Physical Database Space" resource which may be subject to throttling.
- ///
- PhysicalDatabaseSpace = 0,
-
- ///
- /// Corresponds to "Physical Log File Space" resource which may be subject to throttling.
- ///
- PhysicalLogSpace = 1,
-
- ///
- /// Corresponds to "Transaction Log Write IO Delay" resource which may be subject to throttling.
- ///
- LogWriteIODelay = 2,
-
- ///
- /// Corresponds to "Database Read IO Delay" resource which may be subject to throttling.
- ///
- DataReadIODelay = 3,
-
- ///
- /// Corresponds to "CPU" resource which may be subject to throttling.
- ///
- CPU = 4,
-
- ///
- /// Corresponds to "Database Size" resource which may be subject to throttling.
- ///
- DatabaseSize = 5,
-
- ///
- /// Corresponds to "SQL Worker Thread Pool" resource which may be subject to throttling.
- ///
- WorkerThreads = 7,
-
- ///
- /// Corresponds to an internal resource which may be subject to throttling.
- ///
- Internal = 6,
-
- ///
- /// Corresponds to an unknown resource type in the event when the actual resource cannot be determined with certainty.
- ///
- Unknown = -1
- }
- #endregion
- }
-}
diff --git a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.cs b/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.cs
deleted file mode 100644
index 26c579c0..00000000
--- a/external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.cs
+++ /dev/null
@@ -1,542 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-// This code is copied from the source described in the comment below.
-
-// =======================================================================================
-// Microsoft Windows Server AppFabric Customer Advisory Team (CAT) Best Practices Series
-//
-// This sample is supplemental to the technical guidance published on the community
-// blog at http://blogs.msdn.com/appfabriccat/ and copied from
-// sqlmain ./sql/manageability/mfx/common/
-//
-// =======================================================================================
-// Copyright © 2012 Microsoft Corporation. All rights reserved.
-//
-// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE RISK OF USING IT.
-// =======================================================================================
-
-// namespace Microsoft.SQL.CAT.BestPractices.SqlAzure.Framework
-// namespace Microsoft.SqlServer.Management.Common
-
-using System;
-using Microsoft.Data.SqlClient;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using System.Globalization;
-using System.Threading;
-using Microsoft.SqlTools.Hosting.Utility;
-
-namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
-{
- ///
- /// Implements a policy defining and implementing the retry mechanism for unreliable actions.
- ///
- internal abstract partial class RetryPolicy
- {
- ///
- /// Defines a callback delegate which will be invoked whenever a retry condition is encountered.
- ///
- /// The state of current retry attempt.
- internal delegate void RetryCallbackDelegate(RetryState retryState);
-
- ///
- /// Defines a callback delegate which will be invoked whenever an error is ignored on retry.
- ///
- /// The state of current retry attempt.
- internal delegate void IgnoreErrorCallbackDelegate(RetryState retryState);
-
- private readonly IErrorDetectionStrategy _errorDetectionStrategy;
-
- protected RetryPolicy(IErrorDetectionStrategy strategy)
- {
- Contract.Assert(strategy != null);
-
- _errorDetectionStrategy = strategy;
- this.FastFirstRetry = true;
-
- //TODO Defect 1078447 Validate whether CommandTimeout needs to be used differently in schema/data scenarios
- this.CommandTimeoutInSeconds = AmbientSettings.LongRunningQueryTimeoutSeconds;
- }
-
- ///
- /// An instance of a callback delegate which will be invoked whenever a retry condition is encountered.
- ///
- public event RetryCallbackDelegate RetryOccurred;
-
- ///
- /// An instance of a callback delegate which will be invoked whenever an error is ignored on retry.
- ///
- public event IgnoreErrorCallbackDelegate IgnoreErrorOccurred;
-
- ///
- /// Gets or sets a value indicating whether or not the very first retry attempt will be made immediately
- /// whereas the subsequent retries will remain subject to retry interval.
- ///
- public bool FastFirstRetry { get; set; }
-
- ///
- /// Gets or sets the timeout in seconds of sql commands
- ///
- public int CommandTimeoutInSeconds
- {
- get;
- set;
- }
-
- ///
- /// Gets the error detection strategy of this retry policy
- ///
- internal IErrorDetectionStrategy ErrorDetectionStrategy
- {
- get
- {
- return _errorDetectionStrategy;
- }
- }
-
- ///
- /// We should only ignore errors if they happen after the first retry.
- /// This flag is used to allow the ignore even on first try, for testing purposes.
- ///
- ///
- /// This flag is currently being used for TESTING PURPOSES ONLY.
- ///
- internal bool ShouldIgnoreOnFirstTry
- {
- get;
- set;
- }
-
- protected static bool IsLessThanMaxRetryCount(int currentRetryCount, int maxRetryCount)
- {
- return currentRetryCount <= maxRetryCount;
- }
-
- ///
- /// Repetitively executes the specified action while it satisfies the current retry policy.
- ///
- /// A delegate representing the executable action which doesn't return any results.
- /// Cancellation token to cancel action between retries.
- public void ExecuteAction(Action action, CancellationToken? token = null)
- {
- ExecuteAction(
- _ => action(), token);
- }
-
- ///
- /// Repetitively executes the specified action while it satisfies the current retry policy.
- ///
- /// A delegate representing the executable action which doesn't return any results.
- /// Cancellation token to cancel action between retries.
- public void ExecuteAction(Action action, CancellationToken? token = null)
- {
- ExecuteAction