mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-25 01:25:40 -05:00
3278 Kusto Unit Test Refactor (#1053)
* 3278 Moved functions related to Metadata from DataSourceFactory to MetadataFactory.cs * 3278 Refactored DataSourceFactory to not be static. Added IDataSourceFactory interface. * 3278 Refactored IKustoIntellisenseHelper.cs to not be static. Added IKustoIntellisenseHelper.cs interface. * 3278 Removed unused functions from Scripter and deleted ScripterCore.cs because it was unused. Refactored Scripter.cs methods to not be static and created IScripter.cs * 3278 Refactored datsasourceConnectionFactory in ConnectionService to use MEF through the InitializeService function * 3278 Refactored IAutoCompleteHelper to not be static and added IAutoCompleteHelper interface. * 3278 Removed unused classes DatabaseFullAccessException and FeatureWithFullDbAccess. Refactored ObjectExplorerService to use ImportingConstructor attribute. Removed commented out in KustoResultsReader. Removed unused functions from DatabaseLocksManager. Removed unused IDataSourceConnectionFactory from ConnectionService * 3278 Moved SqlConnectionOpener class to new file. Added new interfaces IConnectedBindingQueue.cs and ISqlConnectionOpener.cs Added sqlConnectionOpener to dependency in ConnectedBindingQueue. * 3278 Removed needsMetadata param from ConnectedBindingQueue. Added param to AddConnectionContext where it's used * 3278 Refactored ConnectedBindingQueue to use MEF. Refactored usages to run against interface. * 3278 Corrected ServiceHost namespace. Removed unused dependency to sqlToolsContext in LanguageService. Updated dependency in MetadataService and LanguageService to IProtocolEndpoint instead of ServiceHost * 3278 Added back NextResult function and summary to KustoResultsReader. Renamed instance to _instance in ConnectionService and DatabaseLocksManager to stay consistent. Changed OpenDataSourceConnection to private in ConnectionService * 3278 Converted helper methods back to static and removed backing interfaces * 3278 Reverted AdminService > InitializeService to use ServiceHost as param
This commit is contained in:
@@ -2,13 +2,11 @@
|
||||
// Copyright (c) Microsoft. All Rights Reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Linq;
|
||||
using System.Data;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
{
|
||||
class DataReaderWrapper:IDataReader
|
||||
public class DataReaderWrapper : IDataReader
|
||||
{
|
||||
private readonly IDataReader _inner ;
|
||||
public DataReaderWrapper(IDataReader inner)
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Kusto.ServiceLayer.Utility;
|
||||
using Microsoft.Kusto.ServiceLayer.Admin.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
|
||||
using Microsoft.Kusto.ServiceLayer.Metadata.Contracts;
|
||||
using Microsoft.Kusto.ServiceLayer.DataSource.DataSourceIntellisense;
|
||||
using Microsoft.Kusto.ServiceLayer.DataSource.Metadata;
|
||||
using Microsoft.Kusto.ServiceLayer.LanguageServices.Contracts;
|
||||
using Microsoft.Kusto.ServiceLayer.Workspace.Contracts;
|
||||
using Microsoft.Kusto.ServiceLayer.LanguageServices.Completion;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
{
|
||||
/// <summary>
|
||||
/// Data source factory.
|
||||
/// </summary>
|
||||
public static class DataSourceFactory
|
||||
public class DataSourceFactory
|
||||
{
|
||||
public static IDataSource Create(DataSourceType dataSourceType, string connectionString, string azureAccountToken)
|
||||
{
|
||||
@@ -26,57 +19,16 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
switch (dataSourceType)
|
||||
{
|
||||
case DataSourceType.Kusto:
|
||||
{
|
||||
return new KustoDataSource(connectionString, azureAccountToken);
|
||||
}
|
||||
{
|
||||
return new KustoDataSource(connectionString, azureAccountToken);
|
||||
}
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Unsupported data source type \"{dataSourceType}\"", nameof(dataSourceType));
|
||||
throw new ArgumentException($"Unsupported data source type \"{dataSourceType}\"",
|
||||
nameof(dataSourceType));
|
||||
}
|
||||
}
|
||||
|
||||
public static DataSourceObjectMetadata CreateClusterMetadata(string clusterName)
|
||||
{
|
||||
ValidationUtils.IsArgumentNotNullOrWhiteSpace(clusterName, nameof(clusterName));
|
||||
|
||||
return new DataSourceObjectMetadata{
|
||||
MetadataType = DataSourceMetadataType.Cluster,
|
||||
MetadataTypeName = DataSourceMetadataType.Cluster.ToString(),
|
||||
Name = clusterName,
|
||||
PrettyName = clusterName,
|
||||
Urn = $"{clusterName}"
|
||||
};
|
||||
}
|
||||
|
||||
public static DataSourceObjectMetadata CreateDatabaseMetadata(DataSourceObjectMetadata clusterMetadata, string databaseName)
|
||||
{
|
||||
ValidationUtils.IsTrue<ArgumentException>(clusterMetadata.MetadataType == DataSourceMetadataType.Cluster, nameof(clusterMetadata));
|
||||
ValidationUtils.IsArgumentNotNullOrWhiteSpace(databaseName, nameof(databaseName));
|
||||
|
||||
return new DatabaseMetadata{
|
||||
ClusterName = clusterMetadata.Name,
|
||||
MetadataType = DataSourceMetadataType.Database,
|
||||
MetadataTypeName = DataSourceMetadataType.Database.ToString(),
|
||||
Name = databaseName,
|
||||
PrettyName = databaseName,
|
||||
Urn = $"{clusterMetadata.Urn}.{databaseName}"
|
||||
};
|
||||
}
|
||||
|
||||
public static FolderMetadata CreateFolderMetadata(DataSourceObjectMetadata parentMetadata, string path, string name)
|
||||
{
|
||||
ValidationUtils.IsNotNull(parentMetadata, nameof(parentMetadata));
|
||||
|
||||
return new FolderMetadata{
|
||||
MetadataType = DataSourceMetadataType.Folder,
|
||||
MetadataTypeName = DataSourceMetadataType.Folder.ToString(),
|
||||
Name = name,
|
||||
PrettyName = name,
|
||||
ParentMetadata = parentMetadata,
|
||||
Urn = $"{path}.{name}"
|
||||
};
|
||||
}
|
||||
|
||||
// Gets default keywords for intellisense when there is no connection.
|
||||
public static CompletionItem[] GetDefaultAutoComplete(DataSourceType dataSourceType, ScriptDocumentInfo scriptDocumentInfo, Position textDocumentPosition){
|
||||
switch (dataSourceType)
|
||||
@@ -105,41 +57,6 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
}
|
||||
}
|
||||
|
||||
// Converts database details shown on cluster manage dashboard to DatabaseInfo type. Add DataSourceType as param if required to show different properties
|
||||
public static List<DatabaseInfo> ConvertToDatabaseInfo(IEnumerable<DataSourceObjectMetadata> clusterDBDetails)
|
||||
{
|
||||
var databaseDetails = new List<DatabaseInfo>();
|
||||
|
||||
if(typeof(DatabaseMetadata) == clusterDBDetails.FirstOrDefault().GetType()){
|
||||
foreach(var dbDetail in clusterDBDetails)
|
||||
{
|
||||
DatabaseInfo databaseInfo = new DatabaseInfo();
|
||||
Int64.TryParse(dbDetail.SizeInMB.ToString(), out long sum_OriginalSize);
|
||||
databaseInfo.Options["name"] = dbDetail.Name;
|
||||
databaseInfo.Options["sizeInMB"] = (sum_OriginalSize /(1024 * 1024)).ToString();
|
||||
databaseDetails.Add(databaseInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return databaseDetails;
|
||||
}
|
||||
|
||||
// Converts tables details shown on database manage dashboard to ObjectMetadata type. Add DataSourceType as param if required to show different properties
|
||||
public static List<ObjectMetadata> ConvertToObjectMetadata(IEnumerable<DataSourceObjectMetadata> dbChildDetails)
|
||||
{
|
||||
var databaseChildDetails = new List<ObjectMetadata>();
|
||||
|
||||
foreach(var childDetail in dbChildDetails)
|
||||
{
|
||||
ObjectMetadata dbChildInfo = new ObjectMetadata();
|
||||
dbChildInfo.Name = childDetail.PrettyName;
|
||||
dbChildInfo.MetadataTypeName = childDetail.MetadataTypeName;
|
||||
dbChildInfo.MetadataType = MetadataType.Table; // Add mapping here.
|
||||
databaseChildDetails.Add(dbChildInfo);
|
||||
}
|
||||
return databaseChildDetails;
|
||||
}
|
||||
|
||||
public static ReliableConnectionHelper.ServerInfo ConvertToServerinfoFormat(DataSourceType dataSourceType, DiagnosticsInfo clusterDiagnostics)
|
||||
{
|
||||
switch (dataSourceType)
|
||||
|
||||
@@ -22,9 +22,8 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource.DataSourceIntellisense
|
||||
/// <summary>
|
||||
/// Kusto specific class for intellisense helper functions.
|
||||
/// </summary>
|
||||
public static class KustoIntellisenseHelper
|
||||
public class KustoIntellisenseHelper
|
||||
{
|
||||
|
||||
public class ShowDatabasesResult
|
||||
{
|
||||
public string DatabaseName;
|
||||
@@ -162,7 +161,7 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource.DataSourceIntellisense
|
||||
/// <summary>
|
||||
/// Loads the schema for the specified databasea into a a <see cref="DatabaseSymbol"/>.
|
||||
/// </summary>
|
||||
public static async Task<DatabaseSymbol> LoadDatabaseAsync(IDataSource dataSource, string databaseName, bool throwOnError = false)
|
||||
private static async Task<DatabaseSymbol> LoadDatabaseAsync(IDataSource dataSource, string databaseName, bool throwOnError = false)
|
||||
{
|
||||
var members = new List<Symbol>();
|
||||
CancellationTokenSource source = new CancellationTokenSource();
|
||||
|
||||
@@ -88,9 +88,12 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
ClusterName = GetClusterName(connectionString);
|
||||
DatabaseName = GetDatabaseName(connectionString);
|
||||
UserToken = azureAccountToken;
|
||||
SchemaState = Task.Run(() => KustoIntellisenseHelper.AddOrUpdateDatabaseAsync(this, GlobalState.Default, DatabaseName, ClusterName, throwOnError: false)).Result;
|
||||
SchemaState = Task.Run(() =>
|
||||
KustoIntellisenseHelper.AddOrUpdateDatabaseAsync(this, GlobalState.Default, DatabaseName, ClusterName,
|
||||
throwOnError: false)).Result;
|
||||
// Check if a connection can be made
|
||||
ValidationUtils.IsTrue<ArgumentException>(Exists().Result, $"Unable to connect. ClusterName = {ClusterName}, DatabaseName = {DatabaseName}");
|
||||
ValidationUtils.IsTrue<ArgumentException>(Exists().Result,
|
||||
$"Unable to connect. ClusterName = {ClusterName}, DatabaseName = {DatabaseName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -736,7 +739,7 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
if (tableInfos.Any(x => !string.IsNullOrWhiteSpace(x.Folder)))
|
||||
{
|
||||
// create Table folder to hold functions tables
|
||||
var tableFolder = DataSourceFactory.CreateFolderMetadata(databaseMetadata, rootTableFolderKey.ToString(), "Tables");
|
||||
var tableFolder = MetadataFactory.CreateFolderMetadata(databaseMetadata, rootTableFolderKey.ToString(), "Tables");
|
||||
_folderMetadata.AddRange(rootTableFolderKey.ToString(), new List<FolderMetadata> {tableFolder});
|
||||
rootTableFolderKey.Append($".{tableFolder.Name}");
|
||||
|
||||
@@ -782,7 +785,7 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
continue;
|
||||
}
|
||||
|
||||
var folder = DataSourceFactory.CreateFolderMetadata(objectMetadata, rootTableFolderKey, columnGroup.Key);
|
||||
var folder = MetadataFactory.CreateFolderMetadata(objectMetadata, rootTableFolderKey, columnGroup.Key);
|
||||
tableFolders.Add(folder);
|
||||
}
|
||||
|
||||
@@ -800,7 +803,7 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
|
||||
// create Functions folder to hold functions folders
|
||||
var rootFunctionFolderKey = $"{databaseMetadata.Urn}";
|
||||
var rootFunctionFolder = DataSourceFactory.CreateFolderMetadata(databaseMetadata, rootFunctionFolderKey, "Functions");
|
||||
var rootFunctionFolder = MetadataFactory.CreateFolderMetadata(databaseMetadata, rootFunctionFolderKey, "Functions");
|
||||
_folderMetadata.AddRange(rootFunctionFolderKey, new List<FolderMetadata> {rootFunctionFolder});
|
||||
|
||||
// create each folder to hold functions
|
||||
@@ -834,13 +837,13 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
var topFolder = subFolders.First();
|
||||
|
||||
var folderKey = functionFolder.Urn;
|
||||
var folder = DataSourceFactory.CreateFolderMetadata(databaseMetadata, folderKey, topFolder);
|
||||
var folder = MetadataFactory.CreateFolderMetadata(databaseMetadata, folderKey, topFolder);
|
||||
functionFolders.SafeAdd(folderKey, folder);
|
||||
|
||||
for (int i = 1; i < subFolders.Length; i++)
|
||||
{
|
||||
folderKey = $"{folderKey}.{subFolders[i - 1]}";
|
||||
var subFolder = DataSourceFactory.CreateFolderMetadata(databaseMetadata, folderKey, subFolders[i]);
|
||||
var subFolder = MetadataFactory.CreateFolderMetadata(databaseMetadata, folderKey, subFolders[i]);
|
||||
functionFolders.SafeAdd(folderKey, subFolder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,19 +4,18 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
{
|
||||
internal class KustoResultsReader : DataReaderWrapper
|
||||
{
|
||||
public KustoResultsReader(IDataReader reader)
|
||||
: base(reader)
|
||||
public KustoResultsReader(IDataReader reader) : base(reader)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Kusto returns 3 results tables - QueryResults, QueryProperties, QueryStatus. When returning query results
|
||||
/// we want the caller to only read the first table. We override the NextResult function here to only return one table
|
||||
/// from the IDataReader.
|
||||
/// </summary>
|
||||
/*public override bool NextResult()
|
||||
{
|
||||
return false;
|
||||
/// Kusto returns 3 results tables - QueryResults, QueryProperties, QueryStatus. When returning query results
|
||||
/// we want the caller to only read the first table. We override the NextResult function here to only return one table
|
||||
/// from the IDataReader.
|
||||
/// </summary>
|
||||
/*public override bool NextResult()
|
||||
{
|
||||
return false;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Kusto.ServiceLayer.Admin.Contracts;
|
||||
using Microsoft.Kusto.ServiceLayer.Metadata.Contracts;
|
||||
using Microsoft.Kusto.ServiceLayer.Utility;
|
||||
|
||||
namespace Microsoft.Kusto.ServiceLayer.DataSource.Metadata
|
||||
{
|
||||
public class MetadataFactory
|
||||
{
|
||||
public static DataSourceObjectMetadata CreateClusterMetadata(string clusterName)
|
||||
{
|
||||
ValidationUtils.IsArgumentNotNullOrWhiteSpace(clusterName, nameof(clusterName));
|
||||
|
||||
return new DataSourceObjectMetadata
|
||||
{
|
||||
MetadataType = DataSourceMetadataType.Cluster,
|
||||
MetadataTypeName = DataSourceMetadataType.Cluster.ToString(),
|
||||
Name = clusterName,
|
||||
PrettyName = clusterName,
|
||||
Urn = $"{clusterName}"
|
||||
};
|
||||
}
|
||||
|
||||
public static DataSourceObjectMetadata CreateDatabaseMetadata(DataSourceObjectMetadata clusterMetadata,
|
||||
string databaseName)
|
||||
{
|
||||
ValidationUtils.IsTrue<ArgumentException>(clusterMetadata.MetadataType == DataSourceMetadataType.Cluster,
|
||||
nameof(clusterMetadata));
|
||||
ValidationUtils.IsArgumentNotNullOrWhiteSpace(databaseName, nameof(databaseName));
|
||||
|
||||
return new DatabaseMetadata
|
||||
{
|
||||
ClusterName = clusterMetadata.Name,
|
||||
MetadataType = DataSourceMetadataType.Database,
|
||||
MetadataTypeName = DataSourceMetadataType.Database.ToString(),
|
||||
Name = databaseName,
|
||||
PrettyName = databaseName,
|
||||
Urn = $"{clusterMetadata.Urn}.{databaseName}"
|
||||
};
|
||||
}
|
||||
|
||||
public static FolderMetadata CreateFolderMetadata(DataSourceObjectMetadata parentMetadata, string path, string name)
|
||||
{
|
||||
ValidationUtils.IsNotNull(parentMetadata, nameof(parentMetadata));
|
||||
|
||||
return new FolderMetadata
|
||||
{
|
||||
MetadataType = DataSourceMetadataType.Folder,
|
||||
MetadataTypeName = DataSourceMetadataType.Folder.ToString(),
|
||||
Name = name,
|
||||
PrettyName = name,
|
||||
ParentMetadata = parentMetadata,
|
||||
Urn = $"{path}.{name}"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts database details shown on cluster manage dashboard to DatabaseInfo type. Add DataSourceType as param if required to show different properties
|
||||
/// </summary>
|
||||
/// <param name="clusterDBDetails"></param>
|
||||
/// <returns></returns>
|
||||
public static List<DatabaseInfo> ConvertToDatabaseInfo(IEnumerable<DataSourceObjectMetadata> clusterDBDetails)
|
||||
{
|
||||
var databaseDetails = new List<DatabaseInfo>();
|
||||
|
||||
if (typeof(DatabaseMetadata) == clusterDBDetails.FirstOrDefault().GetType())
|
||||
{
|
||||
foreach (var dbDetail in clusterDBDetails)
|
||||
{
|
||||
DatabaseInfo databaseInfo = new DatabaseInfo();
|
||||
Int64.TryParse(dbDetail.SizeInMB.ToString(), out long sum_OriginalSize);
|
||||
databaseInfo.Options["name"] = dbDetail.Name;
|
||||
databaseInfo.Options["sizeInMB"] = (sum_OriginalSize / (1024 * 1024)).ToString();
|
||||
databaseDetails.Add(databaseInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return databaseDetails;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts tables details shown on database manage dashboard to ObjectMetadata type. Add DataSourceType as param if required to show different properties
|
||||
/// </summary>
|
||||
/// <param name="dbChildDetails"></param>
|
||||
/// <returns></returns>
|
||||
public static List<ObjectMetadata> ConvertToObjectMetadata(IEnumerable<DataSourceObjectMetadata> dbChildDetails)
|
||||
{
|
||||
var databaseChildDetails = new List<ObjectMetadata>();
|
||||
|
||||
foreach (var childDetail in dbChildDetails)
|
||||
{
|
||||
ObjectMetadata dbChildInfo = new ObjectMetadata();
|
||||
dbChildInfo.Name = childDetail.PrettyName;
|
||||
dbChildInfo.MetadataTypeName = childDetail.MetadataTypeName;
|
||||
dbChildInfo.MetadataType = MetadataType.Table; // Add mapping here.
|
||||
databaseChildDetails.Add(dbChildInfo);
|
||||
}
|
||||
|
||||
return databaseChildDetails;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,16 +21,8 @@
|
||||
// =======================================================================================
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Collections;
|
||||
using System.Data.Common;
|
||||
using System.Data.SqlClient;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
|
||||
@@ -42,15 +34,15 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
|
||||
/// Provides a reliable way of opening connections to and executing commands
|
||||
/// taking into account potential network unreliability and a requirement for connection retry.
|
||||
/// </summary>
|
||||
public sealed partial class ReliableDataSourceConnection : IDisposable
|
||||
public sealed class ReliableDataSourceConnection : IDisposable
|
||||
{
|
||||
private IDataSource _dataSource;
|
||||
private readonly RetryPolicy _connectionRetryPolicy;
|
||||
private RetryPolicy _commandRetryPolicy;
|
||||
private Guid _azureSessionId = Guid.NewGuid();
|
||||
private readonly Guid _azureSessionId = Guid.NewGuid();
|
||||
|
||||
private string _connectionString;
|
||||
private string _azureAccountToken;
|
||||
private readonly string _connectionString;
|
||||
private readonly string _azureAccountToken;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ReliableKustoClient class with a given connection string
|
||||
|
||||
Reference in New Issue
Block a user