mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
3326 Kusto HTTPS url fix (#1086)
* 3326 Removed sqlConnection.Open from CreateSqlConnection in ConnectionService. * 3326 Removed unused variables and functions from ConnectedBindingContext, ConnectedBindingQueue, IBindingContext, and IConnectedBindingQueue * 3326 Removed unused constant SqlAzureEdition and unused functions CreateSqlConnection and CreateServerConnection from ConnectionService. Removed ServerConnection, MetadataDisplayInfoProvider, Binder, and SmoMetaDataProvider from ConnectedBindingContext. Deleted SqlConnectionOpener and ISqlConnectionOpener.
This commit is contained in:
@@ -31,9 +31,8 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ConnectionService
|
public class ConnectionService
|
||||||
{
|
{
|
||||||
public const string AdminConnectionPrefix = "ADMIN:";
|
private const string AdminConnectionPrefix = "ADMIN:";
|
||||||
internal const string PasswordPlaceholder = "******";
|
private const string PasswordPlaceholder = "******";
|
||||||
private const string SqlAzureEdition = "SQL Azure";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Singleton service instance
|
/// Singleton service instance
|
||||||
@@ -984,7 +983,7 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
/// Build a connection string builder a connection details instance
|
/// Build a connection string builder a connection details instance
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connectionDetails"></param>
|
/// <param name="connectionDetails"></param>
|
||||||
public static SqlConnectionStringBuilder CreateConnectionStringBuilder(ConnectionDetails connectionDetails)
|
private static SqlConnectionStringBuilder CreateConnectionStringBuilder(ConnectionDetails connectionDetails)
|
||||||
{
|
{
|
||||||
SqlConnectionStringBuilder connectionBuilder;
|
SqlConnectionStringBuilder connectionBuilder;
|
||||||
|
|
||||||
@@ -1359,63 +1358,6 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 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
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="connInfo">The connection info to connect with</param>
|
|
||||||
/// <param name="featureName">A plaintext string that will be included in the application name for the connection</param>
|
|
||||||
/// <returns>A SqlConnection created with the given connection info</returns>
|
|
||||||
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 = BuildConnectionString(connInfo.ConnectionDetails);
|
|
||||||
|
|
||||||
// restore original values
|
|
||||||
connInfo.ConnectionDetails.ConnectTimeout = originalTimeout;
|
|
||||||
connInfo.ConnectionDetails.PersistSecurityInfo = originalPersistSecurityInfo;
|
|
||||||
connInfo.ConnectionDetails.Pooling = originalPooling;
|
|
||||||
|
|
||||||
// open a dedicated binding server connection
|
|
||||||
using (SqlConnection sqlConn = new SqlConnection(connectionString))
|
|
||||||
{
|
|
||||||
// Fill in Azure authentication token if needed
|
|
||||||
if (connInfo.ConnectionDetails.AzureAccountToken != null)
|
|
||||||
{
|
|
||||||
sqlConn.AccessToken = connInfo.ConnectionDetails.AzureAccountToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create and open a new SqlConnection from a ConnectionInfo object
|
/// 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
|
/// Note: we need to audit all uses of this method to determine why we're
|
||||||
@@ -1445,23 +1387,6 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create and open a new ServerConnection from a ConnectionInfo object.
|
|
||||||
/// This calls ConnectionService.OpenSqlConnection and then creates a
|
|
||||||
/// ServerConnection from it.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="connInfo">The connection info to connect with</param>
|
|
||||||
/// <param name="featureName">A plaintext string that will be included in the application name for the connection</param>
|
|
||||||
/// <returns>A ServerConnection (wrapping a SqlConnection) created with the given connection info</returns>
|
|
||||||
internal static ServerConnection OpenServerConnection(ConnectionInfo connInfo, string featureName = null)
|
|
||||||
{
|
|
||||||
SqlConnection sqlConnection = OpenSqlConnection(connInfo, featureName);
|
|
||||||
|
|
||||||
return connInfo.ConnectionDetails.AzureAccountToken != null
|
|
||||||
? new ServerConnection(sqlConnection, new AzureAccessToken(connInfo.ConnectionDetails.AzureAccountToken))
|
|
||||||
: new ServerConnection(sqlConnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EnsureConnectionIsOpen(ReliableDataSourceConnection conn, bool forceReopen = false)
|
public static void EnsureConnectionIsOpen(ReliableDataSourceConnection conn, bool forceReopen = false)
|
||||||
{
|
{
|
||||||
// verify that the connection is open
|
// verify that the connection is open
|
||||||
|
|||||||
@@ -202,15 +202,6 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
{
|
{
|
||||||
// disconnect existing connection
|
// disconnect existing connection
|
||||||
var bindingContext = this.BindingContextMap[key];
|
var bindingContext = this.BindingContextMap[key];
|
||||||
if (bindingContext.ServerConnection != null && bindingContext.ServerConnection.IsOpen)
|
|
||||||
{
|
|
||||||
// Disconnecting can take some time so run it in a separate task so that it doesn't block removal
|
|
||||||
Task.Run(() =>
|
|
||||||
{
|
|
||||||
bindingContext.ServerConnection.Cancel();
|
|
||||||
bindingContext.ServerConnection.Disconnect();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove key from the map
|
// remove key from the map
|
||||||
this.BindingContextMap.Remove(key);
|
this.BindingContextMap.Remove(key);
|
||||||
@@ -483,17 +474,6 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
{
|
{
|
||||||
_itemQueuedEvent.Dispose();
|
_itemQueuedEvent.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.BindingContextMap != null)
|
|
||||||
{
|
|
||||||
foreach (var item in this.BindingContextMap)
|
|
||||||
{
|
|
||||||
if (item.Value != null && item.Value.ServerConnection != null && item.Value.ServerConnection.SqlConnectionObject != null)
|
|
||||||
{
|
|
||||||
item.Value.ServerConnection.SqlConnectionObject.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsExceptionOfType(Exception ex, Type t)
|
private bool IsExceptionOfType(Exception ex, Type t)
|
||||||
|
|||||||
@@ -3,14 +3,7 @@
|
|||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
//
|
//
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.SqlServer.Management.Common;
|
|
||||||
using Microsoft.SqlServer.Management.SmoMetadataProvider;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.Binder;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.Common;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.MetadataProvider;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.Parser;
|
|
||||||
using Microsoft.Kusto.ServiceLayer.DataSource;
|
using Microsoft.Kusto.ServiceLayer.DataSource;
|
||||||
|
|
||||||
namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
||||||
@@ -20,11 +13,7 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ConnectedBindingContext : IBindingContext
|
public class ConnectedBindingContext : IBindingContext
|
||||||
{
|
{
|
||||||
private ParseOptions parseOptions;
|
private readonly ManualResetEvent bindingLock;
|
||||||
|
|
||||||
private ManualResetEvent bindingLock;
|
|
||||||
|
|
||||||
private ServerConnection serverConnection;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IDataSource DataSource { get; set; }
|
public IDataSource DataSource { get; set; }
|
||||||
@@ -36,7 +25,6 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
{
|
{
|
||||||
this.bindingLock = new ManualResetEvent(initialState: true);
|
this.bindingLock = new ManualResetEvent(initialState: true);
|
||||||
this.BindingTimeout = ConnectedBindingQueue.DefaultBindingTimeout;
|
this.BindingTimeout = ConnectedBindingQueue.DefaultBindingTimeout;
|
||||||
this.MetadataDisplayInfoProvider = new MetadataDisplayInfoProvider();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -44,39 +32,6 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsConnected { get; set; }
|
public bool IsConnected { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the binding server connection
|
|
||||||
/// </summary>
|
|
||||||
public ServerConnection ServerConnection
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this.serverConnection;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
this.serverConnection = value;
|
|
||||||
|
|
||||||
// reset the parse options so the get recreated for the current connection
|
|
||||||
this.parseOptions = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the metadata display info provider
|
|
||||||
/// </summary>
|
|
||||||
public MetadataDisplayInfoProvider MetadataDisplayInfoProvider { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the SMO metadata provider
|
|
||||||
/// </summary>
|
|
||||||
public SmoMetadataProvider SmoMetadataProvider { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the binder
|
|
||||||
/// </summary>
|
|
||||||
public IBinder Binder { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the binding lock object
|
/// Gets the binding lock object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -91,130 +46,6 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the binding operation timeout in milliseconds
|
/// Gets or sets the binding operation timeout in milliseconds
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int BindingTimeout { get; set; }
|
public int BindingTimeout { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the Language Service ServerVersion
|
|
||||||
/// </summary>
|
|
||||||
public ServerVersion ServerVersion
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this.ServerConnection != null
|
|
||||||
? this.ServerConnection.ServerVersion
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current DataEngineType
|
|
||||||
/// </summary>
|
|
||||||
public DatabaseEngineType DatabaseEngineType
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this.ServerConnection != null
|
|
||||||
? this.ServerConnection.DatabaseEngineType
|
|
||||||
: DatabaseEngineType.Standalone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current connections TransactSqlVersion
|
|
||||||
/// </summary>
|
|
||||||
public TransactSqlVersion TransactSqlVersion
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this.IsConnected
|
|
||||||
? GetTransactSqlVersion(this.ServerVersion)
|
|
||||||
: TransactSqlVersion.Current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current DatabaseCompatibilityLevel
|
|
||||||
/// </summary>
|
|
||||||
public DatabaseCompatibilityLevel DatabaseCompatibilityLevel
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this.IsConnected
|
|
||||||
? GetDatabaseCompatibilityLevel(this.ServerVersion)
|
|
||||||
: DatabaseCompatibilityLevel.Current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current ParseOptions
|
|
||||||
/// </summary>
|
|
||||||
public ParseOptions ParseOptions
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (this.parseOptions == null)
|
|
||||||
{
|
|
||||||
this.parseOptions = new ParseOptions(
|
|
||||||
batchSeparator: LanguageService.DefaultBatchSeperator,
|
|
||||||
isQuotedIdentifierSet: true,
|
|
||||||
compatibilityLevel: DatabaseCompatibilityLevel,
|
|
||||||
transactSqlVersion: TransactSqlVersion);
|
|
||||||
}
|
|
||||||
return this.parseOptions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the database compatibility level from a server version
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="serverVersion"></param>
|
|
||||||
private static DatabaseCompatibilityLevel GetDatabaseCompatibilityLevel(ServerVersion serverVersion)
|
|
||||||
{
|
|
||||||
int versionMajor = Math.Max(serverVersion.Major, 8);
|
|
||||||
|
|
||||||
switch (versionMajor)
|
|
||||||
{
|
|
||||||
case 8:
|
|
||||||
return DatabaseCompatibilityLevel.Version80;
|
|
||||||
case 9:
|
|
||||||
return DatabaseCompatibilityLevel.Version90;
|
|
||||||
case 10:
|
|
||||||
return DatabaseCompatibilityLevel.Version100;
|
|
||||||
case 11:
|
|
||||||
return DatabaseCompatibilityLevel.Version110;
|
|
||||||
case 12:
|
|
||||||
return DatabaseCompatibilityLevel.Version120;
|
|
||||||
case 13:
|
|
||||||
return DatabaseCompatibilityLevel.Version130;
|
|
||||||
default:
|
|
||||||
return DatabaseCompatibilityLevel.Current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the transaction sql version from a server version
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="serverVersion"></param>
|
|
||||||
private static TransactSqlVersion GetTransactSqlVersion(ServerVersion serverVersion)
|
|
||||||
{
|
|
||||||
int versionMajor = Math.Max(serverVersion.Major, 9);
|
|
||||||
|
|
||||||
switch (versionMajor)
|
|
||||||
{
|
|
||||||
case 9:
|
|
||||||
case 10:
|
|
||||||
// In case of 10.0 we still use Version 10.5 as it is the closest available.
|
|
||||||
return TransactSqlVersion.Version105;
|
|
||||||
case 11:
|
|
||||||
return TransactSqlVersion.Version110;
|
|
||||||
case 12:
|
|
||||||
return TransactSqlVersion.Version120;
|
|
||||||
case 13:
|
|
||||||
return TransactSqlVersion.Version130;
|
|
||||||
default:
|
|
||||||
return TransactSqlVersion.Current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,8 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Composition;
|
using System.Composition;
|
||||||
using Microsoft.SqlServer.Management.SmoMetadataProvider;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.Binder;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.MetadataProvider;
|
|
||||||
using Microsoft.Kusto.ServiceLayer.Connection;
|
using Microsoft.Kusto.ServiceLayer.Connection;
|
||||||
using Microsoft.Kusto.ServiceLayer.Connection.Contracts;
|
using Microsoft.Kusto.ServiceLayer.Connection.Contracts;
|
||||||
using Microsoft.Kusto.ServiceLayer.SqlContext;
|
|
||||||
using Microsoft.Kusto.ServiceLayer.Workspace;
|
|
||||||
using Microsoft.Kusto.ServiceLayer.DataSource;
|
using Microsoft.Kusto.ServiceLayer.DataSource;
|
||||||
|
|
||||||
namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
||||||
@@ -23,21 +18,11 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
public class ConnectedBindingQueue : BindingQueue<ConnectedBindingContext>, IConnectedBindingQueue
|
public class ConnectedBindingQueue : BindingQueue<ConnectedBindingContext>, IConnectedBindingQueue
|
||||||
{
|
{
|
||||||
internal const int DefaultBindingTimeout = 500;
|
internal const int DefaultBindingTimeout = 500;
|
||||||
private readonly ISqlConnectionOpener _connectionOpener;
|
|
||||||
private readonly IDataSourceFactory _dataSourceFactory;
|
private readonly IDataSourceFactory _dataSourceFactory;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current settings
|
|
||||||
/// </summary>
|
|
||||||
private SqlToolsSettings CurrentSettings
|
|
||||||
{
|
|
||||||
get { return WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[ImportingConstructor]
|
[ImportingConstructor]
|
||||||
public ConnectedBindingQueue(ISqlConnectionOpener sqlConnectionOpener, IDataSourceFactory dataSourceFactory)
|
public ConnectedBindingQueue(IDataSourceFactory dataSourceFactory)
|
||||||
{
|
{
|
||||||
_connectionOpener = sqlConnectionOpener;
|
|
||||||
_dataSourceFactory = dataSourceFactory;
|
_dataSourceFactory = dataSourceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,52 +52,6 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
return Uri.EscapeUriString(key);
|
return Uri.EscapeUriString(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Generate a unique key based on the ConnectionInfo object
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="serverName"></param>
|
|
||||||
/// <param name="databaseName"></param>
|
|
||||||
private string GetConnectionContextKey(string serverName, string databaseName)
|
|
||||||
{
|
|
||||||
return string.Format("{0}_{1}",
|
|
||||||
serverName ?? "NULL",
|
|
||||||
databaseName ?? "NULL");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CloseConnections(string serverName, string databaseName, int millisecondsTimeout)
|
|
||||||
{
|
|
||||||
string connectionKey = GetConnectionContextKey(serverName, databaseName);
|
|
||||||
var contexts = GetBindingContexts(connectionKey);
|
|
||||||
foreach (var bindingContext in contexts)
|
|
||||||
{
|
|
||||||
if (bindingContext.BindingLock.WaitOne(millisecondsTimeout))
|
|
||||||
{
|
|
||||||
bindingContext.ServerConnection.Disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenConnections(string serverName, string databaseName, int millisecondsTimeout)
|
|
||||||
{
|
|
||||||
string connectionKey = GetConnectionContextKey(serverName, databaseName);
|
|
||||||
var contexts = GetBindingContexts(connectionKey);
|
|
||||||
foreach (var bindingContext in contexts)
|
|
||||||
{
|
|
||||||
if (bindingContext.BindingLock.WaitOne(millisecondsTimeout))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
bindingContext.ServerConnection.Connect();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
//TODO: remove the binding context?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveBindingContext(ConnectionInfo connInfo)
|
public void RemoveBindingContext(ConnectionInfo connInfo)
|
||||||
{
|
{
|
||||||
string connectionKey = GetConnectionContextKey(connInfo.ConnectionDetails);
|
string connectionKey = GetConnectionContextKey(connInfo.ConnectionDetails);
|
||||||
@@ -157,24 +96,10 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
bindingContext.BindingLock.Reset();
|
bindingContext.BindingLock.Reset();
|
||||||
|
|
||||||
// populate the binding context to work with the SMO metadata provider
|
|
||||||
bindingContext.ServerConnection = _connectionOpener.OpenServerConnection(connInfo, featureName);
|
|
||||||
|
|
||||||
string connectionString = ConnectionService.BuildConnectionString(connInfo.ConnectionDetails);
|
string connectionString = ConnectionService.BuildConnectionString(connInfo.ConnectionDetails);
|
||||||
bindingContext.DataSource = _dataSourceFactory.Create(DataSourceType.Kusto, connectionString, connInfo.ConnectionDetails.AzureAccountToken);
|
bindingContext.DataSource = _dataSourceFactory.Create(DataSourceType.Kusto, connectionString, connInfo.ConnectionDetails.AzureAccountToken);
|
||||||
|
bindingContext.BindingTimeout = DefaultBindingTimeout;
|
||||||
if (needMetadata)
|
|
||||||
{
|
|
||||||
bindingContext.SmoMetadataProvider = SmoMetadataProvider.CreateConnectedProvider(bindingContext.ServerConnection);
|
|
||||||
bindingContext.MetadataDisplayInfoProvider = new MetadataDisplayInfoProvider();
|
|
||||||
bindingContext.MetadataDisplayInfoProvider.BuiltInCasing =
|
|
||||||
this.CurrentSettings.SqlTools.IntelliSense.LowerCaseSuggestions.Value
|
|
||||||
? CasingStyle.Lowercase : CasingStyle.Uppercase;
|
|
||||||
bindingContext.Binder = BinderProvider.CreateBinder(bindingContext.SmoMetadataProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
bindingContext.BindingTimeout = ConnectedBindingQueue.DefaultBindingTimeout;
|
|
||||||
bindingContext.IsConnected = true;
|
bindingContext.IsConnected = true;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
|
|||||||
@@ -4,12 +4,6 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.SqlServer.Management.Common;
|
|
||||||
using Microsoft.SqlServer.Management.SmoMetadataProvider;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.Binder;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.Common;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.MetadataProvider;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.Parser;
|
|
||||||
using Microsoft.Kusto.ServiceLayer.DataSource;
|
using Microsoft.Kusto.ServiceLayer.DataSource;
|
||||||
|
|
||||||
|
|
||||||
@@ -25,31 +19,11 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsConnected { get; set; }
|
bool IsConnected { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the binding server connection
|
|
||||||
/// </summary>
|
|
||||||
ServerConnection ServerConnection { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets data source interface
|
/// Gets or sets data source interface
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IDataSource DataSource { get; set; }
|
IDataSource DataSource { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the metadata display info provider
|
|
||||||
/// </summary>
|
|
||||||
MetadataDisplayInfoProvider MetadataDisplayInfoProvider { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the SMO metadata provider
|
|
||||||
/// </summary>
|
|
||||||
SmoMetadataProvider SmoMetadataProvider { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the binder
|
|
||||||
/// </summary>
|
|
||||||
IBinder Binder { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the binding lock object
|
/// Gets the binding lock object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -59,30 +33,5 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
/// Gets or sets the binding operation timeout in milliseconds
|
/// Gets or sets the binding operation timeout in milliseconds
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int BindingTimeout { get; set; }
|
int BindingTimeout { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the current connection parse options
|
|
||||||
/// </summary>
|
|
||||||
ParseOptions ParseOptions { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the current connection server version
|
|
||||||
/// </summary>
|
|
||||||
ServerVersion ServerVersion { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the database engine type
|
|
||||||
/// </summary>
|
|
||||||
DatabaseEngineType DatabaseEngineType { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the T-SQL version
|
|
||||||
/// </summary>
|
|
||||||
TransactSqlVersion TransactSqlVersion { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the database compatibility level
|
|
||||||
/// </summary>
|
|
||||||
DatabaseCompatibilityLevel DatabaseCompatibilityLevel { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|||||||
public interface IConnectedBindingQueue
|
public interface IConnectedBindingQueue
|
||||||
{
|
{
|
||||||
event BindingQueue<ConnectedBindingContext>.UnhandledExceptionDelegate OnUnhandledException;
|
event BindingQueue<ConnectedBindingContext>.UnhandledExceptionDelegate OnUnhandledException;
|
||||||
|
|
||||||
void CloseConnections(string serverName, string databaseName, int millisecondsTimeout);
|
|
||||||
void OpenConnections(string serverName, string databaseName, int millisecondsTimeout);
|
|
||||||
string AddConnectionContext(ConnectionInfo connInfo, bool needMetadata, string featureName = null, bool overwrite = false);
|
string AddConnectionContext(ConnectionInfo connInfo, bool needMetadata, string featureName = null, bool overwrite = false);
|
||||||
void Dispose();
|
void Dispose();
|
||||||
bool IsBindingContextConnected(string key);
|
bool IsBindingContextConnected(string key);
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
using Microsoft.Kusto.ServiceLayer.Connection;
|
|
||||||
using Microsoft.SqlServer.Management.Common;
|
|
||||||
|
|
||||||
namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|
||||||
{
|
|
||||||
public interface ISqlConnectionOpener
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Virtual method used to support mocking and testing
|
|
||||||
/// </summary>
|
|
||||||
ServerConnection OpenServerConnection(ConnectionInfo connInfo, string featureName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System.Composition;
|
|
||||||
using Microsoft.Kusto.ServiceLayer.Connection;
|
|
||||||
using Microsoft.SqlServer.Management.Common;
|
|
||||||
|
|
||||||
namespace Microsoft.Kusto.ServiceLayer.LanguageServices
|
|
||||||
{
|
|
||||||
[Export(typeof(ISqlConnectionOpener))]
|
|
||||||
public class SqlConnectionOpener : ISqlConnectionOpener
|
|
||||||
{
|
|
||||||
public ServerConnection OpenServerConnection(ConnectionInfo connInfo, string featureName)
|
|
||||||
{
|
|
||||||
return ConnectionService.OpenServerConnection(connInfo, featureName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -412,19 +412,7 @@ namespace Microsoft.Kusto.ServiceLayer.ObjectExplorer
|
|||||||
}
|
}
|
||||||
response.Nodes = nodes;
|
response.Nodes = nodes;
|
||||||
response.ErrorMessage = node.ErrorMessage;
|
response.ErrorMessage = node.ErrorMessage;
|
||||||
try
|
|
||||||
{
|
|
||||||
// SMO changes the database when getting sql objects. Make sure the database is changed back to the original one
|
|
||||||
if (bindingContext.ServerConnection.CurrentDatabase != bindingContext.ServerConnection.DatabaseName)
|
|
||||||
{
|
|
||||||
bindingContext.ServerConnection.SqlConnectionObject.ChangeDatabase(bindingContext.ServerConnection.DatabaseName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
Logger.Write(TraceEventType.Warning, $"Failed to change the database in OE connection. error: {ex.Message}");
|
|
||||||
// We should just try to change the connection. If it fails, there's not much we can do
|
|
||||||
}
|
|
||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -66,9 +66,8 @@ namespace Microsoft.Kusto.ServiceLayer.UnitTests.LanguageServices
|
|||||||
[Test]
|
[Test]
|
||||||
public void AddConnectionContext_Returns_EmptyString_For_NullConnectionInfo()
|
public void AddConnectionContext_Returns_EmptyString_For_NullConnectionInfo()
|
||||||
{
|
{
|
||||||
var connectionOpenerMock = new Mock<ISqlConnectionOpener>();
|
|
||||||
var dataSourceFactory = new Mock<IDataSourceFactory>();
|
var dataSourceFactory = new Mock<IDataSourceFactory>();
|
||||||
var connectedBindingQueue = new ConnectedBindingQueue(connectionOpenerMock.Object, dataSourceFactory.Object);
|
var connectedBindingQueue = new ConnectedBindingQueue(dataSourceFactory.Object);
|
||||||
var connectionKey = connectedBindingQueue.AddConnectionContext(null, false);
|
var connectionKey = connectedBindingQueue.AddConnectionContext(null, false);
|
||||||
|
|
||||||
Assert.AreEqual(string.Empty, connectionKey);
|
Assert.AreEqual(string.Empty, connectionKey);
|
||||||
@@ -81,9 +80,8 @@ namespace Microsoft.Kusto.ServiceLayer.UnitTests.LanguageServices
|
|||||||
var connectionFactory = new Mock<IDataSourceConnectionFactory>();
|
var connectionFactory = new Mock<IDataSourceConnectionFactory>();
|
||||||
var connectionInfo = new ConnectionInfo(connectionFactory.Object, "ownerUri", connectionDetails);
|
var connectionInfo = new ConnectionInfo(connectionFactory.Object, "ownerUri", connectionDetails);
|
||||||
|
|
||||||
var connectionOpenerMock = new Mock<ISqlConnectionOpener>();
|
|
||||||
var dataSourceFactory = new Mock<IDataSourceFactory>();
|
var dataSourceFactory = new Mock<IDataSourceFactory>();
|
||||||
var connectedBindingQueue = new ConnectedBindingQueue(connectionOpenerMock.Object, dataSourceFactory.Object);
|
var connectedBindingQueue = new ConnectedBindingQueue(dataSourceFactory.Object);
|
||||||
var connectionKey = connectedBindingQueue.AddConnectionContext(connectionInfo, false, "featureName");
|
var connectionKey = connectedBindingQueue.AddConnectionContext(connectionInfo, false, "featureName");
|
||||||
|
|
||||||
Assert.AreEqual("NULL_NULL_NULL_NULL", connectionKey);
|
Assert.AreEqual("NULL_NULL_NULL_NULL", connectionKey);
|
||||||
@@ -96,12 +94,6 @@ namespace Microsoft.Kusto.ServiceLayer.UnitTests.LanguageServices
|
|||||||
var connectionFactory = new Mock<IDataSourceConnectionFactory>();
|
var connectionFactory = new Mock<IDataSourceConnectionFactory>();
|
||||||
var connectionInfo = new ConnectionInfo(connectionFactory.Object, "ownerUri", connectionDetails);
|
var connectionInfo = new ConnectionInfo(connectionFactory.Object, "ownerUri", connectionDetails);
|
||||||
|
|
||||||
var connectionOpenerMock = new Mock<ISqlConnectionOpener>();
|
|
||||||
var fakeServerConnection = new ServerConnection();
|
|
||||||
connectionOpenerMock
|
|
||||||
.Setup(x => x.OpenServerConnection(It.IsAny<ConnectionInfo>(), It.IsAny<string>()))
|
|
||||||
.Returns(fakeServerConnection);
|
|
||||||
|
|
||||||
var dataSourceFactory = new Mock<IDataSourceFactory>();
|
var dataSourceFactory = new Mock<IDataSourceFactory>();
|
||||||
var dataSourceMock = new Mock<IDataSource>();
|
var dataSourceMock = new Mock<IDataSource>();
|
||||||
dataSourceFactory
|
dataSourceFactory
|
||||||
@@ -109,18 +101,14 @@ namespace Microsoft.Kusto.ServiceLayer.UnitTests.LanguageServices
|
|||||||
.Returns(dataSourceMock.Object);
|
.Returns(dataSourceMock.Object);
|
||||||
|
|
||||||
var connectedBindingQueue =
|
var connectedBindingQueue =
|
||||||
new ConnectedBindingQueue(connectionOpenerMock.Object, dataSourceFactory.Object);
|
new ConnectedBindingQueue(dataSourceFactory.Object);
|
||||||
var connectionKey =
|
var connectionKey =
|
||||||
connectedBindingQueue.AddConnectionContext(connectionInfo, needsMetadata, "featureName");
|
connectedBindingQueue.AddConnectionContext(connectionInfo, needsMetadata, "featureName");
|
||||||
var bindingContext = connectedBindingQueue.GetOrCreateBindingContext(connectionKey);
|
var bindingContext = connectedBindingQueue.GetOrCreateBindingContext(connectionKey);
|
||||||
|
|
||||||
Assert.AreEqual(fakeServerConnection, bindingContext.ServerConnection);
|
|
||||||
Assert.AreEqual(dataSourceMock.Object, bindingContext.DataSource);
|
Assert.AreEqual(dataSourceMock.Object, bindingContext.DataSource);
|
||||||
Assert.AreEqual(500, bindingContext.BindingTimeout);
|
Assert.AreEqual(500, bindingContext.BindingTimeout);
|
||||||
Assert.AreEqual(true, bindingContext.IsConnected);
|
Assert.AreEqual(true, bindingContext.IsConnected);
|
||||||
Assert.AreEqual(CasingStyle.Uppercase, bindingContext.MetadataDisplayInfoProvider.BuiltInCasing);
|
|
||||||
Assert.IsNull(bindingContext.SmoMetadataProvider);
|
|
||||||
Assert.IsNull(bindingContext.Binder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -130,12 +118,10 @@ namespace Microsoft.Kusto.ServiceLayer.UnitTests.LanguageServices
|
|||||||
var connectionFactory = new Mock<IDataSourceConnectionFactory>();
|
var connectionFactory = new Mock<IDataSourceConnectionFactory>();
|
||||||
var connectionInfo = new ConnectionInfo(connectionFactory.Object, "ownerUri", connectionDetails);
|
var connectionInfo = new ConnectionInfo(connectionFactory.Object, "ownerUri", connectionDetails);
|
||||||
|
|
||||||
var connectionOpenerMock = new Mock<ISqlConnectionOpener>();
|
|
||||||
var dataSourceFactory = new Mock<IDataSourceFactory>();
|
var dataSourceFactory = new Mock<IDataSourceFactory>();
|
||||||
var connectedBindingQueue = new ConnectedBindingQueue(connectionOpenerMock.Object, dataSourceFactory.Object);
|
var connectedBindingQueue = new ConnectedBindingQueue(dataSourceFactory.Object);
|
||||||
var connectionKey = connectedBindingQueue.AddConnectionContext(connectionInfo, false, "featureName");
|
var connectionKey = connectedBindingQueue.AddConnectionContext(connectionInfo, false, "featureName");
|
||||||
|
|
||||||
|
|
||||||
connectedBindingQueue.RemoveBindingContext(connectionInfo);
|
connectedBindingQueue.RemoveBindingContext(connectionInfo);
|
||||||
|
|
||||||
Assert.IsFalse(connectedBindingQueue.BindingContextMap.ContainsKey(connectionKey));
|
Assert.IsFalse(connectedBindingQueue.BindingContextMap.ContainsKey(connectionKey));
|
||||||
|
|||||||
Reference in New Issue
Block a user